diff --git a/papers/format.md b/papers/format.md index 083fd766..8d977e84 100644 --- a/papers/format.md +++ b/papers/format.md @@ -197,7 +197,7 @@ size | description | - 0xa6: Neo Geo extended (YM2610) - 17 channels | - 0xa7: OPLL drums (YM2413) - 11 channels | - 0xa8: Atari Lynx - 4 channels - | - 0xa9: SegaPCM (for Deflemask Compatibility) - 5 channels + | - 0xa9: SegaPCM (for DefleMask compatibility) - 5 channels | - 0xaa: MSM6295 - 4 channels | - 0xab: MSM6258 - 1 channel | - 0xac: Commander X16 (VERA) - 17 channels @@ -209,8 +209,12 @@ size | description | - 0xb2: Yamaha Y8950 - 10 channels | - 0xb3: Yamaha Y8950 drums - 12 channels | - 0xb4: Konami SCC+ - 5 channels + | - 0xb5: tildearrow Sound Unit - 8 channels | - 0xde: YM2610B extended - 19 channels | - 0xe0: QSound - 19 channels + | - 0xfd: Dummy System - 8 channels + | - 0xfe: reserved for development + | - 0xff: reserved for development | - (compound!) means that the system is composed of two or more chips, | and has to be flattened. 32 | sound chip volumes @@ -328,6 +332,10 @@ size | description | - 24: VERA | - 25: X1-010 | - 26: VRC6 (saw) + | - 27: ES5506 + | - 28: MultiPCM + | - 29: SNES + | - 30: Sound Unit 1 | reserved STR | instrument name --- | **FM instrument data** diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 88575f1c..a671e118 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -35,74 +35,77 @@ // names as strings for the commands (and other debug stuff). // // if you miss it, the program will crash or misbehave at some point. +// +// the comments are: (arg1, arg2) -> val +// not all commands have a return value enum DivDispatchCmds { - DIV_CMD_NOTE_ON=0, + DIV_CMD_NOTE_ON=0, // (note) DIV_CMD_NOTE_OFF, DIV_CMD_NOTE_OFF_ENV, DIV_CMD_ENV_RELEASE, - DIV_CMD_INSTRUMENT, - DIV_CMD_VOLUME, - DIV_CMD_GET_VOLUME, - DIV_CMD_GET_VOLMAX, - DIV_CMD_NOTE_PORTA, - DIV_CMD_PITCH, - DIV_CMD_PANNING, - DIV_CMD_LEGATO, - DIV_CMD_PRE_PORTA, - DIV_CMD_PRE_NOTE, // used in C64 + DIV_CMD_INSTRUMENT, // (ins, force) + DIV_CMD_VOLUME, // (vol) + DIV_CMD_GET_VOLUME, // () -> vol + DIV_CMD_GET_VOLMAX, // () -> volMax + DIV_CMD_NOTE_PORTA, // (target, speed) -> 2 if target reached + DIV_CMD_PITCH, // (pitch) + DIV_CMD_PANNING, // (pan) + DIV_CMD_LEGATO, // (note) + DIV_CMD_PRE_PORTA, // (inPorta, isPortaOrSlide) + DIV_CMD_PRE_NOTE, // used in C64 (note) - DIV_CMD_SAMPLE_MODE, - DIV_CMD_SAMPLE_FREQ, - DIV_CMD_SAMPLE_BANK, - DIV_CMD_SAMPLE_POS, + DIV_CMD_SAMPLE_MODE, // (enabled) + DIV_CMD_SAMPLE_FREQ, // (frequency) + DIV_CMD_SAMPLE_BANK, // (bank) + DIV_CMD_SAMPLE_POS, // (pos) - DIV_CMD_FM_HARD_RESET, - DIV_CMD_FM_LFO, - DIV_CMD_FM_LFO_WAVE, - DIV_CMD_FM_TL, - DIV_CMD_FM_AR, - DIV_CMD_FM_FB, - DIV_CMD_FM_MULT, - DIV_CMD_FM_EXTCH, - DIV_CMD_FM_AM_DEPTH, - DIV_CMD_FM_PM_DEPTH, + DIV_CMD_FM_HARD_RESET, // (enabled) + DIV_CMD_FM_LFO, // (speed) + DIV_CMD_FM_LFO_WAVE, // (waveform) + DIV_CMD_FM_TL, // (op, value) + DIV_CMD_FM_AR, // (op, value) + DIV_CMD_FM_FB, // (value) + DIV_CMD_FM_MULT, // (op, value) + DIV_CMD_FM_EXTCH, // (enabled) + DIV_CMD_FM_AM_DEPTH, // (depth) + DIV_CMD_FM_PM_DEPTH, // (depth) - DIV_CMD_GENESIS_LFO, + DIV_CMD_GENESIS_LFO, // unused? - DIV_CMD_ARCADE_LFO, + DIV_CMD_ARCADE_LFO, // unused? - DIV_CMD_STD_NOISE_FREQ, - DIV_CMD_STD_NOISE_MODE, + DIV_CMD_STD_NOISE_FREQ, // (freq) + DIV_CMD_STD_NOISE_MODE, // (mode) - DIV_CMD_WAVE, + DIV_CMD_WAVE, // (waveform) - DIV_CMD_GB_SWEEP_TIME, - DIV_CMD_GB_SWEEP_DIR, + DIV_CMD_GB_SWEEP_TIME, // (time) + DIV_CMD_GB_SWEEP_DIR, // (direction) - DIV_CMD_PCE_LFO_MODE, - DIV_CMD_PCE_LFO_SPEED, + DIV_CMD_PCE_LFO_MODE, // (mode) + DIV_CMD_PCE_LFO_SPEED, // (speed) - DIV_CMD_NES_SWEEP, + DIV_CMD_NES_SWEEP, // (direction, value) - DIV_CMD_C64_CUTOFF, - DIV_CMD_C64_RESONANCE, - DIV_CMD_C64_FILTER_MODE, - DIV_CMD_C64_RESET_TIME, - DIV_CMD_C64_RESET_MASK, - DIV_CMD_C64_FILTER_RESET, - DIV_CMD_C64_DUTY_RESET, - DIV_CMD_C64_EXTENDED, - DIV_CMD_C64_FINE_DUTY, - DIV_CMD_C64_FINE_CUTOFF, + DIV_CMD_C64_CUTOFF, // (value) + DIV_CMD_C64_RESONANCE, // (value) + DIV_CMD_C64_FILTER_MODE, // (value) + DIV_CMD_C64_RESET_TIME, // (value) + DIV_CMD_C64_RESET_MASK, // (mask) + DIV_CMD_C64_FILTER_RESET, // (value) + DIV_CMD_C64_DUTY_RESET, // (value) + DIV_CMD_C64_EXTENDED, // (value) + DIV_CMD_C64_FINE_DUTY, // (value) + DIV_CMD_C64_FINE_CUTOFF, // (value) DIV_CMD_AY_ENVELOPE_SET, DIV_CMD_AY_ENVELOPE_LOW, DIV_CMD_AY_ENVELOPE_HIGH, DIV_CMD_AY_ENVELOPE_SLIDE, - DIV_CMD_AY_NOISE_MASK_AND, - DIV_CMD_AY_NOISE_MASK_OR, - DIV_CMD_AY_AUTO_ENVELOPE, - DIV_CMD_AY_IO_WRITE, + DIV_CMD_AY_NOISE_MASK_AND, // (value) + DIV_CMD_AY_NOISE_MASK_OR, // (value) + DIV_CMD_AY_AUTO_ENVELOPE, // (value) + DIV_CMD_AY_IO_WRITE, // (port, value) DIV_CMD_AY_AUTO_PWM, DIV_CMD_FDS_MOD_DEPTH, @@ -111,13 +114,13 @@ enum DivDispatchCmds { DIV_CMD_FDS_MOD_POS, DIV_CMD_FDS_MOD_WAVE, - DIV_CMD_SAA_ENVELOPE, + DIV_CMD_SAA_ENVELOPE, // (value) - DIV_CMD_AMIGA_FILTER, - DIV_CMD_AMIGA_AM, - DIV_CMD_AMIGA_PM, + DIV_CMD_AMIGA_FILTER, // (enabled) + DIV_CMD_AMIGA_AM, // (enabled) + DIV_CMD_AMIGA_PM, // (enabled) - DIV_CMD_LYNX_LFSR_LOAD, + DIV_CMD_LYNX_LFSR_LOAD, // (value) DIV_CMD_QSOUND_ECHO_FEEDBACK, DIV_CMD_QSOUND_ECHO_DELAY, @@ -146,16 +149,16 @@ enum DivDispatchCmds { DIV_CMD_N163_GLOBAL_WAVE_LOADLEN, DIV_CMD_N163_GLOBAL_WAVE_LOADMODE, - DIV_CMD_ES5506_FILTER_MODE, - DIV_CMD_ES5506_FILTER_K1, - DIV_CMD_ES5506_FILTER_K2, - DIV_CMD_ES5506_ENVELOPE_COUNT, - DIV_CMD_ES5506_ENVELOPE_LVRAMP, - DIV_CMD_ES5506_ENVELOPE_RVRAMP, - DIV_CMD_ES5506_ENVELOPE_K1RAMP, - DIV_CMD_ES5506_ENVELOPE_K2RAMP, + DIV_CMD_ES5506_FILTER_MODE, // (value) + DIV_CMD_ES5506_FILTER_K1, // (value) + DIV_CMD_ES5506_FILTER_K2, // (value) + DIV_CMD_ES5506_ENVELOPE_COUNT, // (count) + DIV_CMD_ES5506_ENVELOPE_LVRAMP, // (ramp) + DIV_CMD_ES5506_ENVELOPE_RVRAMP, // (ramp) + DIV_CMD_ES5506_ENVELOPE_K1RAMP, // (ramp, slowdown) + DIV_CMD_ES5506_ENVELOPE_K2RAMP, // (ramp, slowdown) - DIV_ALWAYS_SET_VOLUME, + DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol DIV_CMD_MAX }; @@ -210,6 +213,7 @@ struct DivRegWrite { }; class DivEngine; +class DivMacroInt; class DivDispatch { protected: @@ -223,11 +227,13 @@ class DivDispatch { /** * the rate the samples are provided. * the engine shall resample to the output rate. + * you have to initialize this one during init() or setFlags(). */ int rate; /** * the actual chip's clock. + * you have to initialize this one during init() or setFlags(). */ int chipClock; @@ -263,6 +269,12 @@ class DivDispatch { * @return a pointer, or NULL. */ virtual void* getChanState(int chan); + + /** + * get the DivMacroInt of a chanmel. + * @return a pointer, or NULL. + */ + virtual DivMacroInt* getChanMacroInt(int chan); /** * get the register pool of this dispatch. @@ -427,17 +439,30 @@ class DivDispatch { /** * quit the DivDispatch. */ - virtual void quit(); + virtual void quit(); - virtual ~DivDispatch(); + virtual ~DivDispatch(); }; +// pitch calculation: +// - a DivDispatch usually contains four variables per channel: +// - baseFreq: this changes on new notes, legato, arpeggio and slides. +// - pitch: this changes with DIV_CMD_PITCH (E5xx/04xy). +// - freq: this is the result of combining baseFreq and pitch using DivEngine::calcFreq(). +// - freqChanged: whether baseFreq and/or pitch have changed, and a frequency recalculation is required on the next tick. +// - the following definitions will help you calculate baseFreq. +// - to use them, define CHIP_DIVIDER and/or CHIP_FREQBASE in your code (not in the header though!). #define NOTE_PERIODIC(x) round(parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true)) #define NOTE_PERIODIC_NOROUND(x) parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true) #define NOTE_FREQUENCY(x) parent->calcBaseFreq(chipClock,CHIP_FREQBASE,x,false) +// this is a special case definition. only use it for f-num/block-based chips. #define NOTE_FNUM_BLOCK(x,bits) parent->calcBaseFreqFNumBlock(chipClock,CHIP_FREQBASE,x,bits) +// these are here for convenience. +// it is encouraged to use these, since you get an exact value this way. +// - NTSC colorburst: 3.58MHz +// - PAL colorburst: 4.43MHz #define COLOR_NTSC (315000000.0/88.0) #define COLOR_PAL (283.75*15625.0+25.0) diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index 9e5cd4b8..d905b89d 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -315,6 +315,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do case DIV_SYSTEM_ES5506: dispatch=new DivPlatformES5506; break; + case DIV_SYSTEM_DUMMY: + dispatch=new DivPlatformDummy; + break; default: logW("this system is not supported yet! using dummy platform."); dispatch=new DivPlatformDummy; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 1c80d413..ad7b085a 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1470,6 +1470,10 @@ bool DivEngine::addWaveFromFile(const char* path) { fclose(f); return false; } + if (len==(SIZE_MAX>>1)) { + fclose(f); + return false; + } if (len==0) { fclose(f); return false; @@ -1662,6 +1666,14 @@ int DivEngine::addSampleFromFile(const char* path) { return -1; } + if (len==(SIZE_MAX>>1)) { + fclose(f); + BUSY_END; + lastError="file is invalid!"; + delete sample; + return -1; + } + if (fseek(f,0,SEEK_SET)<0) { fclose(f); BUSY_END; @@ -2457,6 +2469,9 @@ bool DivEngine::deinitAudioBackend() { #endif bool DivEngine::init() { + // register systems + if (!systemsRegistered) registerSystems(); + // init config #ifdef _WIN32 configPath=getWinConfigPath(); diff --git a/src/engine/engine.h b/src/engine/engine.h index 735c516b..0f20c723 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -27,6 +27,7 @@ #include "../audio/taAudio.h" #include "blip_buf.h" #include +#include #include #include #include @@ -43,8 +44,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev87" -#define DIV_ENGINE_VERSION 87 +#define DIV_VERSION "dev88" +#define DIV_ENGINE_VERSION 88 // for imports #define DIV_VERSION_MOD 0xff01 @@ -177,6 +178,91 @@ struct DivDispatchContainer { dcOffCompensation(false) {} }; +typedef std::function EffectProcess; + +struct DivSysDef { + const char* name; + const char* nameJ; + unsigned char id; + unsigned char id_DMF; + int channels; + bool isFM, isSTD, isCompound; + unsigned int vgmVersion; + const char* chanNames[DIV_MAX_CHANS]; + const char* chanShortNames[DIV_MAX_CHANS]; + int chanTypes[DIV_MAX_CHANS]; + // 0: primary + // 1: alternate (usually PCM) + DivInstrumentType chanInsType[DIV_MAX_CHANS][2]; + EffectProcess effectFunc; + EffectProcess postEffectFunc; + DivSysDef( + const char* sysName, const char* sysNameJ, unsigned char fileID, unsigned char fileID_DMF, int chans, + bool isFMChip, bool isSTDChip, unsigned int vgmVer, bool compound, + std::initializer_list chNames, + std::initializer_list chShortNames, + std::initializer_list chTypes, + std::initializer_list chInsType1, + std::initializer_list chInsType2={}, + EffectProcess fxHandler=NULL, + EffectProcess postFxHandler=NULL): + name(sysName), + nameJ(sysNameJ), + id(fileID), + id_DMF(fileID_DMF), + channels(chans), + isFM(isFMChip), + isSTD(isSTDChip), + isCompound(compound), + vgmVersion(vgmVer), + effectFunc(fxHandler), + postEffectFunc(postFxHandler) { + memset(chanNames,0,DIV_MAX_CHANS*sizeof(void*)); + memset(chanShortNames,0,DIV_MAX_CHANS*sizeof(void*)); + memset(chanTypes,0,DIV_MAX_CHANS*sizeof(int)); + memset(chanInsType,0,DIV_MAX_CHANS*2*sizeof(DivInstrumentType)); + + int index=0; + for (const char* i: chNames) { + chanNames[index++]=i; + if (index>=DIV_MAX_CHANS) break; + } + + index=0; + for (const char* i: chShortNames) { + chanShortNames[index++]=i; + if (index>=DIV_MAX_CHANS) break; + } + + index=0; + for (int i: chTypes) { + chanTypes[index++]=i; + if (index>=DIV_MAX_CHANS) break; + } + + index=0; + for (DivInstrumentType i: chInsType1) { + chanInsType[index++][0]=i; + if (index>=DIV_MAX_CHANS) break; + } + + index=0; + for (DivInstrumentType i: chInsType2) { + chanInsType[index++][1]=i; + if (index>=DIV_MAX_CHANS) break; + } + } +}; + +enum DivChanTypes { + DIV_CH_FM=0, + DIV_CH_PULSE=1, + DIV_CH_NOISE=2, + DIV_CH_WAVE=3, + DIV_CH_PCM=4, + DIV_CH_OP=5 +}; + class DivEngine { DivDispatchContainer disCont[32]; TAAudio* output; @@ -204,6 +290,7 @@ class DivEngine { bool skipping; bool midiIsDirect; bool lowLatency; + bool systemsRegistered; int softLockCount; int subticks, ticks, curRow, curOrder, remainingLoops, nextSpeed; double divider; @@ -230,6 +317,9 @@ class DivEngine { std::vector midiIns; std::vector midiOuts; std::vector cmdStream; + DivSysDef* sysDefs[256]; + DivSystem sysFileMapFur[256]; + DivSystem sysFileMapDMF[256]; struct SamplePreview { int sample; @@ -300,6 +390,8 @@ class DivEngine { bool initAudioBackend(); bool deinitAudioBackend(); + void registerSystems(); + void exchangeIns(int one, int two); public: @@ -432,9 +524,6 @@ class DivEngine { // get sys name const char* getSystemName(DivSystem sys); - // get sys chips - const char* getSystemChips(DivSystem sys); - // get japanese system name const char* getSystemNameJ(DivSystem sys); @@ -720,7 +809,7 @@ class DivEngine { // quit dispatch void quitDispatch(); - // initialize the engine. optionally provide an output file name. + // initialize the engine. bool init(); // terminate the engine. @@ -765,6 +854,7 @@ class DivEngine { skipping(false), midiIsDirect(false), lowLatency(false), + systemsRegistered(false), softLockCount(0), subticks(0), ticks(0), @@ -834,6 +924,12 @@ class DivEngine { memset(vibTable,0,64*sizeof(short)); memset(reversePitchTable,0,4096*sizeof(int)); memset(pitchTable,0,4096*sizeof(int)); + memset(sysDefs,0,256*sizeof(void*)); + + for (int i=0; i<256; i++) { + sysFileMapFur[i]=DIV_SYSTEM_NULL; + sysFileMapDMF[i]=DIV_SYSTEM_NULL; + } } }; #endif diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index c689fdc8..a50b122f 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -1101,9 +1101,11 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { return false; } + logD("systems:"); for (int i=0; i<32; i++) { unsigned char sysID=reader.readC(); ds.system[i]=systemFromFileFur(sysID); + logD("- %d: %.2x (%s)",i,sysID,getSystemName(ds.system[i])); if (sysID!=0 && systemToFileFur(ds.system[i])==0) { logE("unrecognized system ID %.2x",ds.system[i]); lastError=fmt::sprintf("unrecognized system ID %.2x!",ds.system[i]); @@ -2036,6 +2038,8 @@ bool DivEngine::load(unsigned char* f, size_t slen) { return false; } + if (!systemsRegistered) registerSystems(); + // step 1: try loading as a zlib-compressed file logD("trying zlib..."); try { diff --git a/src/engine/fileOpsIns.cpp b/src/engine/fileOpsIns.cpp index 1173d59a..521ab424 100644 --- a/src/engine/fileOpsIns.cpp +++ b/src/engine/fileOpsIns.cpp @@ -1220,6 +1220,11 @@ std::vector DivEngine::instrumentFromFile(const char* path) { fclose(f); return ret; } + if (len==(SIZE_MAX>>1)) { + lastError=strerror(errno); + fclose(f); + return ret; + } if (len==0) { lastError=strerror(errno); fclose(f); diff --git a/src/engine/instrument.h b/src/engine/instrument.h index e19b3203..63354901 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -55,7 +55,11 @@ enum DivInstrumentType: unsigned short { DIV_INS_X1_010=25, DIV_INS_VRC6_SAW=26, DIV_INS_ES5506=27, + DIV_INS_MULTIPCM=28, + DIV_INS_SNES=29, + DIV_INS_SU=30, DIV_INS_MAX, + DIV_INS_NULL }; // FM operator structure: diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 343838e7..56f2aa3d 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -29,6 +29,10 @@ void* DivDispatch::getChanState(int chan) { return NULL; } +DivMacroInt* DivDispatch::getChanMacroInt(int chan) { + return NULL; +} + unsigned char* DivDispatch::getRegisterPool() { return NULL; } diff --git a/src/engine/platform/dummy.cpp b/src/engine/platform/dummy.cpp index e751e3b6..9b972ac1 100644 --- a/src/engine/platform/dummy.cpp +++ b/src/engine/platform/dummy.cpp @@ -22,15 +22,20 @@ #include #include +#define CHIP_FREQBASE 2048 + void DivPlatformDummy::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; i>13; + if (!isMuted[j]) out+=(((signed short)chan[j].pos)*chan[j].amp*chan[j].vol)>>12; chan[j].pos+=chan[j].freq; } } + if (out<-32768) out=-32768; + if (out>32767) out=32767; + bufL[i]=out; } } @@ -41,8 +46,8 @@ void DivPlatformDummy::muteChannel(int ch, bool mute) { void DivPlatformDummy::tick(bool sysTick) { for (unsigned char i=0; ichan[c.chan].baseFreq) { + chan[c.chan].baseFreq+=c.value; + if (chan[c.chan].baseFreq>=destFreq) { + chan[c.chan].baseFreq=destFreq; + return2=true; + } + } else { + chan[c.chan].baseFreq-=c.value; + if (chan[c.chan].baseFreq<=destFreq) { + chan[c.chan].baseFreq=destFreq; + return2=true; + } + } + chan[c.chan].freqChanged=true; + if (return2) return 2; + break; + } case DIV_CMD_LEGATO: - chan[c.chan].baseFreq=65.6f*pow(2.0f,((float)c.value/12.0f)); + chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); chan[c.chan].freqChanged=true; break; case DIV_CMD_GET_VOLMAX: @@ -108,6 +133,7 @@ int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, unsigned int isMuted[i]=false; } rate=65536; + chipClock=65536; chans=channels; reset(); return channels; diff --git a/src/engine/platform/dummy.h b/src/engine/platform/dummy.h index aa38b33b..ff24df62 100644 --- a/src/engine/platform/dummy.h +++ b/src/engine/platform/dummy.h @@ -23,8 +23,7 @@ // used when a DivDispatch for a system is not found. class DivPlatformDummy: public DivDispatch { struct Channel { - unsigned short freq, baseFreq; - short pitch; + int freq, baseFreq, pitch; unsigned short pos; bool active, freqChanged; unsigned char vol; diff --git a/src/engine/platform/sound/su.cpp b/src/engine/platform/sound/su.cpp new file mode 100644 index 00000000..daf710fc --- /dev/null +++ b/src/engine/platform/sound/su.cpp @@ -0,0 +1,261 @@ +#include "su.h" +#include + +#define minval(a,b) (((a)<(b))?(a):(b)) +#define maxval(a,b) (((a)>(b))?(a):(b)) + +void SoundUnit::NextSample(short* l, short* r) { + for (int i=0; i<8; i++) { + if (chan[i].vol==0 && !chan[i].flags.swvol) {fns[i]=0; continue;} + if (chan[i].flags.pcm) { + ns[i]=pcm[chan[i].pcmpos]; + } else switch (chan[i].flags.shape) { + case 0: + ns[i]=(((cycle[i]>>15)&127)>chan[i].duty)*127; + break; + case 1: + ns[i]=cycle[i]>>14; + break; + case 2: + ns[i]=SCsine[(cycle[i]>>14)&255]; + break; + case 3: + ns[i]=SCtriangle[(cycle[i]>>14)&255]; + break; + case 4: case 5: + ns[i]=(lfsr[i]&1)*127; + break; + case 6: + ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCsine[(cycle[i]>>14)&255]; + break; + case 7: + ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCtriangle[(cycle[i]>>14)&255]; + break; + } + + if (chan[i].flags.pcm) { + if (chan[i].freq>0x8000) { + pcmdec[i]+=0x8000; + } else { + pcmdec[i]+=chan[i].freq; + } + if (pcmdec[i]>=32768) { + pcmdec[i]-=32768; + if (chan[i].pcmpos>4)&3) { + case 0: + cycle[i]+=chan[i].freq*1-(chan[i].freq>>3); + break; + case 1: + cycle[i]+=chan[i].freq*2-(chan[i].freq>>3); + break; + case 2: + cycle[i]+=chan[i].freq*4-(chan[i].freq>>3); + break; + case 3: + cycle[i]+=chan[i].freq*8-(chan[i].freq>>3); + break; + } + } else { + cycle[i]+=chan[i].freq; + } + if ((cycle[i]&0xf80000)!=(ocycle[i]&0xf80000)) { + if (chan[i].flags.shape==4) { + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<31); + } else { + switch ((chan[i].duty>>4)&3) { + case 0: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 3) ^ (lfsr[i] >> 4) ) & 1)<<5); + break; + case 1: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5); + break; + case 2: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5); + break; + case 3: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<5); + break; + } + if ((lfsr[i]&63)==0) { + lfsr[i]=0xaaaa; + } + } + } + if (chan[i].flags.restim) { + if (--rcycle[i]<=0) { + cycle[i]=0; + rcycle[i]=chan[i].restimer; + lfsr[i]=0xaaaa; + } + } + } + fns[i]=ns[i]*chan[i].vol*2; + if (chan[i].flags.fmode!=0) { + int ff=chan[i].cutoff; + nslow[i]=nslow[i]+(((ff)*nsband[i])>>16); + nshigh[i]=fns[i]-nslow[i]-(((256-chan[i].reson)*nsband[i])>>8); + nsband[i]=(((ff)*nshigh[i])>>16)+nsband[i]; + fns[i]=(((chan[i].flags.fmode&1)?(nslow[i]):(0))+((chan[i].flags.fmode&2)?(nshigh[i]):(0))+((chan[i].flags.fmode&4)?(nsband[i]):(0))); + } + nsL[i]=(fns[i]*SCpantabL[(unsigned char)chan[i].pan])>>8; + nsR[i]=(fns[i]*SCpantabR[(unsigned char)chan[i].pan])>>8; + oldfreq[i]=chan[i].freq; + oldflags[i]=chan[i].flags.flags; + if (chan[i].flags.swvol) { + if (--swvolt[i]<=0) { + swvolt[i]=chan[i].swvol.speed; + if (chan[i].swvol.dir) { + chan[i].vol+=chan[i].swvol.amt; + if (chan[i].vol>chan[i].swvol.bound && !chan[i].swvol.loop) { + chan[i].vol=chan[i].swvol.bound; + } + if (chan[i].vol&0x80) { + if (chan[i].swvol.loop) { + if (chan[i].swvol.loopi) { + chan[i].swvol.dir=!chan[i].swvol.dir; + chan[i].vol=0xff-chan[i].vol; + } else { + chan[i].vol&=~0x80; + } + } else { + chan[i].vol=0x7f; + } + } + } else { + chan[i].vol-=chan[i].swvol.amt; + if (chan[i].vol&0x80) { + if (chan[i].swvol.loop) { + if (chan[i].swvol.loopi) { + chan[i].swvol.dir=!chan[i].swvol.dir; + chan[i].vol=-chan[i].vol; + } else { + chan[i].vol&=~0x80; + } + } else { + chan[i].vol=0x0; + } + } + if (chan[i].vol(0xffff-chan[i].swfreq.amt)) { + chan[i].freq=0xffff; + } else { + chan[i].freq=(chan[i].freq*(0x80+chan[i].swfreq.amt))>>7; + if ((chan[i].freq>>8)>chan[i].swfreq.bound) { + chan[i].freq=chan[i].swfreq.bound<<8; + } + } + } else { + if (chan[i].freq>8; + if ((chan[i].freq>>8)(0xffff-chan[i].swcut.amt)) { + chan[i].cutoff=0xffff; + } else { + chan[i].cutoff+=chan[i].swcut.amt; + if ((chan[i].cutoff>>8)>chan[i].swcut.bound) { + chan[i].cutoff=chan[i].swcut.bound<<8; + } + } + } else { + if (chan[i].cutoff>11; + if ((chan[i].cutoff>>8)>2; + tnsR=(nsR[0]+nsR[1]+nsR[2]+nsR[3]+nsR[4]+nsR[5]+nsR[6]+nsR[7])>>2; + + *l=minval(32767,maxval(-32767,tnsL)); + *r=minval(32767,maxval(-32767,tnsR)); +} + +void SoundUnit::Init() { + Reset(); + memset(pcm,0,SOUNDCHIP_PCM_SIZE); + for (int i=0; i<256; i++) { + SCsine[i]=sin((i/128.0f)*M_PI)*127; + SCtriangle[i]=(i>127)?(255-i):(i); + SCpantabL[i]=127; + SCpantabR[i]=127; + } + for (int i=0; i<128; i++) { + SCpantabL[i]=127-i; + SCpantabR[128+i]=i-1; + } + SCpantabR[128]=0; +} + +void SoundUnit::Reset() { + for (int i=0; i<8; i++) { + cycle[i]=0; + resetfreq[i]=0; + voldcycles[i]=0; + volicycles[i]=0; + fscycles[i]=0; + sweep[i]=0; + ns[i]=0; + swvolt[i]=1; + swfreqt[i]=1; + swcutt[i]=1; + lfsr[i]=0xaaaa; + } + memset(chan,0,sizeof(SUChannel)*8); +} + +void SoundUnit::Write(unsigned char addr, unsigned char data) { + ((unsigned char*)chan)[addr]=data; +} + +SoundUnit::SoundUnit() { + Init(); +} diff --git a/src/engine/platform/sound/su.h b/src/engine/platform/sound/su.h new file mode 100644 index 00000000..a201e955 --- /dev/null +++ b/src/engine/platform/sound/su.h @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#define SOUNDCHIP_PCM_SIZE 8192 + +class SoundUnit { + signed char SCsine[256]; + signed char SCtriangle[256]; + signed char SCpantabL[256]; + signed char SCpantabR[256]; + unsigned int ocycle[8]; + unsigned int cycle[8]; + int rcycle[8]; + unsigned int lfsr[8]; + signed char ns[8]; + int fns[8]; + int nsL[8]; + int nsR[8]; + int nslow[8]; + int nshigh[8]; + int nsband[8]; + int tnsL, tnsR; + unsigned short oldfreq[8]; + unsigned short oldflags[8]; + public: + unsigned short resetfreq[8]; + unsigned short voldcycles[8]; + unsigned short volicycles[8]; + unsigned short fscycles[8]; + unsigned char sweep[8]; + unsigned short swvolt[8]; + unsigned short swfreqt[8]; + unsigned short swcutt[8]; + unsigned short pcmdec[8]; + struct SUChannel { + unsigned short freq; + signed char vol; + signed char pan; + union { + unsigned short flags; + struct { + unsigned char shape: 3; + unsigned char pcm: 1; + unsigned char ring: 1; + unsigned char fmode: 3; + unsigned char resosc: 1; + unsigned char resfilt: 1; + unsigned char pcmloop: 1; + unsigned char restim: 1; + unsigned char swfreq: 1; + unsigned char swvol: 1; + unsigned char swcut: 1; + unsigned char padding: 1; + }; + } flags; + unsigned short cutoff; + unsigned char duty; + unsigned char reson; + unsigned short pcmpos; + unsigned short pcmbnd; + unsigned short pcmrst; + struct { + unsigned short speed; + unsigned char amt: 7; + unsigned char dir: 1; + unsigned char bound; + } swfreq; + struct { + unsigned short speed; + unsigned char amt: 5; + unsigned char dir: 1; + unsigned char loop: 1; + unsigned char loopi: 1; + unsigned char bound; + } swvol; + struct { + unsigned short speed; + unsigned char amt: 7; + unsigned char dir: 1; + unsigned char bound; + } swcut; + unsigned short wc; + unsigned short restimer; + } chan[8]; + signed char pcm[SOUNDCHIP_PCM_SIZE]; + void Write(unsigned char addr, unsigned char data); + void NextSample(short* l, short* r); + void Init(); + void Reset(); + SoundUnit(); +}; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 35201cae..fef3b450 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1977,7 +1977,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi // 2. check whether we gonna tick if (cycles<=0) { // we have to tick - if (!freelance && stepPlay!=-1) { + if (!freelance && stepPlay!=-1 && subticks==1) { unsigned int realPos=size-(runLeftG>>MASTER_CLOCK_PREC); if (realPos>=size) realPos=size-1; if (song.hilightA>0) { diff --git a/src/engine/song.h b/src/engine/song.h index 9ff989f7..317ffa9b 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -96,7 +96,16 @@ enum DivSystem { DIV_SYSTEM_SEGAPCM_COMPAT, DIV_SYSTEM_X1_010, DIV_SYSTEM_BUBSYS_WSG, - DIV_SYSTEM_ES5506 + DIV_SYSTEM_OPL4, + DIV_SYSTEM_OPL4_DRUMS, + DIV_SYSTEM_ES5506, + DIV_SYSTEM_Y8950, + DIV_SYSTEM_Y8950_DRUMS, + DIV_SYSTEM_SCC_PLUS, + DIV_SYSTEM_SOUND_UNIT, + DIV_SYSTEM_MSM6295, + DIV_SYSTEM_MSM6258, + DIV_SYSTEM_DUMMY }; struct DivSong { diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 7ec13fc3..2c5e3c73 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -19,470 +19,29 @@ #include "engine.h" #include "song.h" +#include "../ta-log.h" DivSystem DivEngine::systemFromFileFur(unsigned char val) { - switch (val) { - case 0x01: - return DIV_SYSTEM_YMU759; - case 0x02: - return DIV_SYSTEM_GENESIS; - case 0x03: - return DIV_SYSTEM_SMS; - case 0x04: - return DIV_SYSTEM_GB; - case 0x05: - return DIV_SYSTEM_PCE; - case 0x06: - return DIV_SYSTEM_NES; - case 0x07: - return DIV_SYSTEM_C64_8580; - case 0x08: - return DIV_SYSTEM_ARCADE; - case 0x09: - return DIV_SYSTEM_YM2610; - case 0x42: - return DIV_SYSTEM_GENESIS_EXT; - case 0x43: - return DIV_SYSTEM_SMS_OPLL; - case 0x46: - return DIV_SYSTEM_NES_VRC7; - case 0x47: - return DIV_SYSTEM_C64_6581; - case 0x49: - return DIV_SYSTEM_YM2610_EXT; - case 0x80: - return DIV_SYSTEM_AY8910; - case 0x81: - return DIV_SYSTEM_AMIGA; - case 0x82: - return DIV_SYSTEM_YM2151; - case 0x83: - return DIV_SYSTEM_YM2612; - case 0x84: - return DIV_SYSTEM_TIA; - case 0x85: - return DIV_SYSTEM_VIC20; - case 0x86: - return DIV_SYSTEM_PET; - case 0x87: - return DIV_SYSTEM_SNES; - case 0x88: - return DIV_SYSTEM_VRC6; - case 0x89: - return DIV_SYSTEM_OPLL; - case 0x8a: - return DIV_SYSTEM_FDS; - case 0x8b: - return DIV_SYSTEM_MMC5; - case 0x8c: - return DIV_SYSTEM_N163; - case 0x8d: - return DIV_SYSTEM_OPN; - case 0x8e: - return DIV_SYSTEM_PC98; - case 0x8f: - return DIV_SYSTEM_OPL; - case 0x90: - return DIV_SYSTEM_OPL2; - case 0x91: - return DIV_SYSTEM_OPL3; - case 0x92: - return DIV_SYSTEM_MULTIPCM; - case 0x93: - return DIV_SYSTEM_PCSPKR; - case 0x94: - return DIV_SYSTEM_POKEY; - case 0x95: - return DIV_SYSTEM_RF5C68; - case 0x96: - return DIV_SYSTEM_SWAN; - case 0x97: - return DIV_SYSTEM_SAA1099; - case 0x98: - return DIV_SYSTEM_OPZ; - case 0x99: - return DIV_SYSTEM_POKEMINI; - case 0x9a: - return DIV_SYSTEM_AY8930; - case 0x9b: - return DIV_SYSTEM_SEGAPCM; - case 0x9c: - return DIV_SYSTEM_VBOY; - case 0x9d: - return DIV_SYSTEM_VRC7; - case 0x9e: - return DIV_SYSTEM_YM2610B; - case 0x9f: - return DIV_SYSTEM_SFX_BEEPER; - case 0xa0: - return DIV_SYSTEM_YM2612_EXT; - case 0xa1: - return DIV_SYSTEM_SCC; - case 0xa2: - return DIV_SYSTEM_OPL_DRUMS; - case 0xa3: - return DIV_SYSTEM_OPL2_DRUMS; - case 0xa4: - return DIV_SYSTEM_OPL3_DRUMS; - case 0xa5: - return DIV_SYSTEM_YM2610_FULL; - case 0xa6: - return DIV_SYSTEM_YM2610_FULL_EXT; - case 0xa7: - return DIV_SYSTEM_OPLL_DRUMS; - case 0xa8: - return DIV_SYSTEM_LYNX; - case 0xa9: - return DIV_SYSTEM_SEGAPCM_COMPAT; - case 0xac: - return DIV_SYSTEM_VERA; - case 0xad: - return DIV_SYSTEM_BUBSYS_WSG; - case 0xb0: - return DIV_SYSTEM_X1_010; - case 0xb1: - return DIV_SYSTEM_ES5506; - case 0xde: - return DIV_SYSTEM_YM2610B_EXT; - case 0xe0: - return DIV_SYSTEM_QSOUND; - } - return DIV_SYSTEM_NULL; + return sysFileMapFur[val]; } unsigned char DivEngine::systemToFileFur(DivSystem val) { - switch (val) { - case DIV_SYSTEM_YMU759: - return 0x01; - case DIV_SYSTEM_GENESIS: - return 0x02; - case DIV_SYSTEM_SMS: - return 0x03; - case DIV_SYSTEM_GB: - return 0x04; - case DIV_SYSTEM_PCE: - return 0x05; - case DIV_SYSTEM_NES: - return 0x06; - case DIV_SYSTEM_C64_8580: - return 0x07; - case DIV_SYSTEM_ARCADE: - return 0x08; - case DIV_SYSTEM_YM2610: - return 0x09; - case DIV_SYSTEM_GENESIS_EXT: - return 0x42; - case DIV_SYSTEM_SMS_OPLL: - return 0x43; - case DIV_SYSTEM_NES_VRC7: - return 0x46; - case DIV_SYSTEM_NES_FDS: - return 0; // unsupported - case DIV_SYSTEM_C64_6581: - return 0x47; - case DIV_SYSTEM_YM2610_EXT: - return 0x49; - case DIV_SYSTEM_AY8910: - return 0x80; - case DIV_SYSTEM_AMIGA: - return 0x81; - case DIV_SYSTEM_YM2151: - return 0x82; - case DIV_SYSTEM_YM2612: - return 0x83; - case DIV_SYSTEM_TIA: - return 0x84; - case DIV_SYSTEM_VIC20: - return 0x85; - case DIV_SYSTEM_PET: - return 0x86; - case DIV_SYSTEM_SNES: - return 0x87; - case DIV_SYSTEM_VRC6: - return 0x88; - case DIV_SYSTEM_OPLL: - return 0x89; - case DIV_SYSTEM_FDS: - return 0x8a; - case DIV_SYSTEM_MMC5: - return 0x8b; - case DIV_SYSTEM_N163: - return 0x8c; - case DIV_SYSTEM_OPN: - return 0x8d; - case DIV_SYSTEM_PC98: - return 0x8e; - case DIV_SYSTEM_OPL: - return 0x8f; - case DIV_SYSTEM_OPL2: - return 0x90; - case DIV_SYSTEM_OPL3: - return 0x91; - case DIV_SYSTEM_MULTIPCM: - return 0x92; - case DIV_SYSTEM_PCSPKR: - return 0x93; - case DIV_SYSTEM_POKEY: - return 0x94; - case DIV_SYSTEM_RF5C68: - return 0x95; - case DIV_SYSTEM_SWAN: - return 0x96; - case DIV_SYSTEM_SAA1099: - return 0x97; - case DIV_SYSTEM_OPZ: - return 0x98; - case DIV_SYSTEM_POKEMINI: - return 0x99; - case DIV_SYSTEM_AY8930: - return 0x9a; - case DIV_SYSTEM_SEGAPCM: - return 0x9b; - case DIV_SYSTEM_VBOY: - return 0x9c; - case DIV_SYSTEM_VRC7: - return 0x9d; - case DIV_SYSTEM_YM2610B: - return 0x9e; - case DIV_SYSTEM_SFX_BEEPER: - return 0x9f; - case DIV_SYSTEM_YM2612_EXT: - return 0xa0; - case DIV_SYSTEM_SCC: - return 0xa1; - case DIV_SYSTEM_OPL_DRUMS: - return 0xa2; - case DIV_SYSTEM_OPL2_DRUMS: - return 0xa3; - case DIV_SYSTEM_OPL3_DRUMS: - return 0xa4; - case DIV_SYSTEM_YM2610_FULL: - return 0xa5; - case DIV_SYSTEM_YM2610_FULL_EXT: - return 0xa6; - case DIV_SYSTEM_OPLL_DRUMS: - return 0xa7; - case DIV_SYSTEM_LYNX: - return 0xa8; - case DIV_SYSTEM_SEGAPCM_COMPAT: - return 0xa9; - case DIV_SYSTEM_VERA: - return 0xac; - case DIV_SYSTEM_BUBSYS_WSG: - return 0xad; - case DIV_SYSTEM_X1_010: - return 0xb0; - case DIV_SYSTEM_ES5506: - return 0xb1; - case DIV_SYSTEM_YM2610B_EXT: - return 0xde; - case DIV_SYSTEM_QSOUND: - return 0xe0; - - case DIV_SYSTEM_NULL: - return 0; - } - return 0; + if (sysDefs[val]==NULL) return 0; + return sysDefs[val]->id; } DivSystem DivEngine::systemFromFileDMF(unsigned char val) { - switch (val) { - case 0x01: - return DIV_SYSTEM_YMU759; - case 0x02: - return DIV_SYSTEM_GENESIS; - case 0x03: - return DIV_SYSTEM_SMS; - case 0x04: - return DIV_SYSTEM_GB; - case 0x05: - return DIV_SYSTEM_PCE; - case 0x06: - return DIV_SYSTEM_NES; - case 0x07: - return DIV_SYSTEM_C64_8580; - case 0x08: - return DIV_SYSTEM_ARCADE; - case 0x09: - return DIV_SYSTEM_YM2610; - case 0x42: - return DIV_SYSTEM_GENESIS_EXT; - case 0x43: - return DIV_SYSTEM_SMS_OPLL; - case 0x46: - return DIV_SYSTEM_NES_VRC7; - case 0x47: - return DIV_SYSTEM_C64_6581; - case 0x49: - return DIV_SYSTEM_YM2610_EXT; - case 0x86: - return DIV_SYSTEM_NES_FDS; - } - return DIV_SYSTEM_NULL; + return sysFileMapDMF[val]; } unsigned char DivEngine::systemToFileDMF(DivSystem val) { - switch (val) { - case DIV_SYSTEM_YMU759: - return 0x01; - case DIV_SYSTEM_GENESIS: - return 0x02; - case DIV_SYSTEM_SMS: - return 0x03; - case DIV_SYSTEM_GB: - return 0x04; - case DIV_SYSTEM_PCE: - return 0x05; - case DIV_SYSTEM_NES: - return 0x06; - case DIV_SYSTEM_C64_8580: - return 0x07; - case DIV_SYSTEM_ARCADE: - return 0x08; - case DIV_SYSTEM_YM2610: - return 0x09; - case DIV_SYSTEM_GENESIS_EXT: - return 0x42; - case DIV_SYSTEM_SMS_OPLL: - return 0x43; - case DIV_SYSTEM_NES_VRC7: - return 0x46; - case DIV_SYSTEM_NES_FDS: - return 0x86; - case DIV_SYSTEM_C64_6581: - return 0x47; - case DIV_SYSTEM_YM2610_EXT: - return 0x49; - default: - return 0; - } - return 0; + if (sysDefs[val]==NULL) return 0; + return sysDefs[val]->id_DMF; } int DivEngine::getChannelCount(DivSystem sys) { - switch (sys) { - case DIV_SYSTEM_NULL: - return 0; - case DIV_SYSTEM_YMU759: - return 17; - case DIV_SYSTEM_GENESIS: - return 10; - case DIV_SYSTEM_SMS: - case DIV_SYSTEM_GB: - return 4; - case DIV_SYSTEM_PCE: - return 6; - case DIV_SYSTEM_NES: - return 5; - case DIV_SYSTEM_C64_6581: - case DIV_SYSTEM_C64_8580: - return 3; - case DIV_SYSTEM_ARCADE: - case DIV_SYSTEM_GENESIS_EXT: - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_SMS_OPLL: - return 13; - case DIV_SYSTEM_NES_VRC7: - return 11; - case DIV_SYSTEM_NES_FDS: - return 6; - case DIV_SYSTEM_YM2610_EXT: - return 16; - case DIV_SYSTEM_AY8910: - case DIV_SYSTEM_AY8930: - return 3; - case DIV_SYSTEM_AMIGA: - return 4; - case DIV_SYSTEM_YM2151: - return 8; - case DIV_SYSTEM_YM2612: - return 6; - case DIV_SYSTEM_TIA: - return 2; - case DIV_SYSTEM_VIC20: - return 4; - case DIV_SYSTEM_PET: - return 1; - case DIV_SYSTEM_SNES: - return 8; - case DIV_SYSTEM_VRC6: - return 3; - case DIV_SYSTEM_OPLL: - return 9; - case DIV_SYSTEM_FDS: - return 1; - case DIV_SYSTEM_MMC5: - return 3; - case DIV_SYSTEM_N163: - return 8; - case DIV_SYSTEM_OPN: - return 6; - case DIV_SYSTEM_PC98: - return 16; - case DIV_SYSTEM_OPL: - return 9; - case DIV_SYSTEM_OPL2: - return 9; - case DIV_SYSTEM_OPL3: - return 18; - case DIV_SYSTEM_MULTIPCM: - return 28; - case DIV_SYSTEM_PCSPKR: - return 1; - case DIV_SYSTEM_POKEY: - return 4; - case DIV_SYSTEM_RF5C68: - return 8; - case DIV_SYSTEM_SWAN: - return 4; - case DIV_SYSTEM_SAA1099: - return 6; - case DIV_SYSTEM_OPZ: - return 8; - case DIV_SYSTEM_POKEMINI: - return 1; - case DIV_SYSTEM_SEGAPCM: - case DIV_SYSTEM_X1_010: - return 16; - case DIV_SYSTEM_VBOY: - return 6; - case DIV_SYSTEM_VRC7: - return 6; - case DIV_SYSTEM_YM2610B: - return 16; - case DIV_SYSTEM_SFX_BEEPER: - return 6; - case DIV_SYSTEM_YM2612_EXT: - return 9; - case DIV_SYSTEM_SCC: - return 5; - case DIV_SYSTEM_OPL_DRUMS: - return 11; - case DIV_SYSTEM_OPL2_DRUMS: - return 11; - case DIV_SYSTEM_OPL3_DRUMS: - return 20; - case DIV_SYSTEM_YM2610_FULL: - return 14; - case DIV_SYSTEM_YM2610_FULL_EXT: - return 17; - case DIV_SYSTEM_OPLL_DRUMS: - return 11; - case DIV_SYSTEM_LYNX: - return 4; - case DIV_SYSTEM_SEGAPCM_COMPAT: - return 5; - case DIV_SYSTEM_YM2610B_EXT: - case DIV_SYSTEM_QSOUND: - return 19; - case DIV_SYSTEM_VERA: - return 17; - case DIV_SYSTEM_BUBSYS_WSG: - return 2; - case DIV_SYSTEM_ES5506: - return 32; - } - return 0; + if (sysDefs[sys]==NULL) return 0; + return sysDefs[sys]->channels; } int DivEngine::getTotalChannelCount() { @@ -639,274 +198,15 @@ const char* DivEngine::getSongSystemName() { } const char* DivEngine::getSystemName(DivSystem sys) { - switch (sys) { - case DIV_SYSTEM_NULL: - return "Unknown"; - case DIV_SYSTEM_YMU759: - return "Yamaha YMU759"; - case DIV_SYSTEM_GENESIS: - return "Sega Genesis/Mega Drive"; - case DIV_SYSTEM_SMS: - return "TI SN76489"; - case DIV_SYSTEM_SMS_OPLL: - return "Sega Master System + FM Expansion"; - case DIV_SYSTEM_GB: - return "Game Boy"; - case DIV_SYSTEM_PCE: - return "PC Engine/TurboGrafx-16"; - case DIV_SYSTEM_NES: - return "NES"; - case DIV_SYSTEM_NES_VRC7: - return "NES + Konami VRC7"; - case DIV_SYSTEM_NES_FDS: - return "Famicom Disk System"; - case DIV_SYSTEM_C64_6581: - return "Commodore 64 with 6581"; - case DIV_SYSTEM_C64_8580: - return "Commodore 64 with 8580"; - case DIV_SYSTEM_ARCADE: - return "YM2151 + SegaPCM Arcade"; - case DIV_SYSTEM_GENESIS_EXT: - return "Sega Genesis Extended Channel 3"; - case DIV_SYSTEM_YM2610: - return "Neo Geo CD"; - case DIV_SYSTEM_YM2610_EXT: - return "Neo Geo CD Extended Channel 2"; - case DIV_SYSTEM_YM2610_FULL: - return "Neo Geo"; - case DIV_SYSTEM_YM2610_FULL_EXT: - return "Neo Geo Extended Channel 2"; - case DIV_SYSTEM_AY8910: - return "AY-3-8910"; - case DIV_SYSTEM_AMIGA: - return "Amiga"; - case DIV_SYSTEM_YM2151: - return "Yamaha YM2151"; - case DIV_SYSTEM_YM2612: - return "Yamaha YM2612"; - case DIV_SYSTEM_TIA: - return "Atari 2600"; - case DIV_SYSTEM_VIC20: - return "Commodore VIC-20"; - case DIV_SYSTEM_PET: - return "Commodore PET"; - case DIV_SYSTEM_SNES: - return "SNES"; - case DIV_SYSTEM_VRC6: - return "Konami VRC6"; - case DIV_SYSTEM_OPLL: - return "Yamaha OPLL"; - case DIV_SYSTEM_FDS: - return "Famicom Disk System (chip)"; - case DIV_SYSTEM_MMC5: - return "MMC5"; - case DIV_SYSTEM_N163: - return "Namco 163"; - case DIV_SYSTEM_OPN: - return "NEC PC-9801-26K"; - case DIV_SYSTEM_PC98: - return "PC-9801-86 + Chibi-oto"; - case DIV_SYSTEM_OPL: - return "Yamaha OPL"; - case DIV_SYSTEM_OPL2: - return "Yamaha OPL2"; - case DIV_SYSTEM_OPL3: - return "Yamaha OPL3"; - case DIV_SYSTEM_MULTIPCM: - return "MultiPCM"; - case DIV_SYSTEM_PCSPKR: - return "PC Speaker"; - case DIV_SYSTEM_POKEY: - return "Atari 400/800"; - case DIV_SYSTEM_RF5C68: - return "Ricoh RF5C68"; - case DIV_SYSTEM_SWAN: - return "WonderSwan"; - case DIV_SYSTEM_SAA1099: - return "Philips SAA1099"; - case DIV_SYSTEM_OPZ: - return "Yamaha TX81Z/YS200"; - case DIV_SYSTEM_POKEMINI: - return "Pokémon Mini"; - case DIV_SYSTEM_AY8930: - return "Microchip AY8930"; - case DIV_SYSTEM_SEGAPCM: - return "SegaPCM"; - case DIV_SYSTEM_VBOY: - return "Virtual Boy"; - case DIV_SYSTEM_VRC7: - return "Konami VRC7"; - case DIV_SYSTEM_YM2610B: - return "Taito Arcade"; - case DIV_SYSTEM_SFX_BEEPER: - return "ZX Spectrum Beeper"; - case DIV_SYSTEM_YM2612_EXT: - return "Yamaha YM2612 Extended Channel 3"; - case DIV_SYSTEM_SCC: - return "Konami SCC"; - case DIV_SYSTEM_OPL_DRUMS: - return "Yamaha OPL with drums"; - case DIV_SYSTEM_OPL2_DRUMS: - return "Yamaha OPL2 with drums"; - case DIV_SYSTEM_OPL3_DRUMS: - return "Yamaha OPL3 with drums"; - case DIV_SYSTEM_OPLL_DRUMS: - return "Yamaha OPLL with drums"; - case DIV_SYSTEM_LYNX: - return "Atari Lynx"; - case DIV_SYSTEM_SEGAPCM_COMPAT: - return "SegaPCM (compatible 5-channel mode)"; - case DIV_SYSTEM_YM2610B_EXT: - return "Taito Arcade Extended Channel 3"; - case DIV_SYSTEM_QSOUND: - return "Capcom QSound"; - case DIV_SYSTEM_VERA: - return "VERA"; - case DIV_SYSTEM_X1_010: - return "Seta/Allumer X1-010"; - case DIV_SYSTEM_BUBSYS_WSG: - return "Konami Bubble System WSG"; - case DIV_SYSTEM_ES5506: - return "Ensoniq ES5506 OTTO"; - } - return "Unknown"; -} - -const char* DivEngine::getSystemChips(DivSystem sys) { - switch (sys) { - case DIV_SYSTEM_NULL: - return "Unknown"; - case DIV_SYSTEM_YMU759: - return "Yamaha YMU759"; - case DIV_SYSTEM_GENESIS: - return "Yamaha YM2612 + TI SN76489"; - case DIV_SYSTEM_SMS: - return "TI SN76489"; - case DIV_SYSTEM_SMS_OPLL: - return "TI SN76489 + Yamaha YM2413"; - case DIV_SYSTEM_GB: - return "Sharp LR35902"; - case DIV_SYSTEM_PCE: - return "Hudson Soft HuC6280"; - case DIV_SYSTEM_NES: - return "Ricoh 2A03"; - case DIV_SYSTEM_NES_VRC7: - return "Ricoh 2A03 + Konami VRC7"; - case DIV_SYSTEM_NES_FDS: - return "Ricoh 2A03 + Famicom Disk System"; - case DIV_SYSTEM_C64_6581: - return "SID 6581"; - case DIV_SYSTEM_C64_8580: - return "SID 8580"; - case DIV_SYSTEM_ARCADE: - return "Yamaha YM2151 + SegaPCM"; - case DIV_SYSTEM_GENESIS_EXT: - return "Yamaha YM2612 (extended channel 3) + TI SN76489"; - case DIV_SYSTEM_YM2610: - return "Yamaha YM2610 no ADPCM-B"; - case DIV_SYSTEM_YM2610_EXT: - return "Yamaha YM2610 no ADPCM-B (extended channel 2)"; - case DIV_SYSTEM_AY8910: - return "AY-3-8910"; - case DIV_SYSTEM_AMIGA: - return "MOS 8364 Paula"; - case DIV_SYSTEM_YM2151: - return "Yamaha YM2151"; - case DIV_SYSTEM_YM2612: - return "Yamaha YM2612"; - case DIV_SYSTEM_TIA: - return "Atari TIA"; - case DIV_SYSTEM_VIC20: - return "VIC"; - case DIV_SYSTEM_PET: - return "Commodore PET"; - case DIV_SYSTEM_SNES: - return "SPC700"; - case DIV_SYSTEM_VRC6: - return "Konami VRC6"; - case DIV_SYSTEM_OPLL: - return "Yamaha YM2413"; - case DIV_SYSTEM_FDS: - return "Famicom Disk System"; - case DIV_SYSTEM_MMC5: - return "MMC5"; - case DIV_SYSTEM_N163: - return "Namco 163"; - case DIV_SYSTEM_OPN: - return "Yamaha YM2203"; - case DIV_SYSTEM_PC98: - return "Yamaha YM2608"; - case DIV_SYSTEM_OPL: - return "Yamaha YM3526"; - case DIV_SYSTEM_OPL2: - return "Yamaha YM3812"; - case DIV_SYSTEM_OPL3: - return "Yamaha YMF262"; - case DIV_SYSTEM_MULTIPCM: - return "Yamaha YMW258"; - case DIV_SYSTEM_PCSPKR: - return "Intel 8253"; - case DIV_SYSTEM_POKEY: - return "POKEY"; - case DIV_SYSTEM_RF5C68: - return "Ricoh RF5C68"; - case DIV_SYSTEM_SWAN: - return "WonderSwan"; - case DIV_SYSTEM_SAA1099: - return "Philips SAA1099"; - case DIV_SYSTEM_OPZ: - return "Yamaha YM2414"; - case DIV_SYSTEM_POKEMINI: - return "Pokémon Mini"; - case DIV_SYSTEM_AY8930: - return "Microchip AY8930"; - case DIV_SYSTEM_SEGAPCM: - return "SegaPCM"; - case DIV_SYSTEM_VBOY: - return "VSU"; - case DIV_SYSTEM_VRC7: - return "Konami VRC7"; - case DIV_SYSTEM_YM2610B: - return "Yamaha YM2610B"; - case DIV_SYSTEM_SFX_BEEPER: - return "ZX Spectrum Beeper"; - case DIV_SYSTEM_YM2612_EXT: - return "Yamaha YM2612 Extended Channel 3"; - case DIV_SYSTEM_SCC: - return "Konami K051649"; - case DIV_SYSTEM_OPL_DRUMS: - return "Yamaha YM3526 with drums"; - case DIV_SYSTEM_OPL2_DRUMS: - return "Yamaha YM3812 with drums"; - case DIV_SYSTEM_OPL3_DRUMS: - return "Yamaha YMF262 with drums"; - case DIV_SYSTEM_YM2610_FULL: - return "Yamaha YM2610"; - case DIV_SYSTEM_YM2610_FULL_EXT: - return "Yamaha YM2610 (extended channel 2)"; - case DIV_SYSTEM_OPLL_DRUMS: - return "Yamaha YM2413 with drums"; - case DIV_SYSTEM_LYNX: - return "Mikey"; - case DIV_SYSTEM_SEGAPCM_COMPAT: - return "SegaPCM (compatible 5-channel mode)"; - case DIV_SYSTEM_YM2610B_EXT: - return "Yamaha YM2610B Extended Channel 3"; - case DIV_SYSTEM_QSOUND: - return "Capcom DL-1425"; - case DIV_SYSTEM_VERA: - return "VERA"; - case DIV_SYSTEM_X1_010: - return "Seta/Allumer X1-010"; - case DIV_SYSTEM_BUBSYS_WSG: - return "Konami Bubble System WSG"; - case DIV_SYSTEM_ES5506: - return "Ensoniq ES5506"; - } - return "Unknown"; + if (sysDefs[sys]==NULL) return "Unknown"; + return sysDefs[sys]->name; } const char* DivEngine::getSystemNameJ(DivSystem sys) { + if (sysDefs[sys]==NULL) return "不明"; + if (sysDefs[sys]->nameJ==NULL) return ""; + return sysDefs[sys]->nameJ; + /* switch (sys) { case DIV_SYSTEM_NULL: return "不明"; @@ -956,817 +256,49 @@ const char* DivEngine::getSystemNameJ(DivSystem sys) { default: // TODO return ""; } - return "不明"; + */ } bool DivEngine::isFMSystem(DivSystem sys) { - return (sys==DIV_SYSTEM_GENESIS || - sys==DIV_SYSTEM_GENESIS_EXT || - sys==DIV_SYSTEM_SMS_OPLL || - sys==DIV_SYSTEM_NES_VRC7 || - sys==DIV_SYSTEM_ARCADE || - sys==DIV_SYSTEM_YM2610 || - sys==DIV_SYSTEM_YM2610_EXT || - sys==DIV_SYSTEM_YM2610_FULL || - sys==DIV_SYSTEM_YM2610_FULL_EXT || - sys==DIV_SYSTEM_YM2610B || - sys==DIV_SYSTEM_YM2610B_EXT || - sys==DIV_SYSTEM_YMU759 || - sys==DIV_SYSTEM_YM2151 || - sys==DIV_SYSTEM_YM2612); + if (sysDefs[sys]==NULL) return false; + return sysDefs[sys]->isFM; } bool DivEngine::isSTDSystem(DivSystem sys) { - return (sys!=DIV_SYSTEM_ARCADE && - sys!=DIV_SYSTEM_YMU759 && - sys!=DIV_SYSTEM_YM2612 && - sys!=DIV_SYSTEM_YM2151); + if (sysDefs[sys]==NULL) return false; + return sysDefs[sys]->isSTD; } -const char* chanNames[40][32]={ - {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM"}, // YMU759/SegaPCM - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Noise"}, // Genesis - {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Noise"}, // Genesis (extended channel 3) - {"Square 1", "Square 2", "Square 3", "Noise"}, // SMS - {"Pulse 1", "Pulse 2", "Wavetable", "Noise"}, // GB - {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"}, // PCE/ZX Beeper - {"Pulse 1", "Pulse 2", "Triangle", "Noise", "PCM"}, // NES - {"Channel 1", "Channel 2", "Channel 3"}, // C64 - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5"}, // Arcade - {"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, // YM2610 - {"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, // YM2610 (extended channel 2) - {"PSG 1", "PSG 2", "PSG 3"}, // AY-3-8910 - {"Channel 1", "Channel 2", "Channel 3", "Channel 4"}, // Amiga/POKEY/Lynx - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"}, // YM2151/YM2414 - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"}, // YM2612 - {"Channel 1", "Channel 2"}, // TIA - {"PSG 1", "PSG 2", "PSG 3", "PSG 4", "PSG 5", "PSG 6"}, // SAA1099 - {"PSG 1", "PSG 2", "PSG 3"}, // AY8930 - {"Low", "Mid", "High", "Noise"}, // VIC-20 - {"Wave"}, // PET - {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, // SNES/N163/RF5C68 - {"VRC6 1", "VRC6 2", "VRC6 Saw"}, // VRC6 - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"}, // OPLL/OPL/OPL2/VRC7 - {"FDS"}, // FDS - {"Pulse 1", "Pulse 2", "PCM"}, // MMC5 - {"FM 1", "FM 2", "FM 3", "PSG 1", "PSG 2", "PSG 3"}, // OPN - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"}, // PC-98 - {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18"}, // OPL3 - {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28", "Channel 29", "Channel 30", "Channel 31", "Channel 32"}, // MultiPCM/ES5506 - {"Square"}, // PC Speaker/Pokémon Mini - {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Noise"}, // Virtual Boy/SCC - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, // YM2610B - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, // OPLL/OPL/OPL2 drums - {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"}, // OPL3 drums - {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "4OP 1", "4OP 2", "4OP 3", "4OP 4", "4OP 5", "4OP 6"}, // OPL3 4-op (UNUSED) - {"FM 1", "FM 2", "FM 3", "4OP 1", "4OP 2", "4OP 3", "4OP 4", "4OP 5", "4OP 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, // OPL3 4-op + drums (UNUSED) - {"PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "ADPCM 1", "ADPCM 2", "ADPCM 3"}, // QSound - {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, // YM2610B (extended channel 3) - {"Wave", "Wave/PCM", "Wave", "Wave/Noise"}, // Swan - {"PSG 1", "PSG 2", "PSG 3", "PSG 4", "PSG 5", "PSG 6", "PSG 7", "PSG 8", "PSG 9", "PSG 10", "PSG 11", "PSG 12", "PSG 13", "PSG 14", "PSG 15", "PSG 16", "PCM"}, // VERA -}; - -const char* chanShortNames[38][32]={ - {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM"}, // YMU759 - {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "NO"}, // Genesis - {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "S4"}, // Genesis (extended channel 3) - {"S1", "S2", "S3", "NO"}, // SMS - {"S1", "S2", "WA", "NO"}, // GB - {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"}, // PCE - {"S1", "S2", "TR", "NO", "PCM"}, // NES - {"CH1", "CH2", "CH3"}, // C64 - {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "P1", "P2", "P3", "P4", "P5"}, // Arcade - {"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, // YM2610 - {"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, // YM2610 (extended channel 2) - {"S1", "S2", "S3"}, // AY-3-8910 - {"CH1", "CH2", "CH3", "CH4"}, // Amiga/Lynx - {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"}, // YM2151 - {"F1", "F2", "F3", "F4", "F5", "F6"}, // YM2612 - {"CH1", "CH2"}, // TIA - {"S1", "S2", "S3", "S4", "S5", "S6"}, // SAA1099 - {"S1", "S2", "S3"}, // AY8930 - {"LO", "MID", "HI", "NO"}, // VIC-20 - {"PET"}, // PET - {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, // SNES/N163/RF5C68 - {"V1", "V2", "VS"}, // VRC6 - {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"}, // OPLL/OPL/OPL2/VRC7 - {"FDS"}, // FDS - {"S1", "S2", "PCM"}, // MMC5 - {"F1", "F2", "F3", "S1", "S2", "S3"}, // OPN - {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"}, // PC-98 - {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"}, // OPL3 - {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"}, // MultiPCM/ES5506 - {"SQ"}, // PC Speaker/Pokémon Mini - {"CH1", "CH2", "CH3", "CH4", "CH5", "NO"}, // Virtual Boy/SCC - {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, // YM2610B - {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, // OPLL/OPL/OPL2 drums - {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"}, // OPL3 drums - {"F1", "F2", "F3", "F4", "F5", "F6", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6"}, // OPL3 4-op (UNUSED) - {"F1", "F2", "F3", "Q1", "Q2", "Q3", "Q4", "Q5", "Q6", "BD", "SD", "TM", "TP", "HH"}, // OPL3 4-op + drums (UNUSED) - {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "A1", "A2", "A3"}, // QSound - {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, // YM2610B (extended channel 3) -}; - -const int chanTypes[41][32]={ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, // YMU759 - {0, 0, 0, 0, 0, 0, 1, 1, 1, 2}, // Genesis - {0, 0, 5, 5, 5, 5, 0, 0, 0, 1, 1, 1, 2}, // Genesis (extended channel 3) - {1, 1, 1, 2}, // SMS - {1, 1, 3, 2}, // GB - {3, 3, 3, 3, 3, 3}, // PCE - {1, 1, 3, 2, 4}, // NES - {2, 2, 2}, // C64 - {0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4}, // Arcade - {0, 0, 0, 0, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4}, // YM2610 - {0, 5, 5, 5, 5, 0, 0, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4}, // YM2610 (extended channel 2) - {1, 1, 1}, // AY-3-8910 - {4, 4, 4, 4}, // Amiga - {0, 0, 0, 0, 0, 0, 0, 0}, // YM2151 - {0, 0, 0, 0, 0, 0}, // YM2612 - {3, 3}, // TIA - {1, 1, 1, 1, 1, 1}, // SAA1099 - {1, 1, 1}, // AY8930 - {1, 1, 1, 2}, // VIC-20 - {1}, // PET - {4, 4, 4, 4, 4, 4, 4, 4}, // SNES/N163/RF5C68 - {1, 1, 3}, // VRC6 - {0, 0, 0, 0, 0, 0, 0, 0, 0}, // OPLL/OPL/OPL2/VRC7 - {3}, // FDS - {1, 1, 4}, // MMC5 - {0, 0, 0, 1, 1, 1}, // OPN - {0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 4}, // PC-98 - {5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 0}, // OPL3 - {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, // MultiPCM/QSound/ES5506 - {1}, // PC Speaker/Pokémon Mini - {3, 3, 3, 3, 3, 2}, // Virtual Boy/SCC - {0, 0, 0, 0, 0, 0, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4}, // YM2610B - {0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}, // OPLL/OPL/OPL2 drums - {5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 0, 0, 0, 2, 2, 2, 2, 2}, // OPL3 drums - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // OPL3 4-op (UNUSED) - {0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2}, // OPL3 4-op + drums (UNUSED) - {3, 3, 3, 3}, // Lynx - {0, 0, 5, 5, 5, 5, 0, 0, 0, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4}, // YM2610B (extended channel 3) - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4}, // VERA - {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // X1-010 - {3, 4, 3, 2}, // Swan -}; - -const DivInstrumentType chanPrefType[48][32]={ - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM}, // YMU759 - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD}, // Genesis - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD}, // Genesis (extended channel 3) - {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD}, // SMS - {DIV_INS_GB, DIV_INS_GB, DIV_INS_GB, DIV_INS_GB}, // GB - {DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE}, // PCE - {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD}, // NES - {DIV_INS_C64, DIV_INS_C64, DIV_INS_C64}, // C64 - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // Arcade - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // YM2610 - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // YM2610 (extended channel 2) - {DIV_INS_AY, DIV_INS_AY, DIV_INS_AY}, // AY-3-8910 - {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // Amiga - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM}, // YM2151 - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM}, // YM2612 - {DIV_INS_TIA, DIV_INS_TIA}, // TIA - {DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099}, // SAA1099 - {DIV_INS_AY8930, DIV_INS_AY8930, DIV_INS_AY8930}, // AY8930 - {DIV_INS_VIC, DIV_INS_VIC, DIV_INS_VIC, DIV_INS_VIC}, // VIC-20 - {DIV_INS_PET}, // PET - {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // SNES/N163/RF5C68 - {DIV_INS_VRC6, DIV_INS_VRC6, DIV_INS_VRC6_SAW}, // VRC6 - {DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL}, // OPLL/VRC7 - {DIV_INS_FDS}, // FDS - {DIV_INS_STD, DIV_INS_STD, DIV_INS_AMIGA}, // MMC5 - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY}, // OPN - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // PC-98 - {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, // OPL/OPL2/OPL3 - {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // MultiPCM/QSound - {DIV_INS_STD}, // PC Speaker/Pokémon Mini - {DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY}, // Virtual Boy - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // YM2610B - {DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL}, // OPLL drums - {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, // OPL3 drums - {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ}, // OPL3 4-op - {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL}, // OPL3 4-op + drums - {DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC}, // SCC - {DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163}, // N163 - {DIV_INS_POKEY, DIV_INS_POKEY, DIV_INS_POKEY, DIV_INS_POKEY}, // POKEY - {DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER}, // ZX beeper - {DIV_INS_SWAN, DIV_INS_SWAN, DIV_INS_SWAN, DIV_INS_SWAN}, // Swan - {DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ}, // Z - {DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY}, // Lynx - {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, // YM2610B (extended channel 3) - {DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_AMIGA}, // VERA - {DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010}, // X1-010 - {DIV_INS_SCC, DIV_INS_SCC}, // Bubble System WSG - {DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506}, // ES5506 -}; - const char* DivEngine::getChannelName(int chan) { if (chan<0 || chan>chans) return "??"; if (!song.chanName[chan].empty()) return song.chanName[chan].c_str(); - switch (sysOfChan[chan]) { - case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanNames[0][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS: - return chanNames[1][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS_EXT: - case DIV_SYSTEM_YM2612_EXT: - return chanNames[2][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS: - return chanNames[3][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS_OPLL: // this is flattened to SMS + OPLL. - case DIV_SYSTEM_NES_VRC7: // this is flattened to NES + VRC7. - case DIV_SYSTEM_NES_FDS: // this is flattened to NES + FDS. - return "??"; - break; - case DIV_SYSTEM_GB: - return chanNames[4][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCE: - case DIV_SYSTEM_SFX_BEEPER: - case DIV_SYSTEM_BUBSYS_WSG: - return chanNames[5][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_NES: - return chanNames[6][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanNames[7][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_ARCADE: - case DIV_SYSTEM_OPZ: - return chanNames[8][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_YM2610_FULL: - return chanNames[9][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610_EXT: - case DIV_SYSTEM_YM2610_FULL_EXT: - return chanNames[10][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8910: - return chanNames[11][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AMIGA: - case DIV_SYSTEM_POKEY: - case DIV_SYSTEM_LYNX: - return chanNames[12][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SWAN: - return chanNames[38][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2151: - return chanNames[13][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2612: - return chanNames[14][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_TIA: - return chanNames[15][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VIC20: - return chanNames[18][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PET: - return chanNames[19][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SNES: - case DIV_SYSTEM_N163: - case DIV_SYSTEM_RF5C68: - return chanNames[20][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VRC6: - return chanNames[21][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL: - case DIV_SYSTEM_OPL: - case DIV_SYSTEM_OPL2: - case DIV_SYSTEM_VRC7: - return chanNames[22][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_FDS: - return chanNames[23][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MMC5: - return chanNames[24][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPN: - return chanNames[25][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PC98: - return chanNames[26][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3: - return chanNames[27][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MULTIPCM: - case DIV_SYSTEM_SEGAPCM: - case DIV_SYSTEM_SEGAPCM_COMPAT: - case DIV_SYSTEM_X1_010: - case DIV_SYSTEM_ES5506: - return chanNames[28][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCSPKR: - case DIV_SYSTEM_POKEMINI: - return chanNames[29][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VBOY: - case DIV_SYSTEM_SCC: - return chanNames[30][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B: - return chanNames[31][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B_EXT: - return chanNames[37][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL_DRUMS: - case DIV_SYSTEM_OPL_DRUMS: - case DIV_SYSTEM_OPL2_DRUMS: - return chanNames[32][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3_DRUMS: - return chanNames[33][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SAA1099: - return chanNames[16][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8930: - return chanNames[17][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_QSOUND: - return chanNames[36][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VERA: - return chanNames[39][dispatchChanOfChan[chan]]; - break; - } - return "??"; + if (sysDefs[sysOfChan[chan]]==NULL) return "??"; + + const char* ret=sysDefs[sysOfChan[chan]]->chanNames[dispatchChanOfChan[chan]]; + if (ret==NULL) return "??"; + return ret; } const char* DivEngine::getChannelShortName(int chan) { if (chan<0 || chan>chans) return "??"; if (!song.chanShortName[chan].empty()) return song.chanShortName[chan].c_str(); - switch (sysOfChan[chan]) { - case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanShortNames[0][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS: - return chanShortNames[1][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS_EXT: - case DIV_SYSTEM_YM2612_EXT: - return chanShortNames[2][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS: - return chanShortNames[3][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS_OPLL: // this is flattened to SMS + OPLL. - case DIV_SYSTEM_NES_VRC7: // this is flattened to NES + VRC7. - case DIV_SYSTEM_NES_FDS: // this is flattened to NES + FDS. - return "??"; - break; - case DIV_SYSTEM_GB: - return chanShortNames[4][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCE: - case DIV_SYSTEM_SFX_BEEPER: - case DIV_SYSTEM_BUBSYS_WSG: - return chanShortNames[5][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_NES: - return chanShortNames[6][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanShortNames[7][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_ARCADE: - case DIV_SYSTEM_OPZ: - return chanShortNames[8][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_YM2610_FULL: - return chanShortNames[9][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610_EXT: - case DIV_SYSTEM_YM2610_FULL_EXT: - return chanShortNames[10][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8910: - return chanShortNames[11][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AMIGA: - case DIV_SYSTEM_POKEY: - case DIV_SYSTEM_SWAN: - case DIV_SYSTEM_LYNX: - return chanShortNames[12][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2151: - return chanShortNames[13][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2612: - return chanShortNames[14][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_TIA: - return chanShortNames[15][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VIC20: - return chanShortNames[18][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PET: - return chanShortNames[19][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SNES: - case DIV_SYSTEM_N163: - case DIV_SYSTEM_RF5C68: - return chanShortNames[20][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VRC6: - return chanShortNames[21][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL: - case DIV_SYSTEM_OPL: - case DIV_SYSTEM_OPL2: - case DIV_SYSTEM_VRC7: - return chanShortNames[22][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_FDS: - return chanShortNames[23][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MMC5: - return chanShortNames[24][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPN: - return chanShortNames[25][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PC98: - return chanShortNames[26][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3: - return chanShortNames[27][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MULTIPCM: - case DIV_SYSTEM_SEGAPCM: - case DIV_SYSTEM_SEGAPCM_COMPAT: - case DIV_SYSTEM_X1_010: - case DIV_SYSTEM_ES5506: - return chanShortNames[28][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCSPKR: - case DIV_SYSTEM_POKEMINI: - return chanShortNames[29][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VBOY: - case DIV_SYSTEM_SCC: - return chanShortNames[30][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B: - return chanShortNames[31][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B_EXT: - return chanShortNames[37][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL_DRUMS: - case DIV_SYSTEM_OPL_DRUMS: - case DIV_SYSTEM_OPL2_DRUMS: - return chanShortNames[32][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3_DRUMS: - return chanShortNames[33][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SAA1099: - return chanShortNames[16][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8930: - return chanShortNames[17][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_QSOUND: - return chanShortNames[36][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VERA: - return chanShortNames[0][dispatchChanOfChan[chan]]; - break; - } - return "??"; + if (sysDefs[sysOfChan[chan]]==NULL) return "??"; + + const char* ret=sysDefs[sysOfChan[chan]]->chanShortNames[dispatchChanOfChan[chan]]; + if (ret==NULL) return "??"; + return ret; } int DivEngine::getChannelType(int chan) { - switch (sysOfChan[chan]) { - case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanTypes[0][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS: - return chanTypes[1][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS_EXT: - case DIV_SYSTEM_YM2612_EXT: - return chanTypes[2][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS: - return chanTypes[3][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS_OPLL: // this is flattened to SMS + OPLL. - case DIV_SYSTEM_NES_VRC7: // this is flattened to NES + VRC7. - case DIV_SYSTEM_NES_FDS: // this is flattened to NES + FDS. - return 0; - break; - case DIV_SYSTEM_GB: - return chanTypes[4][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCE: - case DIV_SYSTEM_SFX_BEEPER: - case DIV_SYSTEM_BUBSYS_WSG: - return chanTypes[5][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_NES: - return chanTypes[6][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanTypes[7][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_ARCADE: - case DIV_SYSTEM_OPZ: - return chanTypes[8][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_YM2610_FULL: - return chanTypes[9][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610_EXT: - case DIV_SYSTEM_YM2610_FULL_EXT: - return chanTypes[10][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8910: - return chanTypes[11][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AMIGA: - case DIV_SYSTEM_POKEY: - return chanTypes[12][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2151: - return chanTypes[13][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2612: - return chanTypes[14][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_TIA: - return chanTypes[15][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VIC20: - return chanTypes[18][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PET: - return chanTypes[19][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SNES: - case DIV_SYSTEM_N163: - case DIV_SYSTEM_RF5C68: - return chanTypes[20][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VRC6: - return chanTypes[21][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL: - case DIV_SYSTEM_OPL: - case DIV_SYSTEM_OPL2: - case DIV_SYSTEM_VRC7: - return chanTypes[22][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_FDS: - return chanTypes[23][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MMC5: - return chanTypes[24][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPN: - return chanTypes[25][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PC98: - return chanTypes[26][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3: - return chanTypes[27][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MULTIPCM: - case DIV_SYSTEM_SEGAPCM: - case DIV_SYSTEM_SEGAPCM_COMPAT: - case DIV_SYSTEM_QSOUND: - case DIV_SYSTEM_ES5506: - return chanTypes[28][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCSPKR: - case DIV_SYSTEM_POKEMINI: - return chanTypes[29][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VBOY: - case DIV_SYSTEM_SCC: - return chanTypes[30][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B: - return chanTypes[31][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B_EXT: - return chanTypes[37][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL_DRUMS: - case DIV_SYSTEM_OPL_DRUMS: - case DIV_SYSTEM_OPL2_DRUMS: - return chanTypes[32][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL3_DRUMS: - return chanTypes[33][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SAA1099: - return chanTypes[16][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8930: - return chanTypes[17][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_LYNX: - return chanTypes[36][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VERA: - return chanTypes[38][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_X1_010: - return chanTypes[39][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SWAN: - return chanTypes[40][dispatchChanOfChan[chan]]; - break; - } - return 1; + if (chan<0 || chan>chans) return DIV_CH_NOISE; + if (sysDefs[sysOfChan[chan]]==NULL) return DIV_CH_NOISE; + return sysDefs[sysOfChan[chan]]->chanTypes[dispatchChanOfChan[chan]]; } DivInstrumentType DivEngine::getPreferInsType(int chan) { - switch (sysOfChan[chan]) { - case DIV_SYSTEM_NULL: case DIV_SYSTEM_YMU759: - return chanPrefType[0][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS: - return chanPrefType[1][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_GENESIS_EXT: - case DIV_SYSTEM_YM2612_EXT: - return chanPrefType[2][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS: - return chanPrefType[3][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SMS_OPLL: // this is flattened to SMS + OPLL. - case DIV_SYSTEM_NES_VRC7: // this is flattened to NES + VRC7. - return DIV_INS_OPLL; - break; - case DIV_SYSTEM_NES_FDS: // this is flattened to NES + FDS. - return DIV_INS_STD; - break; - case DIV_SYSTEM_GB: - return chanPrefType[4][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCE: - return chanPrefType[5][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_NES: - return chanPrefType[6][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: - return chanPrefType[7][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_ARCADE: - return chanPrefType[8][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610: - case DIV_SYSTEM_YM2610_FULL: - return chanPrefType[9][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610_EXT: - case DIV_SYSTEM_YM2610_FULL_EXT: - return chanPrefType[10][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8910: - return chanPrefType[11][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AMIGA: - return chanPrefType[12][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2151: - return chanPrefType[13][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2612: - return chanPrefType[14][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_TIA: - return chanPrefType[15][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VIC20: - return chanPrefType[18][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PET: - return chanPrefType[19][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SNES: - case DIV_SYSTEM_RF5C68: - return chanPrefType[20][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VRC6: - return chanPrefType[21][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL: - case DIV_SYSTEM_VRC7: - return chanPrefType[22][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_FDS: - return chanPrefType[23][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MMC5: - return chanPrefType[24][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPN: - return chanPrefType[25][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PC98: - return chanPrefType[26][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL: - case DIV_SYSTEM_OPL2: - case DIV_SYSTEM_OPL3: - return chanPrefType[27][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_MULTIPCM: - case DIV_SYSTEM_SEGAPCM: - case DIV_SYSTEM_SEGAPCM_COMPAT: - case DIV_SYSTEM_QSOUND: - return chanPrefType[28][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_PCSPKR: - case DIV_SYSTEM_POKEMINI: - return chanPrefType[29][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VBOY: - return chanPrefType[30][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SCC: - return chanPrefType[36][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_N163: - return chanPrefType[37][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B: - return chanPrefType[31][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_YM2610B_EXT: - return chanPrefType[43][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPLL_DRUMS: - return chanPrefType[32][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPL_DRUMS: - case DIV_SYSTEM_OPL2_DRUMS: - case DIV_SYSTEM_OPL3_DRUMS: - return chanPrefType[33][dispatchChanOfChan[chan]]; - return chanPrefType[33][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SAA1099: - return chanPrefType[16][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_AY8930: - return chanPrefType[17][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_POKEY: - return chanPrefType[38][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SFX_BEEPER: - return chanPrefType[39][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_SWAN: - return chanPrefType[40][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_OPZ: - return chanPrefType[41][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_LYNX: - return chanPrefType[42][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_VERA: - return chanPrefType[44][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_X1_010: - return chanPrefType[45][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_BUBSYS_WSG: - return chanPrefType[46][dispatchChanOfChan[chan]]; - break; - case DIV_SYSTEM_ES5506: - return chanPrefType[47][dispatchChanOfChan[chan]]; - break; - } - return DIV_INS_FM; + if (chan<0 || chan>chans) return DIV_INS_STD; + if (sysDefs[sysOfChan[chan]]==NULL) return DIV_INS_STD; + return sysDefs[sysOfChan[chan]]->chanInsType[dispatchChanOfChan[chan]][0]; } int DivEngine::minVGMVersion(DivSystem which) { @@ -1811,3 +343,597 @@ int DivEngine::minVGMVersion(DivSystem which) { } return 0; } + +// define systems like: +// sysDefs[DIV_SYSTEM_ID]=new DivSysDef( +// "Name", "Name (japanese, optional)", fileID, fileID_DMF, channels, isFM, isSTD, vgmVersion, +// {"Channel Names", ...}, +// {"Channel Short Names", ...}, +// {chanTypes, ...}, +// {chanPreferInsType, ...}, +// {chanPreferInsType2, ...}, (optional) +// [this](int ch, unsigned char effect, unsigned char effectVal) -> bool {}, (effect handler, optional) +// [this](int ch, unsigned char effect, unsigned char effectVal) -> bool {} (post effect handler, optional) +// ); + +void DivEngine::registerSystems() { + logD("registering systems..."); + + sysDefs[DIV_SYSTEM_YMU759]=new DivSysDef( + "Yamaha YMU759", NULL, 0x01, 0x01, 17, true, false, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM" }, // name + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM" }, // short + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM}, // type + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM} // ins + ); + + sysDefs[DIV_SYSTEM_GENESIS]=new DivSysDef( + "Sega Genesis/Mega Drive", "セガメガドライブ", 0x02, 0x02, 10, true, true, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_GENESIS_EXT]=new DivSysDef( + "Sega Genesis Extended Channel 3", NULL, 0x42, 0x42, 13, true, true, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_SMS]=new DivSysDef( + "TI SN76489", NULL, 0x03, 0x03, 4, false, true, 0x150, false, + {"Square 1", "Square 2", "Square 3", "Noise"}, + {"S1", "S2", "S3", "NO"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE}, + {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD} + ); + + sysDefs[DIV_SYSTEM_SMS_OPLL]=new DivSysDef( + "Sega Master System + FM Expansion", NULL, 0x43, 0x43, 13, true, true, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_GB]=new DivSysDef( + "Game Boy", NULL, 0x04, 0x04, 4, false, true, 0x161, false, + {"Pulse 1", "Pulse 2", "Wavetable", "Noise"}, + {"S1", "S2", "WA", "NO"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE}, + {DIV_INS_GB, DIV_INS_GB, DIV_INS_GB, DIV_INS_GB} + ); + + sysDefs[DIV_SYSTEM_PCE]=new DivSysDef( + "PC Engine/TurboGrafx-16", NULL, 0x05, 0x05, 6, false, true, 0x161, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE} + ); + + sysDefs[DIV_SYSTEM_NES]=new DivSysDef( + "NES (Ricoh 2A03)", NULL, 0x06, 0x06, 5, false, true, 0x161, false, + {"Pulse 1", "Pulse 2", "Triangle", "Noise", "PCM"}, + {"S1", "S2", "TR", "NO", "PCM"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE, DIV_CH_NOISE, DIV_CH_PCM}, + {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_NES_VRC7]=new DivSysDef( + "NES + Konami VRC7", NULL, 0x46, 0x46, 11, true, true, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_NES_FDS]=new DivSysDef( + "Famicom Disk System", NULL, 0, 0x86, 6, false, true, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_C64_6581]=new DivSysDef( + "Commodore 64 (6581)", NULL, 0x47, 0x47, 3, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3"}, + {"CH1", "CH2", "CH3"}, + {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_C64, DIV_INS_C64, DIV_INS_C64} + ); + + sysDefs[DIV_SYSTEM_C64_8580]=new DivSysDef( + "Commodore 64 (8580)", NULL, 0x07, 0x07, 3, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3"}, + {"CH1", "CH2", "CH3"}, + {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_C64, DIV_INS_C64, DIV_INS_C64} + ); + + sysDefs[DIV_SYSTEM_ARCADE]=new DivSysDef( + "DefleCade", NULL, 0x08, 0x08, 13, true, false, 0, true, + {}, {}, {}, {} + ); + + sysDefs[DIV_SYSTEM_YM2610]=new DivSysDef( + "Neo Geo CD", NULL, 0x09, 0x09, 13, true, true, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"}, + {"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_YM2610_EXT]=new DivSysDef( + "Neo Geo CD Extended Channel 2", NULL, 0x49, 0x49, 16, true, true, 0x151, false, + {"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6"}, + {"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6"}, + {DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_AY8910]=new DivSysDef( + "AY-3-8910", NULL, 0x80, 0, 3, false, true, 0x151, false, + {"PSG 1", "PSG 2", "PSG 3"}, + {"S1", "S2", "S3"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE}, + {DIV_INS_AY, DIV_INS_AY, DIV_INS_AY} + ); + + sysDefs[DIV_SYSTEM_AMIGA]=new DivSysDef( + "Amiga", NULL, 0x81, 0, 4, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4"}, + {"CH1", "CH2", "CH3", "CH4"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_YM2151]=new DivSysDef( + "Yamaha YM2151", NULL, 0x82, 0, 8, true, false, 0x150, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM} + ); + + sysDefs[DIV_SYSTEM_YM2612]=new DivSysDef( + "Yamaha YM2612", NULL, 0x83, 0, 6, true, false, 0x150, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"}, + {"F1", "F2", "F3", "F4", "F5", "F6"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM}, + {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_TIA]=new DivSysDef( + "Atari 2600", NULL, 0x84, 0, 2, false, true, 0, false, + {"Channel 1", "Channel 2"}, + {"CH1", "CH2"}, + {DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_TIA, DIV_INS_TIA} + ); + + sysDefs[DIV_SYSTEM_SAA1099]=new DivSysDef( + "Philips SAA1099", NULL, 0x97, 0, 6, false, true, 0x171, false, + {"PSG 1", "PSG 2", "PSG 3", "PSG 4", "PSG 5", "PSG 6"}, + {"S1", "S2", "S3", "S4", "S5", "S6"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE}, + {DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099, DIV_INS_SAA1099} + ); + + sysDefs[DIV_SYSTEM_AY8930]=new DivSysDef( + "Microchip AY8930", NULL, 0x9a, 0, 3, false, true, 0x151, false, + {"PSG 1", "PSG 2", "PSG 3"}, + {"S1", "S2", "S3"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE}, + {DIV_INS_AY8930, DIV_INS_AY8930, DIV_INS_AY8930} + ); + + sysDefs[DIV_SYSTEM_VIC20]=new DivSysDef( + "Commodore VIC-20", NULL, 0x85, 0, 4, false, true, 0, false, + {"Low", "Mid", "High", "Noise"}, + {"LO", "MID", "HI", "NO"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE}, + {DIV_INS_VIC, DIV_INS_VIC, DIV_INS_VIC, DIV_INS_VIC} + ); + + sysDefs[DIV_SYSTEM_PET]=new DivSysDef( + "Commodore PET", NULL, 0x86, 0, 1, false, true, 0, false, + {"Wave"}, + {"PET"}, + {DIV_CH_PULSE}, + {DIV_INS_PET} + ); + + // TODO: DIV_INS_SNES + sysDefs[DIV_SYSTEM_SNES]=new DivSysDef( + "SNES", NULL, 0x87, 0, 8, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES} + ); + + sysDefs[DIV_SYSTEM_VRC6]=new DivSysDef( + "Konami VRC6", NULL, 0x88, 0, 3, false, true, 0, false, + {"VRC6 1", "VRC6 2", "VRC6 Saw"}, + {"V1", "V2", "VS"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_WAVE}, + {DIV_INS_VRC6, DIV_INS_VRC6, DIV_INS_VRC6_SAW}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_NULL} + ); + + sysDefs[DIV_SYSTEM_OPLL]=new DivSysDef( + "Yamaha OPLL", NULL, 0x89, 0, 9, true, false, 0x150, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL} + ); + + sysDefs[DIV_SYSTEM_FDS]=new DivSysDef( + "Famicom Disk System (chip)", NULL, 0x8a, 0, 1, false, true, 0x161, false, + {"FDS"}, + {"FDS"}, + {DIV_CH_WAVE}, + {DIV_INS_FDS} + ); + + sysDefs[DIV_SYSTEM_MMC5]=new DivSysDef( + "MMC5", NULL, 0x8b, 0, 3, false, true, 0, false, + {"Pulse 1", "Pulse 2", "PCM"}, + {"S1", "S2", "PCM"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM}, + {DIV_INS_STD, DIV_INS_STD, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_N163]=new DivSysDef( + "Namco 163", NULL, 0x8c, 0, 8, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163} + ); + + sysDefs[DIV_SYSTEM_OPN]=new DivSysDef( + "Yamaha YM2203", NULL, 0x8d, 0, 6, true, false, 0, false, + {"FM 1", "FM 2", "FM 3", "PSG 1", "PSG 2", "PSG 3"}, + {"F1", "F2", "F3", "S1", "S2", "S3"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY} + ); + + sysDefs[DIV_SYSTEM_PC98]=new DivSysDef( + "Yamaha YM2608", NULL, 0x8e, 0, 16, true, false, 0, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Square 1", "Square 2", "Square 3", "Kick", "Snare", "Top", "HiHat", "Tom", "Rim", "ADPCM"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "BD", "SD", "TP", "HH", "TM", "RM", "P"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_OPL]=new DivSysDef( + "Yamaha OPL", NULL, 0x8f, 0, 9, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_OPL2]=new DivSysDef( + "Yamaha OPL2", NULL, 0x90, 0, 9, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_OPL3]=new DivSysDef( + "Yamaha OPL3", NULL, 0x91, 0, 18, true, false, 0x151, false, + {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18"}, + {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_MULTIPCM]=new DivSysDef( + "MultiPCM", NULL, 0x92, 0, 28, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM} + ); + + sysDefs[DIV_SYSTEM_PCSPKR]=new DivSysDef( + "PC Speaker", NULL, 0x93, 0, 1, false, true, 0, false, + {"Square"}, + {"SQ"}, + {DIV_CH_PULSE}, + {DIV_INS_STD} + ); + + sysDefs[DIV_SYSTEM_POKEY]=new DivSysDef( + "POKEY", NULL, 0x94, 0, 4, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4"}, + {"CH1", "CH2", "CH3", "CH4"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_POKEY, DIV_INS_POKEY, DIV_INS_POKEY, DIV_INS_POKEY} + ); + + sysDefs[DIV_SYSTEM_RF5C68]=new DivSysDef( + "Ricoh RF5C68", NULL, 0x95, 0, 8, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_SWAN]=new DivSysDef( + "WonderSwan", NULL, 0x96, 0, 4, false, true, 0x171, false, + {"Wave", "Wave/PCM", "Wave", "Wave/Noise"}, + {"CH1", "CH2", "CH3", "CH4"}, + {DIV_CH_WAVE, DIV_CH_PCM, DIV_CH_WAVE, DIV_CH_NOISE}, + {DIV_INS_SWAN, DIV_INS_SWAN, DIV_INS_SWAN, DIV_INS_SWAN}, + {DIV_INS_NULL, DIV_INS_AMIGA, DIV_INS_NULL, DIV_INS_NULL} + ); + + sysDefs[DIV_SYSTEM_OPZ]=new DivSysDef( + "Yamaha TX81Z/YS200", NULL, 0x98, 0, 8, true, false, 0, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ, DIV_INS_OPZ} + ); + + sysDefs[DIV_SYSTEM_POKEMINI]=new DivSysDef( + "Pokémon Mini", NULL, 0x99, 0, 1, false, true, 0, false, + {"Square"}, + {"SQ"}, + {DIV_CH_PULSE}, + {DIV_INS_STD} + ); + + sysDefs[DIV_SYSTEM_SEGAPCM]=new DivSysDef( + "SegaPCM", NULL, 0x9b, 0, 16, false, true, 0x151, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_VBOY]=new DivSysDef( + "Virtual Boy", NULL, 0x9c, 0, 6, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Noise"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "NO"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_NOISE}, + {DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY} + ); + + sysDefs[DIV_SYSTEM_VRC7]=new DivSysDef( + "Konami VRC7", NULL, 0x9d, 0, 6, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6"}, + {"F1", "F2", "F3", "F4", "F5", "F6"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL} + ); + + sysDefs[DIV_SYSTEM_YM2610B]=new DivSysDef( + "Yamaha YM2610B", NULL, 0x9e, 0, 16, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_SFX_BEEPER]=new DivSysDef( + "ZX Spectrum Beeper", NULL, 0x9f, 0, 6, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER} + ); + + sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef( + "Yamaha YM2612 Extended Channel 3", NULL, 0xa0, 0, 9, true, false, 0x150, false, + {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6"}, + {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM}, + {DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_NULL, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_SCC]=new DivSysDef( + "Konami SCC", NULL, 0xa1, 0, 5, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"}, + {"CH1", "CH2", "CH3", "CH4", "CH5"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC} + ); + + sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef( + "Yamaha OPL with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef( + "Yamaha OPL2 with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef( + "Yamaha OPL3 with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false, + {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"}, + {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL} + ); + + sysDefs[DIV_SYSTEM_YM2610_FULL]=new DivSysDef( + "Yamaha YM2610", NULL, 0xa5, 0, 14, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, + {"F1", "F2", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_YM2610_FULL_EXT]=new DivSysDef( + "Yamaha YM2610 Extended Channel 2", NULL, 0xa6, 0, 17, true, false, 0x151, false, + {"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, + {"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, + {DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_OPLL_DRUMS]=new DivSysDef( + "Yamaha OPLL with drums", NULL, 0xa7, 0, 11, true, false, 0x150, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL, DIV_INS_OPLL} + ); + + sysDefs[DIV_SYSTEM_LYNX]=new DivSysDef( + "Atari Lynx", NULL, 0xa8, 0, 4, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4"}, + {"CH1", "CH2", "CH3", "CH4"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY} + ); + + sysDefs[DIV_SYSTEM_QSOUND]=new DivSysDef( + "Capcom QSound", NULL, 0xe0, 0, 19, false, true, 0x161, false, + {"PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "ADPCM 1", "ADPCM 2", "ADPCM 3"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "A1", "A2", "A3"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_VERA]=new DivSysDef( + "VERA", NULL, 0xac, 0, 17, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "PCM"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "PCM"}, + {DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM}, + {DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_VERA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_YM2610B_EXT]=new DivSysDef( + "Yamaha YM2610B Extended Channel 3", NULL, 0xde, 0, 19, true, false, 0x151, false, + {"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"}, + {"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_FM, DIV_INS_AY, DIV_INS_AY, DIV_INS_AY, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_SEGAPCM_COMPAT]=new DivSysDef( + "SegaPCM (compatible 5-channel mode)", NULL, 0xa9, 0, 5, false, true, 0x151, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"}, + {"P1", "P2", "P3", "P4", "P5"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_X1_010]=new DivSysDef( + "Seta/Allumer X1-010", NULL, 0xb0, 0, 16, false, true, 0x171, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010, DIV_INS_X1_010}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_BUBSYS_WSG]=new DivSysDef( + "Konami Bubble System WSG", NULL, 0xad, 0, 2, false, true, 0, false, + {"Channel 1", "Channel 2"}, + {"CH1", "CH2"}, + {DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_SCC, DIV_INS_SCC} + ); + + // to Grauw: feel free to change this to 24 during development of OPL4's PCM part. + sysDefs[DIV_SYSTEM_OPL4]=new DivSysDef( + "Yamaha OPL4", NULL, 0xae, 0, 42, true, true, 0, false, + {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "FM 16", "FM 17", "FM 18", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"}, + {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM} + ); + + sysDefs[DIV_SYSTEM_OPL4_DRUMS]=new DivSysDef( + "Yamaha OPL4 with drums", NULL, 0xaf, 0, 44, true, true, 0, false, + {"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM 1", "PCM 2", "PCM 3", "PCM 4", "PCM 5", "PCM 6", "PCM 7", "PCM 8", "PCM 9", "PCM 10", "PCM 11", "PCM 12", "PCM 13", "PCM 14", "PCM 15", "PCM 16", "PCM 17", "PCM 18", "PCM 19", "PCM 20", "PCM 21", "PCM 22", "PCM 23", "PCM 24"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"}, + {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM} + ); + + sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef( + "Ensoniq ES5506", NULL, 0xb1, 0, 32, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8", "Channel 9", "Channel 10", "Channel 11", "Channel 12", "Channel 13", "Channel 14", "Channel 15", "Channel 16", "Channel 17", "Channel 18", "Channel 19", "Channel 20", "Channel 21", "Channel 22", "Channel 23", "Channel 24", "Channel 25", "Channel 26", "Channel 27", "Channel 28", "Channel 29", "Channel 30", "Channel 31", "Channel 32"}, + {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506, DIV_INS_ES5506} + ); + + sysDefs[DIV_SYSTEM_Y8950]=new DivSysDef( + "Yamaha Y8950", NULL, 0xb2, 0, 10, true, false, 0, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef( + "Yamaha Y8950 with drums", NULL, 0xb3, 0, 12, true, false, 0, false, + {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"}, + {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"}, + {DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM}, + {DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_SCC_PLUS]=new DivSysDef( + "Konami SCC+", NULL, 0xb4, 0, 5, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5"}, + {"CH1", "CH2", "CH3", "CH4", "CH5"}, + {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE}, + {DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC, DIV_INS_SCC} + ); + + sysDefs[DIV_SYSTEM_SOUND_UNIT]=new DivSysDef( + "tildearrow Sound Unit", NULL, 0xb5, 0, 8, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_SU, DIV_INS_SU, DIV_INS_SU, DIV_INS_SU, DIV_INS_SU, DIV_INS_SU, DIV_INS_SU, DIV_INS_SU}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_MSM6295]=new DivSysDef( + "OKI MSM6295", NULL, 0xaa, 0, 4, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4"}, + {"CH1", "CH2", "CH3", "CH4"}, + {DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM}, + {DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_MSM6258]=new DivSysDef( + "OKI MSM6258", NULL, 0xab, 0, 1, false, true, 0, false, + {"Sample"}, + {"PCM"}, + {DIV_CH_PCM}, + {DIV_INS_AMIGA} + ); + + sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef( + "Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false, + {"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6", "Channel 7", "Channel 8"}, + {"CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", "CH8"}, + {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, + {DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD, DIV_INS_STD} + ); + + for (int i=0; i<256; i++) { + if (sysDefs[i]==NULL) continue; + if (sysDefs[i]->id!=0) { + sysFileMapFur[sysDefs[i]->id]=(DivSystem)i; + } + if (sysDefs[i]->id_DMF!=0) { + sysFileMapDMF[sysDefs[i]->id_DMF]=(DivSystem)i; + } + } + + systemsRegistered=true; +} diff --git a/src/gui/dataList.cpp b/src/gui/dataList.cpp index 1776caa6..652c2eb9 100644 --- a/src/gui/dataList.cpp +++ b/src/gui/dataList.cpp @@ -191,6 +191,18 @@ void FurnaceGUI::drawInsList() { ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_ES5506]); name=fmt::sprintf(ICON_FA_VOLUME_UP " %.2X: %s##_INS%d",i,ins->name,i); break; + case DIV_INS_MULTIPCM: + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_MULTIPCM]); + name=fmt::sprintf(ICON_FA_VOLUME_UP " %.2X: %s##_INS%d",i,ins->name,i); + break; + case DIV_INS_SNES: + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SNES]); + name=fmt::sprintf(ICON_FA_VOLUME_UP " %.2X: %s##_INS%d",i,ins->name,i); + break; + case DIV_INS_SU: + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SU]); + name=fmt::sprintf(ICON_FA_MICROCHIP " %.2X: %s##_INS%d",i,ins->name,i); + break; default: ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]); name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d",i,ins->name,i); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 4aa37b81..372cf998 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -505,9 +505,11 @@ bool FurnaceGUI::CWVSliderInt(const char* label, const ImVec2& size, int* v, int } const char* FurnaceGUI::getSystemName(DivSystem which) { + /* if (settings.chipNames) { return e->getSystemChips(which); } + */ return e->getSystemName(which); } @@ -1286,6 +1288,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { ); break; case GUI_FILE_INS_OPEN: + prevIns=-3; if (!dirExists(workingDirIns)) workingDirIns=getHomeDir(); hasOpened=fileDialog->openLoad( "Load Instrument", @@ -1298,6 +1301,9 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { std::vector instruments=e->instrumentFromFile(path); if (!instruments.empty()) { e->loadTempIns(instruments[0]); + if (curIns!=-2) { + prevIns=curIns; + } curIns=-2; } for (DivInstrument* i: instruments) delete i; @@ -2666,6 +2672,7 @@ bool FurnaceGUI::loop() { ImGui::Separator(); if (ImGui::BeginMenu("add system...")) { for (int j=0; availableSystems[j]; j++) { + if (!settings.hiddenSystems && (availableSystems[j]==DIV_SYSTEM_YMU759 || availableSystems[j]==DIV_SYSTEM_DUMMY || availableSystems[j]==DIV_SYSTEM_SOUND_UNIT)) continue; sysAddOption((DivSystem)availableSystems[j]); } ImGui::EndMenu(); @@ -2683,6 +2690,7 @@ bool FurnaceGUI::loop() { for (int i=0; isong.systemLen; i++) { if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { for (int j=0; availableSystems[j]; j++) { + if (!settings.hiddenSystems && (availableSystems[j]==DIV_SYSTEM_YMU759 || availableSystems[j]==DIV_SYSTEM_DUMMY || availableSystems[j]==DIV_SYSTEM_SOUND_UNIT)) continue; sysChangeOption(i,(DivSystem)availableSystems[j]); } ImGui::EndMenu(); @@ -2937,6 +2945,9 @@ bool FurnaceGUI::loop() { workingDirLayout=fileDialog->getPath()+DIR_SEPARATOR_STR; break; } + if (prevIns!=-3) { + curIns=prevIns; + } if (fileDialog->accepted()) { fileName=fileDialog->getFileName(); if (fileName!="") { @@ -3791,6 +3802,7 @@ FurnaceGUI::FurnaceGUI(): curSample(0), curOctave(3), curOrder(0), + prevIns(0), oldRow(0), oldOrder(0), oldOrder1(0), @@ -3878,6 +3890,7 @@ FurnaceGUI::FurnaceGUI(): lockLayout(false), editOptsVisible(false), latchNibble(false), + nonLatchNibble(false), curWindow(GUI_WINDOW_NOTHING), nextWindow(GUI_WINDOW_NOTHING), nextDesc(NULL), diff --git a/src/gui/gui.h b/src/gui/gui.h index 9aa7ec28..e5ac963b 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -146,6 +146,9 @@ enum FurnaceGUIColors { GUI_COLOR_INSTR_X1_010, GUI_COLOR_INSTR_VRC6_SAW, GUI_COLOR_INSTR_ES5506, + GUI_COLOR_INSTR_MULTIPCM, + GUI_COLOR_INSTR_SNES, + GUI_COLOR_INSTR_SU, GUI_COLOR_INSTR_UNKNOWN, GUI_COLOR_CHANNEL_FM, @@ -845,6 +848,7 @@ class FurnaceGUI { int absorbInsInput; int eventDelay; int moveWindowTitle; + int hiddenSystems; unsigned int maxUndoSteps; String mainFontPath; String patFontPath; @@ -922,6 +926,7 @@ class FurnaceGUI { absorbInsInput(0), eventDelay(0), moveWindowTitle(0), + hiddenSystems(0), maxUndoSteps(100), mainFontPath(""), patFontPath(""), @@ -932,7 +937,7 @@ class FurnaceGUI { char finalLayoutPath[4096]; - int curIns, curWave, curSample, curOctave, curOrder, oldRow, oldOrder, oldOrder1, editStep, exportLoops, soloChan, soloTimeout, orderEditMode, orderCursor; + int curIns, curWave, curSample, curOctave, curOrder, prevIns, oldRow, oldOrder, oldOrder1, editStep, exportLoops, soloChan, soloTimeout, orderEditMode, orderCursor; int loopOrder, loopRow, loopEnd, isClipping, extraChannelButtons, patNameTarget, newSongCategory, latchTarget; int wheelX, wheelY; @@ -950,7 +955,7 @@ class FurnaceGUI { SelectionPoint selStart, selEnd, cursor; bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders; - bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble; + bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble, nonLatchNibble; FurnaceGUIWindows curWindow, nextWindow; float peak[2]; float patChanX[DIV_MAX_CHANS+1]; diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 96ec52c7..18c2fef1 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -107,7 +107,10 @@ const char* insTypes[DIV_INS_MAX]={ "VERA", "X1-010", "VRC6 (saw)", - "ES5506" + "ES5506", + "MultiPCM", + "SNES", + "Sound Unit", }; const char* sampleDepths[DIV_SAMPLE_DEPTH_MAX]={ @@ -517,7 +520,10 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={ D(GUI_COLOR_INSTR_VERA,"",ImVec4(0.4f,0.6f,1.0f,1.0f)), D(GUI_COLOR_INSTR_X1_010,"",ImVec4(0.3f,0.5f,1.0f,1.0f)), D(GUI_COLOR_INSTR_VRC6_SAW,"",ImVec4(0.8f,0.3f,0.0f,1.0f)), - D(GUI_COLOR_INSTR_ES5506,"",ImVec4(1.0f,0.5f,0.5f,1.0f)), + D(GUI_COLOR_INSTR_ES5506,"",ImVec4(0.5f,0.5f,1.0f,1.0f)), + D(GUI_COLOR_INSTR_MULTIPCM,"",ImVec4(1.0f,0.8f,0.1f,1.0f)), + D(GUI_COLOR_INSTR_SNES,"",ImVec4(0.8f,0.7f,1.0f,1.0f)), + D(GUI_COLOR_INSTR_SU,"",ImVec4(0.95f,0.98f,1.0f,1.0f)), D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)), D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)), @@ -596,6 +602,9 @@ const int availableSystems[]={ DIV_SYSTEM_AY8910, DIV_SYSTEM_AMIGA, DIV_SYSTEM_PCSPKR, + DIV_SYSTEM_YMU759, + DIV_SYSTEM_DUMMY, + DIV_SYSTEM_SOUND_UNIT, DIV_SYSTEM_OPLL, DIV_SYSTEM_OPLL_DRUMS, DIV_SYSTEM_VRC7, diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 61493722..5630f074 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -952,6 +952,13 @@ void FurnaceGUI::drawSettings() { settings.oplStandardWaveNames=oplStandardWaveNamesB; } + if (nonLatchNibble) { + bool hiddenSystemsB=settings.hiddenSystems; + if (ImGui::Checkbox(":smile: :star_struck: :sunglasses: :ok_hand:",&hiddenSystemsB)) { + settings.hiddenSystems=hiddenSystemsB; + } + } + bool overflowHighlightB=settings.overflowHighlight; if (ImGui::Checkbox("Overflow pattern highlights",&overflowHighlightB)) { settings.overflowHighlight=overflowHighlightB; @@ -1167,6 +1174,10 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_INSTR_MIKEY,"Lynx"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VERA,"VERA"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_X1_010,"X1-010"); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_ES5506,"ES5506"); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_MULTIPCM,"MultiPCM"); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_SNES,"SNES"); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_SU,"Sound Unit"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown"); ImGui::TreePop(); } @@ -1668,6 +1679,7 @@ void FurnaceGUI::syncSettings() { settings.absorbInsInput=e->getConfInt("absorbInsInput",0); settings.eventDelay=e->getConfInt("eventDelay",0); settings.moveWindowTitle=e->getConfInt("moveWindowTitle",0); + settings.hiddenSystems=e->getConfInt("hiddenSystems",0); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -1734,6 +1746,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.absorbInsInput,0,1); clampSetting(settings.eventDelay,0,1); clampSetting(settings.moveWindowTitle,0,1); + clampSetting(settings.hiddenSystems,0,1); // keybinds for (int i=0; isetConf("absorbInsInput",settings.absorbInsInput); e->setConf("eventDelay",settings.eventDelay); e->setConf("moveWindowTitle",settings.moveWindowTitle); + e->setConf("hiddenSystems",settings.hiddenSystems); // colors for (int i=0; isong.name)) { MARK_MODIFIED updateWindowTitle(); } + if (e->song.name.size()==27) { + unsigned int checker=0x11111111; + unsigned int checker1=0; + for (int i=0; i<27; i++) { + checker^=e->song.name[i]<song.name[i]; + checker=(checker>>1|(((checker)^(checker>>2)^(checker>>3)^(checker>>5))&1)<<31); + checker1<<=1; + } + if (checker==0x94ffb4f7 && checker1==0x801c68a6) nonLatchNibble=true; + } ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("Author"); @@ -173,4 +184,4 @@ void FurnaceGUI::drawSongInfo() { } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_SONG_INFO; ImGui::End(); -} \ No newline at end of file +}