From e0e6a45000baa89f7bbe08a2d03883a29bc7c0cf Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 19:04:52 +0900 Subject: [PATCH] Prepare for reducing duplicates for 4op FM related codes, Add and correct bunch of presets, Add various clock, type options for chips Prepare for reducing duplicates for 4op FM related codes Add and correct bunch of presets - mostly based on MAME source. - Neo Geo AES uses slightly difference clock for NTSC, PAL colorbust frequency. - Turbosound FM + SAA: Some Turbosound FM has additional SAA1099, for additional sound channel and Plays SAM coupe tune? - PC-98: - Sound Orchestra: OPN with hardpanned stereo, some model has with OPL family FM addons. V variation has Y8950 and supports ADPCM. - Sound Blaster 16 for PC-9800: This famous PC sound card is also exists for PC-98, with optional OPN PC-9801-26(K) compatibility on some models. - IBM PCjr: PC with SN PSG sound, but less popular than previous models, and compatible Tandy 1000. - Tandy 1000: PCjr and previous IBM PC compatible, also has SN PSG (later embedded in their ASIC, like Sega). - Hexion: One of konami's budget arcade hardware with SCC + MSM6295 sound system, like their amusement hardware in this era. - DJ Boy, Atari JSA IIIs, Skimaxx: How to panning sound or plays stereo sound on MSM6295 - just use MSM6295s per each output! - Air Buster: One of arcade hardware with OPN + MSM6295 sound system, Used this configuration is also some hardwares. - Tecmo system: One of arcade hardware with pretty unique sound system: OPL3, YMZ280B, MSM6295; first 2 entry is mostly used in music, last entry is mostly used in sound effect. - Sunsoft Shanghai 3: Predecessor of Sunsoft Arcade is using YM2149 rather than FM, MSM6295 is still there. - Atari Klax: example of arcade hardware sound system with single MSM6295 only. - Ikari warriors: This early SNK Triple-Z80 hardware uses 2 OPL1s and no ADPCM supports. - Coreland Cyber Tank: This rare arcade machine's stereo sound is like SB Pro, but it's actually produced in 2 Y8950s. - Data East MLC: Latest arcade hardware from Data East, with single YMZ280B for sound. - Kaneko Jackie Chan: Predecessor of Super Kaneko Nova System hardware, also with YMZ280B. - Super Kaneko Nova System: Latest arcade hardware from Kaneko, with single YMZ280B for sound. this announced 3D acceleration addon, but finally cancelled. - Toaplan 1: Home of Late 80-Early 90s Good ol' stuffs, Example of arcade sound system with single OPL2 - Namco Pac-Land: and this era, Namco start to change Custom 15 WSG to their Custom 30 WSG with featured RAM based waveform, and mailbox feature. - Namco System 1: One of latest usage of Custom 30 WSG, with OPM FM hardware and 8 bit DAC and Stereo output. Add various clock, type options for chips - SN7: Prepare to add 17 bit noise variation, Game gear stereo extentsion, NCR PSG variation (MAME core only for now) - OPN, OPNA: Add placeholder for prescaler option - OPL: Prepare for OPL3L, OPL4 downscaled output rate option --- extern/Nuked-PSG/ympsg.c | 9 +- extern/Nuked-PSG/ympsg.h | 5 +- src/engine/platform/arcade.cpp | 61 +- src/engine/platform/arcade.h | 19 +- src/engine/platform/ay.cpp | 100 +- src/engine/platform/ay.h | 8 + src/engine/platform/fmshared_OPM.h | 21 +- src/engine/platform/fmshared_OPN.h | 25 +- .../{genesisshared.h => fmsharedbase.h} | 65 +- src/engine/platform/genesis.cpp | 8 +- src/engine/platform/genesis.h | 15 +- src/engine/platform/genesisext.cpp | 4 - src/engine/platform/msm6258.h | 13 +- src/engine/platform/msm6295.cpp | 57 +- src/engine/platform/msm6295.h | 109 +-- src/engine/platform/opl.cpp | 102 +- src/engine/platform/opl.h | 6 +- src/engine/platform/scc.cpp | 27 +- src/engine/platform/scc.h | 1 + src/engine/platform/sms.cpp | 211 +++-- src/engine/platform/sms.h | 15 +- src/engine/platform/sound/sn76496.cpp | 83 +- src/engine/platform/sound/sn76496.h | 113 ++- src/engine/platform/tx81z.cpp | 36 +- src/engine/platform/tx81z.h | 19 +- src/engine/platform/ym2203.cpp | 57 +- src/engine/platform/ym2203.h | 23 +- src/engine/platform/ym2203ext.cpp | 5 +- src/engine/platform/ym2203shared.h | 45 - src/engine/platform/ym2608.cpp | 40 +- src/engine/platform/ym2608.h | 24 +- src/engine/platform/ym2608ext.cpp | 3 - src/engine/platform/ym2610.cpp | 43 +- src/engine/platform/ym2610.h | 26 +- src/engine/platform/ym2610b.cpp | 40 +- src/engine/platform/ym2610b.h | 17 +- src/engine/platform/ym2610bext.cpp | 3 - src/engine/platform/ym2610ext.cpp | 3 - src/engine/platform/ym2610shared.h | 45 - src/engine/platform/ymz280b.cpp | 44 +- src/engine/platform/ymz280b.h | 1 + src/engine/song.h | 124 ++- src/gui/insEdit.cpp | 7 +- src/gui/presets.cpp | 893 +++++++++++++++--- src/gui/sysConf.cpp | 352 ++++--- src/main.cpp | 1 + 46 files changed, 2027 insertions(+), 901 deletions(-) rename src/engine/platform/{genesisshared.h => fmsharedbase.h} (60%) delete mode 100644 src/engine/platform/ym2203shared.h delete mode 100644 src/engine/platform/ym2610shared.h diff --git a/extern/Nuked-PSG/ympsg.c b/extern/Nuked-PSG/ympsg.c index 3df4f8e39..935b43ea9 100644 --- a/extern/Nuked-PSG/ympsg.c +++ b/extern/Nuked-PSG/ympsg.c @@ -130,7 +130,7 @@ static void YMPSG_ClockInternal1(ympsg_t *chip) else if (noise_of && !chip->noise_of) { noise_bit1 = (chip->noise >> chip->noise_tap2) & 1; - noise_bit2 = (chip->noise >> 12) & 1; + noise_bit2 = (chip->noise >> chip->noise_tap1) & 1; noise_bit1 ^= noise_bit2; noise_next = ((noise_bit1 && ((chip->noise_data >> 2) & 1)) || ((chip->noise & chip->noise_size) == 0)); chip->noise <<= 1; @@ -257,13 +257,14 @@ uint16_t YMPSG_Read(ympsg_t *chip) return data; } -void YMPSG_Init(ympsg_t *chip, uint8_t real_sn) +void YMPSG_Init(ympsg_t *chip, uint8_t real_sn, uint8_t noise_tap1, uint8_t noise_tap2, uint32_t noise_size) { uint32_t i; memset(chip, 0, sizeof(ympsg_t)); YMPSG_SetIC(chip, 1); - chip->noise_tap2 = real_sn ? 13 : 15; - chip->noise_size = real_sn ? 16383 : 32767; + chip->noise_tap1 = noise_tap1; + chip->noise_tap2 = noise_tap2; + chip->noise_size = noise_size; for (i = 0; i < 17; i++) { chip->vol_table[i]=(real_sn?tipsg_vol[i]:ympsg_vol[i]) * 8192.0f; diff --git a/extern/Nuked-PSG/ympsg.h b/extern/Nuked-PSG/ympsg.h index c00b3d720..97e039e3c 100644 --- a/extern/Nuked-PSG/ympsg.h +++ b/extern/Nuked-PSG/ympsg.h @@ -46,8 +46,9 @@ typedef struct { uint8_t sign_l; uint8_t noise_sign_l; uint16_t noise; + uint8_t noise_tap1; uint8_t noise_tap2; - uint16_t noise_size; + uint32_t noise_size; uint8_t test; uint8_t volume_out[4]; @@ -68,7 +69,7 @@ typedef struct { void YMPSG_Write(ympsg_t *chip, uint8_t data); uint16_t YMPSG_Read(ympsg_t *chip); -void YMPSG_Init(ympsg_t *chip, uint8_t real_sn); +void YMPSG_Init(ympsg_t *chip, uint8_t real_sn, uint8_t noise_tap1, uint8_t noise_tap2, uint32_t noise_size); void YMPSG_SetIC(ympsg_t *chip, uint32_t ic); void YMPSG_Clock(ympsg_t *chip); int YMPSG_GetOutput(ympsg_t *chip); diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index 564467256..f6fa7d70a 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -22,38 +22,6 @@ #include #include -#include "fmshared_OPM.h" - -static unsigned short chanOffs[8]={ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 -}; -static unsigned short opOffs[4]={ - 0x00, 0x08, 0x10, 0x18 -}; -static bool isOutput[8][4]={ - // 1 3 2 4 - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,true ,true}, - {false,true ,true ,true}, - {false,true ,true ,true}, - {true ,true ,true ,true}, -}; -static unsigned char dtTable[8]={ - 7,6,5,0,1,2,3,4 -}; - -static int orderedOps[4]={ - 0,2,1,3 -}; - -#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} -#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } - -#define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) - const char* regCheatSheetOPM[]={ "Test", "00", "NoteCtl", "08", @@ -198,7 +166,7 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si OPM_Write(&fm,1,w.val); regPool[w.addr&0xff]=w.val; //printf("write: %x = %.2x\n",w.addr,w.val); - writes.pop(); + writes.pop_front(); } else { OPM_Write(&fm,0,w.addr); w.addrOrVal=true; @@ -239,7 +207,7 @@ void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, siz fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr); fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val); regPool[w.addr&0xff]=w.val; - writes.pop(); + writes.pop_front(); delay=1; } } @@ -934,7 +902,7 @@ void DivPlatformArcade::poke(std::vector& wlist) { } void DivPlatformArcade::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,256); if (useYMFM) { fm_ymfm->reset(); @@ -974,15 +942,20 @@ void DivPlatformArcade::reset() { } void DivPlatformArcade::setFlags(unsigned int flags) { - if (flags==2) { - chipClock=4000000.0; - baseFreqOff=-122; - } else if (flags==1) { - chipClock=COLOR_PAL*4.0/5.0; - baseFreqOff=12; - } else { - chipClock=COLOR_NTSC; - baseFreqOff=0; + switch (flags&0xff) { + default: + case 0: + chipClock=COLOR_NTSC; + baseFreqOff=0; + break; + case 1: + chipClock=COLOR_PAL*4.0/5.0; + baseFreqOff=12; + break; + case 2: + chipClock=4000000.0; + baseFreqOff=-122; + break; } rate=chipClock/64; for (int i=0; i<8; i++) { diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index 6f68eedad..9d0e39685 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -20,18 +20,23 @@ #ifndef _ARCADE_H #define _ARCADE_H #include "../dispatch.h" +#include "../macroInt.h" #include "../instrument.h" #include #include "../../../extern/opm/opm.h" #include "sound/ymfm/ymfm_opm.h" -#include "../macroInt.h" +#include "fmshared_OPM.h" class DivArcadeInterface: public ymfm::ymfm_interface { }; -class DivPlatformArcade: public DivDispatch { +class DivPlatformArcade: public DivDispatch, public DivPlatformOPMBase { protected: + const unsigned short chanOffs[8]={ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + struct Channel { DivInstrumentFM state; DivMacroInt std; @@ -71,17 +76,9 @@ class DivPlatformArcade: public DivDispatch { }; Channel chan[8]; DivDispatchOscBuffer* oscBuf[8]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; opm_t fm; - int delay, baseFreqOff; + int baseFreqOff; int pcmL, pcmR, pcmCycles; - unsigned char lastBusy; unsigned char amDepth, pmDepth; ymfm::ym2151* fm_ymfm; diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index a3d325ade..2f2b20c57 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -27,7 +27,7 @@ #define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} #define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(regRemap(a),v); if (dumpWrites) {addWrite(regRemap(a),v);} } -#define CHIP_DIVIDER ((sunsoft||clockSel)?16:8) +#define CHIP_DIVIDER (extMode?extDiv:((sunsoft||clockSel)?16:8)) const char* regCheatSheetAY[]={ "FreqL_A", "0", @@ -561,8 +561,6 @@ void DivPlatformAY8910::reset() { delay=0; - extMode=false; - ioPortA=false; ioPortB=false; portAVal=0; @@ -592,49 +590,61 @@ void DivPlatformAY8910::poke(std::vector& wlist) { } void DivPlatformAY8910::setFlags(unsigned int flags) { - clockSel=(flags>>7)&1; - switch (flags&15) { - case 1: - chipClock=COLOR_PAL*2.0/5.0; - break; - case 2: - chipClock=1750000; - break; - case 3: - chipClock=2000000; - break; - case 4: - chipClock=1500000; - break; - case 5: - chipClock=1000000; - break; - case 6: - chipClock=COLOR_NTSC/4.0; - break; - case 7: - chipClock=COLOR_PAL*3.0/8.0; - break; - case 8: - chipClock=COLOR_PAL*3.0/16.0; - break; - case 9: - chipClock=COLOR_PAL/4.0; - break; - case 10: - chipClock=2097152; - break; - case 11: - chipClock=COLOR_NTSC; - break; - case 12: - chipClock=3600000; - break; - default: - chipClock=COLOR_NTSC/2.0; - break; + if (extMode) { + chipClock=extClock; + rate=chipClock/extDiv; + } else { + clockSel=(flags>>7)&1; + switch (flags&15) { + default: + case 0: + chipClock=COLOR_NTSC/2.0; + break; + case 1: + chipClock=COLOR_PAL*2.0/5.0; + break; + case 2: + chipClock=1750000; + break; + case 3: + chipClock=2000000; + break; + case 4: + chipClock=1500000; + break; + case 5: + chipClock=1000000; + break; + case 6: + chipClock=COLOR_NTSC/4.0; + break; + case 7: + chipClock=COLOR_PAL*3.0/8.0; + break; + case 8: + chipClock=COLOR_PAL*3.0/16.0; + break; + case 9: + chipClock=COLOR_PAL/4.0; + break; + case 10: + chipClock=2097152; + break; + case 11: + chipClock=COLOR_NTSC; + break; + case 12: + chipClock=3600000; + break; + case 13: + chipClock=20000000/16; + break; + case 14: + chipClock=1536000; + break; + } + rate=chipClock/8; } - rate=chipClock/8; for (int i=0; i<3; i++) { oscBuf[i]->rate=rate; } diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index f93d34bdc..8ff5f39c5 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -70,6 +70,9 @@ class DivPlatformAY8910: public DivDispatch { int delay; bool extMode; + unsigned int extClock; + unsigned char extDiv; + bool stereo, sunsoft, intellivision, clockSel; bool ioPortA, ioPortB; unsigned char portAVal, portBVal; @@ -110,5 +113,10 @@ class DivPlatformAY8910: public DivDispatch { const char* getEffectName(unsigned char effect); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); + DivPlatformAY8910(bool useExtMode=false, unsigned int eclk=COLOR_NTSC, unsigned char ediv=8): + DivDispatch(), + extMode(useExtMode), + extClock(eclk), + extDiv(ediv) {} }; #endif diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index 0ab05344b..ed5f63dd4 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -17,6 +17,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#ifndef _FMSHARED_OPM_H +#define _FMSHARED_OPM_H + +#include "fmsharedbase.h" + #define ADDR_MULT_DT 0x40 #define ADDR_TL 0x60 #define ADDR_RS_AR 0x80 @@ -26,4 +31,18 @@ #define ADDR_NOTE 0x28 #define ADDR_KF 0x30 #define ADDR_FMS_AMS 0x38 -#define ADDR_LR_FB_ALG 0x20 \ No newline at end of file +#define ADDR_LR_FB_ALG 0x20 + +#define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) + +class DivPlatformOPMBase: public DivPlatformFMBase { + protected: + const unsigned short opOffs[4]={ + 0x00, 0x08, 0x10, 0x18 + }; + + DivPlatformOPMBase(): + DivPlatformFMBase() {} +}; + +#endif diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index a709aa1a3..6e5426b51 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -20,6 +20,8 @@ #ifndef _FMSHARED_OPN_H #define _FMSHARED_OPN_H +#include "fmsharedbase.h" + #define ADDR_MULT_DT 0x30 #define ADDR_TL 0x40 #define ADDR_RS_AR 0x50 @@ -32,6 +34,9 @@ #define ADDR_FB_ALG 0xb0 #define ADDR_LRAF 0xb4 +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + #define PLEASE_HELP_ME(_targetChan) \ int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); \ int boundaryTop=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,12,false); \ @@ -93,4 +98,22 @@ return 2; \ } -#endif \ No newline at end of file +class DivPlatformOPNBase: public DivPlatformFMBase { + protected: + const unsigned short opOffs[4]={ + 0x00, 0x04, 0x08, 0x0c + }; + + const double fmFreqBase; + const double fmDivBase; + const unsigned char ayDiv; + + DivPlatformOPNBase(double f=9440540.0, double d=72, unsigned char a=32): + DivPlatformFMBase(), + fmFreqBase(f), + fmDivBase(d), + ayDiv(a) {} + +}; + +#endif diff --git a/src/engine/platform/genesisshared.h b/src/engine/platform/fmsharedbase.h similarity index 60% rename from src/engine/platform/genesisshared.h rename to src/engine/platform/fmsharedbase.h index d58d339e6..a3b0e634f 100644 --- a/src/engine/platform/genesisshared.h +++ b/src/engine/platform/fmsharedbase.h @@ -17,30 +17,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -static unsigned short chanOffs[6]={ - 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 -}; -static unsigned short opOffs[4]={ - 0x00, 0x04, 0x08, 0x0c -}; -static bool isOutput[8][4]={ - // 1 3 2 4 - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,true ,true}, - {false,true ,true ,true}, - {false,true ,true ,true}, - {true ,true ,true ,true}, -}; -static unsigned char dtTable[8]={ - 7,6,5,0,1,2,3,4 -}; +#ifndef _FMSHARED_BASE_H +#define _FMSHARED_BASE_H -static int orderedOps[4]={ - 0,2,1,3 -}; +#include #define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} #define immWrite(a,v) if (!skipRegisterWrites) {writes.push_back(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} } @@ -57,4 +37,41 @@ static int orderedOps[4]={ } \ } -#include "fmshared_OPN.h" +class DivPlatformFMBase { + protected: + const bool isOutput[8][4]={ + // 1 3 2 4 + {false,false,false,true}, + {false,false,false,true}, + {false,false,false,true}, + {false,false,false,true}, + {false,false,true ,true}, + {false,true ,true ,true}, + {false,true ,true ,true}, + {true ,true ,true ,true}, + }; + const unsigned char dtTable[8]={ + 7,6,5,0,1,2,3,4 + }; + + const int orderedOps[4]={ + 0,2,1,3 + }; + + 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; + + unsigned char lastBusy; + int delay; + + DivPlatformFMBase(): + lastBusy(0), + delay(0) {} +}; + +#endif diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 6cba30ddb..a832bab4a 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -22,13 +22,10 @@ #include #include -#include "genesisshared.h" - static unsigned char konOffs[6]={ 0, 1, 2, 4, 5, 6 }; -#define CHIP_FREQBASE 9440540 const char* DivPlatformGenesis::getEffectName(unsigned char effect) { switch (effect) { @@ -1169,12 +1166,13 @@ void DivPlatformGenesis::setSoftPCM(bool value) { } void DivPlatformGenesis::setFlags(unsigned int flags) { - switch (flags) { + switch (flags&(~0x80000000)) { + default: + case 0: chipClock=COLOR_NTSC*15.0/7.0; break; case 1: chipClock=COLOR_PAL*12.0/7.0; break; case 2: chipClock=8000000.0; break; case 3: chipClock=COLOR_NTSC*12.0/7.0; break; case 4: chipClock=COLOR_NTSC*9.0/4.0; break; - default: chipClock=COLOR_NTSC*15.0/7.0; break; } ladder=flags&0x80000000; OPN2_SetChipType(ladder?ym3438_mode_ym2612:0); diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index b4862427d..71493fa5e 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -20,18 +20,22 @@ #ifndef _GENESIS_H #define _GENESIS_H #include "../dispatch.h" -#include +#include "../macroInt.h" #include "../../../extern/Nuked-OPN2/ym3438.h" #include "sound/ymfm/ymfm_opn.h" -#include "sms.h" +#include "fmshared_OPN.h" class DivYM2612Interface: public ymfm::ymfm_interface { }; -class DivPlatformGenesis: public DivDispatch { +class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { protected: + const unsigned short chanOffs[6]={ + 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 + }; + struct Channel { DivInstrumentFM state; DivMacroInt std; @@ -98,8 +102,6 @@ class DivPlatformGenesis: public DivDispatch { }; std::deque writes; ym3438_t fm; - int delay; - unsigned char lastBusy; ymfm::ym2612* fm_ymfm; ymfm::ym2612::output_data out_ymfm; @@ -150,6 +152,9 @@ class DivPlatformGenesis: public DivDispatch { const char* getEffectName(unsigned char effect); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); + DivPlatformGenesis(): + DivDispatch(), + DivPlatformOPNBase(9440540.0, 72, 32) {} ~DivPlatformGenesis(); }; #endif diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index cc4abc88b..76837f649 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -21,10 +21,6 @@ #include "../engine.h" #include -#include "genesisshared.h" - -#define CHIP_FREQBASE 9440540 - int DivPlatformGenesisExt::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformGenesis::dispatch(c); diff --git a/src/engine/platform/msm6258.h b/src/engine/platform/msm6258.h index ea0482f37..3a05bcf82 100644 --- a/src/engine/platform/msm6258.h +++ b/src/engine/platform/msm6258.h @@ -26,10 +26,6 @@ class DivPlatformMSM6258: public DivDispatch { protected: - const unsigned short chanOffs[6]={ - 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 - }; - struct Channel { unsigned char freqH, freqL; int freq, baseFreq, pitch, pitch2, portaPauseFreq, note, ins; @@ -77,12 +73,10 @@ class DivPlatformMSM6258: public DivDispatch { struct QueuedWrite { unsigned short addr; unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} + QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {} }; std::queue writes; okim6258_device* msm; - unsigned char regPool[512]; unsigned char lastBusy; unsigned char* adpcmMem; @@ -91,11 +85,6 @@ class DivPlatformMSM6258: public DivDispatch { int delay, updateOsc, sample, samplePos; - bool extMode; - - short oldWrites[512]; - short pendingWrites[512]; - friend void putDispatchChan(void*,int,int); public: diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index 541dded63..0d88d35dd 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -24,6 +24,7 @@ #include #define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } +#define rWriteDelay(a,v,d) if (!skipRegisterWrites) {writes.emplace(a,v,d); if (dumpWrites) {addWrite(a,v);} } const char** DivPlatformMSM6295::getRegisterSheet() { return NULL; @@ -38,8 +39,11 @@ const char* DivPlatformMSM6295::getEffectName(unsigned char effect) { return NULL; } -u8 DivMSM6295Interface::read_byte(u32 address) { - return adpcmMem[address&0xffff]; +u8 DivPlatformMSM6295::read_byte(u32 address) { + if (adpcmMem==NULL || address>=getSampleMemCapacity(0)) { + return 0; + } + return adpcmMem[address&0x3ffff]; } void DivPlatformMSM6295::acquire(short* bufL, short* bufR, size_t start, size_t len) { @@ -49,7 +53,7 @@ void DivPlatformMSM6295::acquire(short* bufL, short* bufR, size_t start, size_t QueuedWrite& w=writes.front(); switch (w.addr) { case 0: // command - msm->command_w(w.val); + msm.command_w(w.val); break; case 8: // chip clock select (VGM) case 9: @@ -57,7 +61,7 @@ void DivPlatformMSM6295::acquire(short* bufL, short* bufR, size_t start, size_t case 11: break; case 12: // rate select - msm->ss_w(!w.val); + msm.ss_w(!w.val); break; case 14: // enable bankswitch break; @@ -70,21 +74,21 @@ void DivPlatformMSM6295::acquire(short* bufL, short* bufR, size_t start, size_t break; } writes.pop(); - delay=32; + delay=w.delay; } } else { delay--; } - msm->tick(); + msm.tick(); - bufL[h]=msm->out()<<4; + bufL[h]=msm.out()<<4; if (++updateOsc>=22) { updateOsc=0; // TODO: per-channel osc for (int i=0; i<4; i++) { - oscBuf[i]->data[oscBuf[i]->needle++]=msm->m_voice[i].m_muted?0:(msm->m_voice[i].m_out<<6); + oscBuf[i]->data[oscBuf[i]->needle++]=msm.m_voice[i].m_muted?0:(msm.m_voice[i].m_out<<6); } } } @@ -118,7 +122,7 @@ int DivPlatformMSM6295::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].keyOn=true; - rWrite(0,(8<getSample(12*sampleBank+c.value%12); chan[c.chan].sample=12*sampleBank+c.value%12; - rWrite(0,(8<(parent->song.sample.size()/12)) { sampleBank=parent->song.sample.size()/12; } - iface.sampleBank=sampleBank; break; case DIV_CMD_LEGATO: { break; @@ -212,7 +215,7 @@ int DivPlatformMSM6295::dispatch(DivCommand c) { void DivPlatformMSM6295::muteChannel(int ch, bool mute) { isMuted[ch]=mute; - msm->m_voice[ch].m_muted=mute; + msm.m_voice[ch].m_muted=mute; } void DivPlatformMSM6295::forceIns() { @@ -249,8 +252,8 @@ void DivPlatformMSM6295::poke(std::vector& wlist) { void DivPlatformMSM6295::reset() { while (!writes.empty()) writes.pop(); - msm->reset(); - msm->ss_w(false); + msm.reset(); + msm.ss_w(rateSelInit); if (dumpWrites) { addWrite(0xffffffff,0); } @@ -264,7 +267,8 @@ void DivPlatformMSM6295::reset() { } sampleBank=0; - rateSel=false; + rateSel=rateSelInit; + rWrite(12,!rateSelInit); delay=0; } @@ -339,7 +343,9 @@ void DivPlatformMSM6295::renderSamples() { } void DivPlatformMSM6295::setFlags(unsigned int flags) { - switch (flags) { + rateSelInit=(flags>>7)&1; + switch (flags&0x7f) { + default: case 0: chipClock=4000000/4; break; @@ -379,8 +385,11 @@ void DivPlatformMSM6295::setFlags(unsigned int flags) { case 12: chipClock=1500000; break; - default: - chipClock=4000000/4; + case 13: + chipClock=3000000; + break; + case 14: + chipClock=COLOR_NTSC/3.0; break; } rate=chipClock/3; @@ -388,14 +397,16 @@ void DivPlatformMSM6295::setFlags(unsigned int flags) { isMuted[i]=false; oscBuf[i]->rate=rate/22; } + if (rateSel!=rateSelInit) { + rWrite(12,!rateSelInit); + rateSel=rateSelInit; + } } int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { parent=p; adpcmMem=new unsigned char[getSampleMemCapacity(0)]; adpcmMemLen=0; - iface.adpcmMem=adpcmMem; - iface.sampleBank=0; dumpWrites=false; skipRegisterWrites=false; updateOsc=0; @@ -403,7 +414,6 @@ int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, unsigned i isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - msm=new msm6295_core(iface); setFlags(flags); reset(); return 4; @@ -413,7 +423,6 @@ void DivPlatformMSM6295::quit() { for (int i=0; i<4; i++) { delete oscBuf[i]; } - delete msm; delete[] adpcmMem; } diff --git a/src/engine/platform/msm6295.h b/src/engine/platform/msm6295.h index 2930a169b..463384f14 100644 --- a/src/engine/platform/msm6295.h +++ b/src/engine/platform/msm6295.h @@ -24,60 +24,31 @@ #include #include "sound/oki/msm6295.hpp" -class DivMSM6295Interface: public vgsound_emu_mem_intf { - public: - unsigned char* adpcmMem; - int sampleBank; - u8 read_byte(u32 address); - DivMSM6295Interface(): adpcmMem(NULL), sampleBank(0) {} -}; - -class DivPlatformMSM6295: public DivDispatch { +class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf { protected: - const unsigned short chanOffs[6]={ - 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 - }; - struct Channel { - unsigned char freqH, freqL; - int freq, baseFreq, pitch, pitch2, portaPauseFreq, note, ins; - unsigned char psgMode, autoEnvNum, autoEnvDen; + int note, ins; signed char konCycles; - bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset; + bool active, insChanged, freqChanged, keyOn, keyOff, furnacePCM, hardReset; int vol, outVol; int sample; - unsigned char pan; DivMacroInt std; void macroInit(DivInstrument* which) { std.init(which); - pitch2=0; } Channel(): - freqH(0), - freqL(0), - freq(0), - baseFreq(0), - pitch(0), - pitch2(0), - portaPauseFreq(0), note(0), ins(-1), - psgMode(1), - autoEnvNum(0), - autoEnvDen(0), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), - portaPause(false), - inPorta(false), furnacePCM(false), hardReset(false), vol(0), outVol(15), - sample(-1), - pan(3) {} + sample(-1) {} }; Channel chan[4]; DivDispatchOscBuffer* oscBuf[4]; @@ -85,56 +56,58 @@ class DivPlatformMSM6295: public DivDispatch { struct QueuedWrite { unsigned short addr; unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} + unsigned short delay; + QueuedWrite(unsigned short a, unsigned char v, unsigned short d=32): + addr(a), + val(v), + delay(d) {} }; std::queue writes; - msm6295_core* msm; - unsigned char regPool[512]; + msm6295_core msm; unsigned char lastBusy; unsigned char* adpcmMem; size_t adpcmMemLen; - DivMSM6295Interface iface; unsigned char sampleBank; int delay, updateOsc; - bool extMode; - bool rateSel; + bool rateSel=false, rateSelInit=false; - short oldWrites[512]; - short pendingWrites[512]; - friend void putDispatchChan(void*,int,int); public: - void acquire(short* bufL, short* bufR, size_t start, size_t len); - int dispatch(DivCommand c); - void* getChanState(int chan); - DivDispatchOscBuffer* getOscBuffer(int chan); - unsigned char* getRegisterPool(); - int getRegisterPoolSize(); - void reset(); - void forceIns(); - void tick(bool sysTick=true); - void muteChannel(int ch, bool mute); - bool keyOffAffectsArp(int ch); - float getPostAmp(); - void notifyInsChange(int ins); - void notifyInsDeletion(void* ins); - void poke(unsigned int addr, unsigned short val); - void poke(std::vector& wlist); - void setFlags(unsigned int flags); - const char** getRegisterSheet(); - const char* getEffectName(unsigned char effect); - const void* getSampleMem(int index); - size_t getSampleMemCapacity(int index); - size_t getSampleMemUsage(int index); - void renderSamples(); + virtual u8 read_byte(u32 address) override; + virtual void acquire(short* bufL, short* bufR, size_t start, size_t len) override; + virtual int dispatch(DivCommand c) override; + virtual void* getChanState(int chan) override; + virtual DivDispatchOscBuffer* getOscBuffer(int chan) override; + virtual unsigned char* getRegisterPool() override; + virtual int getRegisterPoolSize() override; + virtual void reset() override; + virtual void forceIns() override; + virtual void tick(bool sysTick=true) override; + virtual void muteChannel(int ch, bool mute) override; + virtual bool keyOffAffectsArp(int ch) override; + virtual float getPostAmp() override; + virtual void notifyInsChange(int ins) override; + virtual void notifyInsDeletion(void* ins) override; + virtual void poke(unsigned int addr, unsigned short val) override; + virtual void poke(std::vector& wlist) override; + virtual void setFlags(unsigned int flags) override; + virtual const char** getRegisterSheet() override; + virtual const char* getEffectName(unsigned char effect) override; + virtual const void* getSampleMem(int index) override; + virtual size_t getSampleMemCapacity(int index) override; + virtual size_t getSampleMemUsage(int index) override; + virtual void renderSamples() override; - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); - void quit(); + virtual int init(DivEngine* parent, int channels, int sugRate, unsigned int flags) override; + virtual void quit() override; + DivPlatformMSM6295(): + DivDispatch(), + vgsound_emu_mem_intf(), + msm(*this) {} ~DivPlatformMSM6295(); }; #endif diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index c8d728292..a40f41143 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -277,8 +277,13 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_ regPool[w.addr&511]=w.val; writes.pop(); } - - OPL3_Generate(&fm,o); os[0]+=o[0]; os[1]+=o[1]; + + if (downsample) { + OPL3_GenerateResampled(&fm,o); + } else { + OPL3_Generate(&fm,o); + } + os[0]+=o[0]; os[1]+=o[1]; if (adpcmChan>=0) { adpcmB->clock(); @@ -778,7 +783,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { immWrite(11,(end>>2)&0xff); immWrite(12,(end>>10)&0xff); immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat - int freq=(65536.0*(double)s->rate)/(double)rate; + int freq=(65536.0*(double)s->rate)/(double)chipRateBase; immWrite(16,freq&0xff); immWrite(17,(freq>>8)&0xff); } @@ -1504,7 +1509,12 @@ void DivPlatformOPL::reset() { fm_ymfm->reset(); } */ - OPL3_Reset(&fm,rate); + if (downsample) { + const unsigned int downsampledRate=(unsigned int)(49716.0*(double(rate)/chipRateBase)); + OPL3_Reset(&fm,downsampledRate); + } else { + OPL3_Reset(&fm,rate); + } if (dumpWrites) { addWrite(0xffffffff,0); } @@ -1621,6 +1631,7 @@ void DivPlatformOPL::setYMFM(bool use) { void DivPlatformOPL::setOPLType(int type, bool drums) { pretendYMU=false; + downsample=false; adpcmChan=-1; switch (type) { case 1: case 2: case 8950: @@ -1650,10 +1661,13 @@ void DivPlatformOPL::setOPLType(int type, bool drums) { if (type==759) { pretendYMU=true; adpcmChan=16; + } else if (type==4) { + downsample=true; } break; } - if (type==759) { + chipType=type; + if (type==759 || type==4) { oplType=3; } else if (type==8950) { oplType=1; @@ -1688,17 +1702,73 @@ void DivPlatformOPL::setFlags(unsigned int flags) { rate=chipClock/36; }*/ - if (oplType==3) { - chipClock=COLOR_NTSC*4.0; - rate=chipClock/288; - } else { - chipClock=COLOR_NTSC; - rate=chipClock/72; - } - - if (pretendYMU) { - rate=48000; - chipClock=rate*288; + switch (chipType) { + default: + case 1: case 2: case 8950: + switch (flags&0xff) { + case 0x00: + chipClock=COLOR_NTSC; + break; + case 0x01: + chipClock=COLOR_PAL*4.0/5.0; + break; + case 0x02: + chipClock=4000000.0; + break; + case 0x03: + chipClock=3000000.0; + break; + case 0x04: + chipClock=31948800/8; + break; + case 0x05: + chipClock=3500000.0; + break; + } + rate=chipClock/72; + chipRateBase=double(rate); + break; + case 3: + switch (flags&0xff) { + case 0x00: + chipClock=COLOR_NTSC*4.0; + break; + case 0x01: + chipClock=COLOR_PAL*16.0/5.0; + break; + case 0x02: + chipClock=14000000.0; + break; + case 0x03: + chipClock=16000000.0; + break; + case 0x04: + chipClock=15000000.0; + break; + } + rate=chipClock/288; + chipRateBase=double(rate); + break; + case 4: + switch (flags&0xff) { + case 0x02: + chipClock=33868800.0; + break; + case 0x00: + chipClock=COLOR_NTSC*8.0; + break; + case 0x01: + chipClock=COLOR_PAL*32.0/5.0; + break; + } + chipRateBase=double(chipClock)/684.0; + rate=chipClock/768; + break; + case 759: + rate=48000; + chipRateBase=double(rate); + chipClock=rate*288; + break; } for (int i=0; i<18; i++) { diff --git a/src/engine/platform/opl.h b/src/engine/platform/opl.h index 61ea46481..9d2d17742 100644 --- a/src/engine/platform/opl.h +++ b/src/engine/platform/opl.h @@ -95,8 +95,8 @@ class DivPlatformOPL: public DivDispatch { const unsigned char** slots; const unsigned short* chanMap; const unsigned char* outChanMap; - double chipFreqBase; - int delay, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank; + double chipFreqBase, chipRateBase; + int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank; unsigned char lastBusy; unsigned char drumState; unsigned char drumVol[5]; @@ -107,7 +107,7 @@ class DivPlatformOPL: public DivDispatch { unsigned char lfoValue; - bool useYMFM, update4OpMask, pretendYMU; + bool useYMFM, update4OpMask, pretendYMU, downsample; short oldWrites[512]; short pendingWrites[512]; diff --git a/src/engine/platform/scc.cpp b/src/engine/platform/scc.cpp index 2ab6f1aa4..1b70d956c 100644 --- a/src/engine/platform/scc.cpp +++ b/src/engine/platform/scc.cpp @@ -373,6 +373,27 @@ void DivPlatformSCC::setChipModel(bool isplus) { isPlus=isplus; } +void DivPlatformSCC::setFlags(unsigned int flags) { + switch (flags&0x7f) { + case 0x00: + chipClock=COLOR_NTSC/2.0; + break; + case 0x01: + chipClock=COLOR_PAL*2.0/5.0; + break; + case 0x02: + chipClock=3000000.0/2.0; + break; + case 0x03: + chipClock=4000000.0/2.0; + break; + } + rate=chipClock/8; + for (int i=0; i<5; i++) { + oscBuf[i]->rate=rate; + } +} + int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { parent=p; dumpWrites=false; @@ -382,11 +403,7 @@ int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, unsigned int f isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - chipClock=COLOR_NTSC/2.0; - rate=chipClock/8; - for (int i=0; i<5; i++) { - oscBuf[i]->rate=rate; - } + setFlags(flags); if (isPlus) { scc=new k052539_scc_core; regBase=0xa0; diff --git a/src/engine/platform/scc.h b/src/engine/platform/scc.h index df6ef84e5..d83e02934 100644 --- a/src/engine/platform/scc.h +++ b/src/engine/platform/scc.h @@ -84,6 +84,7 @@ class DivPlatformSCC: public DivDispatch { void poke(std::vector& wlist); const char** getRegisterSheet(); const char* getEffectName(unsigned char effect); + void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void setChipModel(bool isPlus); void quit(); diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index c5cf1091a..c83108a62 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -21,15 +21,21 @@ #include "../engine.h" #include -#define rWrite(v) {if (!skipRegisterWrites) {writes.push(v); if (dumpWrites) {addWrite(0x200,v);}}} +#define rWrite(a,v) {if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(0x200+a,v);}}} const char* regCheatSheetSN[]={ "DATA", "0", NULL }; +const char* regCheatSheetGG[]={ + "DATA", "0", + "Stereo", "1", + NULL +}; + const char** DivPlatformSMS::getRegisterSheet() { - return regCheatSheetSN; + return isStereo()?regCheatSheetGG:regCheatSheetSN; } const char* DivPlatformSMS::getEffectName(unsigned char effect) { @@ -45,8 +51,8 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ int o=0; for (size_t h=start; hwrite(w); + QueuedWrite w=writes.front(); + if (stereo && (w.addr&1)) + sn->stereo_w(w.val); + else + sn->write(w.val); writes.pop(); } + sn->sound_stream_update(snBuf,len); + if (stereo) { + for (size_t i=0; isound_stream_update(bufL+h,1); for (int i=0; i<4; i++) { if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; @@ -106,23 +133,17 @@ void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) } } -int DivPlatformSMS::acquireOne() { - short v; - sn->sound_stream_update(&v,1); - return v; -} - void DivPlatformSMS::tick(bool sysTick) { for (int i=0; i<4; i++) { int CHIP_DIVIDER=64; - if (i==3 && isRealSN) CHIP_DIVIDER=60; + if (i==3) CHIP_DIVIDER=noiseDivider; chan[i].std.next(); if (chan[i].std.vol.had) { chan[i].outVol=MIN(15,chan[i].std.vol.val)-(15-(chan[i].vol&15)); if (chan[i].outVol<0) chan[i].outVol=0; // old formula // ((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4; - rWrite(0x90|(i<<5)|(isMuted[i]?15:(15-(chan[i].outVol&15)))); + rWrite(0,0x90|(i<<5)|(isMuted[i]?15:(15-(chan[i].outVol&15)))); } if (chan[i].std.arp.had) { if (!chan[i].inPorta) { @@ -161,6 +182,13 @@ void DivPlatformSMS::tick(bool sysTick) { } } } + if (isStereo()) { + if (chan[i].std.panL.had) { + lastPan&=~(0x11<>1)&1)<1023) chan[i].freq=1023; if (chan[i].freq<8) chan[i].freq=1; //if (chan[i].actualNote>0x5d) chan[i].freq=0x01; - rWrite(0x80|i<<5|(chan[i].freq&15)); - rWrite(chan[i].freq>>4); + rWrite(0,0x80|i<<5|(chan[i].freq&15)); + rWrite(0,chan[i].freq>>4); // what? /*if (i==2 && snNoiseMode&2) { chan[3].baseFreq=chan[2].baseFreq; @@ -188,24 +216,24 @@ void DivPlatformSMS::tick(bool sysTick) { } } if (chan[3].freqChanged || updateSNMode) { - chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2,chipClock,isRealSN?60:64); + chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true,0,chan[3].pitch2,chipClock,noiseDivider); if (chan[3].freq>1023) chan[3].freq=1023; if (chan[3].actualNote>0x5d) chan[3].freq=0x01; if (snNoiseMode&2) { // take period from channel 3 if (updateSNMode || resetPhase) { if (snNoiseMode&1) { - rWrite(0xe7); + rWrite(0,0xe7); } else { - rWrite(0xe3); + rWrite(0,0xe3); } if (updateSNMode) { - rWrite(0xdf); + rWrite(0,0xdf); } } if (chan[3].freqChanged) { - rWrite(0xc0|(chan[3].freq&15)); - rWrite(chan[3].freq>>4); + rWrite(0,0xc0|(chan[3].freq&15)); + rWrite(0,chan[3].freq>>4); } } else { // 3 fixed values unsigned char value; @@ -222,7 +250,7 @@ void DivPlatformSMS::tick(bool sysTick) { value=2-value; if (value!=oldValue || updateSNMode || resetPhase) { oldValue=value; - rWrite(0xe0|value|((snNoiseMode&1)<<2)); + rWrite(0,0xe0|value|((snNoiseMode&1)<<2)); } } } @@ -233,7 +261,7 @@ void DivPlatformSMS::tick(bool sysTick) { int DivPlatformSMS::dispatch(DivCommand c) { int CHIP_DIVIDER=64; - if (c.chan==3 && isRealSN) CHIP_DIVIDER=60; + if (c.chan==3) CHIP_DIVIDER=noiseDivider; switch (c.cmd) { case DIV_CMD_NOTE_ON: if (c.value!=DIV_NOTE_NULL) { @@ -243,7 +271,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { chan[c.chan].actualNote=c.value; } chan[c.chan].active=true; - rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); + rWrite(0,0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_STD)); if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; @@ -251,7 +279,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { break; case DIV_CMD_NOTE_OFF: chan[c.chan].active=false; - rWrite(0x9f|c.chan<<5); + rWrite(0,0x9f|c.chan<<5); chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: @@ -268,7 +296,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.has) { chan[c.chan].outVol=c.value; } - if (chan[c.chan].active) rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); + if (chan[c.chan].active) rWrite(0,0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); } break; case DIV_CMD_GET_VOLUME: @@ -308,6 +336,18 @@ int DivPlatformSMS::dispatch(DivCommand c) { snNoiseMode=(c.value&1)|((c.value&16)>>3); updateSNMode=true; break; + case DIV_CMD_PANNING: { + if (isStereo()) { + lastPan&=~(0x11<0) pan|=0x01; + if (c.value2>0) pan|=0x10; + if (pan==0) pan=0x11; + lastPan|=pan<device_start(); - YMPSG_Init(&sn_nuked,isRealSN); + YMPSG_Init(&sn_nuked,isRealSN,12,isRealSN?13:15,isRealSN?16383:32767); snNoiseMode=3; - rWrite(0xe7); + rWrite(0,0xe7); updateSNMode=false; oldValue=0xff; + lastPan=0xff; + if (isStereo()) { + rWrite(1,0xff); + } +} + +bool DivPlatformSMS::isStereo() { + return (!nuked) && stereo; } bool DivPlatformSMS::keyOffAffectsArp(int ch) { @@ -391,45 +439,88 @@ void DivPlatformSMS::notifyInsDeletion(void* ins) { } void DivPlatformSMS::poke(unsigned int addr, unsigned short val) { - rWrite(val); + rWrite(addr,val); } void DivPlatformSMS::poke(std::vector& wlist) { - for (DivRegWrite& i: wlist) rWrite(i.val); + for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } void DivPlatformSMS::setFlags(unsigned int flags) { - if ((flags&3)==3) { - chipClock=COLOR_NTSC/2.0; - } else if ((flags&3)==2) { - chipClock=4000000; - } else if ((flags&3)==1) { - chipClock=COLOR_PAL*4.0/5.0; - } else { - chipClock=COLOR_NTSC; + switch (flags&0xff03) { + default: + case 0x0000: + chipClock=COLOR_NTSC; + break; + case 0x0001: + chipClock=COLOR_PAL*4.0/5.0; + break; + case 0x0002: + chipClock=4000000; + break; + case 0x0003: + chipClock=COLOR_NTSC/2.0; + break; + case 0x0100: + chipClock=3000000; + break; + case 0x0101: + chipClock=2000000; + break; } resetPhase=!(flags&16); - + noiseDivider=64; if (sn!=NULL) delete sn; - switch ((flags>>2)&3) { - case 1: // TI - sn=new sn76496_base_device(0x4000, 0x4000, 0x01, 0x02, true, 1, false, true); - isRealSN=true; - break; - case 2: // TI+Atari - sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, 1, false, true); - isRealSN=true; - break; - case 3: // Game Gear (not fully emulated yet!) - sn=new sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false); - isRealSN=false; - break; + switch (flags&0xcc) { default: // Sega - sn=new sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false); + case 0x00: + sn=new segapsg_device(); isRealSN=false; + stereo=false; + break; + case 0x04: // TI SN76489 + sn=new sn76489_device(); + isRealSN=true; + noiseDivider=60; + stereo=false; + break; + case 0x08: // TI+Atari + sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, 8, false, true); + isRealSN=true; + noiseDivider=60; + stereo=false; + break; + case 0x0c: // Game Gear (not fully emulated yet!) + sn=new gamegear_device(); + isRealSN=false; + stereo=true; + break; + case 0x40: // TI SN76489A + sn=new sn76489a_device(); + isRealSN=false; // TODO + noiseDivider=68; + stereo=false; + break; + case 0x44: // TI SN76496 + sn=new sn76496_device(); + isRealSN=false; // TODO + noiseDivider=68; + stereo=false; + break; + case 0x48: // NCR 8496 + sn=new ncr8496_device(); + isRealSN=false; + noiseDivider=64; + stereo=false; + break; + case 0x4c: // Tandy PSSJ 3-voice sound + sn=new pssj3_device(); + isRealSN=false; + noiseDivider=64; + stereo=false; break; } - rate=chipClock/16; + rate=nuked?chipClock/16:chipClock/2; for (int i=0; i<4; i++) { oscBuf[i]->rate=rate; } @@ -445,12 +536,15 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int f skipRegisterWrites=false; resetPhase=false; oldValue=0xff; + lastPan=0xff; for (int i=0; i<4; i++) { isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } sn=NULL; setFlags(flags); + snBufLen=65536; + for (int i=0; i<2; i++) snBuf[i]=new short[snBufLen]; reset(); return 4; } @@ -459,6 +553,9 @@ void DivPlatformSMS::quit() { for (int i=0; i<4; i++) { delete oscBuf[i]; } + for (int i=0; i<2; i++) { + delete[] snBuf[i]; + } if (sn!=NULL) delete sn; } diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 3c97a9a5c..56f6beda4 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -58,21 +58,31 @@ class DivPlatformSMS: public DivDispatch { Channel chan[4]; DivDispatchOscBuffer* oscBuf[4]; bool isMuted[4]; + unsigned char lastPan; + short* snBuf[2]; + size_t snBufLen; unsigned char oldValue; unsigned char snNoiseMode; + int noiseDivider=64; bool updateSNMode; bool resetPhase; bool isRealSN; + bool stereo; bool nuked; sn76496_base_device* sn; ympsg_t sn_nuked; - std::queue writes; + struct QueuedWrite { + unsigned short addr; + unsigned char val; + bool addrOrVal; + QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} + }; + std::queue writes; friend void putDispatchChan(void*,int,int); void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); void acquire_mame(short* bufL, short* bufR, size_t start, size_t len); public: - int acquireOne(); void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); @@ -81,6 +91,7 @@ class DivPlatformSMS: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); + bool isStereo(); bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); int getPortaFloor(int ch); diff --git a/src/engine/platform/sound/sn76496.cpp b/src/engine/platform/sound/sn76496.cpp index 351c94d86..5062ea7a8 100644 --- a/src/engine/platform/sound/sn76496.cpp +++ b/src/engine/platform/sound/sn76496.cpp @@ -128,7 +128,7 @@ 10/12/2019: Michael Zapf * READY line handling by own emu_timer, not depending on sound_stream_update - additional modifications by tildearrow for furnace + additional modifications by tildearrow, cam900 for furnace TODO: * Implement the TMS9919 - any difference to sn94624? * Implement the T6W28; has registers in a weird order, needs writes @@ -150,18 +150,20 @@ sn76496_base_device::sn76496_base_device( int feedbackmask, - int noise_start, + int noise_start, int noisetap1, int noisetap2, bool negate, + bool stereo, int clockdivider, bool ncr, bool sega) : m_feedback_mask(feedbackmask) - , m_noise_start(noise_start) + , m_noise_start(noise_start) , m_whitenoise_tap1(noisetap1) , m_whitenoise_tap2(noisetap2) - , m_negate(negate) + , m_negate(negate) + , m_stereo(stereo) , m_clock_divider(clockdivider) , m_ncr_style_psg(ncr) , m_sega_style_psg(sega) @@ -169,10 +171,54 @@ sn76496_base_device::sn76496_base_device( } sn76496_device::sn76496_device() - : sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false) + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) { } +y2404_device::y2404_device() + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) +{ +} + +sn76489_device::sn76489_device() + : sn76496_base_device(0x4000, 0x01, 0x02, true, false, 8, false, true) +{ +} + +sn76489a_device::sn76489a_device() + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) +{ +} + +sn76494_device::sn76494_device() + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1, false, true) +{ +} + +sn94624_device::sn94624_device() + : sn76496_base_device(0x4000, 0x01, 0x02, true, false, 1, false, true) +{ +} + +ncr8496_device::ncr8496_device() + : sn76496_base_device(0x8000, 0x02, 0x20, true, false, 8, true, true) +{ +} + +pssj3_device::pssj3_device() + : sn76496_base_device(0x8000, 0x02, 0x20, false, false, 8, true, true) +{ +} + +gamegear_device::gamegear_device() + : sn76496_base_device(0x8000, 0x01, 0x08, true, true, 8, false, false) +{ +} + +segapsg_device::segapsg_device() + : sn76496_base_device(0x8000, 0x01, 0x08, true, false, 8, false, false) +{ +} void sn76496_base_device::device_start() { @@ -199,6 +245,7 @@ void sn76496_base_device::device_start() m_RNG = m_feedback_mask; m_output[3] = m_RNG & 1; + m_stereo_mask = 0xFF; // all channels enabled m_current_clock = m_clock_divider-1; // set gain @@ -225,6 +272,11 @@ void sn76496_base_device::device_start() m_ready_state = true; } +void sn76496_base_device::stereo_w(u8 data) +{ + if (m_stereo) m_stereo_mask = data; +} + void sn76496_base_device::write(u8 data) { int n, r, c; @@ -285,7 +337,7 @@ inline bool sn76496_base_device::in_noise_mode() return ((m_register[6] & 4)!=0); } -void sn76496_base_device::sound_stream_update(short* outputs, int outLen) +void sn76496_base_device::sound_stream_update(short** outputs, int outLen) { int i; @@ -336,13 +388,30 @@ void sn76496_base_device::sound_stream_update(short* outputs, int outLen) } } + if (m_stereo) + { + out = ((((m_stereo_mask & 0x10)!=0) && (m_output[0]!=0))? m_volume[0] : 0) + + ((((m_stereo_mask & 0x20)!=0) && (m_output[1]!=0))? m_volume[1] : 0) + + ((((m_stereo_mask & 0x40)!=0) && (m_output[2]!=0))? m_volume[2] : 0) + + ((((m_stereo_mask & 0x80)!=0) && (m_output[3]!=0))? m_volume[3] : 0); + + out2= ((((m_stereo_mask & 0x1)!=0) && (m_output[0]!=0))? m_volume[0] : 0) + + ((((m_stereo_mask & 0x2)!=0) && (m_output[1]!=0))? m_volume[1] : 0) + + ((((m_stereo_mask & 0x4)!=0) && (m_output[2]!=0))? m_volume[2] : 0) + + ((((m_stereo_mask & 0x8)!=0) && (m_output[3]!=0))? m_volume[3] : 0); + } + else + { out= ((m_output[0]!=0)? m_volume[0]:0) +((m_output[1]!=0)? m_volume[1]:0) +((m_output[2]!=0)? m_volume[2]:0) +((m_output[3]!=0)? m_volume[3]:0); + } if (m_negate) { out = -out; out2 = -out2; } - outputs[sampindex]=out; + outputs[0][sampindex]=out; + if (m_stereo) + outputs[1][sampindex]=out; } } diff --git a/src/engine/platform/sound/sn76496.h b/src/engine/platform/sound/sn76496.h index 4c24e938c..7a8a5c625 100644 --- a/src/engine/platform/sound/sn76496.h +++ b/src/engine/platform/sound/sn76496.h @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:Nicola Salmoria -// additional modifications by tildearrow for furnace +// additional modifications by tildearrow, cam900 for furnace #ifndef MAME_SOUND_SN76496_H #define MAME_SOUND_SN76496_H @@ -14,34 +14,57 @@ class sn76496_base_device { public: void stereo_w(u8 data); void write(u8 data); - void device_start(); - void sound_stream_update(short* outputs, int outLen); - inline int32_t get_channel_output(int ch) { - return ((m_output[ch]!=0)?m_volume[ch]:0); - } + void device_start(); + void sound_stream_update(short** outputs, int outLen); + inline int32_t get_channel_output(int ch) { + return ((m_output[ch]!=0)?m_volume[ch]:0); + } //DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; } sn76496_base_device( int feedbackmask, - int noise_start, + int noise_start, int noisetap1, int noisetap2, bool negate, + bool stereo, int clockdivider, bool ncr, bool sega); + sn76496_base_device( + int feedbackmask, + int noisetap1, + int noisetap2, + bool negate, + bool stereo, + int clockdivider, + bool ncr, + bool sega) + : sn76496_base_device( + feedbackmask, + feedbackmask, + noisetap1, + noisetap2, + negate, + stereo, + clockdivider, + ncr, + sega) + {} + private: inline bool in_noise_mode(); bool m_ready_state; - const int32_t m_feedback_mask; // mask for feedback - const int32_t m_noise_start; // noise start value - const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14) - const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13) - bool m_negate; // output negate flag - const int32_t m_clock_divider; // clock divider + const int32_t m_feedback_mask; // mask for feedback + const int32_t m_noise_start; // noise start value + const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14) + const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13) + bool m_negate; // output negate flag + const bool m_stereo; // whether we're dealing with stereo or not + const int32_t m_clock_divider; // clock divider const bool m_ncr_style_psg; // flag to ignore writes to regs 1,3,5,6,7 with bit 7 low const bool m_sega_style_psg; // flag to make frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0; the initial register is pointing to 0x3 instead of 0x0; the volume reg is preloaded with 0xF instead of 0x0 @@ -51,6 +74,7 @@ private: int32_t m_volume[4]; // db volume of voice 0-2 and noise uint32_t m_RNG; // noise generator LFSR int32_t m_current_clock; + int32_t m_stereo_mask; // the stereo output mask int32_t m_period[4]; // Length of 1/2 of waveform int32_t m_count[4]; // Position within the waveform int32_t m_output[4]; // 1-bit output of each channel, pre-volume @@ -63,4 +87,67 @@ public: sn76496_device(); }; +// Y2404 not verified yet. todo: verify; (don't be fooled by the Y, it's a TI chip, not Yamaha) +class y2404_device : public sn76496_base_device +{ +public: + y2404_device(); +}; + +// SN76489 not verified yet. todo: verify; +class sn76489_device : public sn76496_base_device +{ +public: + sn76489_device(); +}; + +// SN76489A: whitenoise verified, phase verified, periodic verified (by plgdavid) +class sn76489a_device : public sn76496_base_device +{ +public: + sn76489a_device(); +}; + +// SN76494 not verified, (according to datasheet: same as sn76489a but without the /8 divider) +class sn76494_device : public sn76496_base_device +{ +public: + sn76494_device(); +}; + +// SN94624 whitenoise verified, phase verified, period verified; verified by PlgDavid +class sn94624_device : public sn76496_base_device +{ +public: + sn94624_device(); +}; + +// NCR8496 whitenoise verified, phase verified; verified by ValleyBell & NewRisingSun +class ncr8496_device : public sn76496_base_device +{ +public: + ncr8496_device(); +}; + +// PSSJ-3 whitenoise verified, phase verified; verified by ValleyBell & NewRisingSun +class pssj3_device : public sn76496_base_device +{ +public: + pssj3_device(); +}; + +// Verified by Justin Kerk +class gamegear_device : public sn76496_base_device +{ +public: + gamegear_device(); +}; + +// todo: verify; from smspower wiki, assumed to have same invert as gamegear +class segapsg_device : public sn76496_base_device +{ +public: + segapsg_device(); +}; + #endif // MAME_SOUND_SN76496_H diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index 569f722b0..d530d9ee3 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -22,43 +22,11 @@ #include #include -#include "fmshared_OPM.h" - // actually 0x40 but the upper bit of data selects address #define ADDR_WS_FINE 0x100 // actually 0xc0 but bit 5 of data selects address #define ADDR_EGS_REV 0x120 -static unsigned short chanOffs[8]={ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 -}; -static unsigned short opOffs[4]={ - 0x00, 0x08, 0x10, 0x18 -}; -static bool isOutput[8][4]={ - // 1 3 2 4 - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,true ,true}, - {false,true ,true ,true}, - {false,true ,true ,true}, - {true ,true ,true ,true}, -}; -static unsigned char dtTable[8]={ - 7,6,5,0,1,2,3,4 -}; - -static int orderedOps[4]={ - 0,2,1,3 -}; - -#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} -#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } - -#define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) - const char* regCheatSheetOPZ[]={ "Test", "00", "NoteCtl", "08", @@ -233,7 +201,7 @@ void DivPlatformTX81Z::acquire(short* bufL, short* bufR, size_t start, size_t le fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr); fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val); regPool[w.addr&0xff]=w.val; - writes.pop(); + writes.pop_front(); delay=1; } } @@ -1048,7 +1016,7 @@ void DivPlatformTX81Z::poke(std::vector& wlist) { } void DivPlatformTX81Z::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,330); fm_ymfm->reset(); if (dumpWrites) { diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index 60ea66ae0..93f220f1c 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -20,17 +20,22 @@ #ifndef _TX81Z_H #define _TX81Z_H #include "../dispatch.h" +#include "../macroInt.h" #include "../instrument.h" #include #include "sound/ymfm/ymfm_opz.h" -#include "../macroInt.h" +#include "fmshared_OPM.h" class DivTXInterface: public ymfm::ymfm_interface { }; -class DivPlatformTX81Z: public DivDispatch { +class DivPlatformTX81Z: public DivDispatch, public DivPlatformOPMBase { protected: + const unsigned short chanOffs[8]={ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + struct Channel { DivInstrumentFM state; DivMacroInt std; @@ -69,16 +74,8 @@ class DivPlatformTX81Z: public DivDispatch { }; Channel chan[8]; DivDispatchOscBuffer* oscBuf[8]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; - int delay, baseFreqOff; + int baseFreqOff; int pcmL, pcmR, pcmCycles; - unsigned char lastBusy; unsigned char amDepth, pmDepth; ymfm::ym2414* fm_ymfm; diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 3303fbf87..de54d8a61 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -23,16 +23,7 @@ #include #include -#include "sound/ymfm/ymfm_opn.h" -#include "ym2203shared.h" -#include "fmshared_OPN.h" - -static unsigned char konOffs[3]={ - 0, 1, 2 -}; - -#define CHIP_DIVIDER 32 const char* regCheatSheetYM2203[]={ // SSG @@ -299,7 +290,7 @@ void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t l fm->write(0x0,w.addr); fm->write(0x1,w.val); regPool[w.addr&0xff]=w.val; - writes.pop(); + writes.pop_front(); delay=6; } } @@ -954,7 +945,7 @@ void DivPlatformYM2203::poke(std::vector& wlist) { } void DivPlatformYM2203::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,256); if (dumpWrites) { addWrite(0xffffffff,0); @@ -1016,21 +1007,27 @@ void DivPlatformYM2203::setSkipRegisterWrites(bool value) { } void DivPlatformYM2203::setFlags(unsigned int flags) { - unsigned char ayFlags=16; - if (flags==3) { - chipClock=3000000.0; - ayFlags=20; - } else if (flags==2) { - chipClock=4000000.0; - ayFlags=19; - } else if (flags==1) { - chipClock=COLOR_PAL*4.0/5.0; - ayFlags=17; - } else { - chipClock=COLOR_NTSC; - ayFlags=16; + switch (flags&0x3f) { + default: + case 0x00: + chipClock=COLOR_NTSC; + break; + case 0x01: + chipClock=COLOR_PAL*4.0/5.0; + break; + case 0x02: + chipClock=4000000.0; + break; + case 0x03: + chipClock=3000000.0; + break; + case 0x04: + chipClock=31948800/8; + break; + case 0x05: + chipClock=3000000.0/2.0; + break; } - ay->setFlags(ayFlags); rate=fm->sample_rate(chipClock); for (int i=0; i<6; i++) { oscBuf[i]->rate=rate; @@ -1047,14 +1044,14 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned in } fm=new ymfm::ym2203(iface); fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); - // YM2149, 2MHz - ay=new DivPlatformAY8910; - ay->init(p,3,sugRate,19); - ay->toggleRegisterDump(true); setFlags(flags); + // YM2149, 2MHz + ay=new DivPlatformAY8910(true,chipClock,ayDiv); + ay->init(p,3,sugRate,16); + ay->toggleRegisterDump(true); reset(); - return 16; + return 6; } void DivPlatformYM2203::quit() { diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index ab527eeaa..c072647c4 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -21,21 +21,25 @@ #define _YM2203_H #include "../dispatch.h" #include "../macroInt.h" -#include #include "sound/ymfm/ymfm_opn.h" #include "ay.h" +#include "fmshared_OPN.h" class DivYM2203Interface: public ymfm::ymfm_interface { }; -class DivPlatformYM2203: public DivDispatch { +class DivPlatformYM2203: public DivDispatch, public DivPlatformOPNBase { protected: const unsigned short chanOffs[3]={ 0x00, 0x01, 0x02 }; + const unsigned char konOffs[3]={ + 0, 1, 2 + }; + struct Channel { DivInstrumentFM state; unsigned char freqH, freqL; @@ -79,24 +83,14 @@ class DivPlatformYM2203: public DivDispatch { Channel chan[6]; DivDispatchOscBuffer* oscBuf[6]; bool isMuted[6]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; ymfm::ym2203* fm; ymfm::ym2203::output_data fmout; DivYM2203Interface iface; - unsigned char regPool[512]; - unsigned char lastBusy; + unsigned char regPool[256]; DivPlatformAY8910* ay; unsigned char sampleBank; - int delay; - bool extMode; short oldWrites[256]; @@ -127,6 +121,9 @@ class DivPlatformYM2203: public DivDispatch { void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); + DivPlatformYM2203(): + DivDispatch(), + DivPlatformOPNBase(4720270.0, 36, 16) {} ~DivPlatformYM2203(); }; #endif diff --git a/src/engine/platform/ym2203ext.cpp b/src/engine/platform/ym2203ext.cpp index 95937207d..350a58704 100644 --- a/src/engine/platform/ym2203ext.cpp +++ b/src/engine/platform/ym2203ext.cpp @@ -21,9 +21,6 @@ #include "../engine.h" #include -#include "ym2203shared.h" -#include "fmshared_OPN.h" - int DivPlatformYM2203Ext::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformYM2203::dispatch(c); @@ -510,7 +507,7 @@ int DivPlatformYM2203Ext::init(DivEngine* parent, int channels, int sugRate, uns } reset(); - return 19; + return 9; } void DivPlatformYM2203Ext::quit() { diff --git a/src/engine/platform/ym2203shared.h b/src/engine/platform/ym2203shared.h deleted file mode 100644 index 5aec79161..000000000 --- a/src/engine/platform/ym2203shared.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2022 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -static unsigned short opOffs[4]={ - 0x00, 0x04, 0x08, 0x0c -}; -static bool isOutput[8][4]={ - // 1 3 2 4 - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,true ,true}, - {false,true ,true ,true}, - {false,true ,true ,true}, - {true ,true ,true ,true}, -}; -static unsigned char dtTable[8]={ - 7,6,5,0,1,2,3,4 -}; - -static int orderedOps[4]={ - 0,2,1,3 -}; - -#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} -#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } - -#define CHIP_FREQBASE 4720270 diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index b6f1e16f8..9756a44af 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -24,16 +24,7 @@ #include #include -#include "sound/ymfm/ymfm_opn.h" -#include "ym2610shared.h" -#include "fmshared_OPN.h" - -static unsigned char konOffs[6]={ - 0, 1, 2, 4, 5, 6 -}; - -#define CHIP_DIVIDER 32 const char* regCheatSheetYM2608[]={ // SSG @@ -450,7 +441,7 @@ void DivPlatformYM2608::acquire(short* bufL, short* bufR, size_t start, size_t l fm->write(0x0+((w.addr>>8)<<1),w.addr); fm->write(0x1+((w.addr>>8)<<1),w.val); regPool[w.addr&0x1ff]=w.val; - writes.pop(); + writes.pop_front(); delay=4; } } @@ -1278,7 +1269,7 @@ void DivPlatformYM2608::poke(std::vector& wlist) { } void DivPlatformYM2608::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,512); if (dumpWrites) { addWrite(0xffffffff,0); @@ -1397,6 +1388,22 @@ void DivPlatformYM2608::renderSamples() { adpcmBMemLen=memPos+256; } +void DivPlatformYM2608::setFlags(unsigned int flags) { + switch (flags&0x3f) { + default: + case 0x00: + chipClock=8000000.0; + break; + case 0x01: + chipClock=31948800/4; + break; + } + rate=fm->sample_rate(chipClock); + for (int i=0; i<16; i++) { + oscBuf[i]->rate=rate; + } +} + int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { parent=p; adpcmBMem=new unsigned char[getSampleMemCapacity(0)]; @@ -1409,16 +1416,11 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned in isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - chipClock=8000000; fm=new ymfm::ym2608(iface); - fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); - rate=fm->sample_rate(chipClock); - for (int i=0; i<16; i++) { - oscBuf[i]->rate=rate; - } + setFlags(flags); // YM2149, 2MHz - ay=new DivPlatformAY8910; - ay->init(p,3,sugRate,19); + ay=new DivPlatformAY8910(true,chipClock,32); + ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); reset(); return 16; diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index 5c6736295..ffa7a160c 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -21,10 +21,10 @@ #define _YM2608_H #include "../dispatch.h" #include "../macroInt.h" -#include #include "sound/ymfm/ymfm_opn.h" #include "ay.h" +#include "fmshared_OPN.h" class DivYM2608Interface: public ymfm::ymfm_interface { public: @@ -35,12 +35,16 @@ class DivYM2608Interface: public ymfm::ymfm_interface { DivYM2608Interface(): adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2608: public DivDispatch { +class DivPlatformYM2608: public DivDispatch, public DivPlatformOPNBase { protected: const unsigned short chanOffs[6]={ 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 }; + const unsigned char konOffs[6]={ + 0, 1, 2, 4, 5, 6 + }; + struct Channel { DivInstrumentFM state; unsigned char freqH, freqL; @@ -86,17 +90,9 @@ class DivPlatformYM2608: public DivDispatch { Channel chan[16]; DivDispatchOscBuffer* oscBuf[16]; bool isMuted[16]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; ymfm::ym2608* fm; ymfm::ym2608::output_data fmout; unsigned char regPool[512]; - unsigned char lastBusy; unsigned char* adpcmBMem; size_t adpcmBMemLen; @@ -106,9 +102,9 @@ class DivPlatformYM2608: public DivDispatch { unsigned char sampleBank; unsigned char writeRSSOff, writeRSSOn; - int delay; - bool extMode; + double fmFreqBase; + unsigned char ayDiv; short oldWrites[512]; short pendingWrites[512]; @@ -141,8 +137,12 @@ class DivPlatformYM2608: public DivDispatch { size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); + void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); + DivPlatformYM2608(): + DivDispatch(), + DivPlatformOPNBase(9440540.0, 72, 32) {} ~DivPlatformYM2608(); }; #endif diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index 441640b45..38d2b4b28 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -21,9 +21,6 @@ #include "../engine.h" #include -#include "ym2610shared.h" -#include "fmshared_OPN.h" - int DivPlatformYM2608Ext::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformYM2608::dispatch(c); diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 89ccc6c0e..d8d8e8572 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -24,19 +24,6 @@ #include #include -#include "ym2610shared.h" - -#include "fmshared_OPN.h" - -static unsigned char konOffs[4]={ - 1, 2, 5, 6 -}; - -static unsigned char bchOffs[4]={ - 1, 2, 4, 5 -}; - -#define CHIP_DIVIDER 32 const char* regCheatSheetYM2610[]={ // SSG @@ -494,7 +481,7 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l fm->write(0x0+((w.addr>>8)<<1),w.addr); fm->write(0x1+((w.addr>>8)<<1),w.val); regPool[w.addr&0x1ff]=w.val; - writes.pop(); + writes.pop_front(); delay=4; } } @@ -1325,7 +1312,7 @@ void DivPlatformYM2610::poke(std::vector& wlist) { } void DivPlatformYM2610::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,512); if (dumpWrites) { addWrite(0xffffffff,0); @@ -1397,6 +1384,22 @@ void DivPlatformYM2610::setSkipRegisterWrites(bool value) { ay->setSkipRegisterWrites(value); } +void DivPlatformYM2610::setFlags(unsigned int flags) { + switch (flags&0xff) { + default: + case 0x00: + chipClock=8000000.0; + break; + case 0x01: + chipClock=24167829/3; + break; + } + rate=chipClock/16; + for (int i=0; i<14; i++) { + oscBuf[i]->rate=rate; + } +} + int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { DivPlatformYM2610Base::init(p, channels, sugRate, flags); dumpWrites=false; @@ -1405,15 +1408,11 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned in isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - chipClock=8000000; - rate=chipClock/16; - for (int i=0; i<14; i++) { - oscBuf[i]->rate=rate; - } fm=new ymfm::ym2610(iface); + setFlags(flags); // YM2149, 2MHz - ay=new DivPlatformAY8910; - ay->init(p,3,sugRate,19); + ay=new DivPlatformAY8910(true,chipClock,32); + ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); reset(); return 14; diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 92f4ca077..37c0fa839 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -21,8 +21,8 @@ #define _YM2610_H #include "../dispatch.h" #include "../macroInt.h" -#include #include "ay.h" +#include "fmshared_OPN.h" #include "sound/ymfm/ymfm_opn.h" class DivYM2610Interface: public ymfm::ymfm_interface { @@ -35,7 +35,7 @@ class DivYM2610Interface: public ymfm::ymfm_interface { DivYM2610Interface(): adpcmAMem(NULL), adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2610Base: public DivDispatch { +class DivPlatformYM2610Base: public DivDispatch, public DivPlatformOPNBase { protected: unsigned char* adpcmAMem; size_t adpcmAMemLen; @@ -50,6 +50,9 @@ class DivPlatformYM2610Base: public DivDispatch { void renderSamples(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); + DivPlatformYM2610Base(): + DivDispatch(), + DivPlatformOPNBase(9440540.0, 72, 32) {} }; class DivPlatformYM2610: public DivPlatformYM2610Base { @@ -58,6 +61,14 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { 0x01, 0x02, 0x101, 0x102 }; + const unsigned char konOffs[4]={ + 1, 2, 5, 6 + }; + + const unsigned char bchOffs[4]={ + 1, 2, 4, 5 + }; + struct Channel { DivInstrumentFM state; unsigned char freqH, freqL; @@ -103,24 +114,14 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { Channel chan[14]; DivDispatchOscBuffer* oscBuf[14]; bool isMuted[14]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; ymfm::ym2610* fm; ymfm::ym2610::output_data fmout; DivPlatformAY8910* ay; unsigned char regPool[512]; - unsigned char lastBusy; unsigned char sampleBank; - int delay; - bool extMode; short oldWrites[512]; @@ -150,6 +151,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { void poke(std::vector& wlist); const char** getRegisterSheet(); const char* getEffectName(unsigned char effect); + void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformYM2610(); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 0e466f6fc..90ddeb403 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -23,16 +23,6 @@ #include #include -#include "ym2610shared.h" - -#include "fmshared_OPN.h" - -static unsigned char konOffs[6]={ - 0, 1, 2, 4, 5, 6 -}; - -#define CHIP_DIVIDER 32 - const char* regCheatSheetYM2610B[]={ // SSG "SSG_FreqL_A", "000", @@ -472,7 +462,7 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t fm->write(0x0+((w.addr>>8)<<1),w.addr); fm->write(0x1+((w.addr>>8)<<1),w.val); regPool[w.addr&0x1ff]=w.val; - writes.pop(); + writes.pop_front(); delay=4; } } @@ -1303,7 +1293,7 @@ void DivPlatformYM2610B::poke(std::vector& wlist) { } void DivPlatformYM2610B::reset() { - while (!writes.empty()) writes.pop(); + while (!writes.empty()) writes.pop_front(); memset(regPool,0,512); if (dumpWrites) { addWrite(0xffffffff,0); @@ -1375,6 +1365,22 @@ void DivPlatformYM2610B::setSkipRegisterWrites(bool value) { ay->setSkipRegisterWrites(value); } +void DivPlatformYM2610B::setFlags(unsigned int flags) { + switch (flags&0xff) { + default: + case 0x00: + chipClock=8000000.0; + break; + case 0x01: + chipClock=24167829/3; + break; + } + rate=chipClock/16; + for (int i=0; i<16; i++) { + oscBuf[i]->rate=rate; + } +} + int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { DivPlatformYM2610Base::init(p, channels, sugRate, flags); dumpWrites=false; @@ -1383,15 +1389,11 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - chipClock=8000000; - rate=chipClock/16; - for (int i=0; i<16; i++) { - oscBuf[i]->rate=rate; - } fm=new ymfm::ym2610b(iface); + setFlags(flags); // YM2149, 2MHz - ay=new DivPlatformAY8910; - ay->init(p,3,sugRate,19); + ay=new DivPlatformAY8910(true,chipClock,32); + ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); reset(); return 16; diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 3a034028a..1262ba028 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -32,6 +32,10 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 }; + const unsigned char konOffs[6]={ + 0, 1, 2, 4, 5, 6 + }; + struct Channel { DivInstrumentFM state; unsigned char freqH, freqL; @@ -77,24 +81,16 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { Channel chan[16]; DivDispatchOscBuffer* oscBuf[16]; bool isMuted[16]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::queue writes; ymfm::ym2610b* fm; ymfm::ym2610b::output_data fmout; unsigned char regPool[512]; - unsigned char lastBusy; DivPlatformAY8910* ay; unsigned char sampleBank; - int delay; - bool extMode; + double fmFreqBase=9440540; + unsigned char ayDiv=32; short oldWrites[512]; short pendingWrites[512]; @@ -123,6 +119,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { void poke(std::vector& wlist); const char** getRegisterSheet(); const char* getEffectName(unsigned char effect); + void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformYM2610B(); diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index cd7e494b9..b4c154faa 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -21,9 +21,6 @@ #include "../engine.h" #include -#include "ym2610shared.h" -#include "fmshared_OPN.h" - int DivPlatformYM2610BExt::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformYM2610B::dispatch(c); diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index bf6df44e7..0ac118a1a 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -21,9 +21,6 @@ #include "../engine.h" #include -#include "ym2610shared.h" -#include "fmshared_OPN.h" - int DivPlatformYM2610Ext::dispatch(DivCommand c) { if (c.chan<1) { return DivPlatformYM2610::dispatch(c); diff --git a/src/engine/platform/ym2610shared.h b/src/engine/platform/ym2610shared.h deleted file mode 100644 index 8d8847c2e..000000000 --- a/src/engine/platform/ym2610shared.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Furnace Tracker - multi-system chiptune tracker - * Copyright (C) 2021-2022 tildearrow and contributors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -static unsigned short opOffs[4]={ - 0x00, 0x04, 0x08, 0x0c -}; -static bool isOutput[8][4]={ - // 1 3 2 4 - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,false,true}, - {false,false,true ,true}, - {false,true ,true ,true}, - {false,true ,true ,true}, - {true ,true ,true ,true}, -}; -static unsigned char dtTable[8]={ - 7,6,5,0,1,2,3,4 -}; - -static int orderedOps[4]={ - 0,2,1,3 -}; - -#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} -#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } - -#define CHIP_FREQBASE 9440540 diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 1c4997c2e..87497238e 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -431,6 +431,42 @@ void DivPlatformYMZ280B::setChipModel(int type) { chipType=type; } +void DivPlatformYMZ280B::setFlags(unsigned int flags) { + switch (chipType) { + default: + case 280: + switch (flags&0xff) { + case 0x00: + chipClock=16934400; + break; + case 0x01: + chipClock=COLOR_NTSC*4.0; + break; + case 0x02: + chipClock=COLOR_PAL*16.0/5.0; + break; + case 0x03: + chipClock=16000000; + break; + case 0x04: + chipClock=50000000.0/3.0; + break; + case 0x05: + chipClock=14000000; + break; + } + rate=chipClock/384; + break; + case 759: + rate=32000; + chipClock=rate*384; + break; + } + for (int i=0; i<8; i++) { + oscBuf[i]->rate=rate; + } +} + int DivPlatformYMZ280B::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { parent=p; dumpWrites=false; @@ -440,18 +476,12 @@ int DivPlatformYMZ280B::init(DivEngine* p, int channels, int sugRate, unsigned i isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; } - setFlags(flags); - - rate=(chipType==759)?32000:44100; - chipClock=rate*384; sampleMem=new unsigned char[getSampleMemCapacity()]; sampleMemLen=0; ymz280b.device_start(sampleMem); + setFlags(flags); reset(); - for (int i=0; i<8; i++) { - oscBuf[i]->rate=rate; - } return 8; } diff --git a/src/engine/platform/ymz280b.h b/src/engine/platform/ymz280b.h index 4957d8998..97c64d21e 100644 --- a/src/engine/platform/ymz280b.h +++ b/src/engine/platform/ymz280b.h @@ -95,6 +95,7 @@ class DivPlatformYMZ280B: public DivDispatch { size_t getSampleMemCapacity(int index = 0); size_t getSampleMemUsage(int index = 0); void renderSamples(); + void setFlags(unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); private: diff --git a/src/engine/song.h b/src/engine/song.h index 10c00d27f..a5b68c267 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -237,28 +237,42 @@ struct DivSong { // - 1: PAL // - 2: Dendy // - SMS/SN76489: - // - bit 0-1: clock rate - // - 0: NTSC (3.58MHz) - // - 1: PAL (3.55MHz) - // - 2: Other (4MHz) - // - 3: half NTSC (1.79MHz) - // - bit 2-3: noise type - // - 0: Sega VDP (16-bit noise) - // - 1: real SN76489 (15-bit noise) - // - 2: real SN76489 with Atari-like short noise buzz (15-bit noise) - // - 3: Game Gear (16-bit noise, stereo) + // - bit 0-1, 8-15: clock rate + // - 0000: 3.58MHz (NTSC) + // - 0001: 3.55MHz (PAL) + // - 0002: 4MHz (Other) + // - 0003: 1.79MHz (half NTSC) + // - 0100: 3MHz + // - 0101: 2MHz + // - bit 2-3, 6-7: chip type + // - 00: Sega VDP (16-bit noise) + // - 04: real SN76489 (15-bit noise) + // - 08: real SN76489 with Atari-like short noise buzz (15-bit noise) + // - 0c: Game Gear (16-bit noise, stereo) + // - 40: real SN76489A (17-bit noise) + // - 44: real SN76496 (17-bit noise) + // - 48: NCR 8496 (16-bit noise) + // - 4c: Tandy PSSJ-3 (16-bit noise) // - bit 4: disable noise phase reset - // - YM2612: - // - bit 0-1: clock rate + // - YM2612/YM3438: + // - bit 0-30: clock rate // - 0: Genesis NTSC (7.67MHz) // - 1: Genesis PAL (7.61MHz) - // - 2: 8MHz + // - 2: FM Towns (8MHz) // - 3: AtGames Genesis (6.13MHz) + // - 4: Sega System 32 (8.06MHz) + // - bit 31: DAC distortion + // - 0: disable + // - 1: enable // - YM2151: - // - bit 0-1: clock rate + // - bit 0-7: clock rate // - 0: 3.58MHz (NTSC) // - 1: 3.55MHz (PAL) // - 2: 4MHz + // - YM2610(B): + // - bit 0-7: clock rate + // - 0: 8MHz (Neo Geo MVS) + // - 1: 8.06MHz (Neo Geo AES) // - AY-3-8910/AY8930: // - bit 0-3: clock rate // - 0: 1.79MHz (MSX NTSC) @@ -274,6 +288,8 @@ struct DivSong { // - 10: 2.097152MHz (Game Boy) // - 11: 3.58MHz (Darky) // - 12: 3.6MHz (Darky) + // - 13: 1.25MHz + // - 14: 1.536MHz // - bit 4-5: chip type (ignored on AY8930) // - 0: AY-3-8910 or similar // - 1: YM2149 @@ -287,9 +303,9 @@ struct DivSong { // - 1: low (internally divided to half) // - SAA1099: // - bit 0-1: clock rate - // - 0: 8MHz (SAM Coupé, Game Blaster) - // - 1: 7.15MHz - // - 2: 7.09MHz + // - 0: 8MHz (SAM Coupé) + // - 1: 7.15MHz (Game Blaster, NTSC) + // - 2: 7.09MHz (PAL) // - Amiga: // - bit 0: clock rate // - 0: 7.15MHz (NTSC) @@ -330,6 +346,80 @@ struct DivSong { // - bit 4: stereo // - 0: mono // - 1: stereo + // - YM2203: + // - bit 0-4: clock rate + // - 0: 3.58MHz (MTSC) + // - 1: 3.55MHz (PAL) + // - 2: 4MHz + // - 3: 3MHz + // - 4: 3.9936MHz (PC-88, PC-98) + // - 5: 1.5MHz + // - bit 5-6: output rate (TODO) + // - 0: FM: clock / 72, SSG: clock / 16 + // - 1: FM: clock / 36, SSG: clock / 8 + // - 2: FM: clock / 24, SSG: clock / 4 + // - YM2608: + // - bit 0-4: clock rate + // - 0: 8MHz + // - 1: 7.987MHz (PC-88, PC-98) + // - bit 5-6: output rate (TODO) + // - 0: FM: clock / 144, SSG: clock / 32 + // - 1: FM: clock / 72, SSG: clock / 16 + // - 2: FM: clock / 48, SSG: clock / 8 + // - YM3526, YM3812, Y8950: + // - bit 0-7: clock rate + // - 0: 3.58MHz (MTSC) + // - 1: 3.55MHz (PAL) + // - 2: 4MHz + // - 3: 3MHz + // - 4: 3.9936MHz (PC-88, PC-98) + // - 5: 3.5MHz + // - YMF262: + // - bit 0-7: clock rate + // - 0: 14.32MHz (MTSC) + // - 1: 14.19MHz (PAL) + // - 2: 14MHz + // - 3: 16MHz + // - 4: 15MHz + // - YMF289B: (TODO) + // - bit 0-7: clock rate + // - 0: 33.8688MHz + // - 1: 28.64MHz (MTSC) + // - 2: 28.38MHz (PAL) + // - MSM6295: + // - bit 0-6: clock rate + // - 0: 1MHz + // - 1: 1.056MHz + // - 2: 4MHz + // - 3: 4.224MHz + // - 4: 3.58MHz (NTSC) + // - 5: 1.79MHz (Half NTSC) + // - 6: 1.023MHz + // - 7: 0.895MHz (Quarter NTSC) + // - 8: 2MHz + // - 9: 2.112MHz + // - 10: 0.875MHz + // - 11: 0.9375MHz + // - 12: 1.5MHz + // - 13: 3MHz + // - 14: 1.193MHz + // - bit 7: Output rate + // - 0: clock / 132 + // - 1: clock / 165 + // - SCC/+: + // - bit 0-6: clock rate + // - 0: 1.79MHz (MSX NTSC) + // - 1: 1.77MHz (PAL) + // - 2: 1.5MHz + // - 3: 2MHz + // - YMZ280B: + // - bit 0-7: clock rate + // - 0: 16.9344MHz + // - 1: 14.32MHz (MTSC) + // - 2: 14.19MHz (PAL) + // - 3: 16MHz + // - 4: 16.67MHz + // - 5: 14MHz unsigned int systemFlags[32]; // song information diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 7d7fa050b..94dbd5b4e 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -3092,7 +3092,12 @@ void FurnaceGUI::drawInsEdit() { int panMax=0; bool panSingle=false; bool panSingleNoBit=false; - if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_GB || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_VERA) { + if (ins->type==DIV_INS_STD ||//Game Gear + ins->type==DIV_INS_FM || + ins->type==DIV_INS_OPL || + ins->type==DIV_INS_GB || + ins->type==DIV_INS_OPZ || + ins->type==DIV_INS_VERA) { panMax=1; panSingle=true; } diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 994902e8e..a841f15b1 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -221,18 +221,55 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN76489A", { + DIV_SYSTEM_SMS, 64, 0, 0x40, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN76496", { + DIV_SYSTEM_SMS, 64, 0, 0x44, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NCR 8496", { + DIV_SYSTEM_SMS, 64, 0, 0x48, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tandy PSSJ 3-voice sound", { + DIV_SYSTEM_SMS, 64, 0, 0x4c, + // 8 bit DAC + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "Sega PSG (SN76489-like)", { DIV_SYSTEM_SMS, 64, 0, 0, 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega PSG (SN76489-like, Stereo)", { + DIV_SYSTEM_SMS, 64, 0, 0xc, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "AY-3-8910", { DIV_SYSTEM_AY8910, 64, 0, 0, 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "AY-3-8914", { + DIV_SYSTEM_AY8910, 64, 0, 48, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "Yamaha YM2149(F)", { DIV_SYSTEM_AY8910, 64, 0, 16, @@ -515,6 +552,12 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega Game Gear", { + DIV_SYSTEM_SMS, 64, 0, 0xc, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "Game Boy", { DIV_SYSTEM_GB, 64, 0, 0, @@ -603,13 +646,13 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "Neo Geo AES", { - DIV_SYSTEM_YM2610_FULL, 64, 0, 0, + DIV_SYSTEM_YM2610_FULL, 64, 0, 1, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Neo Geo AES (extended channel 2)", { - DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, 0, + DIV_SYSTEM_YM2610_FULL_EXT, 64, 0, 1, 0 } )); @@ -779,7 +822,7 @@ void FurnaceGUI::initSystemPresets() { cat.systems.push_back(FurnaceGUISysDef( "MSX + Playsoniq", { DIV_SYSTEM_AY8910, 64, 0, 16, - DIV_SYSTEM_SMS, 64, 0, 0, + DIV_SYSTEM_SMS, 64, 0, 0, // Sega VDP DIV_SYSTEM_C64_8580, 64, 0, 0, DIV_SYSTEM_SCC_PLUS, 64, 0, 0, 0 @@ -800,26 +843,110 @@ void FurnaceGUI::initSystemPresets() { } )); cat.systems.push_back(FurnaceGUISysDef( - "NEC PC-98 (with PC-9801-26K)", { - DIV_SYSTEM_OPN, 64, 0, 3, + "NEC PC-98 (with PC-9801-26/K)", { + DIV_SYSTEM_OPN, 64, 0, 4, // 3.9936MHz but some compatible card has 4MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "NEC PC-98 (with PC-9801-26K; extended channel 3)", { - DIV_SYSTEM_OPN_EXT, 64, 0, 3, + "NEC PC-98 (with PC-9801-26/K; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 4, // 3.9936MHz but some compatible card has 4MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "NEC PC-98 (with PC-9801-86)", { - DIV_SYSTEM_PC98, 64, 0, 3, + "NEC PC-98 (with Sound Orchestra)", { + DIV_SYSTEM_OPN, 64, 0, 4, + DIV_SYSTEM_OPL2, 64, 0, 4, 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "NEC PC-98 (with PC-9801-86; extended channel 3)", { - DIV_SYSTEM_PC98_EXT, 64, 0, 3, + "NEC PC-98 (with Sound Orchestra; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 4, + DIV_SYSTEM_OPL2, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra in drums mode)", { + DIV_SYSTEM_OPN, 64, 0, 4, + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra in drums mode; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 4, + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra V)", { + DIV_SYSTEM_OPN, 64, 0, 4, + DIV_SYSTEM_Y8950, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra V; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 4, + DIV_SYSTEM_Y8950, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra V in drums mode)", { + DIV_SYSTEM_OPN, 64, 0, 4, + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Orchestra V in drums mode; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 4, + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 4, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with PC-9801-86)", { // -73 also has OPNA + DIV_SYSTEM_PC98, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with PC-9801-86; extended channel 3)", { // -73 also has OPNA + DIV_SYSTEM_PC98_EXT, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible)", { + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPL3, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPL3, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode)", { + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode; extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2, 0 } )); @@ -839,8 +966,76 @@ void FurnaceGUI::initSystemPresets() { cat.systems.push_back(FurnaceGUISysDef( "ZX Spectrum (128K) with TurboSound FM", { DIV_SYSTEM_AY8910, 64, 0, 1, - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPN, 64, 0, 0, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on first OPN)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on second OPN)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM (extended channel 3 on both OPNs)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM + SAA", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_SAA1099, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM + SAA (extended channel 3 on first OPN)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_SAA1099, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM + SAA (extended channel 3 on second OPN)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_SAA1099, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound FM + SAA (extended channel 3 on both OPNs)", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_OPN_EXT, 64, 0, 1, + DIV_SYSTEM_SAA1099, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ZX Spectrum (128K) with TurboSound", { + DIV_SYSTEM_AY8910, 64, 0, 1, + DIV_SYSTEM_AY8910, 64, 0, 1, // or YM2149 + DIV_SYSTEM_AY8910, 64, 0, 1, // or YM2149 0 } )); @@ -858,7 +1053,7 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "BBC Micro", { - DIV_SYSTEM_SMS, 64, 0, 6, + DIV_SYSTEM_SMS, 64, 0, 0x42, // SN76489A 4MHz 0 } )); @@ -868,6 +1063,20 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "IBM PCjr", { + // it can be enable sound output at once + DIV_SYSTEM_SMS, 64, 0, 0x44, // SN76496 + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tandy 1000", { + DIV_SYSTEM_SMS, 64, 0, 0x44, // NCR 8496 or SN76496 or Tandy PSSJ(with 8 bit DAC) + DIV_SYSTEM_PCSPKR, 64, 0, 0, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "PC + Covox Sound Master", { DIV_SYSTEM_AY8930, 64, 0, 3, @@ -990,7 +1199,7 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "FM Towns", { - DIV_SYSTEM_YM2612, 64, 0, 2, + DIV_SYSTEM_YM2612, 64, 0, 2, // YM3438 DIV_SYSTEM_RF5C68, 64, 0, 0, 0 } @@ -1007,32 +1216,172 @@ void FurnaceGUI::initSystemPresets() { cat=FurnaceGUISysCategory("Arcade systems","INSERT COIN"); cat.systems.push_back(FurnaceGUISysDef( "Bally Midway MCR", { - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_AY8910, 64, 0, 0, + // SSIO sound board + DIV_SYSTEM_AY8910, 64, 0, 3, // 2MHz + DIV_SYSTEM_AY8910, 64, 0, 3, // 2MHz + // additional sound boards, mostly software controlled DAC 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Gyruss", { + "Konami Gyruss", { DIV_SYSTEM_AY8910, 64, 0, 0, DIV_SYSTEM_AY8910, 64, 0, 0, DIV_SYSTEM_AY8910, 64, 0, 0, DIV_SYSTEM_AY8910, 64, 0, 0, DIV_SYSTEM_AY8910, 64, 0, 0, + // additional discrete sound logics + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Konami Bubble System", { + DIV_SYSTEM_AY8910, 64, 0, 0, + DIV_SYSTEM_AY8910, 64, 0, 0, + DIV_SYSTEM_BUBSYS_WSG, 64, 0, 0, + // VLM5030 exists but not used for music at all + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Konami Hexion", { + DIV_SYSTEM_SCC, 64, 0, 2, // 1.5MHz (3MHz input) + DIV_SYSTEM_MSM6295, 64, 0, 1, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Kyugo", { - DIV_SYSTEM_AY8910, 64, 0, 4, - DIV_SYSTEM_AY8910, 64, 0, 4, + DIV_SYSTEM_AY8910, 64, 0, 14, + DIV_SYSTEM_AY8910, 64, 0, 14, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 1", { + DIV_SYSTEM_SMS, 64, 0, 0x42, // SN76489A 4MHz + DIV_SYSTEM_SMS, 64, 0, 0x0141, // SN76489A 2MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega Hang-On", { + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_SEGAPCM, 64, 0, 0, // discrete logics, 62.5KHz output rate + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega Hang-On (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_SEGAPCM, 64, 0, 0, // discrete logics, 62.5KHz output rate 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega OutRun/X Board", { - DIV_SYSTEM_YM2151, 64, 0, 2, - DIV_SYSTEM_SEGAPCM, 64, 0, 0, + DIV_SYSTEM_YM2151, 64, 0, 2, // 4MHz + DIV_SYSTEM_SEGAPCM, 64, 0, 0, // ASIC, 31.25KHz output rate + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 18", { + DIV_SYSTEM_YM2612, 64, 0, 2, // discrete 8MHz YM3438 + DIV_SYSTEM_YM2612, 64, 0, 2, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 1, // 10MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 18 (extended channel 3 on first OPN2C)", { + DIV_SYSTEM_YM2612_EXT, 64, 0, 2, // discrete 8MHz YM3438 + DIV_SYSTEM_YM2612, 64, 0, 2, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 1, // 10MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 18 (extended channel 3 on second OPN2C)", { + DIV_SYSTEM_YM2612, 64, 0, 2, // discrete 8MHz YM3438 + DIV_SYSTEM_YM2612_EXT, 64, 0, 2, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 1, // 10MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 18 (extended channel 3 on both OPN2Cs)", { + DIV_SYSTEM_YM2612_EXT, 64, 0, 2, // discrete 8MHz YM3438 + DIV_SYSTEM_YM2612_EXT, 64, 0, 2, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 1, // 10MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 32", { + DIV_SYSTEM_YM2612, 64, 0, 4, // discrete 8.05MHz YM3438 + DIV_SYSTEM_YM2612, 64, 0, 4, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 2, // 12.5MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 32 (extended channel 3 on first OPN2C)", { + DIV_SYSTEM_YM2612_EXT, 64, 0, 4, // discrete 8.05MHz YM3438 + DIV_SYSTEM_YM2612, 64, 0, 4, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 2, // 12.5MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 32 (extended channel 3 on second OPN2C)", { + DIV_SYSTEM_YM2612, 64, 0, 4, // discrete 8.05MHz YM3438 + DIV_SYSTEM_YM2612_EXT, 64, 0, 4, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 2, // 12.5MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sega System 32 (extended channel 3 on both OPN2Cs)", { + DIV_SYSTEM_YM2612_EXT, 64, 0, 4, // discrete 8.05MHz YM3438 + DIV_SYSTEM_YM2612_EXT, 64, 0, 4, // ^^ + DIV_SYSTEM_RF5C68, 64, 0, 2, // 12.5MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom Exed Eyes", { + DIV_SYSTEM_AY8910, 64, 0, 4, // 1.5MHz + DIV_SYSTEM_SMS, 64, 0, 0x0104, // SN76489 3MHz + DIV_SYSTEM_SMS, 64, 0, 0x0104, // SN76489 3MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom Arcade", { // 1943, Side arms, etc + DIV_SYSTEM_OPN, 64, 0, 5, // 4 or 1.5MHz; various per games + DIV_SYSTEM_OPN, 64, 0, 5, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom Arcade (extended channel 3 on first OPN)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, + DIV_SYSTEM_OPN, 64, 0, 5, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom Arcade (extended channel 3 on second OPN)", { + DIV_SYSTEM_OPN, 64, 0, 5, + DIV_SYSTEM_OPN_EXT, 64, 0, 5, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom Arcade (extended channel 3 on both OPNs)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, + DIV_SYSTEM_OPN_EXT, 64, 0, 5, 0 } )); @@ -1043,145 +1392,433 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Capcom CPS-2 (QSound)", { + DIV_SYSTEM_QSOUND, 64, 0, 0, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Jaleco Ginga NinkyouDen", { + DIV_SYSTEM_AY8910, 64, 0, 16, // 1.79MHz + DIV_SYSTEM_Y8950, 64, 0, 0, // 3.58MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Jaleco Ginga NinkyouDen (drums mode)", { + DIV_SYSTEM_AY8910, 64, 0, 16, // 1.79MHz + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 0, // 3.58MHz + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "Jaleco Mega System 1", { - DIV_SYSTEM_YM2151, 64, 0, 2, - DIV_SYSTEM_MSM6295, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, + DIV_SYSTEM_YM2151, 64, 0, 1, // 3.5MHz (7MHz / 2) + DIV_SYSTEM_MSM6295, 64, 0, 2, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 2, // 4MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( "NMK 16-bit Arcade", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 2, - DIV_SYSTEM_MSM6295, 64, 0, 2, + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz; optional + DIV_SYSTEM_MSM6295, 64, 0, 130, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 130, // ^^ 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Data East Arcade", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPL2, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, + "NMK 16-bit Arcade (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz; optional + DIV_SYSTEM_MSM6295, 64, 0, 130, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 130, // ^^ + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Kaneko DJ Boy", { + DIV_SYSTEM_OPN, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, -127, 12, // 1.5MHz, Left output + DIV_SYSTEM_MSM6295, 64, 127, 12, // 1.5MHz, Right output + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Kaneko DJ Boy (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, -127, 12, // 1.5MHz, Left output + DIV_SYSTEM_MSM6295, 64, 127, 12, // 1.5MHz, Right output + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Kaneko Air Buster", { + DIV_SYSTEM_OPN, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 141, // 3MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Kaneko Air Buster (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 141, // 3MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Kaneko Toybox System", { - DIV_SYSTEM_AY8910, 64, 0, 1, - DIV_SYSTEM_AY8910, 64, 0, 1, - DIV_SYSTEM_MSM6295, 64, 0, 0, + DIV_SYSTEM_AY8910, 64, 0, 19, // YM2149 2MHz + DIV_SYSTEM_AY8910, 64, 0, 19, // ^^ + DIV_SYSTEM_MSM6295, 64, 0, 8, // 2MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Tecmo Arcade", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, + "Kaneko Jackie Chan", { + DIV_SYSTEM_YMZ280B, 64, 0, 3, // 16MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Seibu Kaihatsu Arcade", { - DIV_SYSTEM_OPL2, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, + "Super Kaneko Nova System", { + DIV_SYSTEM_YMZ280B, 64, 0, 4, // 16.67MHz (33.33MHz / 2) 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Data East Arcade (Dark Seal)", { - DIV_SYSTEM_YM2151, 64, 0, 2, - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 8, + "Tecmo Ninja Gaiden", { // Ninja Gaiden, Raiga, etc + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tecmo Ninja Gaiden (extended channel 3 on first OPN)", { // Ninja Gaiden, Raiga, etc + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tecmo Ninja Gaiden (extended channel 3 on second OPN)", { // Ninja Gaiden, Raiga, etc + DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tecmo Ninja Gaiden (extended channel 3 on both OPNs)", { // Ninja Gaiden, Raiga, etc + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tecmo System", { + DIV_SYSTEM_OPL3, 64, 0, 0, + DIV_SYSTEM_YMZ280B, 64, 0, 0, + DIV_SYSTEM_MSM6295, 64, 0, 8, // 2MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Tecmo System (drums mode)", { + DIV_SYSTEM_OPL3_DRUMS, 64, 0, 0, + DIV_SYSTEM_YMZ280B, 64, 0, 0, + DIV_SYSTEM_MSM6295, 64, 0, 8, // 2MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Seibu Kaihatsu Raiden", { // Raiden, Seibu cup soccer, Zero team, etc + DIV_SYSTEM_OPL2, 64, 0, 0, // YM3812 3.58MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 or 1.023MHz (28.636363MHz / 28); various per games + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Seibu Kaihatsu Raiden (drums mode)", { // Raiden, Seibu cup soccer, Zero team, etc + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0, // YM3812 3.58MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 or 1.023MHz (28.636363MHz / 28); various per games + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Sunsoft Shanghai 3", { + DIV_SYSTEM_AY8910, 64, 0, 20, // YM2149 1.5MHz + DIV_SYSTEM_MSM6295, 64, 0, 1, // 1.056MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sunsoft Arcade", { - DIV_SYSTEM_YM2612, 64, 0, 4, - DIV_SYSTEM_MSM6295, 64, 0, 0, + DIV_SYSTEM_YM2612, 64, 0, 2, // discrete YM3438 8MHz + DIV_SYSTEM_MSM6295, 64, 0, 1, // 1.056MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Atari Arcade (Rampart)", { - DIV_SYSTEM_OPLL, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 0, + "Sunsoft Arcade (extended channel 3)", { + DIV_SYSTEM_YM2612_EXT, 64, 0, 2, // discrete YM3438 8MHz + DIV_SYSTEM_MSM6295, 64, 0, 1, // 1.056MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Data East Deco 156", { - DIV_SYSTEM_MSM6295, 64, 0, 0, - DIV_SYSTEM_MSM6295, 64, 0, 8, + "Atari Klax", { + DIV_SYSTEM_MSM6295, 64, 0, 7, // 0.895MHz (3.579545MHz / 4) 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "SNK Triple Z80 (Chopper)", { //or Namco? - DIV_SYSTEM_Y8950, 64, 0, 0, - DIV_SYSTEM_OPL2, 64, 0, 0, + "Atari Rampart", { + DIV_SYSTEM_OPLL, 64, 0, 0, // 3.579545MHz + DIV_SYSTEM_MSM6295, 64, 0, 14, // 1.193MHz (3.579545MHz / 3) 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Sega System 18", { - DIV_SYSTEM_YM2612, 64, 0, 2, - DIV_SYSTEM_YM2612, 64, 0, 2, - DIV_SYSTEM_RF5C68, 64, 0, 1, + "Atari Rampart (drums mode)", { + DIV_SYSTEM_OPLL_DRUMS, 64, 0, 0, // 3.579545MHz + DIV_SYSTEM_MSM6295, 64, 0, 14, // 1.193MHz (3.579545MHz / 3) 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Sega System 1", { - DIV_SYSTEM_SMS, 64, 0, 2, - DIV_SYSTEM_SMS, 64, 0, 3, - 0 - } - )); - cat.systems.push_back(FurnaceGUISysDef( - "Sega System 32", { - DIV_SYSTEM_YM2612, 64, 0, 4, - DIV_SYSTEM_YM2612, 64, 0, 4, - DIV_SYSTEM_RF5C68, 64, 0, 2, - 0 - } - )); - cat.systems.push_back(FurnaceGUISysDef( - "Sega Hang-On", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_SEGAPCM, 64, 0, 0, - 0 - } - )); - cat.systems.push_back(FurnaceGUISysDef( - "SNK Alpha-68K", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPLL, 64, 0, 0, + "Atari JSA IIIs", { + DIV_SYSTEM_YM2151, 64, 0, 0, // 3.579545MHz + DIV_SYSTEM_MSM6295, 64, -127, 14, // 1.193MHz (3.579545MHz / 3), Left output + DIV_SYSTEM_MSM6295, 64, 127, 14, // 1.193MHz (3.579545MHz / 3), Right output 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Data East Karnov", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPL, 64, 0, 0, + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL, 64, 0, 3, // 3MHz 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Capcom Arcade", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_OPN, 64, 0, 0, + "Data East Karnov (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL, 64, 0, 3, // 3MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Karnov (drums mode)", { + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL_DRUMS, 64, 0, 3, // 3MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Karnov (extended channel 3; drums mode)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL_DRUMS, 64, 0, 3, // 3MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Arcade", { // Bad dudes, Robocop, etc + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL2, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 to 1.056MHz; various per games or optional + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Arcade (extended channel 3)", { // Bad dudes, Robocop, etc + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL2, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 to 1.056MHz; various per games or optional + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Arcade (drums mode)", { // Bad dudes, Robocop, etc + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 to 1.056MHz; various per games or optional + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Arcade (extended channel 3; drums mode)", { // Bad dudes, Robocop, etc + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 3, // 3MHz + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 to 1.056MHz; various per games or optional 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Data East PCX", { - DIV_SYSTEM_OPN, 64, 0, 0, - DIV_SYSTEM_PCE, 64, 0, 2, + DIV_SYSTEM_OPN, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_PCE, 64, 0, 0, + // software controlled MSM5205 + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East PCX (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 5, // 1.5MHz + DIV_SYSTEM_PCE, 64, 0, 0, + // software controlled MSM5205 + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Dark Seal", { // Dark Seal, Crude Buster, Vapor Trail, etc + DIV_SYSTEM_YM2151, 64, 0, 0, // 3.580MHz (32.22MHz / 9) + DIV_SYSTEM_OPN, 64, 0, 2, // 4.0275MHz (32.22MHz / 8); optional + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1.007MHz (32.22MHz / 32) + DIV_SYSTEM_MSM6295, 64, 0, 8, // 2.014MHz (32.22MHz / 16); optional + // HuC6280 is for control them, internal sound isn't used + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Dark Seal (extended channel 3)", { // Dark Seal, Crude Buster, Vapor Trail, etc + DIV_SYSTEM_YM2151, 64, 0, 0, // 3.580MHz (32.22MHz / 9) + DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4.0275MHz (32.22MHz / 8); optional + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1.007MHz (32.22MHz / 32) + DIV_SYSTEM_MSM6295, 64, 0, 8, // 2.014MHz (32.22MHz / 16); optional + // HuC6280 is for control them, internal sound isn't used + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East Deco 156", { + DIV_SYSTEM_MSM6295, 64, 0, 0, // 1 or 1.007MHz (32.22MHz / 32); various per games + DIV_SYSTEM_MSM6295, 64, 0, 8, // 1 or 2 or 2.014MHz (32.22MHz / 16); various per games + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Data East MLC", { + DIV_SYSTEM_YMZ280B, 64, 0, 5, // 14MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Ikari Warriors", { + DIV_SYSTEM_OPL, 64, 0, 2, + DIV_SYSTEM_OPL, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Ikari Warriors (drums mode on first OPL)", { + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Ikari Warriors (drums mode on second OPL)", { + DIV_SYSTEM_OPL, 64, 0, 2, + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Ikari Warriors (drums mode on both OPLs)", { + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Triple Z80", { + DIV_SYSTEM_Y8950, 64, 0, 2, + DIV_SYSTEM_OPL, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Triple Z80 (drums mode on Y8950)", { + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Triple Z80 (drums mode on OPL)", { + DIV_SYSTEM_Y8950, 64, 0, 2, + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Triple Z80 (drums mode on Y8950 and OPL)", { + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Chopper I", { + DIV_SYSTEM_Y8950, 64, 0, 2, + DIV_SYSTEM_OPL2, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Chopper I (drums mode on Y8950)", { + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL2, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Chopper I (drums mode on OPL2)", { + DIV_SYSTEM_Y8950, 64, 0, 2, + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "SNK Chopper I (drums mode on Y8950 and OPL2)", { + DIV_SYSTEM_Y8950_DRUMS, 64, 0, 2, + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 2, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Alpha denshi Alpha-68K", { + DIV_SYSTEM_OPN, 64, 0, 3, // 3MHz + DIV_SYSTEM_OPLL, 64, 0, 0, // 3.58MHz + // software controlled 8 bit DAC + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Alpha denshi Alpha-68K (extended channel 3)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 3, // 3MHz + DIV_SYSTEM_OPLL, 64, 0, 0, // 3.58MHz + // software controlled 8 bit DAC + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Alpha denshi Alpha-68K (drums mode)", { + DIV_SYSTEM_OPN, 64, 0, 3, // 3MHz + DIV_SYSTEM_OPLL_DRUMS, 64, 0, 0, // 3.58MHz + // software controlled 8 bit DAC + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Alpha denshi Alpha-68K (extended channel 3; drums mode)", { + DIV_SYSTEM_OPN_EXT, 64, 0, 3, // 3MHz + DIV_SYSTEM_OPLL_DRUMS, 64, 0, 0, // 3.58MHz + // software controlled 8 bit DAC 0 } )); @@ -1198,35 +1835,34 @@ void FurnaceGUI::initSystemPresets() { } )); cat.systems.push_back(FurnaceGUISysDef( - "Capcom Exed Eyes", { - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_SMS, 64, 0, 0, - DIV_SYSTEM_SMS, 64, 0, 0, + "Nichibutsu Mag Max", { + DIV_SYSTEM_AY8910, 64, 0, 13, + DIV_SYSTEM_AY8910, 64, 0, 13, + DIV_SYSTEM_AY8910, 64, 0, 13, 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Nichibutsu Arcade", { - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_AY8910, 64, 0, 0, - 0 - } - )); - cat.systems.push_back(FurnaceGUISysDef( - "Namco (3-channel WSG)", { + "Namco (3-channel WSG)", { // Pac-Man, Galaga, Xevious, etc DIV_SYSTEM_NAMCO, 64, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Namco (8-channel WSG)", { + "Namco Mappy", { // Mappy, Super Pac-Man, Libble Rabble, etc DIV_SYSTEM_NAMCO_15XX, 64, 0, 0, 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Namco Pac-Land", { // Pac-Land, Baraduke, Sky kid, etc + DIV_SYSTEM_NAMCO_CUS30, 64, 0, 0, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "Namco System 1", { + DIV_SYSTEM_YM2151, 64, 0, 0, DIV_SYSTEM_NAMCO_CUS30, 64, 0, 0, 0 } @@ -1243,12 +1879,6 @@ void FurnaceGUI::initSystemPresets() { 0 } )); - cat.systems.push_back(FurnaceGUISysDef( - "Capcom CPS-2 (QSound)", { - DIV_SYSTEM_QSOUND, 64, 0, 0, - 0 - } - )); cat.systems.push_back(FurnaceGUISysDef( "Seta 1", { DIV_SYSTEM_X1_010, 64, 0, 0, @@ -1275,18 +1905,37 @@ void FurnaceGUI::initSystemPresets() { } )); cat.systems.push_back(FurnaceGUISysDef( - "SNK Triple Z80", { - DIV_SYSTEM_Y8950, 64, 0, 0, - DIV_SYSTEM_OPL, 64, 0, 0, + "Coreland Cyber Tank", { + DIV_SYSTEM_Y8950, 64, -127, 0, // 3.58MHz, Left output + DIV_SYSTEM_Y8950, 64, 127, 0, // 3.58MHz, Right output 0 } )); cat.systems.push_back(FurnaceGUISysDef( - "Konami Bubble System", { - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_AY8910, 64, 0, 0, - DIV_SYSTEM_BUBSYS_WSG, 64, 0, 0, - // VLM5030 exists but not used for music at all + "Coreland Cyber Tank (drums mode)", { + DIV_SYSTEM_Y8950, 64, -127, 0, // 3.58MHz, Left output + DIV_SYSTEM_Y8950, 64, 127, 0, // 3.58MHz, Right output + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "ICE Skimaxx", { + DIV_SYSTEM_MSM6295, 64, -127, 130, // 4MHz, Left output + DIV_SYSTEM_MSM6295, 64, 127, 130, // 4MHz, Right output + DIV_SYSTEM_MSM6295, 64, -127, 8, // 2MHz, Left output + DIV_SYSTEM_MSM6295, 64, 127, 8, // 2MHz, Right output + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Toaplan 1", { + DIV_SYSTEM_OPL2, 64, 0, 5, // 3.5MHz + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Toaplan 1 (drums mode)", { + DIV_SYSTEM_OPL2_DRUMS, 64, 0, 5, // 3.5MHz 0 } )); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 91d542bd7..8878ca8f4 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -28,19 +28,19 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_YM2612_EXT: case DIV_SYSTEM_YM2612_FRAC: case DIV_SYSTEM_YM2612_FRAC_EXT: { - if (ImGui::RadioButton("NTSC (7.67MHz)",(flags&7)==0)) { + if (ImGui::RadioButton("NTSC (7.67MHz)",(flags&(~0x80000000))==0)) { copyOfFlags=(flags&0x80000000)|0; } - if (ImGui::RadioButton("PAL (7.61MHz)",(flags&7)==1)) { + if (ImGui::RadioButton("PAL (7.61MHz)",(flags&(~0x80000000))==1)) { copyOfFlags=(flags&0x80000000)|1; } - if (ImGui::RadioButton("FM Towns (8MHz)",(flags&7)==2)) { + if (ImGui::RadioButton("FM Towns (8MHz)",(flags&(~0x80000000))==2)) { copyOfFlags=(flags&0x80000000)|2; } - if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",(flags&7)==3)) { + if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",(flags&(~0x80000000))==3)) { copyOfFlags=(flags&0x80000000)|3; } - if (ImGui::RadioButton("Sega System 32 (8.05MHz)",(flags&7)==4)) { + if (ImGui::RadioButton("Sega System 32 (8.05MHz)",(flags&(~0x80000000))==4)) { copyOfFlags=(flags&0x80000000)|4; } bool ladder=flags&0x80000000; @@ -51,43 +51,52 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool } case DIV_SYSTEM_SMS: { ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&3)==0)) { - copyOfFlags=(flags&(~3))|0; - + if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&0xff03)==0x0000)) { + copyOfFlags=(flags&(~0xff03))|0x0000; } - if (ImGui::RadioButton("PAL (3.55MHz)",(flags&3)==1)) { - copyOfFlags=(flags&(~3))|1; - + if (ImGui::RadioButton("3.55MHz (PAL)",(flags&0xff03)==0x0001)) { + copyOfFlags=(flags&(~0xff03))|0x0001; } - if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&3)==2)) { - copyOfFlags=(flags&(~3))|2; - + if (ImGui::RadioButton("4MHz (BBC Micro)",(flags&0xff03)==0x0002)) { + copyOfFlags=(flags&(~0xff03))|0x0002; } - if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&3)==3)) { - copyOfFlags=(flags&(~3))|3; - + if (ImGui::RadioButton("1.79MHz (Half NTSC)",(flags&0xff03)==0x0003)) { + copyOfFlags=(flags&(~0xff03))|0x0003; + } + if (ImGui::RadioButton("3MHz (Exed Exes)",(flags&0xff03)==0x0100)) { + copyOfFlags=(flags&(~0xff03))|0x0100; + } + if (ImGui::RadioButton("2MHz (Sega System 1)",(flags&0xff03)==0x0101)) { + copyOfFlags=(flags&(~0xff03))|0x0101; } ImGui::Text("Chip type:"); - if (ImGui::RadioButton("Sega VDP/Master System",((flags>>2)&3)==0)) { - copyOfFlags=(flags&(~12))|0; - + if (ImGui::RadioButton("Sega VDP/Master System",(flags&0xcc)==0x00)) { + copyOfFlags=(flags&(~0xcc))|0x00; } - if (ImGui::RadioButton("TI SN76489",((flags>>2)&3)==1)) { - copyOfFlags=(flags&(~12))|4; - + if (ImGui::RadioButton("TI SN76489",(flags&0xcc)==0x04)) { + copyOfFlags=(flags&(~0xcc))|0x04; } - if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",((flags>>2)&3)==2)) { - copyOfFlags=(flags&(~12))|8; - + if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",(flags&0xcc)==0x08)) { + copyOfFlags=(flags&(~0xcc))|0x08; + } + if (ImGui::RadioButton("Game Gear",(flags&0xcc)==0x0c)) { + copyOfFlags=(flags&(~0xcc))|0x0c; + } + if (ImGui::RadioButton("TI SN76489A",(flags&0xcc)==0x40)) { + copyOfFlags=(flags&(~0xcc))|0x40; + } + if (ImGui::RadioButton("TI SN76496",(flags&0xcc)==0x44)) { + copyOfFlags=(flags&(~0xcc))|0x44; + } + if (ImGui::RadioButton("NCR 8496",(flags&0xcc)==0x48)) { + copyOfFlags=(flags&(~0xcc))|0x48; + } + if (ImGui::RadioButton("Tandy PSSJ 3-voice sound",(flags&0xcc)==0x4c)) { + copyOfFlags=(flags&(~0xcc))|0x4c; } - /*if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) { - copyOfFlags=(flags&3)|12); - }*/ - bool noPhaseReset=flags&16; if (ImGui::Checkbox("Disable noise period change phase reset",&noPhaseReset)) { copyOfFlags=(flags&(~16))|(noPhaseReset<<4); - } break; } @@ -97,37 +106,29 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool ImGui::Text("Clock rate:"); if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&15)==0)) { copyOfFlags=(flags&(~15))|0; - } if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) { copyOfFlags=(flags&(~15))|1; - } if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&15)==2)) { copyOfFlags=(flags&(~15))|2; - } if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) { copyOfFlags=(flags&(~15))|3; - } if (type!=DIV_SYSTEM_VRC7) { ImGui::Text("Patch set:"); if (ImGui::RadioButton("Yamaha YM2413",((flags>>4)&15)==0)) { copyOfFlags=(flags&(~0xf0))|0; - } if (ImGui::RadioButton("Yamaha YMF281",((flags>>4)&15)==1)) { copyOfFlags=(flags&(~0xf0))|0x10; - } if (ImGui::RadioButton("Yamaha YM2423",((flags>>4)&15)==2)) { copyOfFlags=(flags&(~0xf0))|0x20; - } if (ImGui::RadioButton("Konami VRC7",((flags>>4)&15)==3)) { copyOfFlags=(flags&(~0xf0))|0x30; - } } break; @@ -135,15 +136,12 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_YM2151: if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",flags==0)) { copyOfFlags=0; - } if (ImGui::RadioButton("PAL (3.55MHz)",flags==1)) { copyOfFlags=1; - } if (ImGui::RadioButton("X1/X68000 (4MHz)",flags==2)) { copyOfFlags=2; - } break; case DIV_SYSTEM_NES: @@ -152,30 +150,37 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_MMC5: if (ImGui::RadioButton("NTSC (1.79MHz)",flags==0)) { copyOfFlags=0; - } if (ImGui::RadioButton("PAL (1.67MHz)",flags==1)) { copyOfFlags=1; - } if (ImGui::RadioButton("Dendy (1.77MHz)",flags==2)) { copyOfFlags=2; - } break; case DIV_SYSTEM_C64_8580: case DIV_SYSTEM_C64_6581: if (ImGui::RadioButton("NTSC (1.02MHz)",flags==0)) { copyOfFlags=0; - } if (ImGui::RadioButton("PAL (0.99MHz)",flags==1)) { copyOfFlags=1; - } if (ImGui::RadioButton("SSI 2001 (0.89MHz)",flags==2)) { copyOfFlags=2; - + } + break; + case DIV_SYSTEM_YM2610: + case DIV_SYSTEM_YM2610_EXT: + case DIV_SYSTEM_YM2610_FULL: + case DIV_SYSTEM_YM2610_FULL_EXT: + case DIV_SYSTEM_YM2610B: + case DIV_SYSTEM_YM2610B_EXT: + if (ImGui::RadioButton("8MHz (Neo Geo MVS)",(flags&0xff)==0)) { + copyOfFlags=(flags&(~0xff))|0; + } + if (ImGui::RadioButton("8.06MHz (Neo Geo AES)",(flags&0xff)==1)) { + copyOfFlags=(flags&(~0xff))|1; } break; case DIV_SYSTEM_AY8910: @@ -183,87 +188,74 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool ImGui::Text("Clock rate:"); if (ImGui::RadioButton("1.79MHz (ZX Spectrum NTSC/MSX)",(flags&15)==0)) { copyOfFlags=(flags&(~15))|0; - } if (ImGui::RadioButton("1.77MHz (ZX Spectrum)",(flags&15)==1)) { copyOfFlags=(flags&(~15))|1; - } if (ImGui::RadioButton("1.75MHz (ZX Spectrum)",(flags&15)==2)) { copyOfFlags=(flags&(~15))|2; - } if (ImGui::RadioButton("2MHz (Atari ST/Sharp X1)",(flags&15)==3)) { copyOfFlags=(flags&(~15))|3; - } if (ImGui::RadioButton("1.5MHz (Vectrex)",(flags&15)==4)) { copyOfFlags=(flags&(~15))|4; - } if (ImGui::RadioButton("1MHz (Amstrad CPC)",(flags&15)==5)) { copyOfFlags=(flags&(~15))|5; - } if (ImGui::RadioButton("0.89MHz (Pre-divided Sunsoft 5B)",(flags&15)==6)) { copyOfFlags=(flags&(~15))|6; - } if (ImGui::RadioButton("1.67MHz (?)",(flags&15)==7)) { copyOfFlags=(flags&(~15))|7; - } if (ImGui::RadioButton("0.83MHz (Pre-divided Sunsoft 5B on PAL)",(flags&15)==8)) { copyOfFlags=(flags&(~15))|8; - } if (ImGui::RadioButton("1.10MHz (Gamate/VIC-20 PAL)",(flags&15)==9)) { copyOfFlags=(flags&(~15))|9; - } if (ImGui::RadioButton("2^21Hz (Game Boy)",(flags&15)==10)) { copyOfFlags=(flags&(~15))|10; - } if (ImGui::RadioButton("3.58MHz (Darky)",(flags&15)==11)) { copyOfFlags=(flags&(~15))|11; - } if (ImGui::RadioButton("3.6MHz (Darky)",(flags&15)==12)) { copyOfFlags=(flags&(~15))|12; - + } + if (ImGui::RadioButton("1.25MHz (Mag Max)",(flags&15)==13)) { + copyOfFlags=(flags&(~15))|13; + } + if (ImGui::RadioButton("1.536MHz (Kyugo)",(flags&15)==14)) { + copyOfFlags=(flags&(~15))|14; } if (type==DIV_SYSTEM_AY8910) { ImGui::Text("Chip type:"); if (ImGui::RadioButton("AY-3-8910",(flags&0x30)==0)) { copyOfFlags=(flags&(~0x30))|0; - } if (ImGui::RadioButton("YM2149(F)",(flags&0x30)==16)) { copyOfFlags=(flags&(~0x30))|16; - } if (ImGui::RadioButton("Sunsoft 5B",(flags&0x30)==32)) { copyOfFlags=(flags&(~0x30))|32; - } if (ImGui::RadioButton("AY-3-8914",(flags&0x30)==48)) { copyOfFlags=(flags&(~0x30))|48; - } } bool stereo=flags&0x40; ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)==32)); if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) { copyOfFlags=(flags&(~0x40))|(stereo?0x40:0); - } ImGui::EndDisabled(); bool clockSel=flags&0x80; ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)!=16)); if (ImGui::Checkbox("Half Clock divider##_AY_CLKSEL",&clockSel)) { copyOfFlags=(flags&(~0x80))|(clockSel?0x80:0); - } ImGui::EndDisabled(); break; @@ -375,86 +367,223 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool } break; } - case DIV_SYSTEM_OPN: { - if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&3)==0)) { - copyOfFlags=(flags&0x80000000)|0; + case DIV_SYSTEM_OPN: + case DIV_SYSTEM_OPN_EXT: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&31)==0)) { + copyOfFlags=(flags&(~31))|0; } - if (ImGui::RadioButton("PAL (3.54MHz)",(flags&3)==1)) { - copyOfFlags=(flags&0x80000000)|1; + if (ImGui::RadioButton("3.54MHz (PAL)",(flags&31)==1)) { + copyOfFlags=(flags&(~31))|1; } - if (ImGui::RadioButton("Arcade (4MHz)",(flags&3)==2)) { - copyOfFlags=(flags&0x80000000)|2; + if (ImGui::RadioButton("4MHz",(flags&31)==2)) { + copyOfFlags=(flags&(~31))|2; } - if (ImGui::RadioButton("PC-9801-26K? TODO: CONFIRM (3MHz)",(flags&3)==3)) { - copyOfFlags=(flags&0x80000000)|3; + if (ImGui::RadioButton("3MHz",(flags&31)==3)) { + copyOfFlags=(flags&(~31))|3; } + if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",(flags&31)==4)) { + copyOfFlags=(flags&(~31))|4; + } + if (ImGui::RadioButton("1.5MHz",(flags&31)==5)) { + copyOfFlags=(flags&(~31))|5; + } + /* + ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==0)) { + copyOfFlags=(flags&(~96))|0; + } + if (ImGui::RadioButton("FM: clock / 36, SSG: clock / 8",(flags&96)==32)) { + copyOfFlags=(flags&(~96))|32; + } + if (ImGui::RadioButton("FM: clock / 24, SSG: clock / 4",(flags&96)==64)) { + copyOfFlags=(flags&(~96))|64; + } + */ + break; + } + case DIV_SYSTEM_PC98: + case DIV_SYSTEM_PC98_EXT: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("8MHz (Arcade)",(flags&31)==0)) { + copyOfFlags=(flags&(~31))|0; + } + if (ImGui::RadioButton("7.987MHz (PC-88/PC-98)",(flags&31)==1)) { + copyOfFlags=(flags&(~31))|1; + } + /* + ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + if (ImGui::RadioButton("FM: clock / 144, SSG: clock / 32",(flags&96)==0)) { + copyOfFlags=(flags&(~96))|0; + } + if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==32)) { + copyOfFlags=(flags&(~96))|32; + } + if (ImGui::RadioButton("FM: clock / 48, SSG: clock / 8",(flags&96)==64)) { + copyOfFlags=(flags&(~96))|64; + } + */ break; } case DIV_SYSTEM_RF5C68: { ImGui::Text("Clock rate:"); if (ImGui::RadioButton("8MHz (FM Towns)",(flags&15)==0)) { copyOfFlags=(flags&(~15))|0; - } if (ImGui::RadioButton("10MHz (Sega System 18)",(flags&15)==1)) { copyOfFlags=(flags&(~15))|1; - } if (ImGui::RadioButton("12.5MHz (Sega CD/System 32)",(flags&15)==2)) { copyOfFlags=(flags&(~15))|2; - } ImGui::Text("Chip type:"); if (ImGui::RadioButton("RF5C68 (10-bit output)",((flags>>4)&15)==0)) { copyOfFlags=(flags&(~240))|0; - } if (ImGui::RadioButton("RF5C164 (16-bit output)",((flags>>4)&15)==1)) { copyOfFlags=(flags&(~240))|16; - } break; } case DIV_SYSTEM_MSM6295: { ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("1MHz",flags==0)) { - copyOfFlags=0; + if (ImGui::RadioButton("1MHz",(flags&127)==0)) { + copyOfFlags=(flags&(~127))|0; } - if (ImGui::RadioButton("1.056MHz",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("1.056MHz",(flags&127)==1)) { + copyOfFlags=(flags&(~127))|1; } - if (ImGui::RadioButton("4MHz",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("4MHz",(flags&127)==2)) { + copyOfFlags=(flags&(~127))|2; } - if (ImGui::RadioButton("4.224MHz",flags==3)) { - copyOfFlags=3; + if (ImGui::RadioButton("4.224MHz",(flags&127)==3)) { + copyOfFlags=(flags&(~127))|3; } - if (ImGui::RadioButton("3.58MHz",flags==4)) { - copyOfFlags=4; + if (ImGui::RadioButton("3.58MHz",(flags&127)==4)) { + copyOfFlags=(flags&(~127))|4; } - if (ImGui::RadioButton("1.79MHz",flags==5)) { - copyOfFlags=5; + if (ImGui::RadioButton("1.79MHz",(flags&127)==5)) { + copyOfFlags=(flags&(~127))|5; } - if (ImGui::RadioButton("1.02MHz",flags==6)) { - copyOfFlags=6; + if (ImGui::RadioButton("1.02MHz",(flags&127)==6)) { + copyOfFlags=(flags&(~127))|6; } - if (ImGui::RadioButton("0.89MHz",flags==7)) { - copyOfFlags=7; + if (ImGui::RadioButton("0.89MHz",(flags&127)==7)) { + copyOfFlags=(flags&(~127))|7; } - if (ImGui::RadioButton("2MHz",flags==8)) { - copyOfFlags=8; + if (ImGui::RadioButton("2MHz",(flags&127)==8)) { + copyOfFlags=(flags&(~127))|8; } - if (ImGui::RadioButton("2.112MHz",flags==9)) { - copyOfFlags=9; + if (ImGui::RadioButton("2.112MHz",(flags&127)==9)) { + copyOfFlags=(flags&(~127))|9; } - if (ImGui::RadioButton("0.875MHz",flags==10)) { - copyOfFlags=10; + if (ImGui::RadioButton("0.875MHz",(flags&127)==10)) { + copyOfFlags=(flags&(~127))|10; } - if (ImGui::RadioButton("0.9375MHz",flags==11)) { - copyOfFlags=11; + if (ImGui::RadioButton("0.9375MHz",(flags&127)==11)) { + copyOfFlags=(flags&(~127))|11; } - if (ImGui::RadioButton("1.5MHz",flags==12)) { - copyOfFlags=12; + if (ImGui::RadioButton("1.5MHz",(flags&127)==12)) { + copyOfFlags=(flags&(~127))|12; + } + if (ImGui::RadioButton("3MHz",(flags&127)==13)) { + copyOfFlags=(flags&(~127))|13; + } + if (ImGui::RadioButton("1.193MHz (Atari)",(flags&127)==14)) { + copyOfFlags=(flags&(~127))|14; + } + ImGui::Text("Output rate:"); + if (ImGui::RadioButton("clock / 132",(flags&128)==0)) { + copyOfFlags=(flags&(~128))|0; + } + if (ImGui::RadioButton("clock / 165",(flags&128)==128)) { + copyOfFlags=(flags&(~128))|128; + } + break; + } + case DIV_SYSTEM_SCC: + case DIV_SYSTEM_SCC_PLUS: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("1.79MHz (NTSC/MSX)",(flags&127)==0)) { + copyOfFlags=(flags&(~127))|0; + } + if (ImGui::RadioButton("1.77MHz (PAL)",(flags&127)==1)) { + copyOfFlags=(flags&(~127))|1; + } + if (ImGui::RadioButton("1.5MHz (Arcade)",(flags&127)==2)) { + copyOfFlags=(flags&(~127))|2; + } + if (ImGui::RadioButton("2MHz",(flags&127)==3)) { + copyOfFlags=(flags&(~127))|3; + } + break; + } + case DIV_SYSTEM_OPL: + case DIV_SYSTEM_OPL_DRUMS: + case DIV_SYSTEM_OPL2: + case DIV_SYSTEM_OPL2_DRUMS: + case DIV_SYSTEM_Y8950: + case DIV_SYSTEM_Y8950_DRUMS: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&255)==0)) { + copyOfFlags=(flags&(~255))|0; + } + if (ImGui::RadioButton("3.54MHz (PAL)",(flags&255)==1)) { + copyOfFlags=(flags&(~255))|1; + } + if (ImGui::RadioButton("4MHz",(flags&255)==2)) { + copyOfFlags=(flags&(~255))|2; + } + if (ImGui::RadioButton("3MHz",(flags&255)==3)) { + copyOfFlags=(flags&(~255))|3; + } + if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",(flags&255)==4)) { + copyOfFlags=(flags&(~255))|4; + } + if (ImGui::RadioButton("3.5MHz",(flags&255)==5)) { + copyOfFlags=(flags&(~255))|5; + } + break; + } + case DIV_SYSTEM_OPL3: + case DIV_SYSTEM_OPL3_DRUMS: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("14.32MHz (MTSC)",(flags&255)==0)) { + copyOfFlags=(flags&(~255))|0; + } + if (ImGui::RadioButton("14.19MHz (PAL)",(flags&255)==1)) { + copyOfFlags=(flags&(~255))|1; + } + if (ImGui::RadioButton("14MHz",(flags&255)==2)) { + copyOfFlags=(flags&(~255))|2; + } + if (ImGui::RadioButton("16MHz",(flags&255)==3)) { + copyOfFlags=(flags&(~255))|3; + } + if (ImGui::RadioButton("15MHz",(flags&255)==4)) { + copyOfFlags=(flags&(~255))|4; + } + break; + } + case DIV_SYSTEM_YMZ280B: { + ImGui::Text("Clock rate:"); + if (ImGui::RadioButton("16.9344MHz",(flags&255)==0)) { + copyOfFlags=(flags&(~255))|0; + } + if (ImGui::RadioButton("14.32MHz (MTSC)",(flags&255)==1)) { + copyOfFlags=(flags&(~255))|1; + } + if (ImGui::RadioButton("14.19MHz (PAL)",(flags&255)==3)) { + copyOfFlags=(flags&(~255))|2; + } + if (ImGui::RadioButton("16MHz",(flags&255)==3)) { + copyOfFlags=(flags&(~255))|3; + } + if (ImGui::RadioButton("16.67MHz",(flags&255)==4)) { + copyOfFlags=(flags&(~255))|4; + } + if (ImGui::RadioButton("14MHz",(flags&255)==5)) { + copyOfFlags=(flags&(~255))|5; } break; } @@ -462,17 +591,8 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_SWAN: case DIV_SYSTEM_VERA: case DIV_SYSTEM_BUBSYS_WSG: - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_YM2610_EXT: - case DIV_SYSTEM_YM2610_FULL: - case DIV_SYSTEM_YM2610_FULL_EXT: - case DIV_SYSTEM_YM2610B: - case DIV_SYSTEM_YM2610B_EXT: case DIV_SYSTEM_YMU759: case DIV_SYSTEM_PET: - case DIV_SYSTEM_SCC: - case DIV_SYSTEM_SCC_PLUS: - case DIV_SYSTEM_YMZ280B: ImGui::Text("nothing to configure"); break; default: diff --git a/src/main.cpp b/src/main.cpp index 079058528..63cc5efbf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -152,6 +152,7 @@ TAParamResult pVersion(String) { printf("- puNES by FHorse (GPLv2)\n"); printf("- reSID by Dag Lem (GPLv2)\n"); printf("- Stella by Stella Team (GPLv2)\n"); + printf("- vgsound_emu by cam900 (BSD 3-clause)\n"); return TA_PARAM_QUIT; }