From e0e6a45000baa89f7bbe08a2d03883a29bc7c0cf Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 19:04:52 +0900 Subject: [PATCH 01/16] 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 3df4f8e3..935b43ea 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 c00b3d72..97e039e3 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 56446725..f6fa7d70 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 6f68eeda..9d0e3968 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 a3d325ad..2f2b20c5 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 f93d34bd..8ff5f39c 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 0ab05344..ed5f63dd 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 a709aa1a..6e5426b5 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 d58d339e..a3b0e634 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 6cba30dd..a832bab4 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 b4862427..71493fa5 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 cc4abc88..76837f64 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 ea0482f3..3a05bcf8 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 541dded6..0d88d35d 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 2930a169..463384f1 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 c8d72829..a40f4114 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 61ea4648..9d2d1774 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 2ab6f1aa..1b70d956 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 df6ef84e..d83e0293 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 c5cf1091..c83108a6 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 3c97a9a5..56f6beda 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 351c94d8..5062ea7a 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 4c24e938..7a8a5c62 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 569f722b..d530d9ee 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 60ea66ae..93f220f1 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 3303fbf8..de54d8a6 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 ab527eea..c072647c 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 95937207..350a5870 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 5aec7916..00000000 --- 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 b6f1e16f..9756a44a 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 5c673629..ffa7a160 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 441640b4..38d2b4b2 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 89ccc6c0..d8d8e857 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 92f4ca07..37c0fa83 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 0e466f6f..90ddeb40 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 3a034028..1262ba02 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 cd7e494b..b4c154fa 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 bf6df44e..0ac118a1 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 8d8847c2..00000000 --- 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 1c4997c2..87497238 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 4957d899..97c64d21 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 10c00d27..a5b68c26 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 7d7fa050..94dbd5b4 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 994902e8..a841f15b 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 91d542bd..8878ca8f 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 07905852..63cc5efb 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; } From d1aeabe464daacc1cc55bc473659be18b1cd072a Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 19:26:34 +0900 Subject: [PATCH 02/16] Fix compile --- src/engine/platform/fmshared_OPM.h | 22 +++++++++++----------- src/engine/platform/fmshared_OPN.h | 24 ++++++++++++------------ src/engine/platform/genesis.cpp | 4 ---- src/engine/platform/genesis.h | 4 ++++ 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index ed5f63dd..c21d1c18 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -22,21 +22,21 @@ #include "fmsharedbase.h" -#define ADDR_MULT_DT 0x40 -#define ADDR_TL 0x60 -#define ADDR_RS_AR 0x80 -#define ADDR_AM_DR 0xa0 -#define ADDR_DT2_D2R 0xc0 -#define ADDR_SL_RR 0xe0 -#define ADDR_NOTE 0x28 -#define ADDR_KF 0x30 -#define ADDR_FMS_AMS 0x38 -#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 char ADDR_MULT_DT=0x40; + const unsigned char ADDR_TL=0x60; + const unsigned char ADDR_RS_AR=0x80; + const unsigned char ADDR_AM_DR=0xa0; + const unsigned char ADDR_DT2_D2R=0xc0; + const unsigned char ADDR_SL_RR=0xe0; + const unsigned char ADDR_NOTE=0x28; + const unsigned char ADDR_KF=0x30; + const unsigned char ADDR_FMS_AMS=0x38; + const unsigned char ADDR_LR_FB_ALG=0x20; + const unsigned short opOffs[4]={ 0x00, 0x08, 0x10, 0x18 }; diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index 6e5426b5..ae40748b 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -22,18 +22,6 @@ #include "fmsharedbase.h" -#define ADDR_MULT_DT 0x30 -#define ADDR_TL 0x40 -#define ADDR_RS_AR 0x50 -#define ADDR_AM_DR 0x60 -#define ADDR_DT2_D2R 0x70 -#define ADDR_SL_RR 0x80 -#define ADDR_SSG 0x90 -#define ADDR_FREQ 0xa0 -#define ADDR_FREQH 0xa4 -#define ADDR_FB_ALG 0xb0 -#define ADDR_LRAF 0xb4 - #define CHIP_FREQBASE fmFreqBase #define CHIP_DIVIDER fmDivBase @@ -100,6 +88,18 @@ class DivPlatformOPNBase: public DivPlatformFMBase { protected: + const unsigned char ADDR_MULT_DT=0x30; + const unsigned char ADDR_TL=0x40; + const unsigned char ADDR_RS_AR=0x50; + const unsigned char ADDR_AM_DR=0x60; + const unsigned char ADDR_DT2_D2R=0x70; + const unsigned char ADDR_SL_RR=0x80; + const unsigned char ADDR_SSG=0x90; + const unsigned char ADDR_FREQ=0xa0; + const unsigned char ADDR_FREQH=0xa4; + const unsigned char ADDR_FB_ALG=0xb0; + const unsigned char ADDR_LRAF=0xb4; + const unsigned short opOffs[4]={ 0x00, 0x04, 0x08, 0x0c }; diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 512f55f8..b9a5c686 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -22,10 +22,6 @@ #include #include -static unsigned char konOffs[6]={ - 0, 1, 2, 4, 5, 6 -}; - #define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6]))) const char* DivPlatformGenesis::getEffectName(unsigned char effect) { diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 70b3dc8a..e4bdfffa 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -36,6 +36,10 @@ class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 }; + const unsigned char konOffs[6]={ + 0, 1, 2, 4, 5, 6 + }; + struct Channel { DivInstrumentFM state; DivMacroInt std; From ebbd9784e689af27feea032ef1ca55d1f5c105a4 Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 19:40:37 +0900 Subject: [PATCH 03/16] Reduce more FM codes --- src/engine/platform/arcade.h | 10 ++-------- src/engine/platform/fmsharedbase.h | 7 ++++++- src/engine/platform/genesis.h | 10 ++-------- src/engine/platform/tx81z.h | 10 ++-------- src/engine/platform/ym2203.h | 10 ++-------- src/engine/platform/ym2608.h | 10 ++-------- src/engine/platform/ym2610.h | 10 ++-------- src/engine/platform/ym2610b.h | 7 +------ 8 files changed, 19 insertions(+), 55 deletions(-) diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index 189ce1e9..00af8f25 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -19,19 +19,18 @@ #ifndef _ARCADE_H #define _ARCADE_H -#include "../dispatch.h" +#include "fmshared_OPM.h" #include "../macroInt.h" #include "../instrument.h" #include #include "../../../extern/opm/opm.h" #include "sound/ymfm/ymfm_opm.h" -#include "fmshared_OPM.h" class DivArcadeInterface: public ymfm::ymfm_interface { }; -class DivPlatformArcade: public DivDispatch, public DivPlatformOPMBase { +class DivPlatformArcade: public DivPlatformOPMBase { protected: const unsigned short chanOffs[8]={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 @@ -85,14 +84,9 @@ class DivPlatformArcade: public DivDispatch, public DivPlatformOPMBase { ymfm::ym2151::output_data out_ymfm; DivArcadeInterface iface; - unsigned char regPool[256]; - bool extMode, useYMFM; bool isMuted[8]; - - short oldWrites[256]; - short pendingWrites[256]; int octave(int freq); int toFreq(int freq); diff --git a/src/engine/platform/fmsharedbase.h b/src/engine/platform/fmsharedbase.h index a3b0e634..355b05c2 100644 --- a/src/engine/platform/fmsharedbase.h +++ b/src/engine/platform/fmsharedbase.h @@ -20,6 +20,7 @@ #ifndef _FMSHARED_BASE_H #define _FMSHARED_BASE_H +#include "../dispatch.h" #include #define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} @@ -37,7 +38,7 @@ } \ } -class DivPlatformFMBase { +class DivPlatformFMBase: public DivDispatch { protected: const bool isOutput[8][4]={ // 1 3 2 4 @@ -69,6 +70,10 @@ class DivPlatformFMBase { unsigned char lastBusy; int delay; + unsigned char regPool[512]; + short oldWrites[512]; + short pendingWrites[512]; + DivPlatformFMBase(): lastBusy(0), delay(0) {} diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index e4bdfffa..ace427f6 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -19,18 +19,17 @@ #ifndef _GENESIS_H #define _GENESIS_H -#include "../dispatch.h" +#include "fmshared_OPN.h" #include "../macroInt.h" #include "../../../extern/Nuked-OPN2/ym3438.h" #include "sound/ymfm/ymfm_opn.h" -#include "fmshared_OPN.h" class DivYM2612Interface: public ymfm::ymfm_interface { }; -class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { +class DivPlatformGenesis: public DivPlatformOPNBase { protected: const unsigned short chanOffs[6]={ 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 @@ -112,7 +111,6 @@ class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { ymfm::ym2612* fm_ymfm; ymfm::ym2612::output_data out_ymfm; DivYM2612Interface iface; - unsigned char regPool[512]; unsigned char lfoValue; @@ -121,9 +119,6 @@ class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { bool extMode, softPCM, useYMFM; bool ladder; - short oldWrites[512]; - short pendingWrites[512]; - unsigned char dacVolTable[128]; friend void putDispatchChan(void*,int,int); @@ -160,7 +155,6 @@ class DivPlatformGenesis: public DivDispatch, public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformGenesis(): - DivDispatch(), DivPlatformOPNBase(9440540.0, 72, 32) {} ~DivPlatformGenesis(); }; diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index b185de5f..16167ede 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -19,18 +19,17 @@ #ifndef _TX81Z_H #define _TX81Z_H -#include "../dispatch.h" +#include "fmshared_OPM.h" #include "../macroInt.h" #include "../instrument.h" #include #include "sound/ymfm/ymfm_opz.h" -#include "fmshared_OPM.h" class DivTXInterface: public ymfm::ymfm_interface { }; -class DivPlatformTX81Z: public DivDispatch, public DivPlatformOPMBase { +class DivPlatformTX81Z: public DivPlatformOPMBase { protected: const unsigned short chanOffs[8]={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 @@ -82,15 +81,10 @@ class DivPlatformTX81Z: public DivDispatch, public DivPlatformOPMBase { ymfm::ym2414::output_data out_ymfm; DivTXInterface iface; - unsigned char regPool[330]; - bool extMode; bool isMuted[8]; - short oldWrites[330]; - short pendingWrites[330]; - int octave(int freq); int toFreq(int freq); diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index 70be354d..c650583d 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -19,18 +19,17 @@ #ifndef _YM2203_H #define _YM2203_H -#include "../dispatch.h" +#include "fmshared_OPN.h" #include "../macroInt.h" #include "sound/ymfm/ymfm_opn.h" #include "ay.h" -#include "fmshared_OPN.h" class DivYM2203Interface: public ymfm::ymfm_interface { }; -class DivPlatformYM2203: public DivDispatch, public DivPlatformOPNBase { +class DivPlatformYM2203: public DivPlatformOPNBase { protected: const unsigned short chanOffs[3]={ 0x00, 0x01, 0x02 @@ -86,16 +85,12 @@ class DivPlatformYM2203: public DivDispatch, public DivPlatformOPNBase { ymfm::ym2203* fm; ymfm::ym2203::output_data fmout; DivYM2203Interface iface; - unsigned char regPool[256]; DivPlatformAY8910* ay; unsigned char sampleBank; bool extMode; - short oldWrites[256]; - short pendingWrites[256]; - friend void putDispatchChan(void*,int,int); public: @@ -123,7 +118,6 @@ class DivPlatformYM2203: public DivDispatch, public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2203(): - DivDispatch(), DivPlatformOPNBase(4720270.0, 36, 16) {} ~DivPlatformYM2203(); }; diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index a6d4399a..21eb487f 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -19,12 +19,11 @@ #ifndef _YM2608_H #define _YM2608_H -#include "../dispatch.h" +#include "fmshared_OPN.h" #include "../macroInt.h" #include "sound/ymfm/ymfm_opn.h" #include "ay.h" -#include "fmshared_OPN.h" class DivYM2608Interface: public ymfm::ymfm_interface { public: @@ -35,7 +34,7 @@ class DivYM2608Interface: public ymfm::ymfm_interface { DivYM2608Interface(): adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2608: public DivDispatch, public DivPlatformOPNBase { +class DivPlatformYM2608: public DivPlatformOPNBase { protected: const unsigned short chanOffs[6]={ 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 @@ -92,7 +91,6 @@ class DivPlatformYM2608: public DivDispatch, public DivPlatformOPNBase { bool isMuted[16]; ymfm::ym2608* fm; ymfm::ym2608::output_data fmout; - unsigned char regPool[512]; unsigned char* adpcmBMem; size_t adpcmBMemLen; @@ -106,9 +104,6 @@ class DivPlatformYM2608: public DivDispatch, public DivPlatformOPNBase { double fmFreqBase; unsigned char ayDiv; - short oldWrites[512]; - short pendingWrites[512]; - double NOTE_OPNB(int ch, int note); double NOTE_ADPCMB(int note); friend void putDispatchChan(void*,int,int); @@ -142,7 +137,6 @@ class DivPlatformYM2608: public DivDispatch, public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2608(): - DivDispatch(), DivPlatformOPNBase(9440540.0, 72, 32) {} ~DivPlatformYM2608(); }; diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 39bc82f3..069707dd 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -19,10 +19,9 @@ #ifndef _YM2610_H #define _YM2610_H -#include "../dispatch.h" +#include "fmshared_OPN.h" #include "../macroInt.h" #include "ay.h" -#include "fmshared_OPN.h" #include "sound/ymfm/ymfm_opn.h" class DivYM2610Interface: public ymfm::ymfm_interface { @@ -35,7 +34,7 @@ class DivYM2610Interface: public ymfm::ymfm_interface { DivYM2610Interface(): adpcmAMem(NULL), adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2610Base: public DivDispatch, public DivPlatformOPNBase { +class DivPlatformYM2610Base: public DivPlatformOPNBase { protected: unsigned char* adpcmAMem; size_t adpcmAMemLen; @@ -51,7 +50,6 @@ class DivPlatformYM2610Base: public DivDispatch, public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2610Base(): - DivDispatch(), DivPlatformOPNBase(9440540.0, 72, 32) {} }; @@ -118,15 +116,11 @@ class DivPlatformYM2610: public DivPlatformYM2610Base { ymfm::ym2610::output_data fmout; DivPlatformAY8910* ay; - unsigned char regPool[512]; unsigned char sampleBank; bool extMode; - short oldWrites[512]; - short pendingWrites[512]; - double NOTE_OPNB(int ch, int note); double NOTE_ADPCMB(int note); friend void putDispatchChan(void*,int,int); diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 737251e4..0d1dca2b 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -19,12 +19,11 @@ #ifndef _YM2610B_H #define _YM2610B_H -#include "../dispatch.h" +#include "ym2610.h" #include "../macroInt.h" #include #include "sound/ymfm/ymfm_opn.h" -#include "ym2610.h" class DivPlatformYM2610B: public DivPlatformYM2610Base { protected: @@ -83,7 +82,6 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { bool isMuted[16]; ymfm::ym2610b* fm; ymfm::ym2610b::output_data fmout; - unsigned char regPool[512]; DivPlatformAY8910* ay; unsigned char sampleBank; @@ -91,9 +89,6 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base { bool extMode; double fmFreqBase=9440540; unsigned char ayDiv=32; - - short oldWrites[512]; - short pendingWrites[512]; double NOTE_OPNB(int ch, int note); double NOTE_ADPCMB(int note); From 5473b8722dca28cc3e9a65cf4b6fa3cca7e61ab9 Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 19:52:13 +0900 Subject: [PATCH 04/16] Fix compile, Remove unused include --- src/engine/platform/fmsharedbase.h | 31 +++++++++++++++--------------- src/engine/platform/ym2610b.h | 1 - 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/engine/platform/fmsharedbase.h b/src/engine/platform/fmsharedbase.h index 355b05c2..2555d267 100644 --- a/src/engine/platform/fmsharedbase.h +++ b/src/engine/platform/fmsharedbase.h @@ -23,21 +23,6 @@ #include "../dispatch.h" #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);} } -#define urgentWrite(a,v) if (!skipRegisterWrites) { \ - if (writes.empty()) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else if (writes.size()>16 || writes.front().addrOrVal) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else { \ - writes.push_front(QueuedWrite(a,v)); \ - } \ - if (dumpWrites) { \ - addWrite(a,v); \ - } \ -} - class DivPlatformFMBase: public DivDispatch { protected: const bool isOutput[8][4]={ @@ -75,8 +60,24 @@ class DivPlatformFMBase: public DivDispatch { short pendingWrites[512]; DivPlatformFMBase(): + DivDispatch(), lastBusy(0), delay(0) {} }; +#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);} } +#define urgentWrite(a,v) if (!skipRegisterWrites) { \ + if (writes.empty()) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else if (writes.size()>16 || writes.front().addrOrVal) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else { \ + writes.push_front(QueuedWrite(a,v)); \ + } \ + if (dumpWrites) { \ + addWrite(a,v); \ + } \ +} + #endif diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 0d1dca2b..fefb0692 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -21,7 +21,6 @@ #define _YM2610B_H #include "ym2610.h" #include "../macroInt.h" -#include #include "sound/ymfm/ymfm_opn.h" From 8bc545c8abc46e4061e2db47cc8de367dec3e93c Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 22:45:16 +0900 Subject: [PATCH 05/16] Fix compile (again) --- src/engine/platform/fmshared_OPM.h | 15 +++++++++++++++ src/engine/platform/fmshared_OPN.h | 15 +++++++++++++++ src/engine/platform/fmsharedbase.h | 15 --------------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index c21d1c18..585a42d9 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -22,6 +22,21 @@ #include "fmsharedbase.h" +#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);} } +#define urgentWrite(a,v) if (!skipRegisterWrites) { \ + if (writes.empty()) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else if (writes.size()>16 || writes.front().addrOrVal) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else { \ + writes.push_front(QueuedWrite(a,v)); \ + } \ + if (dumpWrites) { \ + addWrite(a,v); \ + } \ +} + #define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) class DivPlatformOPMBase: public DivPlatformFMBase { diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index ae40748b..b3cd7c3a 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -22,6 +22,21 @@ #include "fmsharedbase.h" +#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);} } +#define urgentWrite(a,v) if (!skipRegisterWrites) { \ + if (writes.empty()) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else if (writes.size()>16 || writes.front().addrOrVal) { \ + writes.push_back(QueuedWrite(a,v)); \ + } else { \ + writes.push_front(QueuedWrite(a,v)); \ + } \ + if (dumpWrites) { \ + addWrite(a,v); \ + } \ +} + #define CHIP_FREQBASE fmFreqBase #define CHIP_DIVIDER fmDivBase diff --git a/src/engine/platform/fmsharedbase.h b/src/engine/platform/fmsharedbase.h index 2555d267..f1312614 100644 --- a/src/engine/platform/fmsharedbase.h +++ b/src/engine/platform/fmsharedbase.h @@ -65,19 +65,4 @@ class DivPlatformFMBase: public DivDispatch { delay(0) {} }; -#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);} } -#define urgentWrite(a,v) if (!skipRegisterWrites) { \ - if (writes.empty()) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else if (writes.size()>16 || writes.front().addrOrVal) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else { \ - writes.push_front(QueuedWrite(a,v)); \ - } \ - if (dumpWrites) { \ - addWrite(a,v); \ - } \ -} - #endif From 74e3892fd997e40148c64ce2e81c5a3f3ba9feb1 Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 23:26:22 +0900 Subject: [PATCH 06/16] Finally fixed --- src/engine/platform/fmshared_OPM.h | 15 --------------- src/engine/platform/fmshared_OPN.h | 15 --------------- src/engine/platform/fmsharedbase.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index 585a42d9..c21d1c18 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -22,21 +22,6 @@ #include "fmsharedbase.h" -#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);} } -#define urgentWrite(a,v) if (!skipRegisterWrites) { \ - if (writes.empty()) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else if (writes.size()>16 || writes.front().addrOrVal) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else { \ - writes.push_front(QueuedWrite(a,v)); \ - } \ - if (dumpWrites) { \ - addWrite(a,v); \ - } \ -} - #define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) class DivPlatformOPMBase: public DivPlatformFMBase { diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index b3cd7c3a..ae40748b 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -22,21 +22,6 @@ #include "fmsharedbase.h" -#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);} } -#define urgentWrite(a,v) if (!skipRegisterWrites) { \ - if (writes.empty()) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else if (writes.size()>16 || writes.front().addrOrVal) { \ - writes.push_back(QueuedWrite(a,v)); \ - } else { \ - writes.push_front(QueuedWrite(a,v)); \ - } \ - if (dumpWrites) { \ - addWrite(a,v); \ - } \ -} - #define CHIP_FREQBASE fmFreqBase #define CHIP_DIVIDER fmDivBase diff --git a/src/engine/platform/fmsharedbase.h b/src/engine/platform/fmsharedbase.h index f1312614..64099739 100644 --- a/src/engine/platform/fmsharedbase.h +++ b/src/engine/platform/fmsharedbase.h @@ -59,6 +59,34 @@ class DivPlatformFMBase: public DivDispatch { short oldWrites[512]; short pendingWrites[512]; + inline void rWrite(unsigned short a, short v) { + if (!skipRegisterWrites) { + pendingWrites[a]=v; + } + } + inline void immWrite(unsigned short a, unsigned char v) { + if (!skipRegisterWrites) { + writes.push_back(QueuedWrite(a,v)); + if (dumpWrites) { + addWrite(a,v); + } + } + } + inline void urgentWrite(unsigned short a, unsigned char v) { + if (!skipRegisterWrites) { + if (writes.empty()) { + writes.push_back(QueuedWrite(a,v)); + } else if (writes.size()>16 || writes.front().addrOrVal) { + writes.push_back(QueuedWrite(a,v)); + } else { + writes.push_front(QueuedWrite(a,v)); + } + if (dumpWrites) { + addWrite(a,v); + } + } + } + DivPlatformFMBase(): DivDispatch(), lastBusy(0), From 44cee98868c46bdeba73e4288f800ba8920964a2 Mon Sep 17 00:00:00 2001 From: cam900 Date: Mon, 6 Jun 2022 23:46:33 +0900 Subject: [PATCH 07/16] Oops --- src/gui/sysConf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index fcd01e0d..e758b179 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -123,7 +123,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool } 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; } From d3a3473f19877f3c305c4c69adab6234dfd5dd4a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 6 Jun 2022 13:32:57 -0500 Subject: [PATCH 08/16] commit requested changes --- src/engine/platform/fmshared_OPN.h | 4 ++-- src/engine/platform/genesis.h | 4 ++-- src/engine/platform/ym2203.h | 4 ++-- src/engine/platform/ym2608.h | 4 ++-- src/engine/platform/ym2610.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index ae40748b..7632e78f 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -86,7 +86,7 @@ return 2; \ } -class DivPlatformOPNBase: public DivPlatformFMBase { +class DivPlatformOPN: public DivPlatformFMBase { protected: const unsigned char ADDR_MULT_DT=0x30; const unsigned char ADDR_TL=0x40; @@ -108,7 +108,7 @@ class DivPlatformOPNBase: public DivPlatformFMBase { const double fmDivBase; const unsigned char ayDiv; - DivPlatformOPNBase(double f=9440540.0, double d=72, unsigned char a=32): + DivPlatformOPN(double f=9440540.0, double d=72, unsigned char a=32): DivPlatformFMBase(), fmFreqBase(f), fmDivBase(d), diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index ace427f6..7d2004f3 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -29,7 +29,7 @@ class DivYM2612Interface: public ymfm::ymfm_interface { }; -class DivPlatformGenesis: public DivPlatformOPNBase { +class DivPlatformGenesis: public DivPlatformOPN { protected: const unsigned short chanOffs[6]={ 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 @@ -155,7 +155,7 @@ class DivPlatformGenesis: public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformGenesis(): - DivPlatformOPNBase(9440540.0, 72, 32) {} + DivPlatformOPN(9440540.0, 72, 32) {} ~DivPlatformGenesis(); }; #endif diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index c650583d..6d7bc420 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -29,7 +29,7 @@ class DivYM2203Interface: public ymfm::ymfm_interface { }; -class DivPlatformYM2203: public DivPlatformOPNBase { +class DivPlatformYM2203: public DivPlatformOPN { protected: const unsigned short chanOffs[3]={ 0x00, 0x01, 0x02 @@ -118,7 +118,7 @@ class DivPlatformYM2203: public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2203(): - DivPlatformOPNBase(4720270.0, 36, 16) {} + DivPlatformOPN(4720270.0, 36, 16) {} ~DivPlatformYM2203(); }; #endif diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index 21eb487f..c1f43f4d 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -34,7 +34,7 @@ class DivYM2608Interface: public ymfm::ymfm_interface { DivYM2608Interface(): adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2608: public DivPlatformOPNBase { +class DivPlatformYM2608: public DivPlatformOPN { protected: const unsigned short chanOffs[6]={ 0x00, 0x01, 0x02, 0x100, 0x101, 0x102 @@ -137,7 +137,7 @@ class DivPlatformYM2608: public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2608(): - DivPlatformOPNBase(9440540.0, 72, 32) {} + DivPlatformOPN(9440540.0, 72, 32) {} ~DivPlatformYM2608(); }; #endif diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 069707dd..dde7ed10 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -34,7 +34,7 @@ class DivYM2610Interface: public ymfm::ymfm_interface { DivYM2610Interface(): adpcmAMem(NULL), adpcmBMem(NULL), sampleBank(0) {} }; -class DivPlatformYM2610Base: public DivPlatformOPNBase { +class DivPlatformYM2610Base: public DivPlatformOPN { protected: unsigned char* adpcmAMem; size_t adpcmAMemLen; @@ -50,7 +50,7 @@ class DivPlatformYM2610Base: public DivPlatformOPNBase { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2610Base(): - DivPlatformOPNBase(9440540.0, 72, 32) {} + DivPlatformOPN(9440540.0, 72, 32) {} }; class DivPlatformYM2610: public DivPlatformYM2610Base { From 3e953f57b368f679c570ed1f95b9054c2dc97517 Mon Sep 17 00:00:00 2001 From: cam900 Date: Tue, 7 Jun 2022 12:57:09 +0900 Subject: [PATCH 09/16] Prepare for TI-99/4A support only works on MAME core only for now. --- src/engine/platform/arcade.h | 2 +- src/engine/platform/fmshared_OPM.h | 4 ++-- src/engine/platform/opl.cpp | 2 +- src/engine/platform/sms.cpp | 20 +++++++++++++++++++- src/engine/platform/sms.h | 1 + src/engine/platform/sound/sn76496.cpp | 16 ++++++++-------- src/engine/platform/tx81z.h | 2 +- src/engine/platform/ym2203.cpp | 2 +- src/engine/platform/ym2608.cpp | 2 +- src/engine/song.h | 3 +++ src/gui/presets.cpp | 6 ++++++ src/gui/sysConf.cpp | 9 +++++++++ 12 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index 00af8f25..daa88362 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -30,7 +30,7 @@ class DivArcadeInterface: public ymfm::ymfm_interface { }; -class DivPlatformArcade: public DivPlatformOPMBase { +class DivPlatformArcade: public DivPlatformOPM { protected: const unsigned short chanOffs[8]={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index c21d1c18..97844656 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -24,7 +24,7 @@ #define NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0) -class DivPlatformOPMBase: public DivPlatformFMBase { +class DivPlatformOPM: public DivPlatformFMBase { protected: const unsigned char ADDR_MULT_DT=0x40; const unsigned char ADDR_TL=0x60; @@ -41,7 +41,7 @@ class DivPlatformOPMBase: public DivPlatformFMBase { 0x00, 0x08, 0x10, 0x18 }; - DivPlatformOPMBase(): + DivPlatformOPM(): DivPlatformFMBase() {} }; diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 43ce2f5f..45cbd619 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -1723,7 +1723,7 @@ void DivPlatformOPL::setFlags(unsigned int flags) { chipClock=3000000.0; break; case 0x04: - chipClock=31948800/8; + chipClock=38400*13*8; // 31948800/8 break; case 0x05: chipClock=3500000.0; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index f6624b97..e5be2304 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -472,8 +472,12 @@ void DivPlatformSMS::setFlags(unsigned int flags) { case 0x0101: chipClock=2000000; break; + case 0x0102: + chipClock=COLOR_NTSC/8.0; + break; } resetPhase=!(flags&16); + divider=16; noiseDivider=64; if (sn!=NULL) delete sn; switch (flags&0xcc) { @@ -524,8 +528,22 @@ void DivPlatformSMS::setFlags(unsigned int flags) { noiseDivider=64; stereo=false; break; + case 0x80: // TI SN94624 + sn=new sn94624_device(); + isRealSN=true; + noiseDivider=60; + stereo=false; + divider=2; + break; + case 0x84: // TI SN76494 + sn=new sn76494_device(); + isRealSN=false; // TODO + noiseDivider=68; + stereo=false; + divider=2; + break; } - rate=nuked?chipClock/16:chipClock/2; + rate=chipClock/divider; for (int i=0; i<4; i++) { oscBuf[i]->rate=rate; } diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index c4e4179f..42399577 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -63,6 +63,7 @@ class DivPlatformSMS: public DivDispatch { size_t snBufLen; unsigned char oldValue; unsigned char snNoiseMode; + int divider=16; int noiseDivider=64; bool updateSNMode; bool resetPhase; diff --git a/src/engine/platform/sound/sn76496.cpp b/src/engine/platform/sound/sn76496.cpp index 5062ea7a..afb82ad3 100644 --- a/src/engine/platform/sound/sn76496.cpp +++ b/src/engine/platform/sound/sn76496.cpp @@ -171,22 +171,22 @@ sn76496_base_device::sn76496_base_device( } sn76496_device::sn76496_device() - : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true) { } y2404_device::y2404_device() - : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true) { } sn76489_device::sn76489_device() - : sn76496_base_device(0x4000, 0x01, 0x02, true, false, 8, false, true) + : sn76496_base_device(0x4000, 0x01, 0x02, true, false, 1/*8*/, false, true) { } sn76489a_device::sn76489a_device() - : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 8, false, true) + : sn76496_base_device(0x10000, 0x04, 0x08, false, false, 1/*8*/, false, true) { } @@ -201,22 +201,22 @@ sn94624_device::sn94624_device() } ncr8496_device::ncr8496_device() - : sn76496_base_device(0x8000, 0x02, 0x20, true, false, 8, true, true) + : sn76496_base_device(0x8000, 0x02, 0x20, true, false, 1/*8*/, true, true) { } pssj3_device::pssj3_device() - : sn76496_base_device(0x8000, 0x02, 0x20, false, false, 8, true, true) + : sn76496_base_device(0x8000, 0x02, 0x20, false, false, 1/*8*/, true, true) { } gamegear_device::gamegear_device() - : sn76496_base_device(0x8000, 0x01, 0x08, true, true, 8, false, false) + : sn76496_base_device(0x8000, 0x01, 0x08, true, true, 1/*8*/, false, false) { } segapsg_device::segapsg_device() - : sn76496_base_device(0x8000, 0x01, 0x08, true, false, 8, false, false) + : sn76496_base_device(0x8000, 0x01, 0x08, true, false, 1/*8*/, false, false) { } diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index 16167ede..e867416c 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -29,7 +29,7 @@ class DivTXInterface: public ymfm::ymfm_interface { }; -class DivPlatformTX81Z: public DivPlatformOPMBase { +class DivPlatformTX81Z: public DivPlatformOPM { protected: const unsigned short chanOffs[8]={ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 3176a1a4..42314615 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -1027,7 +1027,7 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { chipClock=3000000.0; break; case 0x04: - chipClock=31948800/8; + chipClock=38400*13*8; // 31948800/8 break; case 0x05: chipClock=3000000.0/2.0; diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index d4871486..875f4148 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1400,7 +1400,7 @@ void DivPlatformYM2608::setFlags(unsigned int flags) { chipClock=8000000.0; break; case 0x01: - chipClock=31948800/4; + chipClock=38400*13*16; // 31948800/4 break; } rate=fm->sample_rate(chipClock); diff --git a/src/engine/song.h b/src/engine/song.h index a5b68c26..6bbb00cf 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -244,6 +244,7 @@ struct DivSong { // - 0003: 1.79MHz (half NTSC) // - 0100: 3MHz // - 0101: 2MHz + // - 0102: 447KHz (NTSC / 8) // - bit 2-3, 6-7: chip type // - 00: Sega VDP (16-bit noise) // - 04: real SN76489 (15-bit noise) @@ -253,6 +254,8 @@ struct DivSong { // - 44: real SN76496 (17-bit noise) // - 48: NCR 8496 (16-bit noise) // - 4c: Tandy PSSJ-3 (16-bit noise) + // - 80: real SN94624 (15-bit noise) + // - 84: real SN76494 (17-bit noise) // - bit 4: disable noise phase reset // - YM2612/YM3438: // - bit 0-30: clock rate diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index a841f15b..d0e63c11 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -1211,6 +1211,12 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "TI-99/4A", { + DIV_SYSTEM_SMS, 64, 0, 0x182, // SN94624 447KHz + 0 + } + )); sysCategories.push_back(cat); cat=FurnaceGUISysCategory("Arcade systems","INSERT COIN"); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index e758b179..02d06db3 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -69,6 +69,9 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("2MHz (Sega System 1)",(flags&0xff03)==0x0101)) { copyOfFlags=(flags&(~0xff03))|0x0101; } + if (ImGui::RadioButton("447KHz (TI-99/4A)",(flags&0xff03)==0x0102)) { + copyOfFlags=(flags&(~0xff03))|0x0102; + } ImGui::Text("Chip type:"); if (ImGui::RadioButton("Sega VDP/Master System",(flags&0xcc)==0x00)) { copyOfFlags=(flags&(~0xcc))|0x00; @@ -94,6 +97,12 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("Tandy PSSJ 3-voice sound",(flags&0xcc)==0x4c)) { copyOfFlags=(flags&(~0xcc))|0x4c; } + if (ImGui::RadioButton("TI SN94624",(flags&0xcc)==0x80)) { + copyOfFlags=(flags&(~0xcc))|0x80; + } + if (ImGui::RadioButton("TI SN76494",(flags&0xcc)==0x84)) { + copyOfFlags=(flags&(~0xcc))|0x84; + } bool noPhaseReset=flags&16; if (ImGui::Checkbox("Disable noise period change phase reset",&noPhaseReset)) { copyOfFlags=(flags&(~16))|(noPhaseReset<<4); From 7bbfe3af7c8cab34ca65d9416e5dd0cedebc7d1e Mon Sep 17 00:00:00 2001 From: cam900 Date: Tue, 7 Jun 2022 23:59:50 +0900 Subject: [PATCH 10/16] Fix per-channel osc --- src/engine/platform/sms.cpp | 24 ++++++++++++++---------- src/engine/platform/sound/sn76496.cpp | 2 +- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index e5be2304..35bb9c40 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -101,7 +101,20 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t sn->write(w.val); writes.pop(); } - sn->sound_stream_update(snBuf,len); + for (size_t h=0; hsound_stream_update(outs,1); + for (int i=0; i<4; i++) { + if (isMuted[i]) { + oscBuf[i]->data[oscBuf[i]->needle++]=0; + } else { + oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i); + } + } + } if (stereo) { for (size_t i=0; idata[oscBuf[i]->needle++]=0; - } else { - oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i); - } - } - } } void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) { diff --git a/src/engine/platform/sound/sn76496.cpp b/src/engine/platform/sound/sn76496.cpp index afb82ad3..4bbb5848 100644 --- a/src/engine/platform/sound/sn76496.cpp +++ b/src/engine/platform/sound/sn76496.cpp @@ -411,7 +411,7 @@ void sn76496_base_device::sound_stream_update(short** outputs, int outLen) if (m_negate) { out = -out; out2 = -out2; } outputs[0][sampindex]=out; - if (m_stereo) + if (m_stereo && (outputs[1] != nullptr)) outputs[1][sampindex]=out; } } From 6aa88b07705e2b618b58045e7478e116d041329e Mon Sep 17 00:00:00 2001 From: cam900 Date: Wed, 8 Jun 2022 10:10:55 +0900 Subject: [PATCH 11/16] Move on .cpp, prepare for variable rate support --- src/engine/platform/fmshared_OPN.h | 9 +++------ src/engine/platform/genesis.cpp | 3 +++ src/engine/platform/genesisext.cpp | 3 +++ src/engine/platform/ym2203.cpp | 3 ++- src/engine/platform/ym2203ext.cpp | 3 +++ src/engine/platform/ym2608.cpp | 3 ++- src/engine/platform/ym2608ext.cpp | 3 +++ src/engine/platform/ym2610.cpp | 2 ++ src/engine/platform/ym2610b.cpp | 3 +++ src/engine/platform/ym2610bext.cpp | 3 +++ src/engine/platform/ym2610ext.cpp | 3 +++ 11 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index 7632e78f..74e13219 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -22,9 +22,6 @@ #include "fmsharedbase.h" -#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); \ @@ -104,9 +101,9 @@ class DivPlatformOPN: public DivPlatformFMBase { 0x00, 0x04, 0x08, 0x0c }; - const double fmFreqBase; - const double fmDivBase; - const unsigned char ayDiv; + double fmFreqBase; + double fmDivBase; + unsigned char ayDiv; DivPlatformOPN(double f=9440540.0, double d=72, unsigned char a=32): DivPlatformFMBase(), diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index b9a5c686..b3afdd2a 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -22,6 +22,9 @@ #include #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + #define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6]))) const char* DivPlatformGenesis::getEffectName(unsigned char effect) { diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 057049ea..cd4d603c 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -21,6 +21,9 @@ #include "../engine.h" #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + int DivPlatformGenesisExt::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformGenesis::dispatch(c); diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 42314615..a25c0e96 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -23,7 +23,8 @@ #include #include - +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase const char* regCheatSheetYM2203[]={ // SSG diff --git a/src/engine/platform/ym2203ext.cpp b/src/engine/platform/ym2203ext.cpp index fbef7b04..d3fd3487 100644 --- a/src/engine/platform/ym2203ext.cpp +++ b/src/engine/platform/ym2203ext.cpp @@ -21,6 +21,9 @@ #include "../engine.h" #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + int DivPlatformYM2203Ext::dispatch(DivCommand c) { if (c.chan<2) { return DivPlatformYM2203::dispatch(c); diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 875f4148..46b8b0ad 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -24,7 +24,8 @@ #include #include - +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase const char* regCheatSheetYM2608[]={ // SSG diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index d33bf9ed..91c3a897 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -21,6 +21,9 @@ #include "../engine.h" #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + 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 df340804..bed59c20 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -24,6 +24,8 @@ #include #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase const char* regCheatSheetYM2610[]={ // SSG diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 16f198f7..a2291c3f 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -23,6 +23,9 @@ #include #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + const char* regCheatSheetYM2610B[]={ // SSG "SSG_FreqL_A", "000", diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index 61a99789..b5e1ac9f 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -21,6 +21,9 @@ #include "../engine.h" #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + 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 f2006c1c..6f9c8700 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -21,6 +21,9 @@ #include "../engine.h" #include +#define CHIP_FREQBASE fmFreqBase +#define CHIP_DIVIDER fmDivBase + int DivPlatformYM2610Ext::dispatch(DivCommand c) { if (c.chan<1) { return DivPlatformYM2610::dispatch(c); From 25af023dc6c1ce63907766824a82871c6754748b Mon Sep 17 00:00:00 2001 From: cam900 Date: Fri, 17 Jun 2022 14:30:18 +0900 Subject: [PATCH 12/16] Various corrections and fixes Fix SN PSG pitch corrections Revive YM2612 from dead Add Game Gear stereo function finally Add OPN/A prescaler config --- src/engine/platform/ay.cpp | 7 +++ src/engine/platform/ay.h | 1 + src/engine/platform/fmshared_OPM.h | 20 ++++---- src/engine/platform/fmshared_OPN.h | 28 +++++------ src/engine/platform/genesis.h | 7 --- src/engine/platform/sms.cpp | 67 +++++++++------------------ src/engine/platform/sms.h | 3 +- src/engine/platform/sound/sn76496.cpp | 2 +- src/engine/platform/ym2203.cpp | 35 +++++++++++++- src/engine/platform/ym2203.h | 4 +- src/engine/platform/ym2608.cpp | 38 +++++++++++++-- src/engine/platform/ym2608.h | 6 +-- src/engine/song.h | 4 +- src/gui/presets.cpp | 16 ++++++- src/gui/sysConf.cpp | 8 +--- 15 files changed, 147 insertions(+), 99 deletions(-) diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 83de1fa1..52ac6e57 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -593,6 +593,13 @@ void DivPlatformAY8910::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) immWrite(i.addr,i.val); } +void DivPlatformAY8910::setExtClockDiv(unsigned int eclk, unsigned char ediv) { + if (extMode) { + extClock=eclk; + extDiv=ediv; + } +} + void DivPlatformAY8910::setFlags(unsigned int flags) { if (extMode) { chipClock=extClock; diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index a1f35d1b..f67a2ad9 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -91,6 +91,7 @@ class DivPlatformAY8910: public DivDispatch { friend void putDispatchChan(void*,int,int); public: + void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8); void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); diff --git a/src/engine/platform/fmshared_OPM.h b/src/engine/platform/fmshared_OPM.h index 97844656..9b838c19 100644 --- a/src/engine/platform/fmshared_OPM.h +++ b/src/engine/platform/fmshared_OPM.h @@ -26,16 +26,16 @@ class DivPlatformOPM: public DivPlatformFMBase { protected: - const unsigned char ADDR_MULT_DT=0x40; - const unsigned char ADDR_TL=0x60; - const unsigned char ADDR_RS_AR=0x80; - const unsigned char ADDR_AM_DR=0xa0; - const unsigned char ADDR_DT2_D2R=0xc0; - const unsigned char ADDR_SL_RR=0xe0; - const unsigned char ADDR_NOTE=0x28; - const unsigned char ADDR_KF=0x30; - const unsigned char ADDR_FMS_AMS=0x38; - const unsigned char ADDR_LR_FB_ALG=0x20; + const unsigned short ADDR_MULT_DT=0x40; + const unsigned short ADDR_TL=0x60; + const unsigned short ADDR_RS_AR=0x80; + const unsigned short ADDR_AM_DR=0xa0; + const unsigned short ADDR_DT2_D2R=0xc0; + const unsigned short ADDR_SL_RR=0xe0; + const unsigned short ADDR_NOTE=0x28; + const unsigned short ADDR_KF=0x30; + const unsigned short ADDR_FMS_AMS=0x38; + const unsigned short ADDR_LR_FB_ALG=0x20; const unsigned short opOffs[4]={ 0x00, 0x08, 0x10, 0x18 diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index 74e13219..0aaad16d 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -85,27 +85,27 @@ class DivPlatformOPN: public DivPlatformFMBase { protected: - const unsigned char ADDR_MULT_DT=0x30; - const unsigned char ADDR_TL=0x40; - const unsigned char ADDR_RS_AR=0x50; - const unsigned char ADDR_AM_DR=0x60; - const unsigned char ADDR_DT2_D2R=0x70; - const unsigned char ADDR_SL_RR=0x80; - const unsigned char ADDR_SSG=0x90; - const unsigned char ADDR_FREQ=0xa0; - const unsigned char ADDR_FREQH=0xa4; - const unsigned char ADDR_FB_ALG=0xb0; - const unsigned char ADDR_LRAF=0xb4; + const unsigned short ADDR_MULT_DT=0x30; + const unsigned short ADDR_TL=0x40; + const unsigned short ADDR_RS_AR=0x50; + const unsigned short ADDR_AM_DR=0x60; + const unsigned short ADDR_DT2_D2R=0x70; + const unsigned short ADDR_SL_RR=0x80; + const unsigned short ADDR_SSG=0x90; + const unsigned short ADDR_FREQ=0xa0; + const unsigned short ADDR_FREQH=0xa4; + const unsigned short ADDR_FB_ALG=0xb0; + const unsigned short ADDR_LRAF=0xb4; const unsigned short opOffs[4]={ 0x00, 0x04, 0x08, 0x0c }; double fmFreqBase; - double fmDivBase; - unsigned char ayDiv; + unsigned int fmDivBase; + unsigned int ayDiv; - DivPlatformOPN(double f=9440540.0, double d=72, unsigned char a=32): + DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32): DivPlatformFMBase(), fmFreqBase(f), fmDivBase(d), diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 7d2004f3..c46a992d 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -99,13 +99,6 @@ class DivPlatformGenesis: public DivPlatformOPN { Channel chan[10]; DivDispatchOscBuffer* oscBuf[10]; bool isMuted[10]; - struct QueuedWrite { - unsigned short addr; - unsigned char val; - bool addrOrVal; - QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {} - }; - std::deque writes; ym3438_t fm; ymfm::ym2612* fm_ymfm; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 35bb9c40..71e9b0bc 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -35,7 +35,7 @@ const char* regCheatSheetGG[]={ }; const char** DivPlatformSMS::getRegisterSheet() { - return isStereo()?regCheatSheetGG:regCheatSheetSN; + return stereo?regCheatSheetGG:regCheatSheetSN; } const char* DivPlatformSMS::getEffectName(unsigned char effect) { @@ -74,7 +74,7 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ o=YMPSG_GetOutput(&sn_nuked); if (o<-32768) o=-32768; if (o>32767) o=32767; - bufL[h]=o; + bufL[h]=bufR[h]=o; for (int i=0; i<4; i++) { if (isMuted[i]) { oscBuf[i]->data[oscBuf[i]->needle++]=0; @@ -86,13 +86,6 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ } void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t len) { - if (snBufLenwrite(w.val); writes.pop(); } - for (size_t h=0; hsound_stream_update(outs,1); for (int i=0; i<4; i++) { @@ -115,17 +108,6 @@ void DivPlatformSMS::acquire_mame(short* bufL, short* bufR, size_t start, size_t } } } - if (stereo) { - for (size_t i=0; i>1)&1)<>1)&1)<<(i+4)); rWrite(1,lastPan); } } @@ -204,7 +186,7 @@ void DivPlatformSMS::tick(bool sysTick) { } for (int i=0; i<3; i++) { if (chan[i].freqChanged) { - chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,64); + chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,toneDivider); if (chan[i].freq>1023) chan[i].freq=1023; if (chan[i].freq<8) chan[i].freq=1; //if (chan[i].actualNote>0x5d) chan[i].freq=0x01; @@ -263,7 +245,7 @@ void DivPlatformSMS::tick(bool sysTick) { } int DivPlatformSMS::dispatch(DivCommand c) { - int CHIP_DIVIDER=64; + int CHIP_DIVIDER=toneDivider; if (c.chan==3) CHIP_DIVIDER=noiseDivider; switch (c.cmd) { case DIV_CMD_NOTE_ON: @@ -340,11 +322,12 @@ int DivPlatformSMS::dispatch(DivCommand c) { updateSNMode=true; break; case DIV_CMD_PANNING: { - if (isStereo()) { + if (stereo) { + if (c.chan>3) c.chan=3; lastPan&=~(0x11<0) pan|=0x01; - if (c.value2>0) pan|=0x10; + if (c.value>0) pan|=0x10; + if (c.value2>0) pan|=0x01; if (pan==0) pan=0x11; lastPan|=pan<reset(); ay->getRegisterWrites().clear(); ay->flushWrites(); @@ -1013,7 +1017,8 @@ void DivPlatformYM2203::setSkipRegisterWrites(bool value) { } void DivPlatformYM2203::setFlags(unsigned int flags) { - switch (flags&0x3f) { + // Clock flags + switch (flags&0x1f) { default: case 0x00: chipClock=COLOR_NTSC; @@ -1034,10 +1039,36 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { chipClock=3000000.0/2.0; break; } + // Prescaler flags + switch ((flags>>5)&0x3) { + default: + case 0x00: // /6 + prescale=0x2d; + fmFreqBase=4720270.0, + fmDivBase=36, + ayDiv=16; + break; + case 0x01: // /3 + prescale=0x2e; + fmFreqBase=4720270.0/2.0, + fmDivBase=18, + ayDiv=8; + break; + case 0x02: // /2 + prescale=0x2f; + fmFreqBase=4720270.0/3.0, + fmDivBase=12, + ayDiv=4; + break; + } rate=fm->sample_rate(chipClock); for (int i=0; i<6; i++) { oscBuf[i]->rate=rate; } + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->setExtClockDiv(chipClock,ayDiv); + ay->setFlags(16); } int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -1050,11 +1081,11 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned in } fm=new ymfm::ym2203(iface); fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); - setFlags(flags); // YM2149, 2MHz ay=new DivPlatformAY8910(true,chipClock,ayDiv); ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); + setFlags(flags); reset(); return 6; diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index 6d7bc420..d406e2f2 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -90,6 +90,7 @@ class DivPlatformYM2203: public DivPlatformOPN { unsigned char sampleBank; bool extMode; + unsigned char prescale; friend void putDispatchChan(void*,int,int); @@ -118,7 +119,8 @@ class DivPlatformYM2203: public DivPlatformOPN { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2203(): - DivPlatformOPN(4720270.0, 36, 16) {} + DivPlatformOPN(4720270.0, 36, 16), + prescale(0x2d) {} ~DivPlatformYM2203(); }; #endif diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 46b8b0ad..733f0481 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1325,6 +1325,10 @@ void DivPlatformYM2608::reset() { // enable 6 channel mode immWrite(0x29,0x80); + // set prescaler + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->reset(); ay->getRegisterWrites().clear(); ay->flushWrites(); @@ -1395,7 +1399,8 @@ void DivPlatformYM2608::renderSamples() { } void DivPlatformYM2608::setFlags(unsigned int flags) { - switch (flags&0x3f) { + // Clock flags + switch (flags&0x1f) { default: case 0x00: chipClock=8000000.0; @@ -1404,10 +1409,36 @@ void DivPlatformYM2608::setFlags(unsigned int flags) { chipClock=38400*13*16; // 31948800/4 break; } + // Prescaler flags + switch ((flags>>5)&0x3) { + default: + case 0x00: // /6 + prescale=0x2d; + fmFreqBase=9440540.0, + fmDivBase=72, + ayDiv=32; + break; + case 0x01: // /3 + prescale=0x2e; + fmFreqBase=9440540.0/2.0, + fmDivBase=36, + ayDiv=16; + break; + case 0x02: // /2 + prescale=0x2f; + fmFreqBase=9440540.0/3.0, + fmDivBase=24, + ayDiv=8; + break; + } rate=fm->sample_rate(chipClock); for (int i=0; i<16; i++) { oscBuf[i]->rate=rate; } + immWrite(0x2d,0xff); + immWrite(prescale,0xff); + ay->setExtClockDiv(chipClock,ayDiv); + ay->setFlags(16); } int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -1423,11 +1454,12 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned in oscBuf[i]=new DivDispatchOscBuffer; } fm=new ymfm::ym2608(iface); - setFlags(flags); + fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); // YM2149, 2MHz - ay=new DivPlatformAY8910(true,chipClock,32); + ay=new DivPlatformAY8910(true,chipClock,ayDiv); ay->init(p,3,sugRate,16); ay->toggleRegisterDump(true); + setFlags(flags); reset(); return 16; } diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index c1f43f4d..ac38a8c0 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -101,8 +101,7 @@ class DivPlatformYM2608: public DivPlatformOPN { unsigned char writeRSSOff, writeRSSOn; bool extMode; - double fmFreqBase; - unsigned char ayDiv; + unsigned char prescale; double NOTE_OPNB(int ch, int note); double NOTE_ADPCMB(int note); @@ -137,7 +136,8 @@ class DivPlatformYM2608: public DivPlatformOPN { int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); DivPlatformYM2608(): - DivPlatformOPN(9440540.0, 72, 32) {} + DivPlatformOPN(9440540.0, 72, 32), + prescale(0x2d) {} ~DivPlatformYM2608(); }; #endif diff --git a/src/engine/song.h b/src/engine/song.h index 6bbb00cf..df622d86 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -357,7 +357,7 @@ struct DivSong { // - 3: 3MHz // - 4: 3.9936MHz (PC-88, PC-98) // - 5: 1.5MHz - // - bit 5-6: output rate (TODO) + // - bit 5-6: output rate // - 0: FM: clock / 72, SSG: clock / 16 // - 1: FM: clock / 36, SSG: clock / 8 // - 2: FM: clock / 24, SSG: clock / 4 @@ -365,7 +365,7 @@ struct DivSong { // - bit 0-4: clock rate // - 0: 8MHz // - 1: 7.987MHz (PC-88, PC-98) - // - bit 5-6: output rate (TODO) + // - bit 5-6: output rate // - 0: FM: clock / 144, SSG: clock / 32 // - 1: FM: clock / 72, SSG: clock / 16 // - 2: FM: clock / 48, SSG: clock / 8 diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index d0e63c11..5056de74 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -56,13 +56,13 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "Yamaha YM2608 (OPNA)", { - DIV_SYSTEM_PC98, 64, 0, 3, + DIV_SYSTEM_PC98, 64, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Yamaha YM2608 (extended channel 3)", { - DIV_SYSTEM_PC98_EXT, 64, 0, 3, + DIV_SYSTEM_PC98_EXT, 64, 0, 0, 0 } )); @@ -258,6 +258,18 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN94624", { + DIV_SYSTEM_SMS, 64, 0, 0x80, + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "TI SN76494", { + DIV_SYSTEM_SMS, 64, 0, 0x84, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "AY-3-8910", { DIV_SYSTEM_AY8910, 64, 0, 0, diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 02d06db3..21fef35d 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -397,8 +397,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("1.5MHz",(flags&31)==5)) { copyOfFlags=(flags&(~31))|5; } - /* - ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + ImGui::Text("Output rate:"); if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==0)) { copyOfFlags=(flags&(~96))|0; } @@ -408,7 +407,6 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("FM: clock / 24, SSG: clock / 4",(flags&96)==64)) { copyOfFlags=(flags&(~96))|64; } - */ break; } case DIV_SYSTEM_PC98: @@ -420,8 +418,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("7.987MHz (PC-88/PC-98)",(flags&31)==1)) { copyOfFlags=(flags&(~31))|1; } - /* - ImGui::Text("Output rate: (DOES NOT WORK YET!)"); + ImGui::Text("Output rate:"); if (ImGui::RadioButton("FM: clock / 144, SSG: clock / 32",(flags&96)==0)) { copyOfFlags=(flags&(~96))|0; } @@ -431,7 +428,6 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::RadioButton("FM: clock / 48, SSG: clock / 8",(flags&96)==64)) { copyOfFlags=(flags&(~96))|64; } - */ break; } case DIV_SYSTEM_RF5C68: { From 66f3f0e67810fff5a7abfccecd98828f5820f239 Mon Sep 17 00:00:00 2001 From: cam900 Date: Fri, 17 Jun 2022 14:34:00 +0900 Subject: [PATCH 13/16] Input clock is too high for these chips --- src/gui/presets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 5056de74..53ef7d42 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -260,13 +260,13 @@ void FurnaceGUI::initSystemPresets() { )); cat.systems.push_back(FurnaceGUISysDef( "TI SN94624", { - DIV_SYSTEM_SMS, 64, 0, 0x80, + DIV_SYSTEM_SMS, 64, 0, 0x182, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "TI SN76494", { - DIV_SYSTEM_SMS, 64, 0, 0x84, + DIV_SYSTEM_SMS, 64, 0, 0x186, 0 } )); From 6dc81c7af1f1f5d9c596c334e0d8e08e64f7f36f Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 18 Jun 2022 10:38:48 +0900 Subject: [PATCH 14/16] Pitch correction (again), Fix compatibility issue --- src/engine/platform/sms.cpp | 24 +++++++++++++++--------- src/engine/platform/sms.h | 4 ++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 71e9b0bc..3dc7afc4 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -120,7 +120,7 @@ void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) void DivPlatformSMS::tick(bool sysTick) { for (int i=0; i<4; i++) { - int CHIP_DIVIDER=toneDivider; + double CHIP_DIVIDER=toneDivider; if (i==3) CHIP_DIVIDER=noiseDivider; chan[i].std.next(); if (chan[i].std.vol.had) { @@ -245,7 +245,7 @@ void DivPlatformSMS::tick(bool sysTick) { } int DivPlatformSMS::dispatch(DivCommand c) { - int CHIP_DIVIDER=toneDivider; + double CHIP_DIVIDER=toneDivider; if (c.chan==3) CHIP_DIVIDER=noiseDivider; switch (c.cmd) { case DIV_CMD_NOTE_ON: @@ -465,8 +465,8 @@ void DivPlatformSMS::setFlags(unsigned int flags) { } resetPhase=!(flags&16); divider=16; - toneDivider=64; - noiseDivider=64; + toneDivider=64.0; + noiseDivider=64.0; if (sn!=NULL) delete sn; switch (flags&0xcc) { default: // Sega @@ -479,11 +479,13 @@ void DivPlatformSMS::setFlags(unsigned int flags) { sn=new sn76489_device(); isRealSN=true; stereo=false; + noiseDivider=60.0; // 64 for match to tone frequency on non-Sega PSG but compatibility break; case 0x08: // TI+Atari - sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, 8, false, true); + sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, 1/*8*/, false, true); isRealSN=true; stereo=false; + noiseDivider=60.0; break; case 0x0c: // Game Gear (not fully emulated yet!) sn=new gamegear_device(); @@ -494,37 +496,41 @@ void DivPlatformSMS::setFlags(unsigned int flags) { sn=new sn76489a_device(); isRealSN=false; // TODO stereo=false; + noiseDivider=60.0; break; case 0x44: // TI SN76496 sn=new sn76496_device(); isRealSN=false; // TODO stereo=false; + noiseDivider=60.0; break; case 0x48: // NCR 8496 sn=new ncr8496_device(); isRealSN=false; stereo=false; + noiseDivider=60.0; break; case 0x4c: // Tandy PSSJ 3-voice sound sn=new pssj3_device(); isRealSN=false; stereo=false; + noiseDivider=60.0; break; case 0x80: // TI SN94624 sn=new sn94624_device(); isRealSN=true; stereo=false; divider=2; - toneDivider=8; - noiseDivider=8; + toneDivider=8.0; + noiseDivider=7.5; break; case 0x84: // TI SN76494 sn=new sn76494_device(); isRealSN=false; // TODO stereo=false; divider=2; - toneDivider=8; - noiseDivider=8; + toneDivider=8.0; + noiseDivider=7.5; break; } rate=chipClock/divider; diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 589bb9b8..35bb44ba 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -62,8 +62,8 @@ class DivPlatformSMS: public DivDispatch { unsigned char oldValue; unsigned char snNoiseMode; int divider=16; - int toneDivider=64; - int noiseDivider=64; + double toneDivider=64.0; + double noiseDivider=64.0; bool updateSNMode; bool resetPhase; bool isRealSN; From 9cad9077738657572588a6815c2b1d69d165d7fb Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 18 Jun 2022 11:07:36 +0900 Subject: [PATCH 15/16] Fix potential register related issue --- src/engine/platform/sms.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 3dc7afc4..0556d2e4 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -52,7 +52,9 @@ void DivPlatformSMS::acquire_nuked(short* bufL, short* bufR, size_t start, size_ for (size_t h=start; hstereo_w(w.val); - else + else if (w.addr==0) { sn->write(w.val); + } writes.pop(); } for (size_t h=start; h Date: Sat, 18 Jun 2022 11:42:14 +0900 Subject: [PATCH 16/16] More presets Dynax/Nakanihon 3rd generation hardware: Naming reference is MAME source (https://github.com/mamedev/mame/blob/master/src/mame/drivers/ddenlovr.cpp), It's sound system combined with AY PSG(optional), OPLL, MSM6295 and mostly used in their mahjong, hanafuda, and something else. Dynax/Nakanihon Real Break: This sound system is used in Billard Academy Real Break (MAME source: https://github.com/mamedev/mame/blob/master/src/mame/drivers/realbrk.cpp), MSM6295 is replaced to YMZ280B but entire music is still drived in OPLL. --- src/gui/presets.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 53ef7d42..46335227 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -1859,7 +1859,7 @@ void FurnaceGUI::initSystemPresets() { DIV_SYSTEM_AY8910, 64, 0, 13, 0 } - )); + )); cat.systems.push_back(FurnaceGUISysDef( "Namco (3-channel WSG)", { // Pac-Man, Galaga, Xevious, etc DIV_SYSTEM_NAMCO, 64, 0, 0, @@ -1957,6 +1957,21 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Dynax/Nakanihon 3rd generation hardware", { + DIV_SYSTEM_AY8910, 64, 0, 0, // AY or YM, optional - 1.79MHz or 3.58MHz; various per game + DIV_SYSTEM_OPLL, 64, 0, 0, + DIV_SYSTEM_MSM6295, 64, 0, 6, // 1.023MHz mostly + 0 + } + )); + cat.systems.push_back(FurnaceGUISysDef( + "Dynax/Nakanihon Real Break", { + DIV_SYSTEM_OPLL, 64, 0, 0, + DIV_SYSTEM_YMZ280B, 64, 0, 0, + 0 + } + )); sysCategories.push_back(cat); cat=FurnaceGUISysCategory("DefleMask-compatible","these configurations are compatible with DefleMask.\nselect this if you need to save as .dmf or work with that program.");