/** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2024 tildearrow and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "dispatch.h" #include "engine.h" #include "instrument.h" #include "song.h" #include "../ta-log.h" DivSysDef* DivEngine::sysDefs[DIV_MAX_CHIP_DEFS]; DivSystem DivEngine::sysFileMapFur[DIV_MAX_CHIP_DEFS]; DivSystem DivEngine::sysFileMapDMF[DIV_MAX_CHIP_DEFS]; DivSystem DivEngine::systemFromFileFur(unsigned char val) { return sysFileMapFur[val]; } unsigned char DivEngine::systemToFileFur(DivSystem val) { if (sysDefs[val]==NULL) return 0; return sysDefs[val]->id; } DivSystem DivEngine::systemFromFileDMF(unsigned char val) { return sysFileMapDMF[val]; } unsigned char DivEngine::systemToFileDMF(DivSystem val) { if (sysDefs[val]==NULL) return 0; return sysDefs[val]->id_DMF; } int DivEngine::getChannelCount(DivSystem sys) { if (sysDefs[sys]==NULL) return 0; return sysDefs[sys]->channels; } int DivEngine::getTotalChannelCount() { return chans; } std::vector& DivEngine::getPossibleInsTypes() { return possibleInsTypes; } // for pre-dev103 modules String DivEngine::getSongSystemLegacyName(DivSong& ds, bool isMultiSystemAcceptable) { switch (ds.systemLen) { case 0: return "help! what's going on!"; case 1: if (ds.system[0]==DIV_SYSTEM_AY8910) { switch (ds.systemFlags[0].getInt("chipType",0)) { case 0: // AY-3-8910 switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: // AY-3-8910, 1.79MHz case 1: // AY-3-8910, 1.77MHz case 2: // AY-3-8910, 1.75MHz return "ZX Spectrum"; case 3: // AY-3-8910, 2MHz return "Fujitsu Micro-7"; case 4: // AY-3-8910, 1.5MHz return "Vectrex"; case 5: // AY-3-8910, 1MHz return "Amstrad CPC"; default: return "AY-3-8910"; } break; case 1: // YM2149 switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: // YM2149, 1.79MHz return "MSX"; case 3: // YM2149, 2MHz return "Atari ST"; default: return "Yamaha YM2149"; } break; case 2: // 5B switch (ds.systemFlags[0].getInt("clockSel",0)) { case 6: // 5B NTSC return "Sunsoft 5B standalone"; case 8: // 5B PAL return "Sunsoft 5B standalone (PAL)"; default: return "Overclocked Sunsoft 5B"; } break; case 3: // AY-3-8914 switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: // AY-3-8914, 1.79MHz return "Intellivision"; case 3: // AY-3-8914, 2MHz return "Intellivision (PAL)"; default: return "Intellivision"; } break; } } else if (ds.system[0]==DIV_SYSTEM_SMS) { switch (ds.systemFlags[0].getInt("chipType",0)) { case 0: switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: case 1: return "Sega Master System"; } break; case 1: switch (ds.systemFlags[0].getInt("clockSel",0)) { case 2: return "BBC Micro"; } break; } } else if (ds.system[0]==DIV_SYSTEM_YM2612) { switch (ds.systemFlags[0].getInt("clockSel",0)) { case 2: return "FM Towns"; } } else if (ds.system[0]==DIV_SYSTEM_YM2151) { switch (ds.systemFlags[0].getInt("clockSel",0)) { case 2: return "Sharp X68000"; } } else if (ds.system[0]==DIV_SYSTEM_SAA1099) { switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: return "SAM Coupé"; } } return getSystemName(ds.system[0]); case 2: if (ds.system[0]==DIV_SYSTEM_YM2612 && ds.system[1]==DIV_SYSTEM_SMS) { return "Sega Genesis/Mega Drive"; } if (ds.system[0]==DIV_SYSTEM_YM2612_EXT && ds.system[1]==DIV_SYSTEM_SMS) { return "Sega Genesis Extended Channel 3"; } if (ds.system[0]==DIV_SYSTEM_OPLL && ds.system[1]==DIV_SYSTEM_SMS) { return "NTSC-J Sega Master System"; } if (ds.system[0]==DIV_SYSTEM_OPLL_DRUMS && ds.system[1]==DIV_SYSTEM_SMS) { return "NTSC-J Sega Master System + drums"; } if (ds.system[0]==DIV_SYSTEM_OPLL && ds.system[1]==DIV_SYSTEM_AY8910) { return "MSX-MUSIC"; } if (ds.system[0]==DIV_SYSTEM_OPLL_DRUMS && ds.system[1]==DIV_SYSTEM_AY8910) { return "MSX-MUSIC + drums"; } if (ds.system[0]==DIV_SYSTEM_C64_6581 && ds.system[1]==DIV_SYSTEM_C64_6581) { return "Commodore 64 with dual 6581"; } if (ds.system[0]==DIV_SYSTEM_C64_8580 && ds.system[1]==DIV_SYSTEM_C64_8580) { return "Commodore 64 with dual 8580"; } if (ds.system[0]==DIV_SYSTEM_YM2151 && ds.system[1]==DIV_SYSTEM_SEGAPCM_COMPAT) { return "YM2151 + SegaPCM Arcade (compatibility)"; } if (ds.system[0]==DIV_SYSTEM_YM2151 && ds.system[1]==DIV_SYSTEM_SEGAPCM) { return "YM2151 + SegaPCM Arcade"; } if (ds.system[0]==DIV_SYSTEM_SAA1099 && ds.system[1]==DIV_SYSTEM_SAA1099) { return "Creative Music System"; } if (ds.system[0]==DIV_SYSTEM_GB && ds.system[1]==DIV_SYSTEM_AY8910) { return "Game Boy with AY expansion"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_VRC6) { return "Famicom + Konami VRC6"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_VRC7) { return "Famicom + Konami VRC7"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_OPLL) { return "Family Noraebang"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_FDS) { return "Famicom Disk System"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_N163) { return "Famicom + Namco 163"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_MMC5) { return "Famicom + MMC5"; } if (ds.system[0]==DIV_SYSTEM_NES && ds.system[1]==DIV_SYSTEM_AY8910) { return "Famicom + Sunsoft 5B"; } if (ds.system[0]==DIV_SYSTEM_AY8910 && ds.system[1]==DIV_SYSTEM_AY8910) { return "Bally Midway MCR"; } if (ds.system[0]==DIV_SYSTEM_YM2151 && ds.system[1]==DIV_SYSTEM_VERA) { return "Commander X16"; } break; case 3: if (ds.system[0]==DIV_SYSTEM_AY8910 && ds.system[1]==DIV_SYSTEM_AY8910 && ds.system[2]==DIV_SYSTEM_BUBSYS_WSG) { return "Konami Bubble System"; } break; } if (isMultiSystemAcceptable) return "multi-system"; String ret=""; for (int i=0; i0) ret+=" + "; ret+=getSystemName(ds.system[i]); } return ret; } const char* DivEngine::getSystemName(DivSystem sys) { 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 "不明"; case DIV_SYSTEM_YMU759: return ""; case DIV_SYSTEM_GENESIS: return "セガメガドライブ"; case DIV_SYSTEM_SMS: case DIV_SYSTEM_SMS_OPLL: return "セガマスターシステム"; case DIV_SYSTEM_GB: return "ゲームボーイ"; case DIV_SYSTEM_PCE: return "PCエンジン"; case DIV_SYSTEM_NES: return "ファミリーコンピュータ"; case DIV_SYSTEM_C64_6581: return "コモドール64 (6581)"; case DIV_SYSTEM_C64_8580: return "コモドール64 (8580)"; case DIV_SYSTEM_ARCADE: return "Arcade"; case DIV_SYSTEM_GENESIS_EXT: return ""; case DIV_SYSTEM_YM2610: return "業務用ネオジオ"; case DIV_SYSTEM_YM2610_EXT: return "業務用ネオジオ"; case DIV_SYSTEM_YM2610_FULL: return "業務用ネオジオ"; case DIV_SYSTEM_YM2610_FULL_EXT: return "業務用ネオジオ"; case DIV_SYSTEM_AY8910: return ""; case DIV_SYSTEM_AMIGA: return ""; case DIV_SYSTEM_YM2151: return ""; case DIV_SYSTEM_YM2612: return ""; case DIV_SYSTEM_TIA: return ""; case DIV_SYSTEM_SAA1099: return ""; case DIV_SYSTEM_AY8930: return ""; default: // TODO return ""; } */ } const DivSysDef* DivEngine::getSystemDef(DivSystem sys) { return sysDefs[sys]; } bool DivEngine::isFMSystem(DivSystem sys) { if (sysDefs[sys]==NULL) return false; return sysDefs[sys]->isFM; } bool DivEngine::isSTDSystem(DivSystem sys) { if (sysDefs[sys]==NULL) return false; return sysDefs[sys]->isSTD; } const char* DivEngine::getChannelName(int chan) { if (chan<0 || chan>chans) return "??"; if (!curSubSong->chanName[chan].empty()) return curSubSong->chanName[chan].c_str(); 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 (!curSubSong->chanShortName[chan].empty()) return curSubSong->chanShortName[chan].c_str(); 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) { 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) { 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]; } DivInstrumentType DivEngine::getPreferInsSecondType(int chan) { if (chan<0 || chan>chans) return DIV_INS_NULL; if (sysDefs[sysOfChan[chan]]==NULL) return DIV_INS_NULL; return sysDefs[sysOfChan[chan]]->chanInsType[dispatchChanOfChan[chan]][1]; } int DivEngine::minVGMVersion(DivSystem which) { if (sysDefs[which]==NULL) return 0; return sysDefs[which]->vgmVersion; } #define IS_YM2610 (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610B || sysOfChan[ch]==DIV_SYSTEM_YM2610B_EXT) #define IS_OPM_LIKE (sysOfChan[ch]==DIV_SYSTEM_YM2151 || sysOfChan[ch]==DIV_SYSTEM_OPZ) #define OP_EFFECT_MULTI(x,c,op,mask) \ case x: \ dispatchCmd(DivCommand(c,ch,op,effectVal&mask)); \ break; #define OP_EFFECT_SINGLE(x,c,maxOp,mask) \ case x: \ if ((effectVal>>4)>=0 && (effectVal>>4)<=maxOp) { \ dispatchCmd(DivCommand(c,ch,(effectVal>>4)-1,effectVal&mask)); \ } \ break; // define systems like: // sysDefs[DIV_SYSTEM_ID]=new DivSysDef( // "Name", "Name (japanese, optional)", fileID, fileID_DMF, channels, isFM, isSTD, vgmVersion, waveWidth, waveHeight, // "Description", // {"Channel Names", ...}, // {"Channel Short Names", ...}, // {chanTypes, ...}, // {chanPreferInsType, ...}, // {chanPreferInsType2, ...}, (optional) // {{effect, {DIV_CMD_xx, "Description"}}, ...}, (effect handler, optional) // {{effect, {DIV_CMD_xx, "Description"}}, ...} (post effect handler, optional) // ); template int constVal(unsigned char, unsigned char) { return val; }; int effectVal(unsigned char, unsigned char val) { return val; }; int negEffectVal(unsigned char, unsigned char val) { return -(int)val; }; template int effectValAnd(unsigned char, unsigned char val) { return val&mask; }; template int effectValShift(unsigned char, unsigned char val) { return val< int effectOpVal(unsigned char, unsigned char val) { if ((val>>4)>maxOp) throw DivDoNotHandleEffect(); return (val>>4)-1; }; template int effectOpValNoZero(unsigned char, unsigned char val) { if ((val>>4)<1 || (val>>4)>maxOp) throw DivDoNotHandleEffect(); return (val>>4)-1; }; template int effectValLong(unsigned char cmd, unsigned char val) { return ((((unsigned int)cmd)&((1<<(bits-8))-1))<<8)|((unsigned int)val); }; template int effectValLongShift(unsigned char cmd, unsigned char val) { return (((((unsigned int)cmd)&((1<<(bits-8))-1))<<8)|((unsigned int)val))<, effectVal}}, {0x2f, {DIV_CMD_AY_IO_WRITE, _("2Fxx: Write to I/O port B"), constVal<1>, effectVal}}, }; EffectHandlerMap ay8930PostEffectHandlerMap={ {0x20, {DIV_CMD_STD_NOISE_MODE, _("20xx: Set channel mode (bit 0: square; bit 1: noise; bit 2: envelope)")}}, {0x21, {DIV_CMD_STD_NOISE_FREQ, _("21xx: Set noise frequency (0 to FF)")}}, {0x22, {DIV_CMD_AY_ENVELOPE_SET, _("22xy: Set envelope mode (x: shape, y: enable for this channel)")}}, {0x23, {DIV_CMD_AY_ENVELOPE_LOW, _("23xx: Set envelope period low byte")}}, {0x24, {DIV_CMD_AY_ENVELOPE_HIGH, _("24xx: Set envelope period high byte")}}, {0x25, {DIV_CMD_AY_ENVELOPE_SLIDE, _("25xx: Envelope slide up"), negEffectVal}}, {0x26, {DIV_CMD_AY_ENVELOPE_SLIDE, _("26xx: Envelope slide down")}}, {0x29, {DIV_CMD_AY_AUTO_ENVELOPE, _("29xy: Set auto-envelope (x: numerator; y: denominator)")}}, {0x2e, {DIV_CMD_AY_IO_WRITE, _("2Exx: Write to I/O port A"), constVal<0>, effectVal}}, {0x2f, {DIV_CMD_AY_IO_WRITE, _("2Fxx: Write to I/O port B"), constVal<1>, effectVal}}, {0x12, {DIV_CMD_STD_NOISE_MODE, _("12xx: Set duty cycle (0 to 8)"), [](unsigned char, unsigned char val) -> int { return 0x10+(val&15); }}}, {0x27, {DIV_CMD_AY_NOISE_MASK_AND, _("27xx: Set noise AND mask")}}, {0x28, {DIV_CMD_AY_NOISE_MASK_OR, _("28xx: Set noise OR mask")}}, {0x2c, {DIV_CMD_AY_AUTO_PWM, _("2Cxy: Automatic noise frequency (x: mode (0: disable, 1: freq, 2: freq + OR mask); y: offset)")}}, {0x2d, {DIV_CMD_AY_IO_WRITE, _("2Dxx: NOT TO BE EMPLOYED BY THE COMPOSER"), constVal<255>, effectVal}}, }; EffectHandlerMap fmEffectHandlerMap={ {0x30, {DIV_CMD_FM_HARD_RESET, _("30xx: Toggle hard envelope reset on new notes")}}, }; EffectHandlerMap fmExtChEffectHandlerMap(fmEffectHandlerMap); fmExtChEffectHandlerMap.insert({ {0x18, {DIV_CMD_FM_EXTCH, _("18xx: Toggle extended channel 3 mode")}}, }); EffectHandlerMap fmOPN2EffectHandlerMap(fmEffectHandlerMap); fmOPN2EffectHandlerMap.insert({ {0x17, {DIV_CMD_SAMPLE_MODE, _("17xx: Toggle PCM mode (LEGACY)")}}, {0xdf, {DIV_CMD_SAMPLE_DIR, _("DFxx: Set sample playback direction (0: normal; 1: reverse)")}}, }); EffectHandlerMap fmOPLDrumsEffectHandlerMap(fmEffectHandlerMap); fmOPLDrumsEffectHandlerMap.insert({ {0x18, {DIV_CMD_FM_EXTCH, _("18xx: Toggle drums mode (1: enabled; 0: disabled)")}}, }); EffectHandlerMap fmOPNPostEffectHandlerMap={ {0x11, {DIV_CMD_FM_FB, _("11xx: Set feedback (0 to 7)")}}, {0x12, {DIV_CMD_FM_TL, _("12xx: Set level of operator 1 (0 highest, 7F lowest)"), constVal<0>, effectVal}}, {0x13, {DIV_CMD_FM_TL, _("13xx: Set level of operator 2 (0 highest, 7F lowest)"), constVal<1>, effectVal}}, {0x14, {DIV_CMD_FM_TL, _("14xx: Set level of operator 3 (0 highest, 7F lowest)"), constVal<2>, effectVal}}, {0x15, {DIV_CMD_FM_TL, _("15xx: Set level of operator 4 (0 highest, 7F lowest)"), constVal<3>, effectVal}}, {0x16, {DIV_CMD_FM_MULT, _("16xy: Set operator multiplier (x: operator from 1 to 4; y: multiplier)"), effectOpValNoZero<4>, effectValAnd<15>}}, {0x19, {DIV_CMD_FM_AR, _("19xx: Set attack of all operators (0 to 1F)"), constVal<-1>, effectValAnd<31>}}, {0x1a, {DIV_CMD_FM_AR, _("1Axx: Set attack of operator 1 (0 to 1F)"), constVal<0>, effectValAnd<31>}}, {0x1b, {DIV_CMD_FM_AR, _("1Bxx: Set attack of operator 2 (0 to 1F)"), constVal<1>, effectValAnd<31>}}, {0x1c, {DIV_CMD_FM_AR, _("1Cxx: Set attack of operator 3 (0 to 1F)"), constVal<2>, effectValAnd<31>}}, {0x1d, {DIV_CMD_FM_AR, _("1Dxx: Set attack of operator 4 (0 to 1F)"), constVal<3>, effectValAnd<31>}}, {0x50, {DIV_CMD_FM_AM, _("50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)"), effectOpVal<4>, effectValAnd<1>}}, {0x51, {DIV_CMD_FM_SL, _("51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)"), effectOpVal<4>, effectValAnd<15>}}, {0x52, {DIV_CMD_FM_RR, _("52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)"), effectOpVal<4>, effectValAnd<15>}}, {0x53, {DIV_CMD_FM_DT, _("53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)"), effectOpVal<4>, effectValAnd<7>}}, {0x54, {DIV_CMD_FM_RS, _("54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}}, {0x56, {DIV_CMD_FM_DR, _("56xx: Set decay of all operators (0 to 1F)"), constVal<-1>, effectValAnd<31>}}, {0x57, {DIV_CMD_FM_DR, _("57xx: Set decay of operator 1 (0 to 1F)"), constVal<0>, effectValAnd<31>}}, {0x58, {DIV_CMD_FM_DR, _("58xx: Set decay of operator 2 (0 to 1F)"), constVal<1>, effectValAnd<31>}}, {0x59, {DIV_CMD_FM_DR, _("59xx: Set decay of operator 3 (0 to 1F)"), constVal<2>, effectValAnd<31>}}, {0x5a, {DIV_CMD_FM_DR, _("5Axx: Set decay of operator 4 (0 to 1F)"), constVal<3>, effectValAnd<31>}}, {0x5b, {DIV_CMD_FM_D2R, _("5Bxx: Set decay 2 of all operators (0 to 1F)"), constVal<-1>, effectValAnd<31>}}, {0x5c, {DIV_CMD_FM_D2R, _("5Cxx: Set decay 2 of operator 1 (0 to 1F)"), constVal<0>, effectValAnd<31>}}, {0x5d, {DIV_CMD_FM_D2R, _("5Dxx: Set decay 2 of operator 2 (0 to 1F)"), constVal<1>, effectValAnd<31>}}, {0x5e, {DIV_CMD_FM_D2R, _("5Exx: Set decay 2 of operator 3 (0 to 1F)"), constVal<2>, effectValAnd<31>}}, {0x5f, {DIV_CMD_FM_D2R, _("5Fxx: Set decay 2 of operator 4 (0 to 1F)"), constVal<3>, effectValAnd<31>}}, {0x60, {DIV_CMD_FM_OPMASK, _("60xx: Set operator mask (bits 0-3)")}}, }; EffectHandlerMap fmOPMPostEffectHandlerMap(fmOPNPostEffectHandlerMap); fmOPMPostEffectHandlerMap.insert({ {0x10, {DIV_CMD_STD_NOISE_FREQ, _("10xx: Set noise frequency (xx: value; 0 disables noise)")}}, {0x17, {DIV_CMD_FM_LFO, _("17xx: Set LFO speed")}}, {0x18, {DIV_CMD_FM_LFO_WAVE, _("18xx: Set LFO waveform (0 saw, 1 square, 2 triangle, 3 noise)")}}, {0x1e, {DIV_CMD_FM_AM_DEPTH, _("1Exx: Set AM depth (0 to 7F)"), effectValAnd<127>}}, {0x1f, {DIV_CMD_FM_PM_DEPTH, _("1Fxx: Set PM depth (0 to 7F)"), effectValAnd<127>}}, {0x55, {DIV_CMD_FM_DT2, _("55xy: Set detune 2 (x: operator from 1 to 4 (0 for all ops); y: detune from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}}, {0x60, {DIV_CMD_FM_OPMASK, _("60xx: Set operator mask (bits 0-3)")}}, }); EffectHandlerMap fmOPZPostEffectHandlerMap(fmOPMPostEffectHandlerMap); fmOPZPostEffectHandlerMap.insert({ {0x24, {DIV_CMD_FM_LFO2, _("24xx: Set LFO 2 speed")}}, {0x25, {DIV_CMD_FM_LFO2_WAVE, _("25xx: Set LFO 2 waveform (0 saw, 1 square, 2 triangle, 3 noise)")}}, {0x26, {DIV_CMD_FM_AM2_DEPTH, _("26xx: Set AM 2 depth (0 to 7F)"), effectValAnd<127>}}, {0x27, {DIV_CMD_FM_PM2_DEPTH, _("27xx: Set PM 2 depth (0 to 7F)"), effectValAnd<127>}}, {0x28, {DIV_CMD_FM_REV, _("28xy: Set reverb (x: operator from 1 to 4 (0 for all ops); y: reverb from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x2a, {DIV_CMD_FM_WS, _("2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x2b, {DIV_CMD_FM_EG_SHIFT, _("2Bxy: Set envelope generator shift (x: operator from 1 to 4 (0 for all ops); y: shift from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}}, {0x2c, {DIV_CMD_FM_FINE, _("2Cxy: Set fine multiplier (x: operator from 1 to 4 (0 for all ops); y: fine)"), effectOpVal<4>, effectValAnd<15>}}, }); const EffectHandler fmOPZFixFreqHandler[4]={ {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency of operator 1 (x: octave from 0 to 7; y: frequency)"), constVal<0>, effectValLong<11>}, {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency of operator 2 (x: octave from 8 to F; y: frequency)"), constVal<1>, effectValLong<11>}, {DIV_CMD_FM_FIXFREQ, _("4xyy: Set fixed frequency of operator 3 (x: octave from 0 to 7; y: frequency)"), constVal<2>, effectValLong<11>}, {DIV_CMD_FM_FIXFREQ, _("4xyy: Set fixed frequency of operator 4 (x: octave from 8 to F; y: frequency)"), constVal<3>, effectValLong<11>}, }; for (int i=0; i<32; i++) { fmOPZPostEffectHandlerMap.emplace(0x30+i,fmOPZFixFreqHandler[i/8]); } fmOPNPostEffectHandlerMap.insert({ {0x10, {DIV_CMD_FM_LFO, _("10xy: Setup LFO (x: enable; y: speed)")}}, {0x55, {DIV_CMD_FM_SSG, _("55xy: Set SSG envelope (x: operator from 1 to 4 (0 for all ops); y: 0-7 on, 8 off)"), effectOpVal<4>, effectValAnd<15>}}, }); EffectHandlerMap fmOPN2PostEffectHandlerMap(fmOPNPostEffectHandlerMap); fmOPNPostEffectHandlerMap.insert(ayPostEffectHandlerMap.begin(), ayPostEffectHandlerMap.end()); EffectHandlerMap fmOPNAPostEffectHandlerMap(fmOPNPostEffectHandlerMap); fmOPNAPostEffectHandlerMap.insert({ {0x1f, {DIV_CMD_ADPCMA_GLOBAL_VOLUME, _("1Fxx: Set ADPCM-A global volume (0 to 3F)")}}, }); EffectHandlerMap fmOPLLPostEffectHandlerMap={ {0x10, {DIV_CMD_WAVE, _("10xx: Set patch (0 to F)")}}, {0x11, {DIV_CMD_FM_FB, _("11xx: Set feedback (0 to 7)")}}, {0x12, {DIV_CMD_FM_TL, _("12xx: Set level of operator 1 (0 highest, 3F lowest)"), constVal<0>, effectVal}}, {0x13, {DIV_CMD_FM_TL, _("13xx: Set level of operator 2 (0 highest, F lowest)"), constVal<1>, effectVal}}, {0x16, {DIV_CMD_FM_MULT, _("16xy: Set operator multiplier (x: operator from 1 to 2; y: multiplier)"), effectOpValNoZero<2>, effectValAnd<15>}}, {0x19, {DIV_CMD_FM_AR, _("19xx: Set attack of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x1a, {DIV_CMD_FM_AR, _("1Axx: Set attack of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x1b, {DIV_CMD_FM_AR, _("1Bxx: Set attack of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x50, {DIV_CMD_FM_AM, _("50xy: Set AM (x: operator from 1 to 2 (0 for all ops); y: AM)"), effectOpVal<2>, effectValAnd<1>}}, {0x51, {DIV_CMD_FM_SL, _("51xy: Set sustain level (x: operator from 1 to 2 (0 for all ops); y: sustain)"), effectOpVal<2>, effectValAnd<15>}}, {0x52, {DIV_CMD_FM_RR, _("52xy: Set release (x: operator from 1 to 2 (0 for all ops); y: release)"), effectOpVal<2>, effectValAnd<15>}}, {0x53, {DIV_CMD_FM_VIB, _("53xy: Set vibrato (x: operator from 1 to 2 (0 for all ops); y: enabled)"), effectOpVal<2>, effectValAnd<1>}}, {0x54, {DIV_CMD_FM_RS, _("54xy: Set envelope scale (x: operator from 1 to 2 (0 for all ops); y: scale from 0 to 3)"), effectOpVal<2>, effectValAnd<3>}}, {0x55, {DIV_CMD_FM_SUS, _("55xy: Set envelope sustain (x: operator from 1 to 2 (0 for all ops); y: enabled)"), effectOpVal<2>, effectValAnd<1>}}, {0x56, {DIV_CMD_FM_DR, _("56xx: Set decay of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x57, {DIV_CMD_FM_DR, _("57xx: Set decay of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x58, {DIV_CMD_FM_DR, _("58xx: Set decay of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x5b, {DIV_CMD_FM_KSR, _("5Bxy: Set whether key will scale envelope (x: operator from 1 to 2 (0 for all ops); y: enabled)"), effectOpVal<2>, effectValAnd<1>}}, }; EffectHandlerMap fmOPLPostEffectHandlerMap={ {0x10, {DIV_CMD_FM_LFO, _("10xx: Set global AM depth (0: 1dB, 1: 4.8dB)"), effectValAnd<1>}}, {0x11, {DIV_CMD_FM_FB, _("11xx: Set feedback (0 to 7)")}}, {0x12, {DIV_CMD_FM_TL, _("12xx: Set level of operator 1 (0 highest, 3F lowest)"), constVal<0>, effectVal}}, {0x13, {DIV_CMD_FM_TL, _("13xx: Set level of operator 2 (0 highest, 3F lowest)"), constVal<1>, effectVal}}, {0x14, {DIV_CMD_FM_TL, _("14xx: Set level of operator 3 (0 highest, 3F lowest)"), constVal<2>, effectVal}}, {0x15, {DIV_CMD_FM_TL, _("15xx: Set level of operator 4 (0 highest, 3F lowest)"), constVal<3>, effectVal}}, {0x16, {DIV_CMD_FM_MULT, _("16xy: Set operator multiplier (x: operator from 1 to 4; y: multiplier)"), effectOpValNoZero<4>, effectValAnd<15>}}, {0x17, {DIV_CMD_FM_LFO, _("17xx: Set global vibrato depth (0: normal, 1: double)"), [](unsigned char, unsigned char val) -> int { return (val&1)+2; }}}, {0x19, {DIV_CMD_FM_AR, _("19xx: Set attack of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x1a, {DIV_CMD_FM_AR, _("1Axx: Set attack of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x1b, {DIV_CMD_FM_AR, _("1Bxx: Set attack of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x1c, {DIV_CMD_FM_AR, _("1Cxx: Set attack of operator 3 (0 to F)"), constVal<2>, effectValAnd<15>}}, {0x1d, {DIV_CMD_FM_AR, _("1Dxx: Set attack of operator 4 (0 to F)"), constVal<3>, effectValAnd<15>}}, {0x2a, {DIV_CMD_FM_WS, _("2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 3 in OPL2 and 0 to 7 in OPL3)"), effectOpVal<4>, effectValAnd<7>}}, {0x50, {DIV_CMD_FM_AM, _("50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)"), effectOpVal<4>, effectValAnd<1>}}, {0x51, {DIV_CMD_FM_SL, _("51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)"), effectOpVal<4>, effectValAnd<15>}}, {0x52, {DIV_CMD_FM_RR, _("52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)"), effectOpVal<4>, effectValAnd<15>}}, {0x53, {DIV_CMD_FM_VIB, _("53xy: Set vibrato (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}}, {0x54, {DIV_CMD_FM_RS, _("54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}}, {0x55, {DIV_CMD_FM_SUS, _("55xy: Set envelope sustain (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}}, {0x56, {DIV_CMD_FM_DR, _("56xx: Set decay of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x57, {DIV_CMD_FM_DR, _("57xx: Set decay of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x58, {DIV_CMD_FM_DR, _("58xx: Set decay of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x59, {DIV_CMD_FM_DR, _("59xx: Set decay of operator 3 (0 to F)"), constVal<2>, effectValAnd<15>}}, {0x5a, {DIV_CMD_FM_DR, _("5Axx: Set decay of operator 4 (0 to F)"), constVal<3>, effectValAnd<15>}}, {0x5b, {DIV_CMD_FM_KSR, _("5Bxy: Set whether key will scale envelope (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}}, }; EffectHandlerMap fmOPL4PostEffectHandlerMap(fmOPLPostEffectHandlerMap); fmOPL4PostEffectHandlerMap.insert({ {0x1e, {DIV_CMD_MULTIPCM_MIX_FM, _("1Exy: FM global level (x: left, y: right; 0 to 7)"), effectVal}}, {0x1f, {DIV_CMD_MULTIPCM_MIX_PCM, _("1Fxy: PCM global level (x: left, y: right; 0 to 7)"), effectVal}}, {0x20, {DIV_CMD_MULTIPCM_LFO, _("20xx: PCM LFO Rate (0 to 7)"), effectValAnd<7>}}, {0x21, {DIV_CMD_MULTIPCM_VIB, _("21xx: PCM LFO PM Depth (0 to 7)"), effectValAnd<7>}}, {0x22, {DIV_CMD_MULTIPCM_AM, _("22xx: PCM LFO AM Depth (0 to 7)"), effectValAnd<7>}}, {0x23, {DIV_CMD_MULTIPCM_AR, _("23xx: PCM Attack Rate (0 to 15)"), effectValAnd<15>}}, {0x24, {DIV_CMD_MULTIPCM_D1R, _("24xx: PCM Decay 1 Rate (0 to 15)"), effectValAnd<15>}}, {0x25, {DIV_CMD_MULTIPCM_DL, _("25xx: PCM Decay Level (0 to 15)"), effectValAnd<15>}}, {0x26, {DIV_CMD_MULTIPCM_D2R, _("26xx: PCM Decay 2 Rate (0 to 15)"), effectValAnd<15>}}, {0x27, {DIV_CMD_MULTIPCM_RR, _("27xx: PCM Release Rate (0 to 15)"), effectValAnd<15>}}, {0x28, {DIV_CMD_MULTIPCM_RC, _("28xx: PCM Rate Correction (0 to 15)"), effectValAnd<15>}}, {0x2c, {DIV_CMD_MULTIPCM_DAMP, _("2Cxx: PCM Damp"), effectValAnd<1>}}, {0x2d, {DIV_CMD_MULTIPCM_PSEUDO_REVERB, _("2Dxx: PCM Pseudo Reverb"), effectValAnd<1>}}, {0x2e, {DIV_CMD_MULTIPCM_LFO_RESET, _("2Exx: PCM LFO Reset"), effectValAnd<1>}}, {0x2f, {DIV_CMD_MULTIPCM_LEVEL_DIRECT, _("2Fxx: PCM Level Direct"), effectValAnd<1>}}, }); EffectHandlerMap c64PostEffectHandlerMap={ {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform (bit 0: triangle; bit 1: saw; bit 2: pulse; bit 3: noise)")}}, {0x11, {DIV_CMD_C64_CUTOFF, _("11xx: Set coarse cutoff (not recommended; use 4xxx instead)")}}, {0x12, {DIV_CMD_STD_NOISE_MODE, _("12xx: Set coarse pulse width (not recommended; use 3xxx instead)")}}, {0x13, {DIV_CMD_C64_RESONANCE, _("13xx: Set resonance (0 to F)")}}, {0x14, {DIV_CMD_C64_FILTER_MODE, _("14xx: Set filter mode (bit 0: low pass; bit 1: band pass; bit 2: high pass)")}}, {0x15, {DIV_CMD_C64_RESET_TIME, _("15xx: Set envelope reset time")}}, {0x1a, {DIV_CMD_C64_RESET_MASK, _("1Axx: Disable envelope reset for this channel (1 disables; 0 enables)")}}, {0x1b, {DIV_CMD_C64_FILTER_RESET, _("1Bxy: Reset cutoff (x: on new note; y: now)")}}, {0x1c, {DIV_CMD_C64_DUTY_RESET, _("1Cxy: Reset pulse width (x: on new note; y: now)")}}, {0x1e, {DIV_CMD_C64_EXTENDED, _("1Exy: Change other parameters (LEGACY)")}}, {0x20, {DIV_CMD_C64_AD, _("20xy: Set attack/decay (x: attack; y: decay)")}}, {0x21, {DIV_CMD_C64_SR, _("21xy: Set sustain/release (x: sustain; y: release)")}}, {0x22, {DIV_CMD_C64_PW_SLIDE, _("22xx: Pulse width slide up"), effectVal, constVal<1>}}, {0x23, {DIV_CMD_C64_PW_SLIDE, _("23xx: Pulse width slide down"), effectVal, constVal<-1>}}, {0x24, {DIV_CMD_C64_CUTOFF_SLIDE, _("24xx: Filter cutoff slide up"), effectVal, constVal<1>}}, {0x25, {DIV_CMD_C64_CUTOFF_SLIDE, _("25xx: Filter cutoff slide down"), effectVal, constVal<-1>}}, }; const EffectHandler c64FineDutyHandler(DIV_CMD_C64_FINE_DUTY, _("3xxx: Set pulse width (0 to FFF)"), effectValLong<12>); const EffectHandler c64FineCutoffHandler(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff (0 to 7FF)"), effectValLong<11>); for (int i=0; i<16; i++) c64PostEffectHandlerMap.emplace(0x30+i,c64FineDutyHandler); for (int i=0; i<8; i++) c64PostEffectHandlerMap.emplace(0x40+i,c64FineCutoffHandler); EffectHandlerMap waveOnlyEffectHandlerMap={ {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform")}}, }; EffectHandlerMap segaPCMPostEffectHandlerMap={ {0x20, {DIV_CMD_SAMPLE_FREQ, _("20xx: Set PCM frequency")}} }; EffectHandlerMap fmESFMPostEffectHandlerMap={ {0x10, {DIV_CMD_FM_AM_DEPTH, _("10xy: Set AM depth (x: operator from 1 to 4 (0 for all ops); y: depth (0: 1dB, 1: 4.8dB))"), effectOpVal<4>, effectValAnd<1>}}, {0x12, {DIV_CMD_FM_TL, _("12xx: Set level of operator 1 (0 highest, 3F lowest)"), constVal<0>, effectVal}}, {0x13, {DIV_CMD_FM_TL, _("13xx: Set level of operator 2 (0 highest, 3F lowest)"), constVal<1>, effectVal}}, {0x14, {DIV_CMD_FM_TL, _("14xx: Set level of operator 3 (0 highest, 3F lowest)"), constVal<2>, effectVal}}, {0x15, {DIV_CMD_FM_TL, _("15xx: Set level of operator 4 (0 highest, 3F lowest)"), constVal<3>, effectVal}}, {0x16, {DIV_CMD_FM_MULT, _("16xy: Set operator multiplier (x: operator from 1 to 4; y: multiplier)"), effectOpValNoZero<4>, effectValAnd<15>}}, {0x17, {DIV_CMD_FM_PM_DEPTH, _("17xy: Set vibrato depth (x: operator from 1 to 4 (0 for all ops); y: depth (0: normal, 1: double))"), effectOpVal<4>, effectValAnd<1>}}, {0x19, {DIV_CMD_FM_AR, _("19xx: Set attack of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x1a, {DIV_CMD_FM_AR, _("1Axx: Set attack of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x1b, {DIV_CMD_FM_AR, _("1Bxx: Set attack of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x1c, {DIV_CMD_FM_AR, _("1Cxx: Set attack of operator 3 (0 to F)"), constVal<2>, effectValAnd<15>}}, {0x1d, {DIV_CMD_FM_AR, _("1Dxx: Set attack of operator 4 (0 to F)"), constVal<3>, effectValAnd<15>}}, {0x20, {DIV_CMD_ESFM_OP_PANNING, _("20xy: Set panning of operator 1 (x: left; y: right)"), constVal<0>, effectVal}}, {0x21, {DIV_CMD_ESFM_OP_PANNING, _("21xy: Set panning of operator 2 (x: left; y: right)"), constVal<1>, effectVal}}, {0x22, {DIV_CMD_ESFM_OP_PANNING, _("22xy: Set panning of operator 3 (x: left; y: right)"), constVal<2>, effectVal}}, {0x23, {DIV_CMD_ESFM_OP_PANNING, _("23xy: Set panning of operator 4 (x: left; y: right)"), constVal<3>, effectVal}}, {0x24, {DIV_CMD_ESFM_OUTLVL, _("24xy: Set output level register (x: operator from 1 to 4 (0 for all ops); y: level from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x25, {DIV_CMD_ESFM_MODIN, _("25xy: Set modulation input level (x: operator from 1 to 4 (0 for all ops); y: level from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x26, {DIV_CMD_ESFM_ENV_DELAY, _("26xy: Set envelope delay (x: operator from 1 to 4 (0 for all ops); y: delay from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x27, {DIV_CMD_STD_NOISE_MODE, _("27xx: Set noise mode for operator 4 (x: mode from 0 to 3)"), effectValAnd<3>}}, {0x2a, {DIV_CMD_FM_WS, _("2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}}, {0x2f, {DIV_CMD_FM_FIXFREQ, _("2Fxy: Set fixed frequency block (x: operator from 1 to 4; y: octave from 0 to 7)"), effectOpValNoZero<4>, effectValAnd<7>}}, {0x40, {DIV_CMD_FM_DT, _("40xx: Set detune of operator 1 (80: center)"), constVal<0>, effectVal}}, {0x41, {DIV_CMD_FM_DT, _("41xx: Set detune of operator 2 (80: center)"), constVal<1>, effectVal}}, {0x42, {DIV_CMD_FM_DT, _("42xx: Set detune of operator 3 (80: center)"), constVal<2>, effectVal}}, {0x43, {DIV_CMD_FM_DT, _("43xx: Set detune of operator 4 (80: center)"), constVal<3>, effectVal}}, {0x50, {DIV_CMD_FM_AM, _("50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)"), effectOpVal<4>, effectValAnd<1>}}, {0x51, {DIV_CMD_FM_SL, _("51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)"), effectOpVal<4>, effectValAnd<15>}}, {0x52, {DIV_CMD_FM_RR, _("52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)"), effectOpVal<4>, effectValAnd<15>}}, {0x53, {DIV_CMD_FM_VIB, _("53xy: Set vibrato (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}}, {0x54, {DIV_CMD_FM_RS, _("54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}}, {0x55, {DIV_CMD_FM_SUS, _("55xy: Set envelope sustain (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}}, {0x56, {DIV_CMD_FM_DR, _("56xx: Set decay of all operators (0 to F)"), constVal<-1>, effectValAnd<15>}}, {0x57, {DIV_CMD_FM_DR, _("57xx: Set decay of operator 1 (0 to F)"), constVal<0>, effectValAnd<15>}}, {0x58, {DIV_CMD_FM_DR, _("58xx: Set decay of operator 2 (0 to F)"), constVal<1>, effectValAnd<15>}}, {0x59, {DIV_CMD_FM_DR, _("59xx: Set decay of operator 3 (0 to F)"), constVal<2>, effectValAnd<15>}}, {0x5a, {DIV_CMD_FM_DR, _("5Axx: Set decay of operator 4 (0 to F)"), constVal<3>, effectValAnd<15>}}, {0x5b, {DIV_CMD_FM_KSR, _("5Bxy: Set whether key will scale envelope (x: operator from 1 to 4 (0 for all ops); y: enabled)"), effectOpVal<4>, effectValAnd<1>}} }; const EffectHandler fmESFMFixFreqFNumHandler[4]={ {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency F-num of operator 1 (x: high 2 bits from 0 to 3; y: low 8 bits of F-num)"), constVal<4>, effectValLong<10>}, {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency F-num of operator 2 (x: high 2 bits from 4 to 7; y: low 8 bits of F-num)"), constVal<5>, effectValLong<10>}, {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency F-num of operator 3 (x: high 2 bits from 8 to B; y: low 8 bits of F-num)"), constVal<6>, effectValLong<10>}, {DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency F-num of operator 4 (x: high 2 bits from C to F; y: low 8 bits of F-num)"), constVal<7>, effectValLong<10>}, }; for (int i=0; i<16; i++) { fmESFMPostEffectHandlerMap.emplace(0x30+i,fmESFMFixFreqFNumHandler[i/4]); } EffectHandlerMap SID2PostEffectHandlerMap={ {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform (bit 0: triangle; bit 1: saw; bit 2: pulse; bit 3: noise)")}}, {0x11, {DIV_CMD_C64_RESONANCE, _("11xx: Set resonance (0 to FF)")}}, {0x12, {DIV_CMD_C64_FILTER_MODE, _("12xx: Set filter mode (bit 0: low pass; bit 1: band pass; bit 2: high pass)")}}, {0x13, {DIV_CMD_C64_RESET_MASK, _("13xx: Disable envelope reset for this channel (1 disables; 0 enables)")}}, {0x14, {DIV_CMD_C64_FILTER_RESET, _("14xy: Reset cutoff (x: on new note; y: now)")}}, {0x15, {DIV_CMD_C64_DUTY_RESET, _("15xy: Reset pulse width (x: on new note; y: now)")}}, {0x16, {DIV_CMD_C64_EXTENDED, _("16xy: Change other parameters")}}, {0x17, {DIV_CMD_C64_PW_SLIDE, _("17xx: Pulse width slide up"), effectVal, constVal<1>}}, {0x18, {DIV_CMD_C64_PW_SLIDE, _("18xx: Pulse width slide down"), effectVal, constVal<-1>}}, {0x19, {DIV_CMD_C64_CUTOFF_SLIDE, _("19xx: Filter cutoff slide up"), effectVal, constVal<1>}}, {0x1A, {DIV_CMD_C64_CUTOFF_SLIDE, _("1Axx: Filter cutoff slide down"), effectVal, constVal<-1>}}, }; const EffectHandler SID2FineDutyHandler(DIV_CMD_C64_FINE_DUTY, _("3xxx: Set pulse width (0 to FFF)"), effectValLong<12>); const EffectHandler SID2FineCutoffHandler(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff (0 to FFF)"), effectValLong<11>); for (int i=0; i<16; i++) SID2PostEffectHandlerMap.emplace(0x30+i,SID2FineDutyHandler); for (int i=0; i<16; i++) SID2PostEffectHandlerMap.emplace(0x40+i,SID2FineCutoffHandler); EffectHandlerMap SID3PostEffectHandlerMap={ {0x60, {DIV_CMD_WAVE, _("60xx: Set waveform (bit 0: triangle; bit 1: saw; bit 2: pulse; bit 3: noise; bit 4: special wave)")}}, {0x61, {DIV_CMD_SID3_SPECIAL_WAVE, _("61xx: Set special wave (00-39)")}}, {0x62, {DIV_CMD_C64_EXTENDED, _("62xx: Modulation control (bit 0: ring mod; bit 1: osc. sync; bit 2: phase mod)")}}, {0x63, {DIV_CMD_C64_DUTY_RESET, _("63xy: Reset pulse width (x: on new note; y: now)")}}, {0x64, {DIV_CMD_SID3_RING_MOD_SRC, _("64xx: Set ring modulation source channel (0-7)")}}, {0x65, {DIV_CMD_SID3_HARD_SYNC_SRC, _("65xx: Set hard sync source channel (0-6)")}}, {0x66, {DIV_CMD_SID3_PHASE_MOD_SRC, _("66xx: Set phase modulation source channel (0-6)")}}, {0x67, {DIV_CMD_FM_AR, _("67xx: Set attack")}}, {0x68, {DIV_CMD_FM_DR, _("68xx: Set decay")}}, {0x69, {DIV_CMD_FM_SL, _("69xx: Set sustain level")}}, {0x6A, {DIV_CMD_FM_D2R, _("6Axx: Set sustain rate")}}, {0x6B, {DIV_CMD_FM_RR, _("6Bxx: Set release")}}, {0x6C, {DIV_CMD_SID3_WAVE_MIX, _("6Cxx: Set wave mix mode (0-4)")}}, {0x6D, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Dxx: Set noise LFSR feedback bits (low byte)"), effectVal, constVal<0>}}, {0x6E, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Exx: Set noise LFSR feedback bits (medium byte)"), effectVal, constVal<1>}}, {0x6F, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Fxx: Set noise LFSR feedback bits (higher byte)"), effectVal, constVal<2>}}, {0x70, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("70xx: Set noise LFSR feedback bits (highest bits, 0-3F)"), effectVal, constVal<3>}}, {0x71, {DIV_CMD_C64_RESONANCE, _("71xx: Set filter 1 resonance"), effectVal, constVal<0>}}, {0x72, {DIV_CMD_C64_RESONANCE, _("72xx: Set filter 2 resonance"), effectVal, constVal<1>}}, {0x73, {DIV_CMD_C64_RESONANCE, _("73xx: Set filter 3 resonance"), effectVal, constVal<2>}}, {0x74, {DIV_CMD_C64_RESONANCE, _("74xx: Set filter 4 resonance"), effectVal, constVal<3>}}, {0x75, {DIV_CMD_SID3_1_BIT_NOISE, _("75xx: Set noise mode (0: usual noise, 1: 1-bit noise (PCM mode on wave channel))")}}, {0x76, {DIV_CMD_SID3_FILTER_OUTPUT_VOLUME, _("76xx: Set filter 1 output volume"), effectVal, constVal<0>}}, {0x77, {DIV_CMD_SID3_FILTER_OUTPUT_VOLUME, _("77xx: Set filter 2 output volume"), effectVal, constVal<1>}}, {0x78, {DIV_CMD_SID3_FILTER_OUTPUT_VOLUME, _("78xx: Set filter 3 output volume"), effectVal, constVal<2>}}, {0x79, {DIV_CMD_SID3_FILTER_OUTPUT_VOLUME, _("79xx: Set filter 4 output volume"), effectVal, constVal<3>}}, {0x7A, {DIV_CMD_SID3_FILTER_DISTORTION, _("7Axx: Set filter 1 distortion"), effectVal, constVal<0>}}, {0x7B, {DIV_CMD_SID3_FILTER_DISTORTION, _("7Bxx: Set filter 2 distortion"), effectVal, constVal<1>}}, {0x7C, {DIV_CMD_SID3_FILTER_DISTORTION, _("7Cxx: Set filter 3 distortion"), effectVal, constVal<2>}}, {0x7D, {DIV_CMD_SID3_FILTER_DISTORTION, _("7Dxx: Set filter 4 distortion"), effectVal, constVal<3>}}, {0x7E, {DIV_CMD_FM_FB, _("7Exx: Set feedback")}}, {0x7F, {DIV_CMD_SID3_CHANNEL_INVERSION, _("7Fxx: Set channel signal inversion (bit 0: right channel, bit 1: left channel)")}}, {0xA0, {DIV_CMD_C64_FILTER_MODE, _("A0xy: Set filter mode (x: filter (0-3); y: bit 0: low pass; bit 1: band pass; bit 2: high pass)")}}, {0xA1, {DIV_CMD_SID3_FILTER_CONNECTION, _("A1xy: Set filter connection (x: filter (0-3); y: bit 0: connect to channel input; bit 1: connect to channel output)")}}, {0xA2, {DIV_CMD_SID3_FILTER_MATRIX, _("A2xy: Set filter connection matrix (x: filter (0-3); y: bits 0-3: add filter 1-4 output to filter's input)")}}, {0xA3, {DIV_CMD_SID3_FILTER_ENABLE, _("A3xy: Enable filter (x: filter (0-3); y: enable)")}}, {0xA4, {DIV_CMD_C64_PW_SLIDE, _("A4xx: Pulse width slide up"), effectVal, constVal<1>}}, {0xA5, {DIV_CMD_C64_PW_SLIDE, _("A5xx: Pulse width slide down"), effectVal, constVal<-1>}}, {0xA6, {DIV_CMD_C64_CUTOFF_SLIDE, _("A6xx: Filter 1 cutoff slide up"), effectVal, constVal<1>}}, {0xA7, {DIV_CMD_C64_CUTOFF_SLIDE, _("A7xx: Filter 1 cutoff slide down"), effectVal, constVal<-1>}}, {0xA8, {DIV_CMD_C64_CUTOFF_SLIDE, _("A8xx: Filter 2 cutoff slide up"), effectVal, constVal<2>}}, {0xA9, {DIV_CMD_C64_CUTOFF_SLIDE, _("A9xx: Filter 2 cutoff slide down"), effectVal, constVal<-2>}}, {0xAA, {DIV_CMD_C64_CUTOFF_SLIDE, _("AAxx: Filter 3 cutoff slide up"), effectVal, constVal<3>}}, {0xAB, {DIV_CMD_C64_CUTOFF_SLIDE, _("ABxx: Filter 3 cutoff slide down"), effectVal, constVal<-3>}}, {0xAC, {DIV_CMD_C64_CUTOFF_SLIDE, _("ACxx: Filter 4 cutoff slide up"), effectVal, constVal<4>}}, {0xAD, {DIV_CMD_C64_CUTOFF_SLIDE, _("ADxx: Filter 4 cutoff slide down"), effectVal, constVal<-4>}}, {0xAE, {DIV_CMD_SID3_PHASE_RESET, _("AExx: Phase reset on tick xx")}}, {0xAF, {DIV_CMD_SID3_NOISE_PHASE_RESET, _("AFxx: Noise phase reset on tick xx")}}, {0xB0, {DIV_CMD_SID3_ENVELOPE_RESET, _("B0xx: Envelope reset on tick xx")}}, {0xB1, {DIV_CMD_SID3_CUTOFF_SCALING, _("B1xy: Cutoff scaling control (x: filter (0-3); y: bit 0: enable scaling; bit 1: invert scaling)")}}, {0xB2, {DIV_CMD_SID3_RESONANCE_SCALING, _("B2xy: Resonance scaling control (x: filter (0-3); y: bit 0: enable scaling; bit 1: invert scaling)")}}, }; const EffectHandler SID3FineDutyHandler(DIV_CMD_C64_FINE_DUTY, _("5xxx: Set pulse width (0 to FFF)"), effectValLong<12>); const EffectHandler SID3FineCutoffHandler1(DIV_CMD_C64_FINE_CUTOFF, _("1xxx: Set cutoff of filter 1 (0 to FFF)"), effectValLong<12>, constVal<0>); const EffectHandler SID3FineCutoffHandler2(DIV_CMD_C64_FINE_CUTOFF, _("2xxx: Set cutoff of filter 2 (0 to FFF)"), effectValLong<12>, constVal<1>); const EffectHandler SID3FineCutoffHandler3(DIV_CMD_C64_FINE_CUTOFF, _("3xxx: Set cutoff of filter 3 (0 to FFF)"), effectValLong<12>, constVal<2>); const EffectHandler SID3FineCutoffHandler4(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff of filter 4 (0 to FFF)"), effectValLong<12>, constVal<3>); for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x50+i,SID3FineDutyHandler); for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x10+i,SID3FineCutoffHandler1); for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x20+i,SID3FineCutoffHandler2); for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x30+i,SID3FineCutoffHandler3); for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x40+i,SID3FineCutoffHandler4); // SysDefs // this chip uses YMZ ADPCM, but the emulator uses ADPCM-B because I got it wrong back then. sysDefs[DIV_SYSTEM_YMU759]=new DivSysDef( _("Yamaha YMU759 (MA-2)"), NULL, 0x01, 0x01, 17, true, false, 0, false, (1U<", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_GENESIS_EXT]=new DivSysDef( _("Sega Genesis Extended Channel 3"), NULL, 0x42, 0x42, 13, true, true, 0, true, 0, 0, 0, "", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_SMS]=new DivSysDef( _("TI SN76489"), NULL, 0x03, 0x03, 4, false, true, 0x150, false, 0, 0, 0, _("a square/noise sound chip found on the Sega Master System, ColecoVision, Tandy, TI's own 99/4A and a few other places."), {_("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}, {}, { {0x20, {DIV_CMD_STD_NOISE_MODE, _("20xy: Set noise mode (x: preset freq/ch3 freq; y: thin pulse/noise)")}} } ); sysDefs[DIV_SYSTEM_SMS_OPLL]=new DivSysDef( _("Sega Master System + FM Expansion"), NULL, 0x43, 0x43, 13, true, true, 0, true, 0, 0, 0, "", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_GB]=new DivSysDef( _("Game Boy"), NULL, 0x04, 0x04, 4, false, true, 0x161, false, 0, 32, 16, _("the most popular portable game console of the era."), {_("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}, {}, { {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform")}}, {0x11, {DIV_CMD_STD_NOISE_MODE, _("11xx: Set noise length (0: long; 1: short)")}}, {0x12, {DIV_CMD_STD_NOISE_MODE, _("12xx: Set duty cycle (0 to 3)")}}, {0x13, {DIV_CMD_GB_SWEEP_TIME, _("13xy: Setup sweep (x: time; y: shift)")}}, {0x14, {DIV_CMD_GB_SWEEP_DIR, _("14xx: Set sweep direction (0: up; 1: down)")}} } ); sysDefs[DIV_SYSTEM_PCE]=new DivSysDef( _("PC Engine/TurboGrafx-16"), NULL, 0x05, 0x05, 6, false, true, 0x161, false, 1U<,effectVal}}, {0x14, {DIV_CMD_NES_SWEEP, _("14xy: Sweep down (x: time; y: shift)"),constVal<1>,effectVal}}, {0x15, {DIV_CMD_NES_ENV_MODE, _("15xx: Set envelope mode (0: envelope, 1: length, 2: looping, 3: constant)")}}, {0x16, {DIV_CMD_NES_LENGTH, _("16xx: Set length counter (refer to manual for a list of values)")}}, {0x17, {DIV_CMD_NES_COUNT_MODE, _("17xx: Set frame counter mode (0: 4-step, 1: 5-step)")}}, {0x18, {DIV_CMD_SAMPLE_MODE, _("18xx: Select PCM/DPCM mode (0: PCM; 1: DPCM)")}}, {0x19, {DIV_CMD_NES_LINEAR_LENGTH, _("19xx: Set triangle linear counter (0 to 7F; 80 and higher halt)")}}, {0x20, {DIV_CMD_SAMPLE_FREQ, _("20xx: Set DPCM frequency (0 to F)")}} } ); sysDefs[DIV_SYSTEM_NES_VRC7]=new DivSysDef( _("NES + Konami VRC7"), NULL, 0x46, 0x46, 11, true, true, 0, true, 0, 0, 0, "", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_NES_FDS]=new DivSysDef( _("Famicom Disk System"), NULL, 0, 0x86, 6, false, true, 0, true, 0, 0, 0, "", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_C64_6581]=new DivSysDef( _("Commodore 64 (SID 6581)"), NULL, 0x47, 0x47, 3, false, true, 0, false, 0, 0, 0, _("this computer is powered by the SID chip, which had synthesizer features like a filter and ADSR."), {_("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}, {}, {}, c64PostEffectHandlerMap ); sysDefs[DIV_SYSTEM_C64_8580]=new DivSysDef( _("Commodore 64 (SID 8580)"), NULL, 0x07, 0x07, 3, false, true, 0, false, 0, 0, 0, _("this computer is powered by the SID chip, which had synthesizer features like a filter and ADSR.\nthis is the newer revision of the chip."), {_("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}, {}, {}, c64PostEffectHandlerMap ); sysDefs[DIV_SYSTEM_ARCADE]=new DivSysDef( _("DefleCade"), NULL, 0x08, 0x08, 13, true, false, 0, true, 0, 0, 0, "", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_YM2610]=new DivSysDef( _("Neo Geo CD"), NULL, 0x09, 0x09, 13, true, true, 0x151, false, (1U<", {}, {}, {}, {} ); sysDefs[DIV_SYSTEM_AY8910]=new DivSysDef( _("AY-3-8910"), NULL, 0x80, 0, 3, false, true, 0x151, false, 1U<,effectVal}}, {0x31, {DIV_CMD_SNES_ECHO_FIR, _("31xx: Set echo filter coefficient 1"),constVal<1>,effectVal}}, {0x32, {DIV_CMD_SNES_ECHO_FIR, _("32xx: Set echo filter coefficient 2"),constVal<2>,effectVal}}, {0x33, {DIV_CMD_SNES_ECHO_FIR, _("33xx: Set echo filter coefficient 3"),constVal<3>,effectVal}}, {0x34, {DIV_CMD_SNES_ECHO_FIR, _("34xx: Set echo filter coefficient 4"),constVal<4>,effectVal}}, {0x35, {DIV_CMD_SNES_ECHO_FIR, _("35xx: Set echo filter coefficient 5"),constVal<5>,effectVal}}, {0x36, {DIV_CMD_SNES_ECHO_FIR, _("36xx: Set echo filter coefficient 6"),constVal<6>,effectVal}}, {0x37, {DIV_CMD_SNES_ECHO_FIR, _("37xx: Set echo filter coefficient 7"),constVal<7>,effectVal}}, }, { {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform")}}, {0x11, {DIV_CMD_STD_NOISE_MODE, _("11xx: Toggle noise mode")}}, {0x12, {DIV_CMD_SNES_ECHO, _("12xx: Toggle echo on this channel")}}, {0x13, {DIV_CMD_SNES_PITCH_MOD, _("13xx: Toggle pitch modulation")}}, {0x14, {DIV_CMD_SNES_INVERT, _("14xy: Toggle invert (x: left; y: right)")}}, {0x15, {DIV_CMD_SNES_GAIN_MODE, _("15xx: Set envelope mode (0: ADSR, 1: gain/direct, 2: dec, 3: exp, 4: inc, 5: bent)")}}, {0x16, {DIV_CMD_SNES_GAIN, _("16xx: Set gain (00 to 7F if direct; 00 to 1F otherwise)")}}, {0x1d, {DIV_CMD_STD_NOISE_FREQ, _("1Dxx: Set noise frequency (00 to 1F)")}}, {0x20, {DIV_CMD_FM_AR, _("20xx: Set attack (0 to F)")}}, {0x21, {DIV_CMD_FM_DR, _("21xx: Set decay (0 to 7)")}}, {0x22, {DIV_CMD_FM_SL, _("22xx: Set sustain (0 to 7)")}}, {0x23, {DIV_CMD_FM_RR, _("23xx: Set release (00 to 1F)")}}, } ); sysDefs[DIV_SYSTEM_VRC6]=new DivSysDef( _("Konami VRC6"), NULL, 0x88, 0, 3, false, true, 0, false, 1U<); for (int i=0; i<16; i++) { lynxEffectHandlerMap.emplace(0x30+i, lynxLFSRHandler); } sysDefs[DIV_SYSTEM_LYNX]=new DivSysDef( _("Atari Lynx"), NULL, 0xa8, 0, 4, false, true, 0x172, false, 1U<); for (int i=0; i<16; i++) { qSoundEffectHandlerMap.emplace(0x30+i, qSoundEchoDelayHandler); } sysDefs[DIV_SYSTEM_QSOUND]=new DivSysDef( _("Capcom QSound"), NULL, 0xe0, 0, 19, false, true, 0x161, false, (1U<}}, {0x14, {DIV_CMD_ES5506_FILTER_K1, _("14xx: Set filter coefficient K1 low byte (00 to FF)"),effectValShift<0>,constVal<0x00ff>}}, {0x15, {DIV_CMD_ES5506_FILTER_K1, _("15xx: Set filter coefficient K1 high byte (00 to FF)"),effectValShift<8>,constVal<0xff00>}}, {0x16, {DIV_CMD_ES5506_FILTER_K2, _("16xx: Set filter coefficient K2 low byte (00 to FF)"),effectValShift<0>,constVal<0x00ff>}}, {0x17, {DIV_CMD_ES5506_FILTER_K2, _("17xx: Set filter coefficient K2 high byte (00 to FF)"),effectValShift<8>,constVal<0xff00>}}, {0x18, {DIV_CMD_ES5506_FILTER_K1_SLIDE, _("18xx: Set filter coefficient K1 slide up (00 to FF)"),effectVal,constVal<0>}}, {0x19, {DIV_CMD_ES5506_FILTER_K1_SLIDE, _("19xx: Set filter coefficient K1 slide down (00 to FF)"),effectVal,constVal<1>}}, {0x1a, {DIV_CMD_ES5506_FILTER_K2_SLIDE, _("1Axx: Set filter coefficient K2 slide up (00 to FF)"),effectVal,constVal<0>}}, {0x1b, {DIV_CMD_ES5506_FILTER_K2_SLIDE, _("1Bxx: Set filter coefficient K2 slide down (00 to FF)"),effectVal,constVal<1>}}, {0x22, {DIV_CMD_ES5506_ENVELOPE_LVRAMP, _("22xx: Set envelope left volume ramp (signed) (00 to FF)"),effectVal}}, {0x23, {DIV_CMD_ES5506_ENVELOPE_RVRAMP, _("23xx: Set envelope right volume ramp (signed) (00 to FF)"),effectVal}}, {0x24, {DIV_CMD_ES5506_ENVELOPE_K1RAMP, _("24xx: Set envelope filter coefficient k1 ramp (signed) (00 to FF)"),effectVal,constVal<0>}}, {0x25, {DIV_CMD_ES5506_ENVELOPE_K1RAMP, _("25xx: Set envelope filter coefficient k1 ramp (signed, slower) (00 to FF)"),effectVal,constVal<1>}}, {0x26, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, _("26xx: Set envelope filter coefficient k2 ramp (signed) (00 to FF)"),effectVal,constVal<0>}}, {0x27, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, _("27xx: Set envelope filter coefficient k2 ramp (signed, slower) (00 to FF)"),effectVal,constVal<1>}}, {0xdf, {DIV_CMD_SAMPLE_DIR, _("DFxx: Set sample playback direction (0: normal; 1: reverse)")}} }; EffectHandlerMap es5506PostEffectHandlerMap={ {0x12, {DIV_CMD_ES5506_PAUSE, _("120x: Set pause (bit 0)"),effectValAnd<1>}} }; const EffectHandler es5506ECountHandler(DIV_CMD_ES5506_ENVELOPE_COUNT, _("2xxx: Set envelope count (000 to 1FF)"), effectValLong<9>); const EffectHandler es5506K1Handler(DIV_CMD_ES5506_FILTER_K1, _("3xxx: Set filter coefficient K1 (000 to FFF)"), effectValLongShift<12,4>,constVal<0xfff0>); const EffectHandler es5506K2Handler(DIV_CMD_ES5506_FILTER_K2, _("4xxx: Set filter coefficient K2 (000 to FFF)"), effectValLongShift<12,4>,constVal<0xfff0>); for (int i=0; i<2; i++) es5506PreEffectHandlerMap.emplace(0x20+i,es5506ECountHandler); for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x30+i, es5506K1Handler); for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x40+i, es5506K2Handler); // TODO: custom sample format sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef( _("Ensoniq ES5506"), NULL, 0xb1, 0, 32, false, true, 0/*0x171*/, false, (1U<, effectVal}}, {0x16, {DIV_CMD_SU_SWEEP_PERIOD_HIGH, _("16xx: Set frequency sweep period high byte"), constVal<0>, effectVal}}, {0x17, {DIV_CMD_SU_SWEEP_PERIOD_LOW, _("17xx: Set volume sweep period low byte"), constVal<1>, effectVal}}, {0x18, {DIV_CMD_SU_SWEEP_PERIOD_HIGH, _("18xx: Set volume sweep period high byte"), constVal<1>, effectVal}}, {0x19, {DIV_CMD_SU_SWEEP_PERIOD_LOW, _("19xx: Set cutoff sweep period low byte"), constVal<2>, effectVal}}, {0x1a, {DIV_CMD_SU_SWEEP_PERIOD_HIGH, _("1Axx: Set cutoff sweep period high byte"), constVal<2>, effectVal}}, {0x1b, {DIV_CMD_SU_SWEEP_BOUND, _("1Bxx: Set frequency sweep boundary"), constVal<0>, effectVal}}, {0x1c, {DIV_CMD_SU_SWEEP_BOUND, _("1Cxx: Set volume sweep boundary"), constVal<1>, effectVal}}, {0x1d, {DIV_CMD_SU_SWEEP_BOUND, _("1Dxx: Set cutoff sweep boundary"), constVal<2>, effectVal}}, {0x1e, {DIV_CMD_SU_SYNC_PERIOD_LOW, _("1Exx: Set phase reset period low byte")}}, {0x1f, {DIV_CMD_SU_SYNC_PERIOD_HIGH, _("1Fxx: Set phase reset period high byte")}}, {0x20, {DIV_CMD_SU_SWEEP_ENABLE, _("20xx: Toggle frequency sweep (bit 0-6: speed; bit 7: direction is up)"), constVal<0>, effectVal}}, {0x21, {DIV_CMD_SU_SWEEP_ENABLE, _("21xx: Toggle volume sweep (bit 0-4: speed; bit 5: direction is up; bit 6: loop; bit 7: alternate)"), constVal<1>, effectVal}}, {0x22, {DIV_CMD_SU_SWEEP_ENABLE, _("22xx: Toggle cutoff sweep (bit 0-6: speed; bit 7: direction is up)"), constVal<2>, effectVal}}, {0x23, {DIV_CMD_C64_PW_SLIDE, _("23xx: Pulse width slide up"), effectVal, constVal<1>}}, {0x24, {DIV_CMD_C64_PW_SLIDE, _("24xx: Pulse width slide down"), effectVal, constVal<-1>}}, {0x25, {DIV_CMD_C64_CUTOFF_SLIDE, _("25xx: Filter cutoff slide up"), effectVal, constVal<1>}}, {0x26, {DIV_CMD_C64_CUTOFF_SLIDE, _("26xx: Filter cutoff slide down"), effectVal, constVal<-1>}}, }; const EffectHandler suCutoffHandler(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff (0 to FFF)"), effectValLong<12>); for (int i=0; i<16; i++) { suEffectHandlerMap.emplace(0x40+i, suCutoffHandler); } sysDefs[DIV_SYSTEM_SOUND_UNIT]=new DivSysDef( _("tildearrow Sound Unit"), NULL, 0xb5, 0, 8, false, true, 0, false, 1U<, effectVal}}, {0x21, {DIV_CMD_POWERNOISE_COUNTER_LOAD, _("21xx: Load high byte of noise channel LFSR (00 to FF)"), constVal<1>, effectVal}}, {0x22, {DIV_CMD_POWERNOISE_IO_WRITE, _("22xx: Write to I/O port A"), constVal<0>, effectVal}}, {0x23, {DIV_CMD_POWERNOISE_IO_WRITE, _("23xx: Write to I/O port B"), constVal<1>, effectVal}}, }, {} ); sysDefs[DIV_SYSTEM_DAVE]=new DivSysDef( _("Dave"), NULL, 0xd5, 0, 6, false, true, 0, false, 1U<,effectVal}}, {0x14, {DIV_CMD_NES_SWEEP, _("14xy: Sweep down (x: time; y: shift)"),constVal<1>,effectVal}}, {0x15, {DIV_CMD_NES_ENV_MODE, _("15xx: Set envelope mode (0: envelope, 1: length, 2: looping, 3: constant)")}}, {0x16, {DIV_CMD_NES_LENGTH, _("16xx: Set length counter (refer to manual for a list of values)")}}, {0x17, {DIV_CMD_NES_COUNT_MODE, _("17xx: Set frame counter mode (0: 4-step, 1: 5-step)")}}, {0x18, {DIV_CMD_SAMPLE_MODE, _("18xx: Select PCM/DPCM mode (0: PCM; 1: DPCM)")}}, {0x19, {DIV_CMD_NES_LINEAR_LENGTH, _("19xx: Set triangle linear counter (0 to 7F; 80 and higher halt)")}}, {0x20, {DIV_CMD_SAMPLE_FREQ, _("20xx: Set DPCM frequency (0 to F)")}} } ); sysDefs[DIV_SYSTEM_BIFURCATOR]=new DivSysDef( _("Bifurcator"), NULL, 0xd9, 0, 4, false, true, 0, false, 0, 0, 0, _("a fantasy sound chip using logistic map iterations to generate sound."), {_("Channel 1"), _("Channel 2"), _("Channel 3"), _("Channel 4")}, {"CH1", "CH2", "CH3", "CH4"}, {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, {DIV_INS_BIFURCATOR, DIV_INS_BIFURCATOR, DIV_INS_BIFURCATOR, DIV_INS_BIFURCATOR}, {}, { {0x10, {DIV_CMD_BIFURCATOR_STATE_LOAD, _("10xx: Load low byte of channel sample state"), constVal<0>, effectVal}}, {0x11, {DIV_CMD_BIFURCATOR_STATE_LOAD, _("11xx: Load high byte of channel sample state"), constVal<1>, effectVal}}, {0x12, {DIV_CMD_BIFURCATOR_PARAMETER, _("12xx: Set low byte of channel parameter"), constVal<0>, effectVal}}, {0x13, {DIV_CMD_BIFURCATOR_PARAMETER, _("13xx: Set high byte of channel parameter"), constVal<1>, effectVal}}, } ); sysDefs[DIV_SYSTEM_SID2]=new DivSysDef( _("SID2"), NULL, 0xf0, 0, 3, false, true, 0, false, 0, 0, 0, _("a fantasy sound chip created by LTVA. it is similar to the SID chip, but with many of its problems fixed."), {_("Channel 1"), _("Channel 2"), _("Channel 3")}, {"CH1", "CH2", "CH3"}, {DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE}, {DIV_INS_SID2, DIV_INS_SID2, DIV_INS_SID2}, {}, {}, SID2PostEffectHandlerMap ); sysDefs[DIV_SYSTEM_SID3]=new DivSysDef( _("SID3"), NULL, 0xf5, 0, 7, false, true, 0, false, (1U<id!=0) { sysFileMapFur[sysDefs[i]->id]=(DivSystem)i; } if (sysDefs[i]->id_DMF!=0) { sysFileMapDMF[sysDefs[i]->id_DMF]=(DivSystem)i; } } systemsRegistered=true; }