diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac6c5e0e6..afc43c49e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,6 +76,8 @@ additional guidelines: - I will run a test suite to make sure this is the case. - if something breaks, you might want to add a compatibility flag (this requires changing the format though). - do not use `#pragma once`. +- on a switch block, **always** put `default` last and not in any other position. + - I have fear of some C/C++ compilers ignoring the rest of cases upon hitting default. ## Demo Songs diff --git a/papers/format.md b/papers/format.md index 2123d5dde..440a6a400 100644 --- a/papers/format.md +++ b/papers/format.md @@ -1229,7 +1229,7 @@ chips which aren't on this list don't have any flags. ## 0x05: PC Engine -- bit 1: clockSel (int) +- bit 0: clockSel (int) - 0: NTSC - 1: pseudo-PAL - bit 2: chipType (int) @@ -1289,6 +1289,7 @@ chips which aren't on this list don't have any flags. - 2: Sunsoft 5B - 3: AY-3-8914 - bit 6: stereo (bool) +- bit 7: halfClock (bool) - bit 8-15: stereoSep (int) ## 0x81: Amiga @@ -1454,6 +1455,7 @@ chips which aren't on this list don't have any flags. - 11: double NTSC - 12: 3.6MHz - bit 6: stereo (bool) +- bit 7: halfClock (bool) - bit 8-15: stereoSep (int) ## 0x9d: VRC7 @@ -1560,4 +1562,4 @@ chips which aren't on this list don't have any flags. ## 0xe0: QSound - bit 0-11: echoDelay (int) -- bit 12-19: echoFeedback (int) \ No newline at end of file +- bit 12-19: echoFeedback (int) diff --git a/src/engine/config.cpp b/src/engine/config.cpp index 6270bdfad..47ff3997d 100644 --- a/src/engine/config.cpp +++ b/src/engine/config.cpp @@ -48,6 +48,43 @@ String DivConfig::toString() { return ret; } +const char* base64Table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +String DivConfig::toBase64() { + String data=toString(); + String ret; + + ret.reserve((2+data.size()*4)/3); + + unsigned int groupOfThree=0; + unsigned char pos=0; + for (char& i: data) { + groupOfThree|=((unsigned char)i)<<((2-pos)<<3); + if (++pos>=3) { + pos=0; + ret+=base64Table[(groupOfThree>>18)&63]; + ret+=base64Table[(groupOfThree>>12)&63]; + ret+=base64Table[(groupOfThree>>6)&63]; + ret+=base64Table[groupOfThree&63]; + groupOfThree=0; + } + } + if (pos==2) { + ret+=base64Table[(groupOfThree>>18)&63]; + ret+=base64Table[(groupOfThree>>12)&63]; + ret+=base64Table[(groupOfThree>>6)&63]; + ret+='='; + } else if (pos==1) { + ret+=base64Table[(groupOfThree>>18)&63]; + ret+=base64Table[(groupOfThree>>12)&63]; + ret+="=="; + } + + logV("toBase64: %s",ret); + + return ret; +} + void DivConfig::parseLine(const char* line) { String key=""; String value=""; @@ -105,7 +142,43 @@ bool DivConfig::loadFromMemory(const char* buf) { return true; } -bool DivConfig::getConfBool(String key, bool fallback) { +bool DivConfig::loadFromBase64(const char* buf) { + String data; + + unsigned int groupOfThree=0; + signed char pos=18; + for (const char* i=buf; *i; i++) { + unsigned char nextVal=0; + if ((*i)=='/') { + nextVal=63; + } else if ((*i)=='+') { + nextVal=62; + } else if ((*i)>='0' && (*i)<='9') { + nextVal=52+((*i)-'0'); + } else if ((*i)>='a' && (*i)<='z') { + nextVal=26+((*i)-'a'); + } else if ((*i)>='A' && (*i)<='Z') { + nextVal=((*i)-'A'); + } else { + nextVal=0; + } + groupOfThree|=nextVal<>16)&0xff) data+=(groupOfThree>>16)&0xff; + if ((groupOfThree>>8)&0xff) data+=(groupOfThree>>8)&0xff; + if (groupOfThree&0xff) data+=groupOfThree&0xff; + groupOfThree=0; + } + } + + logV("fromBase64: %s",data); + + return loadFromMemory(data.c_str()); +} + +bool DivConfig::getBool(String key, bool fallback) const { try { String val=conf.at(key); if (val=="true") { @@ -118,7 +191,7 @@ bool DivConfig::getConfBool(String key, bool fallback) { return fallback; } -int DivConfig::getConfInt(String key, int fallback) { +int DivConfig::getInt(String key, int fallback) const { try { String val=conf.at(key); int ret=std::stoi(val); @@ -129,7 +202,7 @@ int DivConfig::getConfInt(String key, int fallback) { return fallback; } -float DivConfig::getConfFloat(String key, float fallback) { +float DivConfig::getFloat(String key, float fallback) const { try { String val=conf.at(key); float ret=std::stof(val); @@ -140,7 +213,7 @@ float DivConfig::getConfFloat(String key, float fallback) { return fallback; } -double DivConfig::getConfDouble(String key, double fallback) { +double DivConfig::getDouble(String key, double fallback) const { try { String val=conf.at(key); double ret=std::stod(val); @@ -151,7 +224,7 @@ double DivConfig::getConfDouble(String key, double fallback) { return fallback; } -String DivConfig::getConfString(String key, String fallback) { +String DivConfig::getString(String key, String fallback) const { try { String val=conf.at(key); return val; @@ -160,7 +233,7 @@ String DivConfig::getConfString(String key, String fallback) { return fallback; } -void DivConfig::setConf(String key, bool value) { +void DivConfig::set(String key, bool value) { if (value) { conf[key]="true"; } else { @@ -168,22 +241,30 @@ void DivConfig::setConf(String key, bool value) { } } -void DivConfig::setConf(String key, int value) { +void DivConfig::set(String key, int value) { conf[key]=fmt::sprintf("%d",value); } -void DivConfig::setConf(String key, float value) { +void DivConfig::set(String key, float value) { conf[key]=fmt::sprintf("%f",value); } -void DivConfig::setConf(String key, double value) { +void DivConfig::set(String key, double value) { conf[key]=fmt::sprintf("%f",value); } -void DivConfig::setConf(String key, const char* value) { +void DivConfig::set(String key, const char* value) { conf[key]=String(value); } -void DivConfig::setConf(String key, String value) { +void DivConfig::set(String key, String value) { conf[key]=value; } + +bool DivConfig::remove(String key) { + return conf.erase(key); +} + +void DivConfig::clear() { + conf.clear(); +} diff --git a/src/engine/config.h b/src/engine/config.h index 0d3fdc41b..d573a4515 100644 --- a/src/engine/config.h +++ b/src/engine/config.h @@ -29,24 +29,32 @@ class DivConfig { public: // config loading/saving bool loadFromMemory(const char* buf); + bool loadFromBase64(const char* buf); bool loadFromFile(const char* path, bool createOnFail=true); String toString(); + String toBase64(); bool save(const char* path); // get a config value - bool getConfBool(String key, bool fallback); - int getConfInt(String key, int fallback); - float getConfFloat(String key, float fallback); - double getConfDouble(String key, double fallback); - String getConfString(String key, String fallback); + bool getBool(String key, bool fallback) const; + int getInt(String key, int fallback) const; + float getFloat(String key, float fallback) const; + double getDouble(String key, double fallback) const; + String getString(String key, String fallback) const; // set a config value - void setConf(String key, bool value); - void setConf(String key, int value); - void setConf(String key, float value); - void setConf(String key, double value); - void setConf(String key, const char* value); - void setConf(String key, String value); + void set(String key, bool value); + void set(String key, int value); + void set(String key, float value); + void set(String key, double value); + void set(String key, const char* value); + void set(String key, String value); + + // remove a config value + bool remove(String key); + + // clear config + void clear(); }; -#endif \ No newline at end of file +#endif diff --git a/src/engine/configEngine.cpp b/src/engine/configEngine.cpp index df93cc959..5589e064b 100644 --- a/src/engine/configEngine.cpp +++ b/src/engine/configEngine.cpp @@ -118,45 +118,45 @@ bool DivEngine::loadConf() { } bool DivEngine::getConfBool(String key, bool fallback) { - return conf.getConfBool(key,fallback); + return conf.getBool(key,fallback); } int DivEngine::getConfInt(String key, int fallback) { - return conf.getConfInt(key,fallback); + return conf.getInt(key,fallback); } float DivEngine::getConfFloat(String key, float fallback) { - return conf.getConfFloat(key,fallback); + return conf.getFloat(key,fallback); } double DivEngine::getConfDouble(String key, double fallback) { - return conf.getConfDouble(key,fallback); + return conf.getDouble(key,fallback); } String DivEngine::getConfString(String key, String fallback) { - return conf.getConfString(key,fallback); + return conf.getString(key,fallback); } void DivEngine::setConf(String key, bool value) { - conf.setConf(key,value); + conf.set(key,value); } void DivEngine::setConf(String key, int value) { - conf.setConf(key,value); + conf.set(key,value); } void DivEngine::setConf(String key, float value) { - conf.setConf(key,value); + conf.set(key,value); } void DivEngine::setConf(String key, double value) { - conf.setConf(key,value); + conf.set(key,value); } void DivEngine::setConf(String key, const char* value) { - conf.setConf(key,value); + conf.set(key,value); } void DivEngine::setConf(String key, String value) { - conf.setConf(key,value); -} \ No newline at end of file + conf.set(key,value); +} diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 3412d09b3..983eede65 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -23,6 +23,7 @@ #include #include #include +#include "config.h" #define ONE_SEMITONE 2200 @@ -448,9 +449,9 @@ class DivDispatch { /** * set the chip flags. - * @param flags the flags. see song.h for possible values. + * @param flags a DivConfig containing chip flags. */ - virtual void setFlags(unsigned int flags); + virtual void setFlags(const DivConfig& flags); /** * set skip reg writes. @@ -536,10 +537,10 @@ class DivDispatch { * @param parent the parent DivEngine. * @param channels the number of channels to acquire. * @param sugRate the suggested rate. this may change, so don't rely on it. - * @param flags the chip flags. see song.h for possible values. + * @param flags a DivConfig containing chip flags. * @return the number of channels allocated. */ - virtual int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + virtual int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); /** * quit the DivDispatch. diff --git a/src/engine/dispatchContainer.cpp b/src/engine/dispatchContainer.cpp index a5134110e..6a8438de7 100644 --- a/src/engine/dispatchContainer.cpp +++ b/src/engine/dispatchContainer.cpp @@ -158,7 +158,7 @@ void DivDispatchContainer::clear() { prevSample[1]=temp[1];*/ } -void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, unsigned int flags) { +void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, const DivConfig& flags) { if (dispatch!=NULL) return; bb[0]=blip_new(32768); diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 8adc054a1..b01a2954b 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1037,21 +1037,8 @@ void DivEngine::renderSamples() { } } -String DivEngine::encodeSysDesc(std::vector& desc) { - String ret; - if (desc[0]!=0) { - int index=0; - for (size_t i=0; i=32) break; - } - } - return ret; -} - -std::vector DivEngine::decodeSysDesc(String desc) { - std::vector ret; +String DivEngine::decodeSysDesc(String desc) { + DivConfig newDesc; bool hasVal=false; bool negative=false; int val=0; @@ -1060,6 +1047,7 @@ std::vector DivEngine::decodeSysDesc(String desc) { int sysVol=0; int sysPan=0; int sysFlags=0; + int curSys=0; desc+=' '; // ha for (char i: desc) { switch (i) { @@ -1082,15 +1070,19 @@ std::vector DivEngine::decodeSysDesc(String desc) { case 3: sysFlags=val; - if (systemFromFileFur(sysID)!=0) { + if (sysID!=0) { if (sysVol<-128) sysVol=-128; if (sysVol>127) sysVol=127; if (sysPan<-128) sysPan=-128; if (sysPan>127) sysPan=127; - ret.push_back(systemFromFileFur(sysID)); - ret.push_back(sysVol); - ret.push_back(sysPan); - ret.push_back(sysFlags); + newDesc.set(fmt::sprintf("id%d",curSys),sysID); + newDesc.set(fmt::sprintf("vol%d",curSys),sysVol); + newDesc.set(fmt::sprintf("pan%d",curSys),sysPan); + DivConfig newFlagsC; + newFlagsC.clear(); + convertOldFlags((unsigned int)sysFlags,newFlagsC,systemFromFileFur(sysID)); + newDesc.set(fmt::sprintf("flags%d",curSys),newFlagsC.toBase64()); + curSys++; } curStage=0; @@ -1111,28 +1103,35 @@ std::vector DivEngine::decodeSysDesc(String desc) { break; } } - return ret; + + return newDesc.toBase64(); } -void DivEngine::initSongWithDesc(const int* description) { +void DivEngine::initSongWithDesc(const char* description) { int chanCount=0; - if (description[0]!=0) { - int index=0; - for (int i=0; description[i]; i+=4) { - song.system[index]=(DivSystem)description[i]; - song.systemVol[index]=description[i+1]; - song.systemPan[index]=description[i+2]; - song.systemFlagsOld[index]=description[i+3]; - index++; - chanCount+=getChannelCount(song.system[index]); - if (chanCount>=DIV_MAX_CHANS) break; - if (index>=32) break; + DivConfig c; + c.loadFromBase64(description); + int index=0; + for (; index<32; index++) { + song.system[index]=systemFromFileFur(c.getInt(fmt::sprintf("id%d",index),0)); + if (song.system[index]==DIV_SYSTEM_NULL) { + break; } - song.systemLen=index; + chanCount+=getChannelCount(song.system[index]); + if (chanCount>=DIV_MAX_CHANS) { + song.system[index]=DIV_SYSTEM_NULL; + break; + } + song.systemVol[index]=c.getInt(fmt::sprintf("vol%d",index),DIV_SYSTEM_NULL); + song.systemPan[index]=c.getInt(fmt::sprintf("pan%d",index),DIV_SYSTEM_NULL); + song.systemFlags[index].clear(); + String flags=c.getString(fmt::sprintf("flags%d",index),""); + song.systemFlags[index].loadFromBase64(flags.c_str()); } + song.systemLen=index; } -void DivEngine::createNew(const int* description, String sysName) { +void DivEngine::createNew(const char* description, String sysName) { quitDispatch(); BUSY_BEGIN; saveLock.lock(); @@ -1345,7 +1344,7 @@ void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { } song.system[index]=which; - song.systemFlagsOld[index]=0; + song.systemFlags[index].clear(); recalcChans(); saveLock.unlock(); BUSY_END; @@ -1371,7 +1370,7 @@ bool DivEngine::addSystem(DivSystem which) { song.system[song.systemLen]=which; song.systemVol[song.systemLen]=64; song.systemPan[song.systemLen]=0; - song.systemFlagsOld[song.systemLen++]=0; + song.systemFlags[song.systemLen++].clear(); recalcChans(); saveLock.unlock(); BUSY_END; @@ -1415,7 +1414,7 @@ bool DivEngine::removeSystem(int index, bool preserveOrder) { song.system[i]=song.system[i+1]; song.systemVol[i]=song.systemVol[i+1]; song.systemPan[i]=song.systemPan[i+1]; - song.systemFlagsOld[i]=song.systemFlagsOld[i+1]; + song.systemFlags[i]=song.systemFlags[i+1]; } recalcChans(); saveLock.unlock(); @@ -1541,9 +1540,10 @@ bool DivEngine::swapSystem(int src, int dest, bool preserveOrder) { song.systemPan[dest]^=song.systemPan[src]; song.systemPan[src]^=song.systemPan[dest]; - song.systemFlagsOld[src]^=song.systemFlagsOld[dest]; - song.systemFlagsOld[dest]^=song.systemFlagsOld[src]; - song.systemFlagsOld[src]^=song.systemFlagsOld[dest]; + // I am kinda scared to use std::swap + DivConfig oldFlags=song.systemFlags[src]; + song.systemFlags[src]=song.systemFlags[dest]; + song.systemFlags[dest]=oldFlags; recalcChans(); saveLock.unlock(); @@ -3469,12 +3469,9 @@ void DivEngine::setOrder(unsigned char order) { BUSY_END; } -void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) { +void DivEngine::updateSysFlags(int system, bool restart) { BUSY_BEGIN_SOFT; - saveLock.lock(); - song.systemFlagsOld[system]=flags; - saveLock.unlock(); - disCont[system].dispatch->setFlags(song.systemFlagsOld[system]); + disCont[system].dispatch->setFlags(song.systemFlags[system]); disCont[system].setRates(got.rate); if (restart && isPlaying()) { playSub(false); @@ -3632,7 +3629,7 @@ void DivEngine::rescanAudioDevices() { void DivEngine::initDispatch() { BUSY_BEGIN; for (int i=0; i preset=decodeSysDesc(getConfString("initialSys","")); + String preset=getConfString("initialSys2",""); + if (preset.empty()) { + // try loading old preset + preset=decodeSysDesc(getConfString("initialSys","")); + } logD("preset size %ld",preset.size()); if (preset.size()>0 && (preset.size()&3)==0) { - preset.push_back(0); - initSongWithDesc(preset.data()); + initSongWithDesc(preset.c_str()); } String sysName=getConfString("initialSysName",""); if (sysName=="") { diff --git a/src/engine/engine.h b/src/engine/engine.h index 895a89ea5..4561ba920 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -47,8 +47,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev118" -#define DIV_ENGINE_VERSION 118 +#define DIV_VERSION "dev119" +#define DIV_ENGINE_VERSION 119 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 @@ -183,7 +183,7 @@ struct DivDispatchContainer { void flush(size_t count); void fillBuf(size_t runtotal, size_t offset, size_t size); void clear(); - void init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, unsigned int flags); + void init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, const DivConfig& flags); void quit(); DivDispatchContainer(): dispatch(NULL), @@ -425,10 +425,6 @@ class DivEngine { // MIDI stuff std::function midiCallback=[](const TAMidiMessage&) -> int {return -2;}; - DivSystem systemFromFileFur(unsigned char val); - unsigned char systemToFileFur(DivSystem val); - DivSystem systemFromFileDMF(unsigned char val); - unsigned char systemToFileDMF(DivSystem val); int dispatchCmd(DivCommand c); void processRow(int i, bool afterDelay); void nextOrder(); @@ -442,6 +438,8 @@ class DivEngine { void reset(); void playSub(bool preserveDrift, int goalRow=0); + void convertOldFlags(unsigned int oldFlags, DivConfig& newFlags, DivSystem sys); + bool loadDMF(unsigned char* file, size_t len); bool loadFur(unsigned char* file, size_t len); bool loadMod(unsigned char* file, size_t len); @@ -469,7 +467,7 @@ class DivEngine { bool deinitAudioBackend(bool dueToSwitchMaster=false); void registerSystems(); - void initSongWithDesc(const int* description); + void initSongWithDesc(const char* description); void exchangeIns(int one, int two); void swapChannels(int src, int dest); @@ -500,11 +498,10 @@ class DivEngine { DivWavetable* getWave(int index); DivSample* getSample(int index); DivDispatch* getDispatch(int index); - // parse system setup description - String encodeSysDesc(std::vector& desc); - std::vector decodeSysDesc(String desc); + // parse old system setup description + String decodeSysDesc(String desc); // start fresh - void createNew(const int* description, String sysName); + void createNew(const char* description, String sysName); // load a file. bool load(unsigned char* f, size_t length); // save as .dmf. @@ -532,6 +529,12 @@ class DivEngine { // notify wavetable change void notifyWaveChange(int wave); + // get system IDs + DivSystem systemFromFileFur(unsigned char val); + unsigned char systemToFileFur(DivSystem val); + DivSystem systemFromFileDMF(unsigned char val); + unsigned char systemToFileDMF(DivSystem val); + // benchmark (returns time in seconds) double benchmarkPlayback(); double benchmarkSeek(); @@ -818,8 +821,8 @@ class DivEngine { // go to order void setOrder(unsigned char order); - // set system flags - void setSysFlags(int system, unsigned int flags, bool restart); + // update system flags + void updateSysFlags(int system, bool restart); // set Hz void setSongRate(float hz, bool pal); diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index e6e97fffe..3ffb586e7 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -977,11 +977,587 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { return true; } +void DivEngine::convertOldFlags(unsigned int oldFlags, DivConfig& newFlags, DivSystem sys) { + newFlags.clear(); + + switch (sys) { + case DIV_SYSTEM_SMS: + switch (oldFlags&0xff03) { + case 0x0000: + newFlags.set("clockSel",0); + break; + case 0x0001: + newFlags.set("clockSel",1); + break; + case 0x0002: + newFlags.set("clockSel",2); + break; + case 0x0003: + newFlags.set("clockSel",3); + break; + case 0x0100: + newFlags.set("clockSel",4); + break; + case 0x0101: + newFlags.set("clockSel",5); + break; + case 0x0102: + newFlags.set("clockSel",6); + break; + } + switch (oldFlags&0xcc) { + case 0x00: + newFlags.set("chipType",0); + break; + case 0x04: + newFlags.set("chipType",1); + break; + case 0x08: + newFlags.set("chipType",2); + break; + case 0x0c: + newFlags.set("chipType",3); + break; + case 0x40: + newFlags.set("chipType",4); + break; + case 0x44: + newFlags.set("chipType",5); + break; + case 0x48: + newFlags.set("chipType",6); + break; + case 0x4c: + newFlags.set("chipType",7); + break; + case 0x80: + newFlags.set("chipType",8); + break; + case 0x84: + newFlags.set("chipType",9); + break; + } + if (oldFlags&16) newFlags.set("noPhaseReset",true); + break; + case DIV_SYSTEM_GB: + newFlags.set("chipType",(int)(oldFlags&3)); + if (oldFlags&8) newFlags.set("noAntiClick",true); + break; + case DIV_SYSTEM_PCE: + newFlags.set("clockSel",(int)(oldFlags&1)); + newFlags.set("chipType",(oldFlags&4)?1:0); + if (oldFlags&8) newFlags.set("noAntiClick",true); + break; + case DIV_SYSTEM_NES: + case DIV_SYSTEM_VRC6: + case DIV_SYSTEM_FDS: + case DIV_SYSTEM_MMC5: + case DIV_SYSTEM_SAA1099: + case DIV_SYSTEM_OPZ: + switch (oldFlags) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + break; + case DIV_SYSTEM_C64_6581: + case DIV_SYSTEM_C64_8580: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + break; + case DIV_SYSTEM_YM2610: + case DIV_SYSTEM_YM2610_EXT: + case DIV_SYSTEM_YM2610_FULL: + case DIV_SYSTEM_YM2610_FULL_EXT: + case DIV_SYSTEM_YM2610B: + case DIV_SYSTEM_YM2610B_EXT: + switch (oldFlags&0xff) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + } + break; + case DIV_SYSTEM_AY8910: + case DIV_SYSTEM_AY8930: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + case 5: + newFlags.set("clockSel",5); + break; + case 6: + newFlags.set("clockSel",6); + break; + case 7: + newFlags.set("clockSel",7); + break; + case 8: + newFlags.set("clockSel",8); + break; + case 9: + newFlags.set("clockSel",9); + break; + case 10: + newFlags.set("clockSel",10); + break; + case 11: + newFlags.set("clockSel",11); + break; + case 12: + newFlags.set("clockSel",12); + break; + case 13: + if (sys==DIV_SYSTEM_AY8910) newFlags.set("clockSel",13); + break; + case 14: + if (sys==DIV_SYSTEM_AY8910) newFlags.set("clockSel",14); + break; + } + if (sys==DIV_SYSTEM_AY8910) switch ((oldFlags>>4)&3) { + case 0: + newFlags.set("chipType",0); + break; + case 1: + newFlags.set("chipType",1); + break; + case 2: + newFlags.set("chipType",2); + break; + case 3: + newFlags.set("chipType",3); + break; + } + if (oldFlags&64) newFlags.set("stereo",true); + if (oldFlags&128) newFlags.set("halfClock",true); + newFlags.set("stereoSep",(int)((oldFlags>>8)&255)); + break; + case DIV_SYSTEM_AMIGA: + if (oldFlags&1) newFlags.set("clockSel",1); + if (oldFlags&2) newFlags.set("chipType",1); + if (oldFlags&4) newFlags.set("bypassLimits",true); + newFlags.set("stereoSep",(int)((oldFlags>>8)&127)); + break; + case DIV_SYSTEM_YM2151: + switch (oldFlags&255) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + break; + case DIV_SYSTEM_YM2612: + case DIV_SYSTEM_YM2612_EXT: + case DIV_SYSTEM_YM2612_FRAC: + case DIV_SYSTEM_YM2612_FRAC_EXT: + switch (oldFlags&0x7fffffff) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + } + if (oldFlags&0x80000000) newFlags.set("ladderEffect",true); + break; + case DIV_SYSTEM_TIA: + newFlags.set("clockSel",(int)(oldFlags&1)); + switch ((oldFlags>>1)&3) { + case 0: + newFlags.set("mixingType",0); + break; + case 1: + newFlags.set("mixingType",1); + break; + case 2: + newFlags.set("mixingType",2); + break; + } + break; + case DIV_SYSTEM_VIC20: + newFlags.set("clockSel",(int)(oldFlags&1)); + break; + case DIV_SYSTEM_SNES: + newFlags.set("volScaleL",(int)(oldFlags&127)); + newFlags.set("volScaleR",(int)((oldFlags>>8)&127)); + break; + case DIV_SYSTEM_OPLL: + case DIV_SYSTEM_OPLL_DRUMS: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + } + switch (oldFlags>>4) { + case 0: + newFlags.set("patchSet",0); + break; + case 1: + newFlags.set("patchSet",1); + break; + case 2: + newFlags.set("patchSet",2); + break; + case 3: + newFlags.set("patchSet",3); + break; + } + break; + case DIV_SYSTEM_N163: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + newFlags.set("channels",(int)((oldFlags>>4)&7)); + if (oldFlags&128) newFlags.set("multiplex",true); + break; + case DIV_SYSTEM_OPN: + case DIV_SYSTEM_OPN_EXT: + switch (oldFlags&31) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + case 5: + newFlags.set("clockSel",5); + break; + } + switch ((oldFlags>>5)&3) { + case 0: + newFlags.set("prescale",0); + break; + case 1: + newFlags.set("prescale",1); + break; + case 2: + newFlags.set("prescale",2); + break; + } + break; + case DIV_SYSTEM_PC98: + case DIV_SYSTEM_PC98_EXT: + switch (oldFlags&31) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + } + switch ((oldFlags>>5)&3) { + case 0: + newFlags.set("prescale",0); + break; + case 1: + newFlags.set("prescale",1); + break; + case 2: + newFlags.set("prescale",2); + break; + } + break; + case DIV_SYSTEM_OPL: + case DIV_SYSTEM_OPL2: + case DIV_SYSTEM_Y8950: + case DIV_SYSTEM_OPL_DRUMS: + case DIV_SYSTEM_OPL2_DRUMS: + case DIV_SYSTEM_Y8950_DRUMS: + case DIV_SYSTEM_YMZ280B: + switch (oldFlags&0xff) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + case 5: + newFlags.set("clockSel",5); + break; + } + break; + case DIV_SYSTEM_OPL3: + case DIV_SYSTEM_OPL3_DRUMS: + switch (oldFlags&0xff) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + } + break; + case DIV_SYSTEM_PCSPKR: + newFlags.set("speakerType",(int)(oldFlags&3)); + break; + case DIV_SYSTEM_RF5C68: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + switch (oldFlags>>4) { + case 0: + newFlags.set("chipType",0); + break; + case 1: + newFlags.set("chipType",0); + break; + } + break; + case DIV_SYSTEM_VRC7: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + } + break; + case DIV_SYSTEM_SFX_BEEPER: + newFlags.set("clockSel",(int)(oldFlags&1)); + break; + case DIV_SYSTEM_SCC: + case DIV_SYSTEM_SCC_PLUS: + switch (oldFlags&63) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + } + break; + case DIV_SYSTEM_MSM6295: + switch (oldFlags&63) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + case 4: + newFlags.set("clockSel",4); + break; + case 5: + newFlags.set("clockSel",5); + break; + case 6: + newFlags.set("clockSel",6); + break; + case 7: + newFlags.set("clockSel",7); + break; + case 8: + newFlags.set("clockSel",8); + break; + case 9: + newFlags.set("clockSel",9); + break; + case 10: + newFlags.set("clockSel",10); + break; + case 11: + newFlags.set("clockSel",11); + break; + case 12: + newFlags.set("clockSel",12); + break; + case 13: + newFlags.set("clockSel",13); + break; + case 14: + newFlags.set("clockSel",14); + break; + } + if (oldFlags&128) newFlags.set("rateSel",true); + break; + case DIV_SYSTEM_MSM6258: + switch (oldFlags) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + case 3: + newFlags.set("clockSel",3); + break; + } + break; + case DIV_SYSTEM_OPL4: + case DIV_SYSTEM_OPL4_DRUMS: + switch (oldFlags&0xff) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + case 2: + newFlags.set("clockSel",2); + break; + } + break; + case DIV_SYSTEM_X1_010: + switch (oldFlags&15) { + case 0: + newFlags.set("clockSel",0); + break; + case 1: + newFlags.set("clockSel",1); + break; + } + if (oldFlags&16) newFlags.set("stereo",true); + break; + case DIV_SYSTEM_SOUND_UNIT: + newFlags.set("clockSel",(int)(oldFlags&1)); + if (oldFlags&4) newFlags.set("echo",true); + if (oldFlags&8) newFlags.set("swapEcho",true); + newFlags.set("sampleMemSize",(int)((oldFlags>>4)&1)); + if (oldFlags&32) newFlags.set("pdm",true); + newFlags.set("echoDelay",(int)((oldFlags>>8)&63)); + newFlags.set("echoFeedback",(int)((oldFlags>>16)&15)); + newFlags.set("echoResolution",(int)((oldFlags>>20)&15)); + newFlags.set("echoVol",(int)((oldFlags>>24)&255)); + break; + case DIV_SYSTEM_PCM_DAC: + if (!oldFlags) oldFlags=0x1f0000|44099; + newFlags.set("rate",(int)((oldFlags&0xffff)+1)); + newFlags.set("outDepth",(int)((oldFlags>>16)&15)); + if (oldFlags&0x100000) newFlags.set("stereo",true); + break; + case DIV_SYSTEM_QSOUND: + newFlags.set("echoDelay",(int)(oldFlags&0xfff)); + newFlags.set("echoFeedback",(int)((oldFlags>>12)&255)); + break; + default: + break; + } +} + bool DivEngine::loadFur(unsigned char* file, size_t len) { unsigned int insPtr[256]; unsigned int wavePtr[256]; unsigned int samplePtr[256]; unsigned int subSongPtr[256]; + unsigned int sysFlagsPtr[32]; std::vector patPtr; int numberOfSubSongs=0; char magic[5]; @@ -1235,7 +1811,7 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { // system props for (int i=0; i<32; i++) { - ds.systemFlagsOld[i]=reader.readI(); + sysFlagsPtr[i]=reader.readI(); } // handle compound systems @@ -1587,6 +2163,40 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) { ds.autoSystem=true; } + // read system flags + if (ds.version>=119) { + logD("reading chip flags..."); + for (int i=0; i<32; i++) { + if (sysFlagsPtr[i]==0) continue; + + if (!reader.seek(sysFlagsPtr[i],SEEK_SET)) { + logE("couldn't seek to chip %d flags!",i+1); + lastError=fmt::sprintf("couldn't seek to chip %d flags!",i+1); + ds.unload(); + delete[] file; + return false; + } + + reader.read(magic,4); + if (strcmp(magic,"FLAG")!=0) { + logE("%d: invalid flag header!",i); + lastError="invalid flag header!"; + ds.unload(); + delete[] file; + return false; + } + reader.readI(); + + String data=reader.readString(); + ds.systemFlags[i].loadFromMemory(data.c_str()); + } + } else { + logD("reading old chip flags..."); + for (int i=0; i=95) { for (int i=0; i1 || bypassLimits)?2:0); // PAL + ds.systemFlags[i].set("clockSel",1); // PAL + ds.systemFlags[i].set("stereoSep",80); + ds.systemFlags[i].set("bypassLimits",bypassLimits); + ds.systemFlags[i].set("chipType",(bool)(ds.systemLen>1 || bypassLimits)); } for(int i=0; ichanShow[i]=true; @@ -2579,7 +3192,8 @@ bool DivEngine::loadFC(unsigned char* file, size_t len) { ds.system[0]=DIV_SYSTEM_AMIGA; ds.systemVol[0]=64; ds.systemPan[0]=0; - ds.systemFlagsOld[0]=1|(80<<8); // PAL + ds.systemFlags[0].set("clockSel",1); // PAL + ds.systemFlags[0].set("stereoSep",80); ds.systemName="Amiga"; seqLen=reader.readI_BE(); @@ -3219,11 +3833,11 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len) { } if (expansions&16) { ds.system[systemID]=DIV_SYSTEM_N163; - ds.systemFlagsOld[systemID++]=n163Chans; + ds.systemFlags[systemID++].set("channels",(int)n163Chans); } if (expansions&32) { ds.system[systemID]=DIV_SYSTEM_AY8910; - ds.systemFlagsOld[systemID++]=38; // Sunsoft 5B + ds.systemFlags[systemID++].set("chipType",2); // Sunsoft 5B } ds.systemLen=systemID; @@ -3605,11 +4219,12 @@ struct PatToWrite { SafeWriter* DivEngine::saveFur(bool notPrimary) { saveLock.lock(); std::vector subSongPtr; + std::vector sysFlagsPtr; std::vector insPtr; std::vector wavePtr; std::vector samplePtr; std::vector patPtr; - size_t ptrSeek, subSongPtrSeek, blockStartSeek, blockEndSeek; + size_t ptrSeek, subSongPtrSeek, sysFlagsPtrSeek, blockStartSeek, blockEndSeek; size_t subSongIndex=0; DivSubSong* subSong=song.subsong[subSongIndex]; warnings=""; @@ -3733,8 +4348,10 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->writeC(song.systemPan[i]); } + // chip flags (we'll seek here later) + sysFlagsPtrSeek=w->tell(); for (int i=0; i<32; i++) { - w->writeI(song.systemFlagsOld[i]); + w->writeI(0); } // song name @@ -3933,6 +4550,27 @@ SafeWriter* DivEngine::saveFur(bool notPrimary) { w->seek(0,SEEK_END); } + /// CHIP FLAGS + for (int i=0; itell()); + w->write("FLAG",4); + blockStartSeek=w->tell(); + w->writeI(0); + + w->writeString(data,false); + + blockEndSeek=w->tell(); + w->seek(blockStartSeek,SEEK_SET); + w->writeI(blockEndSeek-blockStartSeek-4); + w->seek(0,SEEK_END); + } + /// INSTRUMENT for (int i=0; iwriteI(i); } - /// SUBSONG POINTERS - w->seek(subSongPtrSeek,SEEK_SET); - // subsong pointers + w->seek(subSongPtrSeek,SEEK_SET); for (size_t i=0; i<(song.subsong.size()-1); i++) { w->writeI(subSongPtr[i]); } + // flag pointers + w->seek(sysFlagsPtrSeek,SEEK_SET); + for (size_t i=0; iwriteI(sysFlagsPtr[i]); + } + saveLock.unlock(); return w; } diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 358e54aa0..746e8e80f 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -94,7 +94,7 @@ bool DivDispatch::getWantPreNote() { return false; } -void DivDispatch::setFlags(unsigned int flags) { +void DivDispatch::setFlags(const DivConfig& flags) { } void DivDispatch::setSkipRegisterWrites(bool value) { @@ -157,7 +157,7 @@ void DivDispatch::renderSamples() { } -int DivDispatch::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivDispatch::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { return 0; } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 7a49fccfa..85e0e8551 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -427,8 +427,8 @@ void DivPlatformAmiga::notifyInsDeletion(void* ins) { } } -void DivPlatformAmiga::setFlags(unsigned int flags) { - if (flags&1) { +void DivPlatformAmiga::setFlags(const DivConfig& flags) { + if (flags.getInt("clockSel",0)) { chipClock=COLOR_PAL*4.0/5.0; } else { chipClock=COLOR_NTSC; @@ -437,10 +437,11 @@ void DivPlatformAmiga::setFlags(unsigned int flags) { for (int i=0; i<4; i++) { oscBuf[i]->rate=rate; } - sep1=((flags>>8)&127)+127; - sep2=127-((flags>>8)&127); - amigaModel=flags&2; - bypassLimits=flags&4; + int sep=flags.getInt("stereoSep",0)&127; + sep1=sep+127; + sep2=127-sep; + amigaModel=flags.getInt("chipType",0); + bypassLimits=flags.getBool("bypassLimits",false); if (amigaModel) { filtConstOff=4000; filtConstOn=sin(M_PI*8000.0/(double)rate)*4096.0; @@ -450,7 +451,7 @@ void DivPlatformAmiga::setFlags(unsigned int flags) { } } -int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformAmiga::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/amiga.h b/src/engine/platform/amiga.h index a0a80d6ce..1b509d1b9 100644 --- a/src/engine/platform/amiga.h +++ b/src/engine/platform/amiga.h @@ -101,12 +101,12 @@ class DivPlatformAmiga: public DivDispatch { bool isStereo(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index aaf64e074..ee003b540 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -849,13 +849,8 @@ void DivPlatformArcade::reset() { //rWrite(0x1b,0x00); } -void DivPlatformArcade::setFlags(unsigned int flags) { - switch (flags&0xff) { - default: - case 0: - chipClock=COLOR_NTSC; - baseFreqOff=0; - break; +void DivPlatformArcade::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 1: chipClock=COLOR_PAL*4.0/5.0; baseFreqOff=12; @@ -864,6 +859,10 @@ void DivPlatformArcade::setFlags(unsigned int flags) { chipClock=4000000.0; baseFreqOff=-122; break; + default: + chipClock=COLOR_NTSC; + baseFreqOff=0; + break; } rate=chipClock/64; for (int i=0; i<8; i++) { @@ -879,7 +878,7 @@ void DivPlatformArcade::setYMFM(bool use) { useYMFM=use; } -int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index 70265be39..eee273df3 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -111,13 +111,13 @@ class DivPlatformArcade: public DivPlatformOPM { void muteChannel(int ch, bool mute); DivMacroInt* getChanMacroInt(int ch); void notifyInsChange(int ins); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); void setYMFM(bool use); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformArcade(); }; diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 05fdfa57e..b01d6a9f5 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -772,17 +772,13 @@ void DivPlatformAY8910::setExtClockDiv(unsigned int eclk, unsigned char ediv) { } } -void DivPlatformAY8910::setFlags(unsigned int flags) { +void DivPlatformAY8910::setFlags(const DivConfig& flags) { if (extMode) { chipClock=extClock; rate=chipClock/extDiv; } else { - clockSel=(flags>>7)&1; - switch (flags&15) { - default: - case 0: - chipClock=COLOR_NTSC/2.0; - break; + clockSel=flags.getBool("halfClock",false); + switch (flags.getInt("clockSel",0)) { case 1: chipClock=COLOR_PAL*2.0/5.0; break; @@ -825,6 +821,9 @@ void DivPlatformAY8910::setFlags(unsigned int flags) { case 14: chipClock=1536000; break; + default: + chipClock=COLOR_NTSC/2.0; + break; } rate=chipClock/8; } @@ -833,7 +832,7 @@ void DivPlatformAY8910::setFlags(unsigned int flags) { } if (ay!=NULL) delete ay; - switch ((flags>>4)&3) { + switch (flags.getInt("chipType",0)) { case 1: ay=new ym2149_device(rate,clockSel); sunsoft=false; @@ -858,11 +857,11 @@ void DivPlatformAY8910::setFlags(unsigned int flags) { ay->device_start(); ay->device_reset(); - stereo=(flags>>6)&1; - stereoSep=(flags>>8)&255; + stereo=flags.getBool("stereo",false); + stereoSep=flags.getInt("stereoSep",0)&255; } -int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index 854eb5fb7..d28eac1bf 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -162,7 +162,7 @@ class DivPlatformAY8910: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); @@ -171,7 +171,7 @@ class DivPlatformAY8910: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformAY8910(bool useExtMode=false, unsigned int eclk=COLOR_NTSC, unsigned char ediv=8): DivDispatch(), diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 9a1067fe3..821fa4fe4 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -761,9 +761,9 @@ void DivPlatformAY8930::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) immWrite(i.addr,i.val); } -void DivPlatformAY8930::setFlags(unsigned int flags) { - clockSel=(flags>>7)&1; - switch (flags&15) { +void DivPlatformAY8930::setFlags(const DivConfig& flags) { + clockSel=flags.getBool("halfClock",false); + switch (flags.getInt("clockSel",0)) { case 1: chipClock=COLOR_PAL*2.0/5.0; break; @@ -809,11 +809,11 @@ void DivPlatformAY8930::setFlags(unsigned int flags) { oscBuf[i]->rate=rate; } - stereo=(flags>>6)&1; - stereoSep=(flags>>8)&255; + stereo=flags.getBool("stereo",false); + stereoSep=flags.getInt("stereoSep",0)&255; } -int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index fa4b83d93..3663ee99b 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -164,7 +164,7 @@ class DivPlatformAY8930: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); @@ -172,7 +172,7 @@ class DivPlatformAY8930: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; #endif diff --git a/src/engine/platform/bubsyswsg.cpp b/src/engine/platform/bubsyswsg.cpp index 89d609cec..c00b4ce2a 100644 --- a/src/engine/platform/bubsyswsg.cpp +++ b/src/engine/platform/bubsyswsg.cpp @@ -321,7 +321,7 @@ void DivPlatformBubSysWSG::notifyInsDeletion(void* ins) { } } -void DivPlatformBubSysWSG::setFlags(unsigned int flags) { +void DivPlatformBubSysWSG::setFlags(const DivConfig& flags) { chipClock=COLOR_NTSC; rate=chipClock; for (int i=0; i<2; i++) { @@ -337,7 +337,7 @@ void DivPlatformBubSysWSG::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/bubsyswsg.h b/src/engine/platform/bubsyswsg.h index 34bdad3dc..0d7e3fd58 100644 --- a/src/engine/platform/bubsyswsg.h +++ b/src/engine/platform/bubsyswsg.h @@ -80,13 +80,13 @@ class DivPlatformBubSysWSG: public DivDispatch { bool isStereo(); bool keyOffAffectsArp(int ch); DivMacroInt* getChanMacroInt(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformBubSysWSG(); }; diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index ad1113470..6e98fd8ab 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -531,8 +531,8 @@ void DivPlatformC64::setFP(bool fp) { isFP=fp; } -void DivPlatformC64::setFlags(unsigned int flags) { - switch (flags&0xf) { +void DivPlatformC64::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 0x0: // NTSC C64 rate=COLOR_NTSC*2.0/7.0; break; @@ -554,7 +554,7 @@ void DivPlatformC64::setFlags(unsigned int flags) { } } -int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index 52685ce72..ba9a05129 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -101,7 +101,7 @@ class DivPlatformC64: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); bool getDCOffRequired(); bool getWantPreNote(); @@ -111,7 +111,7 @@ class DivPlatformC64: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void setChipModel(bool is6581); void setFP(bool fp); void quit(); diff --git a/src/engine/platform/dummy.cpp b/src/engine/platform/dummy.cpp index 48c33f059..56a2420d5 100644 --- a/src/engine/platform/dummy.cpp +++ b/src/engine/platform/dummy.cpp @@ -138,7 +138,7 @@ void DivPlatformDummy::reset() { } } -int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/dummy.h b/src/engine/platform/dummy.h index 0b5181f01..d3a1b91e3 100644 --- a/src/engine/platform/dummy.h +++ b/src/engine/platform/dummy.h @@ -44,7 +44,7 @@ class DivPlatformDummy: public DivDispatch { DivDispatchOscBuffer* getOscBuffer(int chan); void reset(); void tick(bool sysTick=true); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformDummy(); }; diff --git a/src/engine/platform/fds.cpp b/src/engine/platform/fds.cpp index 7622a0990..5859be56f 100644 --- a/src/engine/platform/fds.cpp +++ b/src/engine/platform/fds.cpp @@ -451,10 +451,11 @@ void DivPlatformFDS::setNSFPlay(bool use) { useNP=use; } -void DivPlatformFDS::setFlags(unsigned int flags) { - if (flags==2) { // Dendy +void DivPlatformFDS::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { // Dendy rate=COLOR_PAL*2.0/5.0; - } else if (flags==1) { // PAL + } else if (clockSel==1) { // PAL rate=COLOR_PAL*3.0/8.0; } else { // NTSC rate=COLOR_NTSC/2.0; @@ -485,9 +486,8 @@ void DivPlatformFDS::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformFDS::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformFDS::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; - apuType=flags; dumpWrites=false; skipRegisterWrites=false; writeOscBuf=0; diff --git a/src/engine/platform/fds.h b/src/engine/platform/fds.h index 2721876e9..7a54aa52d 100644 --- a/src/engine/platform/fds.h +++ b/src/engine/platform/fds.h @@ -69,7 +69,6 @@ class DivPlatformFDS: public DivDispatch { DivDispatchOscBuffer* oscBuf; bool isMuted[1]; DivWaveSynth ws; - unsigned char apuType; unsigned char writeOscBuf; bool useNP; struct _fds* fds; @@ -99,13 +98,13 @@ class DivPlatformFDS: public DivDispatch { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); void setNSFPlay(bool use); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); float getPostAmp(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformFDS(); }; diff --git a/src/engine/platform/fmshared_OPN.h b/src/engine/platform/fmshared_OPN.h index 406d7281b..a6eb7185e 100644 --- a/src/engine/platform/fmshared_OPN.h +++ b/src/engine/platform/fmshared_OPN.h @@ -106,6 +106,8 @@ class DivPlatformOPN: public DivPlatformFMBase { unsigned int ayDiv; bool extSys; + DivConfig ayFlags; + DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false): DivPlatformFMBase(), fmFreqBase(f), diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 7c1c5d25a..0c9ab7b30 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -629,9 +629,9 @@ void DivPlatformGB::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) immWrite(i.addr,i.val); } -void DivPlatformGB::setFlags(unsigned int flags) { - antiClickEnabled=!(flags&8); - switch (flags&3) { +void DivPlatformGB::setFlags(const DivConfig& flags) { + antiClickEnabled=!flags.getBool("noAntiClick",false); + switch (flags.getInt("chipType",0)) { case 0: model=GB_MODEL_DMG_B; break; @@ -647,7 +647,7 @@ void DivPlatformGB::setFlags(unsigned int flags) { } } -int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { chipClock=4194304; rate=chipClock/16; for (int i=0; i<4; i++) { diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 347f528bd..d0a2c1f35 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -116,8 +116,8 @@ class DivPlatformGB: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - void setFlags(unsigned int flags); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + void setFlags(const DivConfig& flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformGB(); }; diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 39e7644a5..46690f521 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -1191,16 +1191,25 @@ void DivPlatformGenesis::setSoftPCM(bool value) { softPCM=value; } -void DivPlatformGenesis::setFlags(unsigned int flags) { - switch (flags&(~0x80000000)) { +void DivPlatformGenesis::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { + case 1: + chipClock=COLOR_PAL*12.0/7.0; + break; + case 2: + chipClock=8000000.0; + break; + case 3: + chipClock=COLOR_NTSC*12.0/7.0; + break; + case 4: + chipClock=COLOR_NTSC*9.0/4.0; + break; default: - case 0: chipClock=COLOR_NTSC*15.0/7.0; break; - case 1: chipClock=COLOR_PAL*12.0/7.0; break; - case 2: chipClock=8000000.0; break; - case 3: chipClock=COLOR_NTSC*12.0/7.0; break; - case 4: chipClock=COLOR_NTSC*9.0/4.0; break; + chipClock=COLOR_NTSC*15.0/7.0; + break; } - ladder=flags&0x80000000; + ladder=flags.getBool("ladderEffect",false); OPN2_SetChipType(ladder?ym3438_mode_ym2612:0); if (useYMFM) { if (fm_ymfm!=NULL) delete fm_ymfm; @@ -1218,7 +1227,7 @@ void DivPlatformGenesis::setFlags(unsigned int flags) { } } -int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; ladder=false; diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index d81ba9bc6..662d4c338 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -145,14 +145,14 @@ class DivPlatformGenesis: public DivPlatformOPN { bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); void toggleRegisterDump(bool enable); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); void setSoftPCM(bool value); int getPortaFloor(int ch); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformGenesis(): DivPlatformOPN(9440540.0, 72, 32) {} diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 84b906bec..2134568af 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -630,7 +630,7 @@ int DivPlatformGenesisExt::getPortaFloor(int ch) { return (ch>8)?12:0; } -int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) { +int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) { DivPlatformGenesis::init(parent,channels,sugRate,flags); for (int i=0; i<4; i++) { isOpMuted[i]=false; diff --git a/src/engine/platform/genesisext.h b/src/engine/platform/genesisext.h index ffc83d46c..6f46402f8 100644 --- a/src/engine/platform/genesisext.h +++ b/src/engine/platform/genesisext.h @@ -67,7 +67,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis { bool keyOffAffectsPorta(int ch); void notifyInsChange(int ins); int getPortaFloor(int ch); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformGenesisExt(); }; diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 4db41bcfb..66acdcd5e 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -460,7 +460,7 @@ void DivPlatformLynx::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr, i.val); } -int DivPlatformLynx::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformLynx::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/lynx.h b/src/engine/platform/lynx.h index a6c1c91c1..c03402e24 100644 --- a/src/engine/platform/lynx.h +++ b/src/engine/platform/lynx.h @@ -107,7 +107,7 @@ class DivPlatformLynx: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformLynx(); }; diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index 7d271046e..9e3e52920 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -386,10 +386,11 @@ bool DivPlatformMMC5::keyOffAffectsArp(int ch) { return true; } -void DivPlatformMMC5::setFlags(unsigned int flags) { - if (flags==2) { // Dendy +void DivPlatformMMC5::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { // Dendy rate=COLOR_PAL*2.0/5.0; - } else if (flags==1) { // PAL + } else if (clockSel==1) { // PAL rate=COLOR_PAL*3.0/8.0; } else { // NTSC rate=COLOR_NTSC/2.0; @@ -414,9 +415,8 @@ void DivPlatformMMC5::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformMMC5::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformMMC5::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; - apuType=flags; dumpWrites=false; skipRegisterWrites=false; writeOscBuf=0; diff --git a/src/engine/platform/mmc5.h b/src/engine/platform/mmc5.h index 0da3da32e..ddad9ec2d 100644 --- a/src/engine/platform/mmc5.h +++ b/src/engine/platform/mmc5.h @@ -63,7 +63,6 @@ class DivPlatformMMC5: public DivDispatch { unsigned int dacPos; int dacSample; unsigned char sampleBank; - unsigned char apuType; unsigned char writeOscBuf; struct _mmc5* mmc5; unsigned char regPool[128]; @@ -85,12 +84,12 @@ class DivPlatformMMC5: public DivDispatch { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); float getPostAmp(); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformMMC5(); }; diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index 05465bbed..3d8ec38c5 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -387,8 +387,8 @@ void DivPlatformMSM6258::renderSamples() { adpcmMemLen=memPos+256; } -void DivPlatformMSM6258::setFlags(unsigned int flags) { - switch (flags) { +void DivPlatformMSM6258::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 3: chipClock=8192000; break; @@ -408,7 +408,7 @@ void DivPlatformMSM6258::setFlags(unsigned int flags) { } } -int DivPlatformMSM6258::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformMSM6258::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; adpcmMem=new unsigned char[getSampleMemCapacity(0)]; adpcmMemLen=0; diff --git a/src/engine/platform/msm6258.h b/src/engine/platform/msm6258.h index f06bdc261..02ec7e14b 100644 --- a/src/engine/platform/msm6258.h +++ b/src/engine/platform/msm6258.h @@ -108,14 +108,14 @@ class DivPlatformMSM6258: public DivDispatch { void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); const char** getRegisterSheet(); const void* getSampleMem(int index); size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformMSM6258(); }; diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index 8b9c573d4..0f570d9c3 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -376,13 +376,9 @@ void DivPlatformMSM6295::renderSamples() { } } -void DivPlatformMSM6295::setFlags(unsigned int flags) { - rateSelInit=(flags>>7)&1; - switch (flags&0x7f) { - default: - case 0: - chipClock=4000000/4; - break; +void DivPlatformMSM6295::setFlags(const DivConfig& flags) { + rateSelInit=flags.getBool("rateSel",false); + switch (flags.getInt("clockSel",0)) { case 1: chipClock=4224000/4; break; @@ -425,6 +421,9 @@ void DivPlatformMSM6295::setFlags(unsigned int flags) { case 14: chipClock=COLOR_NTSC/3.0; break; + default: + chipClock=4000000/4; + break; } rate=chipClock/3; for (int i=0; i<4; i++) { @@ -436,7 +435,7 @@ void DivPlatformMSM6295::setFlags(unsigned int flags) { } } -int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; adpcmMem=new unsigned char[getSampleMemCapacity(0)]; adpcmMemLen=0; diff --git a/src/engine/platform/msm6295.h b/src/engine/platform/msm6295.h index 5fc5ac7b8..40d357572 100644 --- a/src/engine/platform/msm6295.h +++ b/src/engine/platform/msm6295.h @@ -96,14 +96,14 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf { virtual void notifyInsDeletion(void* ins) override; virtual void poke(unsigned int addr, unsigned short val) override; virtual void poke(std::vector& wlist) override; - virtual void setFlags(unsigned int flags) override; + virtual void setFlags(const DivConfig& flags) override; virtual const char** getRegisterSheet() override; virtual const void* getSampleMem(int index) override; virtual size_t getSampleMemCapacity(int index) override; virtual size_t getSampleMemUsage(int index) override; virtual void renderSamples() override; - virtual int init(DivEngine* parent, int channels, int sugRate, unsigned int flags) override; + virtual int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) override; virtual void quit() override; DivPlatformMSM6295(): DivDispatch(), diff --git a/src/engine/platform/n163.cpp b/src/engine/platform/n163.cpp index 1597d0fa2..26d42e454 100644 --- a/src/engine/platform/n163.cpp +++ b/src/engine/platform/n163.cpp @@ -621,20 +621,20 @@ void DivPlatformN163::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -void DivPlatformN163::setFlags(unsigned int flags) { - switch (flags&0xf) { - case 0x0: // NTSC - rate=COLOR_NTSC/2.0; - break; - case 0x1: // PAL +void DivPlatformN163::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { + case 1: // PAL rate=COLOR_PAL*3.0/8.0; break; - case 0x2: // Dendy + case 2: // Dendy rate=COLOR_PAL*2.0/5.0; break; + default: // NTSC + rate=COLOR_NTSC/2.0; + break; } - initChanMax=chanMax=(flags>>4)&7; - multiplex=((flags>>7)&1)?false:true; // not accurate in real hardware + initChanMax=chanMax=flags.getInt("channels",0)&7; + multiplex=!flags.getBool("multiplex",false); // not accurate in real hardware chipClock=rate; rate/=15; n163.set_multiplex(multiplex); @@ -647,7 +647,7 @@ void DivPlatformN163::setFlags(unsigned int flags) { reset(); } -int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/n163.h b/src/engine/platform/n163.h index 0ff969b64..2f8e5ef98 100644 --- a/src/engine/platform/n163.h +++ b/src/engine/platform/n163.h @@ -104,14 +104,14 @@ class DivPlatformN163: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformN163(); }; diff --git a/src/engine/platform/namcowsg.cpp b/src/engine/platform/namcowsg.cpp index 236790e37..aab625b12 100644 --- a/src/engine/platform/namcowsg.cpp +++ b/src/engine/platform/namcowsg.cpp @@ -530,7 +530,7 @@ void DivPlatformNamcoWSG::setDeviceType(int type) { } } -void DivPlatformNamcoWSG::setFlags(unsigned int flags) { +void DivPlatformNamcoWSG::setFlags(const DivConfig& flags) { chipClock=3072000; rate=chipClock/32; namco->device_clock_changed(rate); @@ -547,7 +547,7 @@ void DivPlatformNamcoWSG::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformNamcoWSG::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformNamcoWSG::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/namcowsg.h b/src/engine/platform/namcowsg.h index 56a8ba3cd..1656dedd0 100644 --- a/src/engine/platform/namcowsg.h +++ b/src/engine/platform/namcowsg.h @@ -91,13 +91,13 @@ class DivPlatformNamcoWSG: public DivDispatch { bool isStereo(); bool keyOffAffectsArp(int ch); void setDeviceType(int type); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformNamcoWSG(); }; diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index d087ac810..5749167b2 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -640,11 +640,12 @@ bool DivPlatformNES::keyOffAffectsArp(int ch) { return true; } -void DivPlatformNES::setFlags(unsigned int flags) { - if (flags==2) { // Dendy +void DivPlatformNES::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { // Dendy rate=COLOR_PAL*2.0/5.0; apuType=2; - } else if (flags==1) { // PAL + } else if (clockSel==1) { // PAL rate=COLOR_PAL*3.0/8.0; apuType=1; } else { // NTSC @@ -730,9 +731,8 @@ void DivPlatformNES::renderSamples() { dpcmMemLen=memPos; } -int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; - apuType=flags; dumpWrites=false; skipRegisterWrites=false; if (useNP) { diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index e8e04e9e9..ef4a9e725 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -104,7 +104,7 @@ class DivPlatformNES: public DivDispatch { float getPostAmp(); unsigned char readDMC(unsigned short addr); void setNSFPlay(bool use); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); @@ -113,7 +113,7 @@ class DivPlatformNES: public DivDispatch { size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformNES(); }; diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 76adeafdc..1157bf500 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -1646,7 +1646,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) { properDrumsSys=drums; } -void DivPlatformOPL::setFlags(unsigned int flags) { +void DivPlatformOPL::setFlags(const DivConfig& flags) { /* if (flags==3) { chipClock=COLOR_NTSC*12.0/7.0; @@ -1674,7 +1674,7 @@ void DivPlatformOPL::setFlags(unsigned int flags) { switch (chipType) { default: case 1: case 2: case 8950: - switch (flags&0xff) { + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_PAL*4.0/5.0; break; @@ -1698,7 +1698,7 @@ void DivPlatformOPL::setFlags(unsigned int flags) { chipRateBase=rate; break; case 3: - switch (flags&0xff) { + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_PAL*16.0/5.0; break; @@ -1719,7 +1719,7 @@ void DivPlatformOPL::setFlags(unsigned int flags) { chipRateBase=rate; break; case 4: - switch (flags&0xff) { + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_PAL*32.0/5.0; break; @@ -1785,7 +1785,7 @@ void DivPlatformOPL::renderSamples() { adpcmBMemLen=memPos+256; } -int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/opl.h b/src/engine/platform/opl.h index 41be2c896..8fe8cb25a 100644 --- a/src/engine/platform/opl.h +++ b/src/engine/platform/opl.h @@ -143,7 +143,7 @@ class DivPlatformOPL: public DivDispatch { bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); void toggleRegisterDump(bool enable); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); int getPortaFloor(int ch); @@ -153,7 +153,7 @@ class DivPlatformOPL: public DivDispatch { size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformOPL(); }; diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index 5c6981588..4c53350cc 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -947,24 +947,25 @@ void DivPlatformOPLL::setYMFM(bool use) { useYMFM=use; } -void DivPlatformOPLL::setFlags(unsigned int flags) { - if ((flags&15)==3) { +void DivPlatformOPLL::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==3) { chipClock=COLOR_NTSC/2.0; - } else if ((flags&15)==2) { + } else if (clockSel==2) { chipClock=4000000.0; - } else if ((flags&15)==1) { + } else if (clockSel==1) { chipClock=COLOR_PAL*4.0/5.0; } else { chipClock=COLOR_NTSC; } rate=chipClock/36; - patchSet=flags>>4; + patchSet=flags.getInt("patchSet",0); for (int i=0; i<11; i++) { oscBuf[i]->rate=rate/2; } } -int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformOPLL::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/opll.h b/src/engine/platform/opll.h index 3f243057b..390d79a96 100644 --- a/src/engine/platform/opll.h +++ b/src/engine/platform/opll.h @@ -117,13 +117,13 @@ class DivPlatformOPLL: public DivDispatch { void toggleRegisterDump(bool enable); void setVRC7(bool vrc); void setProperDrums(bool pd); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyInsDeletion(void* ins); int getPortaFloor(int ch); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformOPLL(); }; diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 19b71a1be..518b598f2 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -557,14 +557,13 @@ void DivPlatformPCE::notifyInsDeletion(void* ins) { } } -void DivPlatformPCE::setFlags(unsigned int flags) { - if (flags&1) { // technically there is no PAL PC Engine but oh well... +void DivPlatformPCE::setFlags(const DivConfig& flags) { + if (flags.getInt("clockSel",0)) { // technically there is no PAL PC Engine but oh well... chipClock=COLOR_PAL*4.0/5.0; } else { chipClock=COLOR_NTSC; } - // flags&4 will be chip revision - antiClickEnabled=!(flags&8); + antiClickEnabled=!flags.getBool("noAntiClick",false); rate=chipClock/12; for (int i=0; i<6; i++) { oscBuf[i]->rate=rate; @@ -574,7 +573,7 @@ void DivPlatformPCE::setFlags(unsigned int flags) { delete pce; pce=NULL; } - pce=new PCE_PSG(tempL,tempR,(flags&4)?PCE_PSG::REVISION_HUC6280A:PCE_PSG::REVISION_HUC6280); + pce=new PCE_PSG(tempL,tempR,flags.getInt("chipType",0)?PCE_PSG::REVISION_HUC6280A:PCE_PSG::REVISION_HUC6280); } void DivPlatformPCE::poke(unsigned int addr, unsigned short val) { @@ -585,7 +584,7 @@ void DivPlatformPCE::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/pce.h b/src/engine/platform/pce.h index ec0308340..a78783108 100644 --- a/src/engine/platform/pce.h +++ b/src/engine/platform/pce.h @@ -107,13 +107,13 @@ class DivPlatformPCE: public DivDispatch { void muteChannel(int ch, bool mute); bool isStereo(); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformPCE(); }; diff --git a/src/engine/platform/pcmdac.cpp b/src/engine/platform/pcmdac.cpp index ae3362ecd..b961b33e4 100644 --- a/src/engine/platform/pcmdac.cpp +++ b/src/engine/platform/pcmdac.cpp @@ -382,18 +382,17 @@ void DivPlatformPCMDAC::notifyInsDeletion(void* ins) { chan.std.notifyInsDeletion((DivInstrument*)ins); } -void DivPlatformPCMDAC::setFlags(unsigned int flags) { +void DivPlatformPCMDAC::setFlags(const DivConfig& flags) { // default to 44100Hz 16-bit stereo - if (!flags) flags=0x1f0000|44099; - rate=(flags&0xffff)+1; + rate=flags.getInt("rate",44100); // rate can't be too low or the resampler will break if (rate<1000) rate=1000; chipClock=rate; - outDepth=(flags>>16)&0xf; - outStereo=(flags>>20)&1; + outDepth=(flags.getInt("outDepth",15))&15; + outStereo=flags.getBool("stereo",true); } -int DivPlatformPCMDAC::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformPCMDAC::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/pcmdac.h b/src/engine/platform/pcmdac.h index 7292f6ddf..46b9e2247 100644 --- a/src/engine/platform/pcmdac.h +++ b/src/engine/platform/pcmdac.h @@ -91,11 +91,11 @@ class DivPlatformPCMDAC: public DivDispatch { void muteChannel(int ch, bool mute); bool isStereo(); DivMacroInt* getChanMacroInt(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; diff --git a/src/engine/platform/pcspkr.cpp b/src/engine/platform/pcspkr.cpp index ab3b8a7ca..42a9ac5cb 100644 --- a/src/engine/platform/pcspkr.cpp +++ b/src/engine/platform/pcspkr.cpp @@ -586,10 +586,10 @@ bool DivPlatformPCSpeaker::keyOffAffectsArp(int ch) { return true; } -void DivPlatformPCSpeaker::setFlags(unsigned int flags) { +void DivPlatformPCSpeaker::setFlags(const DivConfig& flags) { chipClock=COLOR_NTSC/3.0; rate=chipClock/PCSPKR_DIVIDER; - speakerType=flags&3; + speakerType=flags.getInt("speakerType",0)&3; oscBuf->rate=rate; } @@ -611,7 +611,7 @@ void DivPlatformPCSpeaker::poke(std::vector& wlist) { // ??? } -int DivPlatformPCSpeaker::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformPCSpeaker::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/pcspkr.h b/src/engine/platform/pcspkr.h index 48bf1bf56..9d84c2104 100644 --- a/src/engine/platform/pcspkr.h +++ b/src/engine/platform/pcspkr.h @@ -108,13 +108,13 @@ class DivPlatformPCSpeaker: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void notifyPlaybackStop(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformPCSpeaker(); }; diff --git a/src/engine/platform/pet.cpp b/src/engine/platform/pet.cpp index c314edf6f..8a606ecfa 100644 --- a/src/engine/platform/pet.cpp +++ b/src/engine/platform/pet.cpp @@ -295,7 +295,7 @@ void DivPlatformPET::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformPET::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformPET::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/pet.h b/src/engine/platform/pet.h index 3046cc263..17c0686f5 100644 --- a/src/engine/platform/pet.h +++ b/src/engine/platform/pet.h @@ -81,7 +81,7 @@ class DivPlatformPET: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformPET(); private: diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 2b54a90a6..315255283 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -592,14 +592,14 @@ void DivPlatformQSound::notifyInsDeletion(void* ins) { } } -void DivPlatformQSound::setFlags(unsigned int flags) { - echoDelay = 2725 - (flags & 0xfff); - echoFeedback = (flags >> 12) & 255; +void DivPlatformQSound::setFlags(const DivConfig& flags) { + echoDelay = 2725 - flags.getInt("echoDelay",0); + echoFeedback = flags.getInt("echoFeedback",0) & 255; - if(echoDelay < 0) { + if (echoDelay < 0) { echoDelay = 0; } - if(echoDelay > 2725) { + if (echoDelay > 2725) { echoDelay = 2725; } //rate=chipClock/CHIP_DIVIDER; @@ -678,7 +678,7 @@ void DivPlatformQSound::renderSamples() { sampleMemLen=memPos+256; } -int DivPlatformQSound::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformQSound::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/qsound.h b/src/engine/platform/qsound.h index 7743e5943..894886270 100644 --- a/src/engine/platform/qsound.h +++ b/src/engine/platform/qsound.h @@ -93,7 +93,7 @@ class DivPlatformQSound: public DivDispatch { void muteChannel(int ch, bool mute); bool isStereo(); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); @@ -104,7 +104,7 @@ class DivPlatformQSound: public DivDispatch { size_t getSampleMemCapacity(int index = 0); size_t getSampleMemUsage(int index = 0); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index dccd0fd27..d07868962 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -342,13 +342,13 @@ void DivPlatformRF5C68::notifyInsDeletion(void* ins) { } } -void DivPlatformRF5C68::setFlags(unsigned int flags) { - switch (flags&0x0f) { +void DivPlatformRF5C68::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 1: chipClock=10000000; break; case 2: chipClock=12500000; break; default: chipClock=8000000; break; } - chipType=flags>>4; + chipType=flags.getInt("chipType",0); rate=chipClock/384; for (int i=0; i<8; i++) { oscBuf[i]->rate=rate; @@ -416,7 +416,7 @@ void DivPlatformRF5C68::renderSamples() { sampleMemLen=memPos; } -int DivPlatformRF5C68::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformRF5C68::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/rf5c68.h b/src/engine/platform/rf5c68.h index 840ece46a..4c64c2d6c 100644 --- a/src/engine/platform/rf5c68.h +++ b/src/engine/platform/rf5c68.h @@ -92,7 +92,7 @@ class DivPlatformRF5C68: public DivDispatch { void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); @@ -100,7 +100,7 @@ class DivPlatformRF5C68: public DivDispatch { size_t getSampleMemCapacity(int index = 0); size_t getSampleMemUsage(int index = 0); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); private: void chWrite(unsigned char ch, unsigned int addr, unsigned char val); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index b7a77d968..acbecf68c 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -422,10 +422,11 @@ void DivPlatformSAA1099::notifyInsDeletion(void* ins) { } } -void DivPlatformSAA1099::setFlags(unsigned int flags) { - if (flags==2) { +void DivPlatformSAA1099::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { chipClock=COLOR_PAL*8.0/5.0; - } else if (flags==1) { + } else if (clockSel==1) { chipClock=COLOR_NTSC*2.0; } else { chipClock=8000000; @@ -448,7 +449,7 @@ void DivPlatformSAA1099::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/saa.h b/src/engine/platform/saa.h index d2092efb9..6bae715ed 100644 --- a/src/engine/platform/saa.h +++ b/src/engine/platform/saa.h @@ -89,7 +89,7 @@ class DivPlatformSAA1099: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); int getPortaFloor(int ch); bool keyOffAffectsArp(int ch); @@ -97,7 +97,7 @@ class DivPlatformSAA1099: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; #endif diff --git a/src/engine/platform/scc.cpp b/src/engine/platform/scc.cpp index 725c53da9..a8fbcd7c2 100644 --- a/src/engine/platform/scc.cpp +++ b/src/engine/platform/scc.cpp @@ -360,11 +360,8 @@ void DivPlatformSCC::setChipModel(bool isplus) { isPlus=isplus; } -void DivPlatformSCC::setFlags(unsigned int flags) { - switch (flags&0x7f) { - case 0x00: - chipClock=COLOR_NTSC/2.0; - break; +void DivPlatformSCC::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_PAL*2.0/5.0; break; @@ -374,6 +371,9 @@ void DivPlatformSCC::setFlags(unsigned int flags) { case 0x03: chipClock=4000000.0/2.0; break; + default: + chipClock=COLOR_NTSC/2.0; + break; } rate=chipClock/8; for (int i=0; i<5; i++) { @@ -381,7 +381,7 @@ void DivPlatformSCC::setFlags(unsigned int flags) { } } -int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSCC::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/scc.h b/src/engine/platform/scc.h index 20dcf4a97..ed8865476 100644 --- a/src/engine/platform/scc.h +++ b/src/engine/platform/scc.h @@ -85,8 +85,8 @@ class DivPlatformSCC: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - void setFlags(unsigned int flags); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + void setFlags(const DivConfig& flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void setChipModel(bool isPlus); void quit(); ~DivPlatformSCC(); diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index 8bec9f30d..fc389a81d 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -17,7 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -// TODO: new macro formula #include "segapcm.h" #include "../engine.h" #include "../../ta-log.h" @@ -485,7 +484,7 @@ void DivPlatformSegaPCM::reset() { } } -void DivPlatformSegaPCM::setFlags(unsigned int flags) { +void DivPlatformSegaPCM::setFlags(const DivConfig& flags) { chipClock=8000000.0; rate=31250; for (int i=0; i<16; i++) { @@ -497,7 +496,7 @@ bool DivPlatformSegaPCM::isStereo() { return true; } -int DivPlatformSegaPCM::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSegaPCM::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/segapcm.h b/src/engine/platform/segapcm.h index 2a76143b4..222f4bd9f 100644 --- a/src/engine/platform/segapcm.h +++ b/src/engine/platform/segapcm.h @@ -111,11 +111,11 @@ class DivPlatformSegaPCM: public DivDispatch { void muteChannel(int ch, bool mute); void notifyInsChange(int ins); void renderSamples(); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformSegaPCM(); }; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index e4d408f7b..ffafc0cb1 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -429,85 +429,78 @@ void DivPlatformSMS::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -void DivPlatformSMS::setFlags(unsigned int flags) { - switch (flags&0xff03) { - default: - case 0x0000: - chipClock=COLOR_NTSC; - break; - case 0x0001: +void DivPlatformSMS::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { + case 1: chipClock=COLOR_PAL*4.0/5.0; break; - case 0x0002: + case 2: chipClock=4000000; break; - case 0x0003: + case 3: chipClock=COLOR_NTSC/2.0; break; - case 0x0100: + case 4: chipClock=3000000; break; - case 0x0101: + case 5: chipClock=2000000; break; - case 0x0102: + case 6: chipClock=COLOR_NTSC/8.0; break; + default: + chipClock=COLOR_NTSC; + break; } - resetPhase=!(flags&16); + resetPhase=!flags.getBool("noPhaseReset",false); divider=16; toneDivider=64.0; noiseDivider=64.0; if (sn!=NULL) delete sn; - switch (flags&0xcc) { - default: // Sega - case 0x00: - sn=new segapsg_device(); - isRealSN=false; - stereo=false; - break; - case 0x04: // TI SN76489 + switch (flags.getInt("chipType",0)) { + case 1: // TI SN76489 sn=new sn76489_device(); isRealSN=true; stereo=false; noiseDivider=60.0; // 64 for match to tone frequency on non-Sega PSG but compatibility break; - case 0x08: // TI+Atari + case 2: // TI+Atari sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, false, 1/*8*/, false, true); isRealSN=true; stereo=false; noiseDivider=60.0; break; - case 0x0c: // Game Gear (not fully emulated yet!) + case 3: // Game Gear (not fully emulated yet!) sn=new gamegear_device(); isRealSN=false; stereo=true; break; - case 0x40: // TI SN76489A + case 4: // TI SN76489A sn=new sn76489a_device(); isRealSN=false; // TODO stereo=false; noiseDivider=60.0; break; - case 0x44: // TI SN76496 + case 5: // TI SN76496 sn=new sn76496_device(); isRealSN=false; // TODO stereo=false; noiseDivider=60.0; break; - case 0x48: // NCR 8496 + case 6: // NCR 8496 sn=new ncr8496_device(); isRealSN=false; stereo=false; noiseDivider=60.0; break; - case 0x4c: // Tandy PSSJ 3-voice sound + case 7: // Tandy PSSJ 3-voice sound sn=new pssj3_device(); isRealSN=false; stereo=false; noiseDivider=60.0; break; - case 0x80: // TI SN94624 + case 8: // TI SN94624 sn=new sn94624_device(); isRealSN=true; stereo=false; @@ -515,7 +508,7 @@ void DivPlatformSMS::setFlags(unsigned int flags) { toneDivider=8.0; noiseDivider=7.5; break; - case 0x84: // TI SN76494 + case 9: // TI SN76494 sn=new sn76494_device(); isRealSN=false; // TODO stereo=false; @@ -523,6 +516,11 @@ void DivPlatformSMS::setFlags(unsigned int flags) { toneDivider=8.0; noiseDivider=7.5; break; + default: // Sega + sn=new segapsg_device(); + isRealSN=false; + stereo=false; + break; } rate=chipClock/divider; for (int i=0; i<4; i++) { @@ -534,7 +532,7 @@ void DivPlatformSMS::setNuked(bool value) { nuked=value; } -int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index b382d38da..0a4b121f1 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -97,13 +97,13 @@ class DivPlatformSMS: public DivDispatch { bool keyOffAffectsArp(int ch); bool keyOffAffectsPorta(int ch); int getPortaFloor(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); void setNuked(bool value); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformSMS(); }; diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index e99db88a6..0edc88aa6 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -672,21 +672,27 @@ void DivPlatformSNES::reset() { writeControl=false; writeNoise=false; writePitchMod=false; - writeEcho=false; + writeEcho=true; - echoDelay=0; - echoFeedback=0; - echoFIR[0]=127; - echoFIR[1]=0; - echoFIR[2]=0; - echoFIR[3]=0; - echoFIR[4]=0; - echoFIR[5]=0; - echoFIR[6]=0; - echoFIR[7]=0; - echoVolL=127; - echoVolR=127; - echoOn=false; + echoDelay=initEchoDelay; + echoFeedback=initEchoFeedback; + echoFIR[0]=initEchoFIR[0]; + echoFIR[1]=initEchoFIR[1]; + echoFIR[2]=initEchoFIR[2]; + echoFIR[3]=initEchoFIR[3]; + echoFIR[4]=initEchoFIR[4]; + echoFIR[5]=initEchoFIR[5]; + echoFIR[6]=initEchoFIR[6]; + echoFIR[7]=initEchoFIR[7]; + echoVolL=initEchoVolL; + echoVolR=initEchoVolR; + echoOn=initEchoOn; + + for (int i=0; i<8; i++) { + if (initEchoMask&(1<>8)&127); +void DivPlatformSNES::setFlags(const DivConfig& flags) { + globalVolL=127-flags.getInt("volScaleL",0); + globalVolR=127-flags.getInt("volScaleR",0); + + initEchoOn=flags.getBool("echo",false); + initEchoVolL=flags.getInt("echoVolL",127); + initEchoVolR=flags.getInt("echoVolR",127); + initEchoDelay=flags.getInt("echoDelay",0)&15; + initEchoFeedback=flags.getInt("echoFeedback",0); + + initEchoFIR[0]=flags.getInt("echoFilter0",127); + initEchoFIR[1]=flags.getInt("echoFilter1",0); + initEchoFIR[2]=flags.getInt("echoFilter2",0); + initEchoFIR[3]=flags.getInt("echoFilter3",0); + initEchoFIR[4]=flags.getInt("echoFilter4",0); + initEchoFIR[5]=flags.getInt("echoFilter5",0); + initEchoFIR[6]=flags.getInt("echoFilter6",0); + initEchoFIR[7]=flags.getInt("echoFilter7",0); + + initEchoMask=flags.getInt("echoMask",0); } -int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/snes.h b/src/engine/platform/snes.h index 61ddb486b..ac53a51f9 100644 --- a/src/engine/platform/snes.h +++ b/src/engine/platform/snes.h @@ -87,6 +87,14 @@ class DivPlatformSNES: public DivDispatch { bool writeEcho; bool echoOn; + bool initEchoOn; + signed char initEchoVolL; + signed char initEchoVolR; + signed char initEchoFeedback; + signed char initEchoFIR[8]; + unsigned char initEchoDelay; + unsigned char initEchoMask; + struct QueuedWrite { unsigned char addr; unsigned char val; @@ -117,7 +125,7 @@ class DivPlatformSNES: public DivDispatch { bool isStereo(); void notifyInsChange(int ins); void notifyWaveChange(int wave); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); @@ -126,7 +134,7 @@ class DivPlatformSNES: public DivDispatch { size_t getSampleMemCapacity(int index = 0); size_t getSampleMemUsage(int index = 0); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); private: void updateWave(int ch); diff --git a/src/engine/platform/su.cpp b/src/engine/platform/su.cpp index cd0aea346..66b91ef5b 100644 --- a/src/engine/platform/su.cpp +++ b/src/engine/platform/su.cpp @@ -505,8 +505,8 @@ void DivPlatformSoundUnit::notifyInsDeletion(void* ins) { } } -void DivPlatformSoundUnit::setFlags(unsigned int flags) { - if (flags&1) { +void DivPlatformSoundUnit::setFlags(const DivConfig& flags) { + if (flags.getInt("clockSel",0)) { chipClock=1190000; } else { chipClock=1236000; @@ -515,14 +515,15 @@ void DivPlatformSoundUnit::setFlags(unsigned int flags) { for (int i=0; i<8; i++) { oscBuf[i]->rate=rate; } - initIlCtrl=3|(flags&4); - initIlSize=((flags>>8)&63)|((flags&4)?0x40:0)|((flags&8)?0x80:0); - initFil1=flags>>16; - initEchoVol=flags>>24; + bool echoOn=flags.getBool("echo",false); + initIlCtrl=3|(echoOn?4:0); + initIlSize=((flags.getInt("echoDelay",0))&63)|(echoOn?0x40:0)|(flags.getBool("swapEcho",false)?0x80:0); + initFil1=flags.getInt("echoFeedback",0); + initEchoVol=flags.getInt("echoVol",0); - sampleMemSize=flags&16; + sampleMemSize=flags.getInt("sampleMemSize",0); - su->Init(sampleMemSize?65536:8192,flags&32); + su->Init(sampleMemSize?65536:8192,flags.getBool("pdm",false)); renderSamples(); } @@ -572,7 +573,7 @@ void DivPlatformSoundUnit::renderSamples() { } -int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/su.h b/src/engine/platform/su.h index 784186c66..004c04c5c 100644 --- a/src/engine/platform/su.h +++ b/src/engine/platform/su.h @@ -130,7 +130,7 @@ class DivPlatformSoundUnit: public DivDispatch { void muteChannel(int ch, bool mute); bool isStereo(); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); @@ -139,7 +139,7 @@ class DivPlatformSoundUnit: public DivDispatch { size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformSoundUnit(); }; diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 9db46d14e..222af4a55 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -509,7 +509,7 @@ void DivPlatformSwan::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/swan.h b/src/engine/platform/swan.h index 473667a93..8261e634a 100644 --- a/src/engine/platform/swan.h +++ b/src/engine/platform/swan.h @@ -94,7 +94,7 @@ class DivPlatformSwan: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformSwan(); private: diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index 796c94481..d4703e284 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -350,21 +350,21 @@ void DivPlatformTIA::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -void DivPlatformTIA::setFlags(unsigned int flags) { - if (flags&1) { +void DivPlatformTIA::setFlags(const DivConfig& flags) { + if (flags.getInt("clockSel",0)) { rate=COLOR_PAL*4.0/5.0; } else { rate=COLOR_NTSC; } chipClock=rate; - mixingType=(flags>>1)&3; + mixingType=flags.getInt("mixingType",0)&3; for (int i=0; i<2; i++) { oscBuf[i]->rate=rate/114; } tia.reset(mixingType); } -int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/tia.h b/src/engine/platform/tia.h index 3eb32b97a..85bfcabe3 100644 --- a/src/engine/platform/tia.h +++ b/src/engine/platform/tia.h @@ -63,7 +63,7 @@ class DivPlatformTIA: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); float getPostAmp(); bool isStereo(); bool keyOffAffectsArp(int ch); @@ -71,7 +71,7 @@ class DivPlatformTIA: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); }; #endif diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index fa29cda60..c205435e3 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -914,11 +914,12 @@ void DivPlatformTX81Z::reset() { extMode=false; } -void DivPlatformTX81Z::setFlags(unsigned int flags) { - if (flags==2) { +void DivPlatformTX81Z::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { chipClock=4000000.0; baseFreqOff=-122; - } else if (flags==1) { + } else if (clockSel==1) { chipClock=COLOR_PAL*4.0/5.0; baseFreqOff=12; } else { @@ -935,7 +936,7 @@ bool DivPlatformTX81Z::isStereo() { return true; } -int DivPlatformTX81Z::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformTX81Z::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index b1d09db90..5b4b9f240 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -104,12 +104,12 @@ class DivPlatformTX81Z: public DivPlatformOPM { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); void notifyInsChange(int ins); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); bool isStereo(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformTX81Z(); }; diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index d0e9e00f1..cd76f414c 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -426,7 +426,7 @@ void DivPlatformVERA::poke(std::vector& wlist) { for (auto &i: wlist) poke(i.addr,i.val); } -int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { for (int i=0; i<17; i++) { isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer; diff --git a/src/engine/platform/vera.h b/src/engine/platform/vera.h index 9cda01203..fec113fc7 100644 --- a/src/engine/platform/vera.h +++ b/src/engine/platform/vera.h @@ -80,7 +80,7 @@ class DivPlatformVERA: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformVERA(); }; diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index 93c119484..d6200a16c 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -301,8 +301,8 @@ void DivPlatformVIC20::notifyInsDeletion(void* ins) { } } -void DivPlatformVIC20::setFlags(unsigned int flags) { - if (flags&1) { +void DivPlatformVIC20::setFlags(const DivConfig& flags) { + if (flags.getInt("clockSel",0)) { chipClock=COLOR_PAL/4.0; } else { chipClock=COLOR_NTSC*2.0/7.0; @@ -321,7 +321,7 @@ void DivPlatformVIC20::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformVIC20::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformVIC20::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/vic20.h b/src/engine/platform/vic20.h index 834051ddb..21669c27a 100644 --- a/src/engine/platform/vic20.h +++ b/src/engine/platform/vic20.h @@ -77,13 +77,13 @@ class DivPlatformVIC20: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); bool isStereo(); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformVIC20(); private: diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index 1fb7cbb18..52a9350c9 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -479,10 +479,11 @@ bool DivPlatformVRC6::keyOffAffectsArp(int ch) { return true; } -void DivPlatformVRC6::setFlags(unsigned int flags) { - if (flags==2) { // Dendy +void DivPlatformVRC6::setFlags(const DivConfig& flags) { + int clockSel=flags.getInt("clockSel",0); + if (clockSel==2) { // Dendy rate=COLOR_PAL*2.0/5.0; - } else if (flags==1) { // PAL + } else if (clockSel==1) { // PAL rate=COLOR_PAL*3.0/8.0; } else { // NTSC rate=COLOR_NTSC/2.0; @@ -507,7 +508,7 @@ void DivPlatformVRC6::poke(std::vector& wlist) { for (DivRegWrite& i: wlist) rWrite(i.addr,i.val); } -int DivPlatformVRC6::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformVRC6::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/vrc6.h b/src/engine/platform/vrc6.h index 4c56bc797..839c089b9 100644 --- a/src/engine/platform/vrc6.h +++ b/src/engine/platform/vrc6.h @@ -94,12 +94,12 @@ class DivPlatformVRC6: public DivDispatch, public vrcvi_intf { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformVRC6() : vrc6(*this) {}; ~DivPlatformVRC6(); diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 5f71b8fd8..29e5edbd6 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -903,8 +903,8 @@ void DivPlatformX1_010::notifyInsDeletion(void* ins) { } } -void DivPlatformX1_010::setFlags(unsigned int flags) { - switch (flags&15) { +void DivPlatformX1_010::setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 0: // 16MHz (earlier hardwares) chipClock=16000000; break; @@ -917,7 +917,7 @@ void DivPlatformX1_010::setFlags(unsigned int flags) { break; } rate=chipClock/512; - stereo=flags&16; + stereo=flags.getBool("stereo",false); for (int i=0; i<16; i++) { oscBuf[i]->rate=rate; } @@ -980,7 +980,7 @@ void DivPlatformX1_010::setBanked(bool banked) { isBanked=banked; } -int DivPlatformX1_010::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformX1_010::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/x1_010.h b/src/engine/platform/x1_010.h index ce3e86c18..94d03011e 100644 --- a/src/engine/platform/x1_010.h +++ b/src/engine/platform/x1_010.h @@ -138,7 +138,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf { void muteChannel(int ch, bool mute); bool isStereo(); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); @@ -149,7 +149,7 @@ class DivPlatformX1_010: public DivDispatch, public vgsound_emu_mem_intf { void renderSamples(); const char** getRegisterSheet(); void setBanked(bool banked); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformX1_010(): DivDispatch(), diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 6a0864377..cd85731e0 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -909,13 +909,9 @@ void DivPlatformYM2203::setSkipRegisterWrites(bool value) { ay->setSkipRegisterWrites(value); } -void DivPlatformYM2203::setFlags(unsigned int flags) { +void DivPlatformYM2203::setFlags(const DivConfig& flags) { // Clock flags - switch (flags&0x1f) { - default: - case 0x00: - chipClock=COLOR_NTSC; - break; + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_PAL*4.0/5.0; break; @@ -931,16 +927,12 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { case 0x05: chipClock=3000000.0/2.0; break; + default: + chipClock=COLOR_NTSC; + break; } // Prescaler flags - switch ((flags>>5)&0x3) { - default: - case 0x00: // /6 - prescale=0x2d; - fmFreqBase=4720270.0, - fmDivBase=36, - ayDiv=16; - break; + switch (flags.getInt("prescale",0)) { case 0x01: // /3 prescale=0x2e; fmFreqBase=4720270.0/2.0, @@ -953,6 +945,12 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { fmDivBase=12, ayDiv=4; break; + default: // /6 + prescale=0x2d; + fmFreqBase=4720270.0, + fmDivBase=36, + ayDiv=16; + break; } rate=fm->sample_rate(chipClock); for (int i=0; i<6; i++) { @@ -961,10 +959,11 @@ void DivPlatformYM2203::setFlags(unsigned int flags) { immWrite(0x2d,0xff); immWrite(prescale,0xff); ay->setExtClockDiv(chipClock,ayDiv); - ay->setFlags(16); + ay->setFlags(ayFlags); } -int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { + ayFlags.set("chipType",1); parent=p; dumpWrites=false; skipRegisterWrites=false; @@ -976,7 +975,7 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, unsigned in fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); // YM2149, 2MHz ay=new DivPlatformAY8910(true,chipClock,ayDiv); - ay->init(p,3,sugRate,16); + ay->init(p,3,sugRate,ayFlags); ay->toggleRegisterDump(true); setFlags(flags); diff --git a/src/engine/platform/ym2203.h b/src/engine/platform/ym2203.h index 7a4aa7975..b51a42343 100644 --- a/src/engine/platform/ym2203.h +++ b/src/engine/platform/ym2203.h @@ -117,8 +117,8 @@ class DivPlatformYM2203: public DivPlatformOPN { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - void setFlags(unsigned int flags); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + void setFlags(const DivConfig& flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformYM2203(): DivPlatformOPN(4720270.0, 36, 16), diff --git a/src/engine/platform/ym2203ext.cpp b/src/engine/platform/ym2203ext.cpp index fc6294870..9c404ca6c 100644 --- a/src/engine/platform/ym2203ext.cpp +++ b/src/engine/platform/ym2203ext.cpp @@ -505,7 +505,7 @@ void DivPlatformYM2203Ext::notifyInsChange(int ins) { } } -int DivPlatformYM2203Ext::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2203Ext::init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2203::init(parent,channels,sugRate,flags); for (int i=0; i<4; i++) { isOpMuted[i]=false; diff --git a/src/engine/platform/ym2203ext.h b/src/engine/platform/ym2203ext.h index 9bc460af4..5cf664296 100644 --- a/src/engine/platform/ym2203ext.h +++ b/src/engine/platform/ym2203ext.h @@ -64,7 +64,7 @@ class DivPlatformYM2203Ext: public DivPlatformYM2203 { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformYM2203Ext(); }; diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index 87fc79144..487398233 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1361,26 +1361,18 @@ void DivPlatformYM2608::renderSamples() { adpcmBMemLen=memPos+256; } -void DivPlatformYM2608::setFlags(unsigned int flags) { +void DivPlatformYM2608::setFlags(const DivConfig& flags) { // Clock flags - switch (flags&0x1f) { - default: - case 0x00: - chipClock=8000000.0; - break; + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=38400*13*16; // 31948800/4 break; + default: + chipClock=8000000.0; + break; } // Prescaler flags - switch ((flags>>5)&0x3) { - default: - case 0x00: // /6 - prescale=0x2d; - fmFreqBase=9440540.0, - fmDivBase=72, - ayDiv=32; - break; + switch (flags.getInt("prescale",0)) { case 0x01: // /3 prescale=0x2e; fmFreqBase=9440540.0/2.0, @@ -1393,6 +1385,12 @@ void DivPlatformYM2608::setFlags(unsigned int flags) { fmDivBase=24, ayDiv=8; break; + default: // /6 + prescale=0x2d; + fmFreqBase=9440540.0, + fmDivBase=72, + ayDiv=32; + break; } rate=fm->sample_rate(chipClock); for (int i=0; i<16; i++) { @@ -1401,11 +1399,12 @@ void DivPlatformYM2608::setFlags(unsigned int flags) { immWrite(0x2d,0xff); immWrite(prescale,0xff); ay->setExtClockDiv(chipClock,ayDiv); - ay->setFlags(16); + ay->setFlags(ayFlags); } -int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; + ayFlags.set("chipType",1); adpcmBMem=new unsigned char[getSampleMemCapacity(0)]; adpcmBMemLen=0; iface.adpcmBMem=adpcmBMem; @@ -1420,7 +1419,7 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, unsigned in fm->set_fidelity(ymfm::OPN_FIDELITY_MIN); // YM2149, 2MHz ay=new DivPlatformAY8910(true,chipClock,ayDiv); - ay->init(p,3,sugRate,16); + ay->init(p,3,sugRate,ayFlags); ay->toggleRegisterDump(true); setFlags(flags); reset(); diff --git a/src/engine/platform/ym2608.h b/src/engine/platform/ym2608.h index a1b523208..7a9eefa97 100644 --- a/src/engine/platform/ym2608.h +++ b/src/engine/platform/ym2608.h @@ -138,8 +138,8 @@ class DivPlatformYM2608: public DivPlatformOPN { size_t getSampleMemCapacity(int index); size_t getSampleMemUsage(int index); void renderSamples(); - void setFlags(unsigned int flags); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + void setFlags(const DivConfig& flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformYM2608(): DivPlatformOPN(9440540.0, 72, 32), diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index 0b73b42c9..925e70844 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -541,7 +541,7 @@ void DivPlatformYM2608Ext::notifyInsChange(int ins) { } } -int DivPlatformYM2608Ext::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2608Ext::init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2608::init(parent,channels,sugRate,flags); for (int i=0; i<4; i++) { isOpMuted[i]=false; diff --git a/src/engine/platform/ym2608ext.h b/src/engine/platform/ym2608ext.h index 4792323cc..fc734097f 100644 --- a/src/engine/platform/ym2608ext.h +++ b/src/engine/platform/ym2608ext.h @@ -66,7 +66,7 @@ class DivPlatformYM2608Ext: public DivPlatformYM2608 { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformYM2608Ext(); }; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 63d6e0341..3cb2bca65 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -1278,7 +1278,7 @@ void DivPlatformYM2610::setSkipRegisterWrites(bool value) { ay->setSkipRegisterWrites(value); } -int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2610Base::init(p, channels, sugRate, flags); reset(); return 14; diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index cfe4a5856..1572b4a20 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -58,7 +58,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base<14> { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformYM2610(): DivPlatformYM2610Base<14>(1,4,7,13) {} diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index e3757162a..7bca24a13 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -1345,7 +1345,7 @@ void DivPlatformYM2610B::setSkipRegisterWrites(bool value) { ay->setSkipRegisterWrites(value); } -int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2610Base::init(p, channels, sugRate, flags); reset(); return 16; diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 488fadf9a..1fba7061a 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -54,7 +54,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base<16> { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); DivPlatformYM2610B(): DivPlatformYM2610Base<16>(2,6,9,15) {} diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index 201bb598d..e09f0c579 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -532,7 +532,7 @@ void DivPlatformYM2610BExt::notifyInsChange(int ins) { } } -int DivPlatformYM2610BExt::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2610BExt::init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2610B::init(parent,channels,sugRate,flags); for (int i=0; i<4; i++) { isOpMuted[i]=false; diff --git a/src/engine/platform/ym2610bext.h b/src/engine/platform/ym2610bext.h index fcb5e2b00..accd7eeeb 100644 --- a/src/engine/platform/ym2610bext.h +++ b/src/engine/platform/ym2610bext.h @@ -37,7 +37,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformYM2610BExt(); }; diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index ac82bb81e..5a0fadabc 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -532,7 +532,7 @@ void DivPlatformYM2610Ext::notifyInsChange(int ins) { } } -int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, unsigned int flags) { +int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) { DivPlatformYM2610::init(parent,channels,sugRate,flags); for (int i=0; i<4; i++) { isOpMuted[i]=false; diff --git a/src/engine/platform/ym2610ext.h b/src/engine/platform/ym2610ext.h index 5cc4432c5..97ce9c1cc 100644 --- a/src/engine/platform/ym2610ext.h +++ b/src/engine/platform/ym2610ext.h @@ -37,7 +37,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 { void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); void notifyInsChange(int ins); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformYM2610Ext(); }; diff --git a/src/engine/platform/ym2610shared.h b/src/engine/platform/ym2610shared.h index 920cf499b..3641306ce 100644 --- a/src/engine/platform/ym2610shared.h +++ b/src/engine/platform/ym2610shared.h @@ -260,15 +260,14 @@ template class DivPlatformYM2610Base: public DivPlatformOPN { adpcmBMemLen=memPos+256; } - void setFlags(unsigned int flags) { - switch (flags&0xff) { - default: - case 0x00: - chipClock=8000000.0; - break; + void setFlags(const DivConfig& flags) { + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=24167829/3; break; + default: + chipClock=8000000.0; + break; } rate=chipClock/16; for (int i=0; i class DivPlatformYM2610Base: public DivPlatformOPN { } } - int init(DivEngine* p, int channels, int sugRate, unsigned int flags) { + int init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; + ayFlags.set("chipType",1); dumpWrites=false; skipRegisterWrites=false; for (int i=0; i class DivPlatformYM2610Base: public DivPlatformOPN { setFlags(flags); // YM2149, 2MHz ay=new DivPlatformAY8910(true,chipClock,32); - ay->init(p,3,sugRate,16); + ay->init(p,3,sugRate,ayFlags); ay->toggleRegisterDump(true); return 0; } diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index e89c3f9be..b2797cd60 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -447,14 +447,11 @@ void DivPlatformYMZ280B::setChipModel(int type) { chipType=type; } -void DivPlatformYMZ280B::setFlags(unsigned int flags) { +void DivPlatformYMZ280B::setFlags(const DivConfig& flags) { switch (chipType) { default: case 280: - switch (flags&0xff) { - case 0x00: - chipClock=16934400; - break; + switch (flags.getInt("clockSel",0)) { case 0x01: chipClock=COLOR_NTSC*4.0; break; @@ -470,6 +467,9 @@ void DivPlatformYMZ280B::setFlags(unsigned int flags) { case 0x05: chipClock=14000000; break; + default: + chipClock=16934400; + break; } rate=chipClock/384; break; @@ -483,7 +483,7 @@ void DivPlatformYMZ280B::setFlags(unsigned int flags) { } } -int DivPlatformYMZ280B::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformYMZ280B::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/ymz280b.h b/src/engine/platform/ymz280b.h index e4f658488..3b4b60d5c 100644 --- a/src/engine/platform/ymz280b.h +++ b/src/engine/platform/ymz280b.h @@ -100,8 +100,8 @@ class DivPlatformYMZ280B: public DivDispatch { size_t getSampleMemCapacity(int index = 0); size_t getSampleMemUsage(int index = 0); void renderSamples(); - void setFlags(unsigned int flags); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + void setFlags(const DivConfig& flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); private: void writeOutVol(int ch); diff --git a/src/engine/platform/zxbeeper.cpp b/src/engine/platform/zxbeeper.cpp index 5fa3840bb..76af50220 100644 --- a/src/engine/platform/zxbeeper.cpp +++ b/src/engine/platform/zxbeeper.cpp @@ -286,8 +286,9 @@ void DivPlatformZXBeeper::notifyInsDeletion(void* ins) { } } -void DivPlatformZXBeeper::setFlags(unsigned int flags) { - if (flags&1) { // technically there is no PAL PC Engine but oh well... +void DivPlatformZXBeeper::setFlags(const DivConfig& flags) { + // TODO: where's ZX Spectrum 48K?! + if (flags.getInt("clockSel",0)) { chipClock=COLOR_PAL*4.0/5.0; } else { chipClock=COLOR_NTSC; @@ -306,7 +307,7 @@ void DivPlatformZXBeeper::poke(std::vector& wlist) { } -int DivPlatformZXBeeper::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { +int DivPlatformZXBeeper::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/zxbeeper.h b/src/engine/platform/zxbeeper.h index b02b1fb76..ed82caeeb 100644 --- a/src/engine/platform/zxbeeper.h +++ b/src/engine/platform/zxbeeper.h @@ -87,13 +87,13 @@ class DivPlatformZXBeeper: public DivDispatch { void tick(bool sysTick=true); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); - void setFlags(unsigned int flags); + void setFlags(const DivConfig& flags); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); - int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); + int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags); void quit(); ~DivPlatformZXBeeper(); }; diff --git a/src/engine/song.h b/src/engine/song.h index 03f51836d..4217a3257 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -234,9 +234,6 @@ struct DivSong { unsigned char systemLen; signed char systemVol[32]; signed char systemPan[32]; - // this one will be removed soon... - unsigned int systemFlagsOld[32]; - // ...and replaced with... this! DivConfig systemFlags[32]; // song information @@ -433,7 +430,6 @@ struct DivSong { system[i]=DIV_SYSTEM_NULL; systemVol[i]=64; systemPan[i]=0; - systemFlagsOld[i]=0; } subsong.push_back(new DivSubSong); system[0]=DIV_SYSTEM_YM2612; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 385e20650..0e2f1e11c 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -61,62 +61,81 @@ String DivEngine::getSongSystemLegacyName(DivSong& ds, bool isMultiSystemAccepta return "help! what's going on!"; case 1: if (ds.system[0]==DIV_SYSTEM_AY8910) { - switch (ds.systemFlagsOld[0]&0x3f) { - 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"; - - case 0x10: // YM2149, 1.79MHz - return "MSX"; - case 0x13: // YM2149, 2MHz - return "Atari ST"; - case 0x26: // 5B NTSC - return "Sunsoft 5B standalone"; - case 0x28: // 5B PAL - return "Sunsoft 5B standalone (PAL)"; - - case 0x30: // AY-3-8914, 1.79MHz - return "Intellivision"; - case 0x33: // AY-3-8914, 2MHz - return "Intellivision (PAL)"; - - default: - if ((ds.systemFlagsOld[0]&0x30)==0x00) { - return "AY-3-8910"; - } else if ((ds.systemFlagsOld[0]&0x30)==0x10) { - return "Yamaha YM2149"; - } else if ((ds.systemFlagsOld[0]&0x30)==0x20) { - return "Overclocked Sunsoft 5B"; - } else if ((ds.systemFlagsOld[0]&0x30)==0x30) { - return "Intellivision"; + 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.systemFlagsOld[0]&0x0f) { - case 0: case 1: - return "Sega Master System"; - case 6: - return "BBC Micro"; + 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.systemFlagsOld[0]&3) { + switch (ds.systemFlags[0].getInt("clockSel",0)) { case 2: return "FM Towns"; } } else if (ds.system[0]==DIV_SYSTEM_YM2151) { - switch (ds.systemFlagsOld[0]&3) { + switch (ds.systemFlags[0].getInt("clockSel",0)) { case 2: return "Sharp X68000"; } } else if (ds.system[0]==DIV_SYSTEM_SAA1099) { - switch (ds.systemFlagsOld[0]&3) { + switch (ds.systemFlags[0].getInt("clockSel",0)) { case 0: return "SAM Coupé"; } diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 506998966..975d5eefc 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -979,7 +979,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (!hasSN) { hasSN=disCont[i].dispatch->chipClock; willExport[i]=true; - switch ((song.systemFlagsOld[i]>>2)&3) { + switch (song.systemFlags[i].getInt("chipType",0)) { case 1: // real SN snNoiseConfig=3; snNoiseSize=15; @@ -1094,11 +1094,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p ayConfig=0x03; hasClockDivider=true; } else { - switch ((song.systemFlagsOld[i]>>4)&3) { - default: - case 0: // AY8910 - ayConfig=0x00; - break; + switch (song.systemFlags[i].getInt("chipType",0)) { case 1: // YM2149 ayConfig=0x10; hasClockDivider=true; @@ -1111,12 +1107,15 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case 3: // AY8914 ayConfig=0x04; break; + default: // AY8910 + ayConfig=0x00; + break; } } - if (hasClockDivider && ((song.systemFlagsOld[i]>>7)&1)) { + if (hasClockDivider && song.systemFlags[i].getBool("halfClock",false)) { ayFlags|=0x10; } - if (hasStereo && ((song.systemFlagsOld[i]>>6)&1)) { + if (hasStereo && song.systemFlags[i].getBool("stereo",false)) { ayFlags|=0x80; } willExport[i]=true; @@ -1358,7 +1357,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p // chips even though the only difference is the output resolution // these system types are currently handled by reusing isSecond flag // also this system is not dual-able - if ((song.systemFlagsOld[i]>>4)==1) { + if (song.systemFlags[i].getInt("chipType",0)==1) { if (!hasRFC1) { hasRFC1=disCont[i].dispatch->chipClock; isSecond[i]=true; diff --git a/src/gui/cursor.cpp b/src/gui/cursor.cpp index 5a98a78c6..88d50d2b8 100644 --- a/src/gui/cursor.cpp +++ b/src/gui/cursor.cpp @@ -18,7 +18,7 @@ */ #include "gui.h" - +#include "../ta-log.h" #include "actionUtil.h" void FurnaceGUI::startSelection(int xCoarse, int xFine, int y, bool fullRow) { @@ -187,9 +187,11 @@ void FurnaceGUI::finishSelection() { selStart.xFine=0; } if (e->curSubSong->chanCollapse[selEnd.xCoarse] && selEnd.xFine>=(3-e->curSubSong->chanCollapse[selEnd.xCoarse])) { - selEnd.xFine=2+e->curPat[cursor.xCoarse].effectCols*2; + selEnd.xFine=2+e->curPat[selEnd.xCoarse].effectCols*2; } + logV("finish selection: %d.%d,%d - %d.%d,%d",selStart.xCoarse,selStart.xFine,selStart.y,selEnd.xCoarse,selEnd.xFine,selEnd.y); + e->setMidiBaseChan(cursor.xCoarse); } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 9ce08ab58..4c7850adf 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3438,7 +3438,7 @@ bool FurnaceGUI::loop() { if (ImGui::BeginMenu("configure chip...")) { for (int i=0; isong.systemLen; i++) { if (ImGui::TreeNode(fmt::sprintf("%d. %s##_SYSP%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { - drawSysConf(i,e->song.system[i],e->song.systemFlagsOld[i],true); + drawSysConf(i,e->song.system[i],e->song.systemFlags[i],true); ImGui::TreePop(); } } diff --git a/src/gui/gui.h b/src/gui/gui.h index c4b1005da..6bb0d38f7 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1211,7 +1211,7 @@ class FurnaceGUI { String macroRelLabel; String emptyLabel; String emptyLabel2; - std::vector initialSys; + DivConfig initialSys; Settings(): mainFontSize(18), @@ -1619,7 +1619,7 @@ class FurnaceGUI { void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size); void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, float maxRr, const ImVec2& size, unsigned short instType); void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size); - void drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange); + bool drawSysConf(int chan, DivSystem type, DivConfig& flags, bool modifyOnChange); void kvsConfig(DivInstrument* ins); // these ones offer ctrl-wheel fine value changes. diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index d5cd0385e..12b48277e 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1908,7 +1908,7 @@ void FurnaceGUI::drawInsEdit() { if (e->song.system[i]==DIV_SYSTEM_VRC7) { isPresent[3]=true; } else if (e->song.system[i]==DIV_SYSTEM_OPLL || e->song.system[i]==DIV_SYSTEM_OPLL_DRUMS) { - isPresent[(e->song.systemFlagsOld[i]>>4)&3]=true; + isPresent[(e->song.systemFlags[i].getInt("patchSet",0))&3]=true; } } if (!isPresent[0] && !isPresent[1] && !isPresent[2] && !isPresent[3]) { diff --git a/src/gui/newSong.cpp b/src/gui/newSong.cpp index c819ffd3a..eff8d4a0f 100644 --- a/src/gui/newSong.cpp +++ b/src/gui/newSong.cpp @@ -19,6 +19,7 @@ #include "gui.h" #include "misc/cpp/imgui_stdlib.h" +#include #include void FurnaceGUI::drawNewSong() { @@ -140,7 +141,16 @@ void FurnaceGUI::drawNewSong() { } if (accepted) { - e->createNew(nextDesc,nextDescName); + // TODO: remove after porting all presets to new format + String oldDescFormat; + for (const int* i=nextDesc; *i; i+=4) { + oldDescFormat+=fmt::sprintf("%d ",e->systemToFileFur((DivSystem)i[0])); + oldDescFormat+=fmt::sprintf("%d ",i[1]); + oldDescFormat+=fmt::sprintf("%d ",i[2]); + oldDescFormat+=fmt::sprintf("%d ",i[3]); + } + String oldDesc=e->decodeSysDesc(oldDescFormat.c_str()); + e->createNew(oldDesc.c_str(),nextDescName); undoHist.clear(); redoHist.clear(); curFileName=""; diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index b55a064c5..26557acd2 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -270,10 +270,10 @@ void FurnaceGUI::drawSettings() { if (ImGui::Button("Current system")) { settings.initialSys.clear(); for (int i=0; isong.systemLen; i++) { - settings.initialSys.push_back(e->song.system[i]); - settings.initialSys.push_back(e->song.systemVol[i]); - settings.initialSys.push_back(e->song.systemPan[i]); - settings.initialSys.push_back(e->song.systemFlagsOld[i]); + settings.initialSys.set(fmt::sprintf("id%d",i),e->systemToFileFur(e->song.system[i])); + settings.initialSys.set(fmt::sprintf("vol%d",i),(int)e->song.systemVol[i]); + settings.initialSys.set(fmt::sprintf("pan%d",i),(int)e->song.systemPan[i]); + settings.initialSys.set(fmt::sprintf("flags%d",i),e->song.systemFlags[i].toBase64()); } settings.initialSysName=e->song.systemName; } @@ -285,22 +285,24 @@ void FurnaceGUI::drawSettings() { for (totalAvailSys=0; availableSystems[totalAvailSys]; totalAvailSys++); if (totalAvailSys>0) { for (int i=0; isystemToFileFur((DivSystem)availableSystems[rand()%totalAvailSys])); + settings.initialSys.set(fmt::sprintf("vol%d",i),64); + settings.initialSys.set(fmt::sprintf("pan%d",i),0); + settings.initialSys.set(fmt::sprintf("flags%d",i),""); } } else { - settings.initialSys.push_back(DIV_SYSTEM_DUMMY); - settings.initialSys.push_back(64); - settings.initialSys.push_back(0); - settings.initialSys.push_back(0); + settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_DUMMY)); + settings.initialSys.set("vol0",64); + settings.initialSys.set("pan0",0); + settings.initialSys.set("flags0",""); + howMany=1; } // randomize system name std::vector wordPool[6]; - for (size_t i=0; igetSystemName((DivSystem)settings.initialSys[i*4]); + DivSystem sysID=e->systemFromFileFur(settings.initialSys.getInt(fmt::sprintf("id%d",i),0)); + String sName=e->getSystemName(sysID); String nameWord; sName+=" "; for (char& i: sName) { @@ -325,14 +327,14 @@ void FurnaceGUI::drawSettings() { ImGui::SameLine(); if (ImGui::Button("Reset to defaults")) { settings.initialSys.clear(); - settings.initialSys.push_back(DIV_SYSTEM_YM2612); - settings.initialSys.push_back(64); - settings.initialSys.push_back(0); - settings.initialSys.push_back(0); - settings.initialSys.push_back(DIV_SYSTEM_SMS); - settings.initialSys.push_back(32); - settings.initialSys.push_back(0); - settings.initialSys.push_back(0); + settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_YM2612)); + settings.initialSys.set("vol0",64); + settings.initialSys.set("pan0",0); + settings.initialSys.set("flags0",""); + settings.initialSys.set("id1",e->systemToFileFur(DIV_SYSTEM_SMS)); + settings.initialSys.set("vol1",64); + settings.initialSys.set("pan1",0); + settings.initialSys.set("flags1",""); settings.initialSysName="Sega Genesis/Mega Drive"; } @@ -341,18 +343,23 @@ void FurnaceGUI::drawSettings() { ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputText("##InitSysName",&settings.initialSysName); - for (size_t i=0; isystemFromFileFur(settings.initialSys.getInt(fmt::sprintf("id%d",i),0)); + signed char sysVol=settings.initialSys.getInt(fmt::sprintf("vol%d",i),0); + signed char sysPan=settings.initialSys.getInt(fmt::sprintf("pan%d",i),0); + + //bool doRemove=false; + bool doInvert=sysVol&128; + signed char vol=sysVol&127; ImGui::PushID(i); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-ImGui::CalcTextSize("Invert").x-ImGui::GetFrameHeightWithSpacing()*2.0-ImGui::GetStyle().ItemSpacing.x); - if (ImGui::BeginCombo("##System",getSystemName((DivSystem)settings.initialSys[i]))) { + if (ImGui::BeginCombo("##System",getSystemName(sysID))) { for (int j=0; availableSystems[j]; j++) { - if (ImGui::Selectable(getSystemName((DivSystem)availableSystems[j]),settings.initialSys[i]==availableSystems[j])) { - settings.initialSys[i]=availableSystems[j]; - settings.initialSys[i+3]=0; + if (ImGui::Selectable(getSystemName((DivSystem)availableSystems[j]),sysID==availableSystems[j])) { + sysID=(DivSystem)availableSystems[j]; + settings.initialSys.set(fmt::sprintf("id%d",i),(int)e->systemToFileFur(sysID)); + settings.initialSys.set(fmt::sprintf("flags%d",i),""); } } ImGui::EndCombo(); @@ -360,39 +367,48 @@ void FurnaceGUI::drawSettings() { ImGui::SameLine(); if (ImGui::Checkbox("Invert",&doInvert)) { - settings.initialSys[i+1]^=128; + sysVol^=128; + settings.initialSys.set(fmt::sprintf("vol%d",i),(int)sysVol); } ImGui::SameLine(); - ImGui::BeginDisabled(settings.initialSys.size()<=4); + //ImGui::BeginDisabled(settings.initialSys.size()<=4); if (ImGui::Button(ICON_FA_MINUS "##InitSysRemove")) { - doRemove=true; + //doRemove=true; } - ImGui::EndDisabled(); + //ImGui::EndDisabled(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); if (CWSliderScalar("Volume",ImGuiDataType_S8,&vol,&_ZERO,&_ONE_HUNDRED_TWENTY_SEVEN)) { - settings.initialSys[i+1]=(settings.initialSys[i+1]&128)|vol; + sysVol=(sysVol&128)|vol; + settings.initialSys.set(fmt::sprintf("vol%d",i),(int)sysVol); } rightClickable ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - CWSliderScalar("Panning",ImGuiDataType_S8,&settings.initialSys[i+2],&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN); rightClickable + if (CWSliderScalar("Panning",ImGuiDataType_S8,&sysPan,&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN)) { + settings.initialSys.set(fmt::sprintf("pan%d",i),(int)sysPan); + } rightClickable // oh please MSVC don't cry if (ImGui::TreeNode("Configure")) { - drawSysConf(-1,(DivSystem)settings.initialSys[i],(unsigned int&)settings.initialSys[i+3],false); + String sysFlagsS=settings.initialSys.getString(fmt::sprintf("flags%d",i),""); + DivConfig sysFlags; + sysFlags.loadFromBase64(sysFlagsS.c_str()); + if (drawSysConf(-1,sysID,sysFlags,false)) { + settings.initialSys.set(fmt::sprintf("flags%d",i),sysFlags.toBase64()); + } ImGui::TreePop(); } ImGui::PopID(); - if (doRemove && settings.initialSys.size()>=8) { + /*if (doRemove && settings.initialSys.size()>=8) { settings.initialSys.erase(settings.initialSys.begin()+i,settings.initialSys.begin()+i+4); i-=4; - } + }*/ } if (ImGui::Button(ICON_FA_PLUS "##InitSysAdd")) { - settings.initialSys.push_back(DIV_SYSTEM_YM2612); + /*settings.initialSys.push_back(DIV_SYSTEM_YM2612); settings.initialSys.push_back(64); settings.initialSys.push_back(0); - settings.initialSys.push_back(0); + settings.initialSys.push_back(0);*/ } ImGui::Separator(); @@ -2440,17 +2456,22 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.midiOutClock,0,1); clampSetting(settings.midiOutMode,0,2); - settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys","")); - if (settings.initialSys.size()<4) { + String initialSys2=e->getConfString("initialSys2",""); + if (initialSys2.empty()) { + initialSys2=e->decodeSysDesc(e->getConfString("initialSys","")); + } + settings.initialSys.clear(); + settings.initialSys.loadFromBase64(initialSys2.c_str()); + if (settings.initialSys.getInt("id0",0)==0) { settings.initialSys.clear(); - settings.initialSys.push_back(DIV_SYSTEM_YM2612); - settings.initialSys.push_back(64); - settings.initialSys.push_back(0); - settings.initialSys.push_back(0); - settings.initialSys.push_back(DIV_SYSTEM_SMS); - settings.initialSys.push_back(32); - settings.initialSys.push_back(0); - settings.initialSys.push_back(0); + settings.initialSys.set("id0",e->systemToFileFur(DIV_SYSTEM_YM2612)); + settings.initialSys.set("vol0",64); + settings.initialSys.set("pan0",0); + settings.initialSys.set("flags0",""); + settings.initialSys.set("id1",e->systemToFileFur(DIV_SYSTEM_SMS)); + settings.initialSys.set("vol1",64); + settings.initialSys.set("pan1",0); + settings.initialSys.set("flags1",""); } // keybinds @@ -2564,7 +2585,7 @@ void FurnaceGUI::commitSettings() { e->setConf("eventDelay",settings.eventDelay); e->setConf("moveWindowTitle",settings.moveWindowTitle); e->setConf("hiddenSystems",settings.hiddenSystems); - e->setConf("initialSys",e->encodeSysDesc(settings.initialSys)); + e->setConf("initialSys2",settings.initialSys.toBase64()); e->setConf("initialSysName",settings.initialSysName); e->setConf("horizontalDataView",settings.horizontalDataView); e->setConf("noMultiSystem",settings.noMultiSystem); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 6e90f4530..bbc86b7aa 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -19,656 +19,1041 @@ #include "gui.h" -void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange) { +bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool modifyOnChange) { + bool altered=false; bool restart=settings.restartOnFlagChange && modifyOnChange; - bool sysPal=flags&1; - unsigned int copyOfFlags=flags; + switch (type) { case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612_EXT: case DIV_SYSTEM_YM2612_FRAC: case DIV_SYSTEM_YM2612_FRAC_EXT: { - if (ImGui::RadioButton("NTSC (7.67MHz)",(flags&(~0x80000000))==0)) { - copyOfFlags=(flags&0x80000000)|0; + int clockSel=flags.getInt("clockSel",0); + bool ladder=flags.getBool("ladderEffect",0); + + if (ImGui::RadioButton("NTSC (7.67MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (7.61MHz)",(flags&(~0x80000000))==1)) { - copyOfFlags=(flags&0x80000000)|1; + if (ImGui::RadioButton("PAL (7.61MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("FM Towns (8MHz)",(flags&(~0x80000000))==2)) { - copyOfFlags=(flags&0x80000000)|2; + if (ImGui::RadioButton("FM Towns (8MHz)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",(flags&(~0x80000000))==3)) { - copyOfFlags=(flags&0x80000000)|3; + if (ImGui::RadioButton("AtGames Genesis (6.13MHz)",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("Sega System 32 (8.05MHz)",(flags&(~0x80000000))==4)) { - copyOfFlags=(flags&0x80000000)|4; + if (ImGui::RadioButton("Sega System 32 (8.05MHz)",clockSel==4)) { + clockSel=4; + altered=true; } - bool ladder=flags&0x80000000; if (ImGui::Checkbox("Enable DAC distortion",&ladder)) { - copyOfFlags=(flags&(~0x80000000))|(ladder?0x80000000:0); + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("ladderEffect",ladder); + }); } break; } case DIV_SYSTEM_SMS: { + int clockSel=flags.getInt("clockSel",0); + int chipType=flags.getInt("chipType",0); + bool noPhaseReset=flags.getBool("noPhaseReset",false); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&0xff03)==0x0000)) { - copyOfFlags=(flags&(~0xff03))|0x0000; + if (ImGui::RadioButton("3.58MHz (NTSC)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("3.55MHz (PAL)",(flags&0xff03)==0x0001)) { - copyOfFlags=(flags&(~0xff03))|0x0001; + if (ImGui::RadioButton("3.55MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("4MHz (BBC Micro)",(flags&0xff03)==0x0002)) { - copyOfFlags=(flags&(~0xff03))|0x0002; + if (ImGui::RadioButton("4MHz (BBC Micro)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("1.79MHz (Half NTSC)",(flags&0xff03)==0x0003)) { - copyOfFlags=(flags&(~0xff03))|0x0003; + if (ImGui::RadioButton("1.79MHz (Half NTSC)",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("3MHz (Exed Exes)",(flags&0xff03)==0x0100)) { - copyOfFlags=(flags&(~0xff03))|0x0100; + if (ImGui::RadioButton("3MHz (Exed Exes)",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("2MHz (Sega System 1)",(flags&0xff03)==0x0101)) { - copyOfFlags=(flags&(~0xff03))|0x0101; + if (ImGui::RadioButton("2MHz (Sega System 1)",clockSel==5)) { + clockSel=5; + altered=true; } - if (ImGui::RadioButton("447KHz (TI-99/4A)",(flags&0xff03)==0x0102)) { - copyOfFlags=(flags&(~0xff03))|0x0102; + if (ImGui::RadioButton("447KHz (TI-99/4A)",clockSel==6)) { + clockSel=6; + altered=true; } ImGui::Text("Chip type:"); - if (ImGui::RadioButton("Sega VDP/Master System",(flags&0xcc)==0x00)) { - copyOfFlags=(flags&(~0xcc))|0x00; + if (ImGui::RadioButton("Sega VDP/Master System",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("TI SN76489",(flags&0xcc)==0x04)) { - copyOfFlags=(flags&(~0xcc))|0x04; + if (ImGui::RadioButton("TI SN76489",chipType==1)) { + chipType=1; + altered=true; } - if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",(flags&0xcc)==0x08)) { - copyOfFlags=(flags&(~0xcc))|0x08; + if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",chipType==2)) { + chipType=2; + altered=true; } - if (ImGui::RadioButton("Game Gear",(flags&0xcc)==0x0c)) { - copyOfFlags=(flags&(~0xcc))|0x0c; + if (ImGui::RadioButton("Game Gear",chipType==3)) { + chipType=3; + altered=true; } - if (ImGui::RadioButton("TI SN76489A",(flags&0xcc)==0x40)) { - copyOfFlags=(flags&(~0xcc))|0x40; + if (ImGui::RadioButton("TI SN76489A",chipType==4)) { + chipType=4; + altered=true; } - if (ImGui::RadioButton("TI SN76496",(flags&0xcc)==0x44)) { - copyOfFlags=(flags&(~0xcc))|0x44; + if (ImGui::RadioButton("TI SN76496",chipType==5)) { + chipType=5; + altered=true; } - if (ImGui::RadioButton("NCR 8496",(flags&0xcc)==0x48)) { - copyOfFlags=(flags&(~0xcc))|0x48; + if (ImGui::RadioButton("NCR 8496",chipType==6)) { + chipType=6; + altered=true; } - if (ImGui::RadioButton("Tandy PSSJ 3-voice sound",(flags&0xcc)==0x4c)) { - copyOfFlags=(flags&(~0xcc))|0x4c; + if (ImGui::RadioButton("Tandy PSSJ 3-voice sound",chipType==7)) { + chipType=7; + altered=true; } - if (ImGui::RadioButton("TI SN94624",(flags&0xcc)==0x80)) { - copyOfFlags=(flags&(~0xcc))|0x80; + if (ImGui::RadioButton("TI SN94624",chipType==8)) { + chipType=8; + altered=true; } - if (ImGui::RadioButton("TI SN76494",(flags&0xcc)==0x84)) { - copyOfFlags=(flags&(~0xcc))|0x84; + if (ImGui::RadioButton("TI SN76494",chipType==9)) { + chipType=9; + altered=true; } - bool noPhaseReset=flags&16; + if (ImGui::Checkbox("Disable noise period change phase reset",&noPhaseReset)) { - copyOfFlags=(flags&(~16))|(noPhaseReset<<4); + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("chipType",chipType); + flags.set("noPhaseReset",noPhaseReset); + }); } break; } case DIV_SYSTEM_PCE: { - sysPal=flags&1; - if (ImGui::Checkbox("Pseudo-PAL",&sysPal)) { - copyOfFlags=(flags&(~1))|(unsigned int)sysPal; + bool clockSel=flags.getInt("clockSel",0); + int chipType=flags.getInt("chipType",0); + bool noAntiClick=flags.getBool("noAntiClick",false); + + if (ImGui::Checkbox("Pseudo-PAL",&clockSel)) { + altered=true; } - bool antiClick=flags&8; - if (ImGui::Checkbox("Disable anti-click",&antiClick)) { - copyOfFlags=(flags&(~8))|(antiClick<<3); + if (ImGui::Checkbox("Disable anti-click",&noAntiClick)) { + altered=true; } ImGui::Text("Chip revision:"); - if (ImGui::RadioButton("HuC6280 (original)",(flags&4)==0)) { - copyOfFlags=(flags&(~4))|0; + if (ImGui::RadioButton("HuC6280 (original)",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("HuC6280A (SuperGrafx)",(flags&4)==4)) { - copyOfFlags=(flags&(~4))|4; + if (ImGui::RadioButton("HuC6280A (SuperGrafx)",chipType==1)) { + chipType=1; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",(int)clockSel); + flags.set("chipType",chipType); + flags.set("noAntiClick",noAntiClick); + }); } break; } case DIV_SYSTEM_SOUND_UNIT: { + int clockSel=flags.getInt("clockSel",0); + bool echo=flags.getBool("echo",false); + bool swapEcho=flags.getBool("swapEcho",false); + int sampleMemSize=flags.getInt("sampleMemSize",0); + bool pdm=flags.getBool("pdm",false); + int echoDelay=flags.getInt("echoDelay",0); + int echoFeedback=flags.getInt("echoFeedback",0); + int echoResolution=flags.getInt("echoResolution",0); + int echoVol=(signed char)flags.getInt("echoVol",0); + ImGui::Text("CPU rate:"); - if (ImGui::RadioButton("6.18MHz (NTSC)",(flags&3)==0)) { - copyOfFlags=(flags&(~3))|0; + if (ImGui::RadioButton("6.18MHz (NTSC)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("5.95MHz (PAL)",(flags&3)==1)) { - copyOfFlags=(flags&(~3))|1; + if (ImGui::RadioButton("5.95MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } ImGui::Text("Sample memory:"); - if (ImGui::RadioButton("8K (rev A/B/E)",(flags&16)==0)) { - copyOfFlags=(flags&(~16))|0; + if (ImGui::RadioButton("8K (rev A/B/E)",sampleMemSize==0)) { + sampleMemSize=0; + altered=true; } - if (ImGui::RadioButton("64K (rev D/F)",(flags&16)==16)) { - copyOfFlags=(flags&(~16))|16; + if (ImGui::RadioButton("64K (rev D/F)",sampleMemSize==1)) { + sampleMemSize=1; + altered=true; } - ImGui::Text("DAC resolution"); - if (ImGui::RadioButton("16-bit (rev A/B/D/F)",(flags&32)==0)) { - copyOfFlags=(flags&(~32))|0; + ImGui::Text("DAC resolution:"); + if (ImGui::RadioButton("16-bit (rev A/B/D/F)",pdm==0)) { + pdm=false; + altered=true; } - if (ImGui::RadioButton("1-bit PDM (rev C/E)",(flags&32)==32)) { - copyOfFlags=(flags&(~32))|32; + if (ImGui::RadioButton("1-bit PDM (rev C/E)",pdm==1)) { + pdm=true; + altered=true; } - bool echo=flags&4; if (ImGui::Checkbox("Enable echo",&echo)) { - copyOfFlags=(flags&(~4))|(echo<<2); + altered=true; } - bool flipEcho=flags&8; - if (ImGui::Checkbox("Swap echo channels",&flipEcho)) { - copyOfFlags=(flags&(~8))|(flipEcho<<3); + if (ImGui::Checkbox("Swap echo channels",&swapEcho)) { + altered=true; } ImGui::Text("Echo delay:"); - int echoBufSize=(flags&0x3f00)>>8; - if (CWSliderInt("##EchoBufSize",&echoBufSize,0,63)) { - if (echoBufSize<0) echoBufSize=0; - if (echoBufSize>63) echoBufSize=63; - copyOfFlags=(flags&~0x3f00)|(echoBufSize<<8); + if (CWSliderInt("##EchoBufSize",&echoDelay,0,63)) { + if (echoDelay<0) echoDelay=0; + if (echoDelay>63) echoDelay=63; + altered=true; } rightClickable ImGui::Text("Echo resolution:"); - int echoResolution=(flags&0xf00000)>>20; if (CWSliderInt("##EchoResolution",&echoResolution,0,15)) { if (echoResolution<0) echoResolution=0; if (echoResolution>15) echoResolution=15; - copyOfFlags=(flags&(~0xf00000))|(echoResolution<<20); + altered=true; } rightClickable ImGui::Text("Echo feedback:"); - int echoFeedback=(flags&0xf0000)>>16; if (CWSliderInt("##EchoFeedback",&echoFeedback,0,15)) { if (echoFeedback<0) echoFeedback=0; if (echoFeedback>15) echoFeedback=15; - copyOfFlags=(flags&(~0xf0000))|(echoFeedback<<16); + altered=true; } rightClickable ImGui::Text("Echo volume:"); - int echoVolume=(signed char)((flags&0xff000000)>>24); - if (CWSliderInt("##EchoVolume",&echoVolume,-128,127)) { - if (echoVolume<-128) echoVolume=-128; - if (echoVolume>127) echoVolume=127; - copyOfFlags=(flags&(~0xff000000))|(((unsigned char)echoVolume)<<24); + if (CWSliderInt("##EchoVolume",&echoVol,-128,127)) { + if (echoVol<-128) echoVol=-128; + if (echoVol>127) echoVol=127; + altered=true; } rightClickable + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("echo",echo); + flags.set("swapEcho",swapEcho); + flags.set("sampleMemSize",sampleMemSize); + flags.set("pdm",pdm); + flags.set("echoDelay",echoDelay); + flags.set("echoFeedback",echoFeedback); + flags.set("echoResolution",echoResolution); + flags.set("echoVol",(unsigned char)echoVol); + }); + } break; } case DIV_SYSTEM_GB: { - bool antiClick=flags&8; - if (ImGui::Checkbox("Disable anti-click",&antiClick)) { - copyOfFlags=(flags&(~8))|(antiClick<<3); + int chipType=flags.getInt("chipType",0); + bool noAntiClick=flags.getBool("noAntiClick",false); + + if (ImGui::Checkbox("Disable anti-click",&noAntiClick)) { + altered=true; } ImGui::Text("Chip revision:"); - if (ImGui::RadioButton("Original (DMG)",(flags&7)==0)) { - copyOfFlags=(flags&(~7))|0; + if (ImGui::RadioButton("Original (DMG)",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("Game Boy Color (rev C)",(flags&7)==1)) { - copyOfFlags=(flags&(~7))|1; + if (ImGui::RadioButton("Game Boy Color (rev C)",chipType==1)) { + chipType=1; + altered=true; } - if (ImGui::RadioButton("Game Boy Color (rev E)",(flags&7)==2)) { - copyOfFlags=(flags&(~7))|2; + if (ImGui::RadioButton("Game Boy Color (rev E)",chipType==2)) { + chipType=2; + altered=true; } - if (ImGui::RadioButton("Game Boy Advance",(flags&7)==3)) { - copyOfFlags=(flags&(~7))|3; + if (ImGui::RadioButton("Game Boy Advance",chipType==3)) { + chipType=3; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("chipType",chipType); + flags.set("noAntiClick",noAntiClick); + }); } break; } case DIV_SYSTEM_OPLL: case DIV_SYSTEM_OPLL_DRUMS: case DIV_SYSTEM_VRC7: { + int clockSel=flags.getInt("clockSel",0); + int patchSet=flags.getInt("patchSet",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("NTSC (3.58MHz)",(flags&15)==0)) { - copyOfFlags=(flags&(~15))|0; + if (ImGui::RadioButton("NTSC (3.58MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) { - copyOfFlags=(flags&(~15))|1; + if (ImGui::RadioButton("PAL (3.55MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("Arcade (4MHz)",(flags&15)==2)) { - copyOfFlags=(flags&(~15))|2; + if (ImGui::RadioButton("Arcade (4MHz)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) { - copyOfFlags=(flags&(~15))|3; + if (ImGui::RadioButton("Half NTSC (1.79MHz)",clockSel==3)) { + clockSel=3; + altered=true; } if (type!=DIV_SYSTEM_VRC7) { ImGui::Text("Patch set:"); - if (ImGui::RadioButton("Yamaha YM2413",((flags>>4)&15)==0)) { - copyOfFlags=(flags&(~0xf0))|0; + if (ImGui::RadioButton("Yamaha YM2413",patchSet==0)) { + patchSet=0; + altered=true; } - if (ImGui::RadioButton("Yamaha YMF281",((flags>>4)&15)==1)) { - copyOfFlags=(flags&(~0xf0))|0x10; + if (ImGui::RadioButton("Yamaha YMF281",patchSet==1)) { + patchSet=1; + altered=true; } - if (ImGui::RadioButton("Yamaha YM2423",((flags>>4)&15)==2)) { - copyOfFlags=(flags&(~0xf0))|0x20; + if (ImGui::RadioButton("Yamaha YM2423",patchSet==2)) { + patchSet=2; + altered=true; } - if (ImGui::RadioButton("Konami VRC7",((flags>>4)&15)==3)) { - copyOfFlags=(flags&(~0xf0))|0x30; + if (ImGui::RadioButton("Konami VRC7",patchSet==3)) { + patchSet=3; + altered=true; } } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + if (type!=DIV_SYSTEM_VRC7) { + flags.set("patchSet",patchSet); + } + }); + } break; } - case DIV_SYSTEM_YM2151: - if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",flags==0)) { - copyOfFlags=0; + case DIV_SYSTEM_YM2151: { + int clockSel=flags.getInt("clockSel",0); + + if (ImGui::RadioButton("NTSC/X16 (3.58MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (3.55MHz)",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("PAL (3.55MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("X1/X68000 (4MHz)",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("X1/X68000 (4MHz)",clockSel==2)) { + clockSel=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; + } case DIV_SYSTEM_NES: case DIV_SYSTEM_VRC6: case DIV_SYSTEM_FDS: - case DIV_SYSTEM_MMC5: - if (ImGui::RadioButton("NTSC (1.79MHz)",flags==0)) { - copyOfFlags=0; + case DIV_SYSTEM_MMC5: { + int clockSel=flags.getInt("clockSel",0); + + if (ImGui::RadioButton("NTSC (1.79MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (1.67MHz)",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("PAL (1.67MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("Dendy (1.77MHz)",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("Dendy (1.77MHz)",clockSel==2)) { + clockSel=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; + } case DIV_SYSTEM_C64_8580: - case DIV_SYSTEM_C64_6581: - if (ImGui::RadioButton("NTSC (1.02MHz)",flags==0)) { - copyOfFlags=0; + case DIV_SYSTEM_C64_6581: { + int clockSel=flags.getInt("clockSel",0); + + if (ImGui::RadioButton("NTSC (1.02MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (0.99MHz)",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("PAL (0.99MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("SSI 2001 (0.89MHz)",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("SSI 2001 (0.89MHz)",clockSel==2)) { + clockSel=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; + } case DIV_SYSTEM_YM2610: case DIV_SYSTEM_YM2610_EXT: case DIV_SYSTEM_YM2610_FULL: case DIV_SYSTEM_YM2610_FULL_EXT: case DIV_SYSTEM_YM2610B: - case DIV_SYSTEM_YM2610B_EXT: - if (ImGui::RadioButton("8MHz (Neo Geo MVS)",(flags&0xff)==0)) { - copyOfFlags=(flags&(~0xff))|0; + case DIV_SYSTEM_YM2610B_EXT: { + int clockSel=flags.getInt("clockSel",0); + + if (ImGui::RadioButton("8MHz (Neo Geo MVS)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("8.06MHz (Neo Geo AES)",(flags&0xff)==1)) { - copyOfFlags=(flags&(~0xff))|1; + if (ImGui::RadioButton("8.06MHz (Neo Geo AES)",clockSel==1)) { + clockSel=1; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; + } case DIV_SYSTEM_AY8910: case DIV_SYSTEM_AY8930: { + int clockSel=flags.getInt("clockSel",0); + int chipType=flags.getInt("chipType",0); + bool halfClock=flags.getBool("halfClock",false); + bool stereo=flags.getBool("stereo",false); + int stereoSep=flags.getInt("stereoSep",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("1.79MHz (ZX Spectrum NTSC/MSX)",(flags&15)==0)) { - copyOfFlags=(flags&(~15))|0; + if (ImGui::RadioButton("1.79MHz (ZX Spectrum NTSC/MSX)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("1.77MHz (ZX Spectrum)",(flags&15)==1)) { - copyOfFlags=(flags&(~15))|1; + if (ImGui::RadioButton("1.77MHz (ZX Spectrum)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("1.75MHz (ZX Spectrum)",(flags&15)==2)) { - copyOfFlags=(flags&(~15))|2; + if (ImGui::RadioButton("1.75MHz (ZX Spectrum)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("2MHz (Atari ST/Sharp X1)",(flags&15)==3)) { - copyOfFlags=(flags&(~15))|3; + if (ImGui::RadioButton("2MHz (Atari ST/Sharp X1)",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("1.5MHz (Vectrex)",(flags&15)==4)) { - copyOfFlags=(flags&(~15))|4; + if (ImGui::RadioButton("1.5MHz (Vectrex)",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("1MHz (Amstrad CPC)",(flags&15)==5)) { - copyOfFlags=(flags&(~15))|5; + if (ImGui::RadioButton("1MHz (Amstrad CPC)",clockSel==5)) { + clockSel=5; + altered=true; } - if (ImGui::RadioButton("0.89MHz (Pre-divided Sunsoft 5B)",(flags&15)==6)) { - copyOfFlags=(flags&(~15))|6; + if (ImGui::RadioButton("0.89MHz (Pre-divided Sunsoft 5B)",clockSel==6)) { + clockSel=6; + altered=true; } - if (ImGui::RadioButton("1.67MHz (?)",(flags&15)==7)) { - copyOfFlags=(flags&(~15))|7; + if (ImGui::RadioButton("1.67MHz (?)",clockSel==7)) { + clockSel=7; + altered=true; } - if (ImGui::RadioButton("0.83MHz (Pre-divided Sunsoft 5B on PAL)",(flags&15)==8)) { - copyOfFlags=(flags&(~15))|8; + if (ImGui::RadioButton("0.83MHz (Pre-divided Sunsoft 5B on PAL)",clockSel==8)) { + clockSel=8; + altered=true; } - if (ImGui::RadioButton("1.10MHz (Gamate/VIC-20 PAL)",(flags&15)==9)) { - copyOfFlags=(flags&(~15))|9; + if (ImGui::RadioButton("1.10MHz (Gamate/VIC-20 PAL)",clockSel==9)) { + clockSel=9; + altered=true; } - if (ImGui::RadioButton("2^21Hz (Game Boy)",(flags&15)==10)) { - copyOfFlags=(flags&(~15))|10; + if (ImGui::RadioButton("2^21Hz (Game Boy)",clockSel==10)) { + clockSel=10; + altered=true; } - if (ImGui::RadioButton("3.58MHz (Darky)",(flags&15)==11)) { - copyOfFlags=(flags&(~15))|11; + if (ImGui::RadioButton("3.58MHz (Darky)",clockSel==11)) { + clockSel=11; + altered=true; } - if (ImGui::RadioButton("3.6MHz (Darky)",(flags&15)==12)) { - copyOfFlags=(flags&(~15))|12; + if (ImGui::RadioButton("3.6MHz (Darky)",clockSel==12)) { + clockSel=12; + altered=true; } - if (ImGui::RadioButton("1.25MHz (Mag Max)",(flags&15)==13)) { - copyOfFlags=(flags&(~15))|13; + if (ImGui::RadioButton("1.25MHz (Mag Max)",clockSel==13)) { + clockSel=13; + altered=true; } - if (ImGui::RadioButton("1.536MHz (Kyugo)",(flags&15)==14)) { - copyOfFlags=(flags&(~15))|14; + if (ImGui::RadioButton("1.536MHz (Kyugo)",clockSel==14)) { + clockSel=14; + altered=true; } if (type==DIV_SYSTEM_AY8910) { ImGui::Text("Chip type:"); - if (ImGui::RadioButton("AY-3-8910",(flags&0x30)==0)) { - copyOfFlags=(flags&(~0x30))|0; + if (ImGui::RadioButton("AY-3-8910",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("YM2149(F)",(flags&0x30)==16)) { - copyOfFlags=(flags&(~0x30))|16; + if (ImGui::RadioButton("YM2149(F)",chipType==1)) { + chipType=1; + altered=true; } - if (ImGui::RadioButton("Sunsoft 5B",(flags&0x30)==32)) { - copyOfFlags=(flags&(~0x30))|32; + if (ImGui::RadioButton("Sunsoft 5B",chipType==2)) { + chipType=2; + altered=true; } - if (ImGui::RadioButton("AY-3-8914",(flags&0x30)==48)) { - copyOfFlags=(flags&(~0x30))|48; + if (ImGui::RadioButton("AY-3-8914",chipType==3)) { + chipType=3; + altered=true; } } - bool stereo=flags&0x40; - ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)==32)); + ImGui::BeginDisabled(type==DIV_SYSTEM_AY8910 && chipType==2); if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) { - copyOfFlags=(flags&(~0x40))|(stereo?0x40:0); + altered=true; } if (stereo) { - int sep=256-((flags>>8)&255); + int sep=256-(stereoSep&255); if (CWSliderInt("Separation",&sep,1,256)) { if (sep<1) sep=1; if (sep>256) sep=256; - copyOfFlags=(flags&(~0xff00))|((256-sep)<<8); + stereoSep=256-sep; + altered=true; } } ImGui::EndDisabled(); - bool clockSel=flags&0x80; - ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)!=16)); - if (ImGui::Checkbox("Half Clock divider##_AY_CLKSEL",&clockSel)) { - copyOfFlags=(flags&(~0x80))|(clockSel?0x80:0); + ImGui::BeginDisabled(type==DIV_SYSTEM_AY8910 && chipType!=1); + if (ImGui::Checkbox("Half Clock divider##_AY_CLKSEL",&halfClock)) { + altered=true; } ImGui::EndDisabled(); + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + if (type==DIV_SYSTEM_AY8910) { + flags.set("chipType",chipType); + } + flags.set("halfClock",halfClock); + flags.set("stereo",stereo); + flags.set("stereoSep",stereoSep); + }); + } break; } - case DIV_SYSTEM_SAA1099: - if (ImGui::RadioButton("SAM Coupé (8MHz)",flags==0)) { - copyOfFlags=0; + case DIV_SYSTEM_SAA1099: { + int clockSel=flags.getInt("clockSel",0); + + if (ImGui::RadioButton("SAM Coupé (8MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("NTSC (7.15MHz)",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("NTSC (7.15MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("PAL (7.09MHz)",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("PAL (7.09MHz)",clockSel==2)) { + clockSel=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; + } case DIV_SYSTEM_AMIGA: { + bool clockSel=flags.getInt("clockSel",0); + int chipType=flags.getInt("chipType",0); + int stereoSep=flags.getInt("stereoSep",0); + bool bypassLimits=flags.getBool("bypassLimits",false); + ImGui::Text("Stereo separation:"); - int stereoSep=(flags>>8)&127; if (CWSliderInt("##StereoSep",&stereoSep,0,127)) { if (stereoSep<0) stereoSep=0; if (stereoSep>127) stereoSep=127; - copyOfFlags=(flags&(~0x7f00))|((stereoSep&127)<<8); + altered=true; } rightClickable - if (ImGui::RadioButton("Amiga 500 (OCS)",(flags&2)==0)) { - copyOfFlags=flags&(~2); + if (ImGui::RadioButton("Amiga 500 (OCS)",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("Amiga 1200 (AGA)",(flags&2)==2)) { - copyOfFlags=(flags&(~2))|2; + if (ImGui::RadioButton("Amiga 1200 (AGA)",chipType==1)) { + chipType=1; + altered=true; } - sysPal=flags&1; - if (ImGui::Checkbox("PAL",&sysPal)) { - copyOfFlags=(flags&(~1))|(unsigned int)sysPal; + if (ImGui::Checkbox("PAL",&clockSel)) { + altered=true; } - bool bypassLimits=flags&4; if (ImGui::Checkbox("Bypass frequency limits",&bypassLimits)) { - copyOfFlags=(flags&(~4))|(bypassLimits<<2); + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",(int)clockSel); + flags.set("chipType",chipType); + flags.set("stereoSep",stereoSep); + flags.set("bypassLimits",bypassLimits); + }); } break; } case DIV_SYSTEM_TIA: { + bool clockSel=flags.getInt("clockSel",0); + int mixingType=flags.getInt("mixingType",0); + ImGui::Text("Mixing mode:"); - if (ImGui::RadioButton("Mono",(flags&6)==0)) { - copyOfFlags=(flags&(~6)); + if (ImGui::RadioButton("Mono",mixingType==0)) { + mixingType=0; + altered=true; } - if (ImGui::RadioButton("Mono (no distortion)",(flags&6)==2)) { - copyOfFlags=(flags&(~6))|2; + if (ImGui::RadioButton("Mono (no distortion)",mixingType==1)) { + mixingType=1; + altered=true; } - if (ImGui::RadioButton("Stereo",(flags&6)==4)) { - copyOfFlags=(flags&(~6))|4; + if (ImGui::RadioButton("Stereo",mixingType==2)) { + mixingType=2; + altered=true; } - sysPal=flags&1; - if (ImGui::Checkbox("PAL",&sysPal)) { - copyOfFlags=(flags&(~1))|(unsigned int)sysPal; + if (ImGui::Checkbox("PAL",&clockSel)) { + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",(int)clockSel); + flags.set("mixingType",mixingType); + }); } break; } case DIV_SYSTEM_PCSPKR: { + int speakerType=flags.getInt("speakerType",0); + ImGui::Text("Speaker type:"); - if (ImGui::RadioButton("Unfiltered",(flags&3)==0)) { - copyOfFlags=(flags&(~3))|0; + if (ImGui::RadioButton("Unfiltered",speakerType==0)) { + speakerType=0; + altered=true; } - if (ImGui::RadioButton("Cone",(flags&3)==1)) { - copyOfFlags=(flags&(~3))|1; + if (ImGui::RadioButton("Cone",speakerType==1)) { + speakerType=1; + altered=true; } - if (ImGui::RadioButton("Piezo",(flags&3)==2)) { - copyOfFlags=(flags&(~3))|2; + if (ImGui::RadioButton("Piezo",speakerType==2)) { + speakerType=2; + altered=true; } - if (ImGui::RadioButton("Use system beeper (Linux only!)",(flags&3)==3)) { - copyOfFlags=(flags&(~3))|3; + if (ImGui::RadioButton("Use system beeper (Linux only!)",speakerType==3)) { + speakerType=3; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("speakerType",speakerType); + }); } break; } case DIV_SYSTEM_QSOUND: { + int echoDelay=flags.getInt("echoDelay",0); + int echoFeedback=flags.getInt("echoFeedback",0)&255; + ImGui::Text("Echo delay:"); - int echoBufSize=2725 - (flags & 4095); - if (CWSliderInt("##EchoBufSize",&echoBufSize,0,2725)) { - if (echoBufSize<0) echoBufSize=0; - if (echoBufSize>2725) echoBufSize=2725; - copyOfFlags=(flags & ~4095) | ((2725 - echoBufSize) & 4095); + int echoBufSize1=2725-echoDelay; + if (CWSliderInt("##EchoBufSize",&echoBufSize1,0,2725)) { + if (echoBufSize1<0) echoBufSize1=0; + if (echoBufSize1>2725) echoBufSize1=2725; + echoDelay=2725-echoBufSize1; + altered=true;; } rightClickable ImGui::Text("Echo feedback:"); - int echoFeedback=(flags>>12)&255; if (CWSliderInt("##EchoFeedback",&echoFeedback,0,255)) { if (echoFeedback<0) echoFeedback=0; if (echoFeedback>255) echoFeedback=255; - copyOfFlags=(flags & ~(255 << 12)) | ((echoFeedback & 255) << 12); + altered=true; } rightClickable + + if (altered) { + e->lockSave([&]() { + flags.set("echoDelay",echoDelay); + flags.set("echoFeedback",echoFeedback); + }); + } break; } case DIV_SYSTEM_X1_010: { + int clockSel=flags.getInt("clockSel",0); + bool stereo=flags.getBool("stereo",false); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("16MHz (Seta 1)",(flags&15)==0)) { - copyOfFlags=(flags&(~15))|0; + if (ImGui::RadioButton("16MHz (Seta 1)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("16.67MHz (Seta 2)",(flags&15)==1)) { - copyOfFlags=(flags&(~15))|1; + if (ImGui::RadioButton("16.67MHz (Seta 2)",clockSel==1)) { + clockSel=1; + altered=true; } - bool x1_010Stereo=flags&16; - if (ImGui::Checkbox("Stereo",&x1_010Stereo)) { - copyOfFlags=(flags&(~16))|(x1_010Stereo<<4); + + if (ImGui::Checkbox("Stereo",&stereo)) { + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("stereo",stereo); + }); } break; } case DIV_SYSTEM_N163: { + int clockSel=flags.getInt("clockSel",0); + int channels=flags.getInt("channels",0)+1; + bool multiplex=flags.getBool("multiplex",false); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("NTSC (1.79MHz)",(flags&15)==0)) { - copyOfFlags=(flags&(~15))|0; + if (ImGui::RadioButton("NTSC (1.79MHz)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("PAL (1.67MHz)",(flags&15)==1)) { - copyOfFlags=(flags&(~15))|1; + if (ImGui::RadioButton("PAL (1.67MHz)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("Dendy (1.77MHz)",(flags&15)==2)) { - copyOfFlags=(flags&(~15))|2; + if (ImGui::RadioButton("Dendy (1.77MHz)",clockSel==2)) { + clockSel=2; + altered=true; } ImGui::Text("Initial channel limit:"); - int initialChannelLimit=((flags>>4)&7)+1; - if (CWSliderInt("##N163_InitialChannelLimit",&initialChannelLimit,1,8)) { - if (initialChannelLimit<1) initialChannelLimit=1; - if (initialChannelLimit>8) initialChannelLimit=8; - copyOfFlags=(flags & ~(7 << 4)) | (((initialChannelLimit-1) & 7) << 4); + if (CWSliderInt("##N163_InitialChannelLimit",&channels,1,8)) { + if (channels<1) channels=1; + if (channels>8) channels=8; + altered=true; } rightClickable - bool n163Multiplex=flags&128; - if (ImGui::Checkbox("Disable hissing",&n163Multiplex)) { - copyOfFlags=(flags&(~128))|(n163Multiplex<<7); + if (ImGui::Checkbox("Disable hissing",&multiplex)) { + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("channels",channels-1); + flags.set("multiplex",multiplex); + }); } break; } case DIV_SYSTEM_ES5506: { + int channels=flags.getInt("channels",0)+1; ImGui::Text("Initial channel limit:"); - int initialChannelLimit=(flags&31)+1; - if (CWSliderInt("##OTTO_InitialChannelLimit",&initialChannelLimit,5,32)) { - if (initialChannelLimit<5) initialChannelLimit=5; - if (initialChannelLimit>32) initialChannelLimit=32; - copyOfFlags=(flags & ~31) | ((initialChannelLimit-1) & 31); + if (CWSliderInt("##OTTO_InitialChannelLimit",&channels,5,32)) { + if (channels<5) channels=5; + if (channels>32) channels=32; + altered=true; } rightClickable + + if (altered) { + e->lockSave([&]() { + flags.set("channels",channels-1); + }); + } break; } case DIV_SYSTEM_OPN: case DIV_SYSTEM_OPN_EXT: { + int clockSel=flags.getInt("clockSel",0); + int prescale=flags.getInt("prescale",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&31)==0)) { - copyOfFlags=(flags&(~31))|0; + if (ImGui::RadioButton("3.58MHz (NTSC)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("3.54MHz (PAL)",(flags&31)==1)) { - copyOfFlags=(flags&(~31))|1; + if (ImGui::RadioButton("3.54MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("4MHz",(flags&31)==2)) { - copyOfFlags=(flags&(~31))|2; + if (ImGui::RadioButton("4MHz",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("3MHz",(flags&31)==3)) { - copyOfFlags=(flags&(~31))|3; + if (ImGui::RadioButton("3MHz",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",(flags&31)==4)) { - copyOfFlags=(flags&(~31))|4; + if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("1.5MHz",(flags&31)==5)) { - copyOfFlags=(flags&(~31))|5; + if (ImGui::RadioButton("1.5MHz",clockSel==5)) { + clockSel=5; + altered=true; } ImGui::Text("Output rate:"); - if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==0)) { - copyOfFlags=(flags&(~96))|0; + if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",prescale==0)) { + prescale=0; + altered=true; } - if (ImGui::RadioButton("FM: clock / 36, SSG: clock / 8",(flags&96)==32)) { - copyOfFlags=(flags&(~96))|32; + if (ImGui::RadioButton("FM: clock / 36, SSG: clock / 8",prescale==1)) { + prescale=1; + altered=true; } - if (ImGui::RadioButton("FM: clock / 24, SSG: clock / 4",(flags&96)==64)) { - copyOfFlags=(flags&(~96))|64; + if (ImGui::RadioButton("FM: clock / 24, SSG: clock / 4",prescale==2)) { + prescale=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("prescale",prescale); + }); } break; } case DIV_SYSTEM_PC98: case DIV_SYSTEM_PC98_EXT: { + int clockSel=flags.getInt("clockSel",0); + int prescale=flags.getInt("prescale",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("8MHz (Arcade)",(flags&31)==0)) { - copyOfFlags=(flags&(~31))|0; + if (ImGui::RadioButton("8MHz (Arcade)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("7.987MHz (PC-88/PC-98)",(flags&31)==1)) { - copyOfFlags=(flags&(~31))|1; + if (ImGui::RadioButton("7.987MHz (PC-88/PC-98)",clockSel==1)) { + clockSel=1; + altered=true; } ImGui::Text("Output rate:"); - if (ImGui::RadioButton("FM: clock / 144, SSG: clock / 32",(flags&96)==0)) { - copyOfFlags=(flags&(~96))|0; + if (ImGui::RadioButton("FM: clock / 144, SSG: clock / 32",prescale==0)) { + prescale=0; + altered=true; } - if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",(flags&96)==32)) { - copyOfFlags=(flags&(~96))|32; + if (ImGui::RadioButton("FM: clock / 72, SSG: clock / 16",prescale==1)) { + prescale=1; + altered=true; } - if (ImGui::RadioButton("FM: clock / 48, SSG: clock / 8",(flags&96)==64)) { - copyOfFlags=(flags&(~96))|64; + if (ImGui::RadioButton("FM: clock / 48, SSG: clock / 8",prescale==2)) { + prescale=2; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("prescale",prescale); + }); } break; } case DIV_SYSTEM_RF5C68: { + int clockSel=flags.getInt("clockSel",0); + int chipType=flags.getInt("chipType",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("8MHz (FM Towns)",(flags&15)==0)) { - copyOfFlags=(flags&(~15))|0; + if (ImGui::RadioButton("8MHz (FM Towns)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("10MHz (Sega System 18)",(flags&15)==1)) { - copyOfFlags=(flags&(~15))|1; + if (ImGui::RadioButton("10MHz (Sega System 18)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("12.5MHz (Sega CD/System 32)",(flags&15)==2)) { - copyOfFlags=(flags&(~15))|2; + if (ImGui::RadioButton("12.5MHz (Sega CD/System 32)",clockSel==2)) { + clockSel=2; + altered=true; } ImGui::Text("Chip type:"); - if (ImGui::RadioButton("RF5C68 (10-bit output)",((flags>>4)&15)==0)) { - copyOfFlags=(flags&(~240))|0; + if (ImGui::RadioButton("RF5C68 (10-bit output)",chipType==0)) { + chipType=0; + altered=true; } - if (ImGui::RadioButton("RF5C164 (16-bit output)",((flags>>4)&15)==1)) { - copyOfFlags=(flags&(~240))|16; + if (ImGui::RadioButton("RF5C164 (16-bit output)",chipType==1)) { + chipType=1; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("chipType",chipType); + }); } break; } case DIV_SYSTEM_MSM6258: { + int clockSel=flags.getInt("clockSel",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("4MHz",flags==0)) { - copyOfFlags=0; + if (ImGui::RadioButton("4MHz",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("4.096MHz",flags==1)) { - copyOfFlags=1; + if (ImGui::RadioButton("4.096MHz",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("8MHz (X68000)",flags==2)) { - copyOfFlags=2; + if (ImGui::RadioButton("8MHz (X68000)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("8.192MHz",flags==3)) { - copyOfFlags=3; + if (ImGui::RadioButton("8.192MHz",clockSel==3)) { + clockSel=3; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; } case DIV_SYSTEM_MSM6295: { + int clockSel=flags.getInt("clockSel",0); + bool rateSel=flags.getBool("rateSel",false); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("1MHz",(flags&127)==0)) { - copyOfFlags=(flags&(~127))|0; + if (ImGui::RadioButton("1MHz",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("1.056MHz",(flags&127)==1)) { - copyOfFlags=(flags&(~127))|1; + if (ImGui::RadioButton("1.056MHz",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("4MHz",(flags&127)==2)) { - copyOfFlags=(flags&(~127))|2; + if (ImGui::RadioButton("4MHz",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("4.224MHz",(flags&127)==3)) { - copyOfFlags=(flags&(~127))|3; + if (ImGui::RadioButton("4.224MHz",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("3.58MHz",(flags&127)==4)) { - copyOfFlags=(flags&(~127))|4; + if (ImGui::RadioButton("3.58MHz",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("1.79MHz",(flags&127)==5)) { - copyOfFlags=(flags&(~127))|5; + if (ImGui::RadioButton("1.79MHz",clockSel==5)) { + clockSel=5; + altered=true; } - if (ImGui::RadioButton("1.02MHz",(flags&127)==6)) { - copyOfFlags=(flags&(~127))|6; + if (ImGui::RadioButton("1.02MHz",clockSel==6)) { + clockSel=6; + altered=true; } - if (ImGui::RadioButton("0.89MHz",(flags&127)==7)) { - copyOfFlags=(flags&(~127))|7; + if (ImGui::RadioButton("0.89MHz",clockSel==7)) { + clockSel=7; + altered=true; } - if (ImGui::RadioButton("2MHz",(flags&127)==8)) { - copyOfFlags=(flags&(~127))|8; + if (ImGui::RadioButton("2MHz",clockSel==8)) { + clockSel=8; + altered=true; } - if (ImGui::RadioButton("2.112MHz",(flags&127)==9)) { - copyOfFlags=(flags&(~127))|9; + if (ImGui::RadioButton("2.112MHz",clockSel==9)) { + clockSel=9; + altered=true; } - if (ImGui::RadioButton("0.875MHz",(flags&127)==10)) { - copyOfFlags=(flags&(~127))|10; + if (ImGui::RadioButton("0.875MHz",clockSel==10)) { + clockSel=10; + altered=true; } - if (ImGui::RadioButton("0.9375MHz",(flags&127)==11)) { - copyOfFlags=(flags&(~127))|11; + if (ImGui::RadioButton("0.9375MHz",clockSel==11)) { + clockSel=11; + altered=true; } - if (ImGui::RadioButton("1.5MHz",(flags&127)==12)) { - copyOfFlags=(flags&(~127))|12; + if (ImGui::RadioButton("1.5MHz",clockSel==12)) { + clockSel=12; + altered=true; } - if (ImGui::RadioButton("3MHz",(flags&127)==13)) { - copyOfFlags=(flags&(~127))|13; + if (ImGui::RadioButton("3MHz",clockSel==13)) { + clockSel=13; + altered=true; } - if (ImGui::RadioButton("1.193MHz (Atari)",(flags&127)==14)) { - copyOfFlags=(flags&(~127))|14; + if (ImGui::RadioButton("1.193MHz (Atari)",clockSel==14)) { + clockSel=14; + altered=true; } ImGui::Text("Output rate:"); - if (ImGui::RadioButton("clock / 132",(flags&128)==0)) { - copyOfFlags=(flags&(~128))|0; + if (ImGui::RadioButton("clock / 132",rateSel==0)) { + rateSel=false; + altered=true; } - if (ImGui::RadioButton("clock / 165",(flags&128)==128)) { - copyOfFlags=(flags&(~128))|128; + if (ImGui::RadioButton("clock / 165",rateSel==1)) { + rateSel=true; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + flags.set("rateSel",rateSel); + }); } break; } case DIV_SYSTEM_SCC: case DIV_SYSTEM_SCC_PLUS: { + int clockSel=flags.getInt("clockSel",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("1.79MHz (NTSC/MSX)",(flags&127)==0)) { - copyOfFlags=(flags&(~127))|0; + if (ImGui::RadioButton("1.79MHz (NTSC/MSX)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("1.77MHz (PAL)",(flags&127)==1)) { - copyOfFlags=(flags&(~127))|1; + if (ImGui::RadioButton("1.77MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("1.5MHz (Arcade)",(flags&127)==2)) { - copyOfFlags=(flags&(~127))|2; + if (ImGui::RadioButton("1.5MHz (Arcade)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("2MHz",(flags&127)==3)) { - copyOfFlags=(flags&(~127))|3; + if (ImGui::RadioButton("2MHz",clockSel==3)) { + clockSel=3; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; } @@ -678,106 +1063,247 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_OPL2_DRUMS: case DIV_SYSTEM_Y8950: case DIV_SYSTEM_Y8950_DRUMS: { + int clockSel=flags.getInt("clockSel",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("3.58MHz (NTSC)",(flags&255)==0)) { - copyOfFlags=(flags&(~255))|0; + if (ImGui::RadioButton("3.58MHz (NTSC)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("3.54MHz (PAL)",(flags&255)==1)) { - copyOfFlags=(flags&(~255))|1; + if (ImGui::RadioButton("3.54MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("4MHz",(flags&255)==2)) { - copyOfFlags=(flags&(~255))|2; + if (ImGui::RadioButton("4MHz",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("3MHz",(flags&255)==3)) { - copyOfFlags=(flags&(~255))|3; + if (ImGui::RadioButton("3MHz",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",(flags&255)==4)) { - copyOfFlags=(flags&(~255))|4; + if (ImGui::RadioButton("3.9936MHz (PC-88/PC-98)",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("3.5MHz",(flags&255)==5)) { - copyOfFlags=(flags&(~255))|5; + if (ImGui::RadioButton("3.5MHz",clockSel==5)) { + clockSel=5; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; } case DIV_SYSTEM_OPL3: case DIV_SYSTEM_OPL3_DRUMS: { + int clockSel=flags.getInt("clockSel",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("14.32MHz (NTSC)",(flags&255)==0)) { - copyOfFlags=(flags&(~255))|0; + if (ImGui::RadioButton("14.32MHz (NTSC)",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("14.19MHz (PAL)",(flags&255)==1)) { - copyOfFlags=(flags&(~255))|1; + if (ImGui::RadioButton("14.19MHz (PAL)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("14MHz",(flags&255)==2)) { - copyOfFlags=(flags&(~255))|2; + if (ImGui::RadioButton("14MHz",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("16MHz",(flags&255)==3)) { - copyOfFlags=(flags&(~255))|3; + if (ImGui::RadioButton("16MHz",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("15MHz",(flags&255)==4)) { - copyOfFlags=(flags&(~255))|4; + if (ImGui::RadioButton("15MHz",clockSel==4)) { + clockSel=4; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; } case DIV_SYSTEM_YMZ280B: { + int clockSel=flags.getInt("clockSel",0); + ImGui::Text("Clock rate:"); - if (ImGui::RadioButton("16.9344MHz",(flags&255)==0)) { - copyOfFlags=(flags&(~255))|0; + if (ImGui::RadioButton("16.9344MHz",clockSel==0)) { + clockSel=0; + altered=true; } - if (ImGui::RadioButton("14.32MHz (NTSC)",(flags&255)==1)) { - copyOfFlags=(flags&(~255))|1; + if (ImGui::RadioButton("14.32MHz (NTSC)",clockSel==1)) { + clockSel=1; + altered=true; } - if (ImGui::RadioButton("14.19MHz (PAL)",(flags&255)==2)) { - copyOfFlags=(flags&(~255))|2; + if (ImGui::RadioButton("14.19MHz (PAL)",clockSel==2)) { + clockSel=2; + altered=true; } - if (ImGui::RadioButton("16MHz",(flags&255)==3)) { - copyOfFlags=(flags&(~255))|3; + if (ImGui::RadioButton("16MHz",clockSel==3)) { + clockSel=3; + altered=true; } - if (ImGui::RadioButton("16.67MHz",(flags&255)==4)) { - copyOfFlags=(flags&(~255))|4; + if (ImGui::RadioButton("16.67MHz",clockSel==4)) { + clockSel=4; + altered=true; } - if (ImGui::RadioButton("14MHz",(flags&255)==5)) { - copyOfFlags=(flags&(~255))|5; + if (ImGui::RadioButton("14MHz",clockSel==5)) { + clockSel=5; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",clockSel); + }); } break; } case DIV_SYSTEM_PCM_DAC: { // default to 44100Hz 16-bit stereo - if (!flags) copyOfFlags=flags=0x1f0000|44099; - int sampRate=(flags&65535)+1; - int bitDepth=((flags>>16)&15)+1; - bool stereo=(flags>>20)&1; + int sampRate=flags.getInt("rate",44100); + int bitDepth=flags.getInt("outDepth",15)+1; + bool stereo=flags.getBool("stereo",false); + ImGui::Text("Output rate:"); - if (CWSliderInt("##SampRate",&sampRate,1000,65536)) { + if (CWSliderInt("##SampRate",&sampRate,1000,96000)) { if (sampRate<1000) sampRate=1000; - if (sampRate>65536) sampRate=65536; - copyOfFlags=(flags&(~65535))|(sampRate-1); + if (sampRate>96000) sampRate=96000; + altered=true; } rightClickable ImGui::Text("Output bit depth:"); if (CWSliderInt("##BitDepth",&bitDepth,1,16)) { if (bitDepth<1) bitDepth=1; if (bitDepth>16) bitDepth=16; - copyOfFlags=(flags&(~(15<<16)))|((bitDepth-1)<<16); + altered=true; } rightClickable if (ImGui::Checkbox("Stereo",&stereo)) { - copyOfFlags=(flags&(~(1<<20)))|(stereo<<20); + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("rate",sampRate); + flags.set("outDepth",bitDepth-1); + flags.set("stereo",stereo); + }); } break; } - case DIV_SYSTEM_SNES: { + case DIV_SYSTEM_SNES: { // TODO: echo + char temp[64]; + int vsL=127-(flags.getInt("volScaleL",0)&127); + int vsR=127-(flags.getInt("volScaleR",0)&127); + bool echo=flags.getBool("echo",false); + int echoVolL=flags.getInt("echoVolL",127); + int echoVolR=flags.getInt("echoVolR",127); + int echoDelay=flags.getInt("echoDelay",0)&15; + int echoFeedback=flags.getInt("echoFeedback",0); + int echoMask=flags.getInt("echoMask",0); + + int echoFilter[8]; + echoFilter[0]=flags.getInt("echoFilter0",127); + echoFilter[1]=flags.getInt("echoFilter1",0); + echoFilter[2]=flags.getInt("echoFilter2",0); + echoFilter[3]=flags.getInt("echoFilter3",0); + echoFilter[4]=flags.getInt("echoFilter4",0); + echoFilter[5]=flags.getInt("echoFilter5",0); + echoFilter[6]=flags.getInt("echoFilter6",0); + echoFilter[7]=flags.getInt("echoFilter7",0); + ImGui::Text("Volume scale:"); - int vsL=127-(flags&127); - int vsR=127-((flags>>8)&127); if (CWSliderInt("Left##VolScaleL",&vsL,0,127)) { if (vsL<0) vsL=0; if (vsL>127) vsL=127; - copyOfFlags=(flags&(~0x7f))|(127-vsL); + altered=true; } rightClickable if (CWSliderInt("Right##VolScaleL",&vsR,0,127)) { if (vsR<0) vsR=0; if (vsR>127) vsR=127; - copyOfFlags=(flags&(~0x7f00))|((127-vsR)<<8); + altered=true; } rightClickable + + if (ImGui::Checkbox("Enable echo",&echo)) { + altered=true; + } + + ImGui::Text("Initial echo state:"); + for (int i=0; i<8; i++) { + bool echoChan=(bool)(echoMask&(1<15) echoDelay=15; + altered=true; + } rightClickable + + if (CWSliderInt("Feedback##EchoFeedback",&echoFeedback,-128,127)) { + if (echoFeedback<-128) echoFeedback=-128; + if (echoFeedback>127) echoFeedback=127; + altered=true; + } rightClickable + + ImGui::Text("Echo volume:"); + if (CWSliderInt("Left##EchoVolL",&echoVolL,-128,127)) { + if (echoVolL<-128) echoVolL=-128; + if (echoVolL>127) echoVolL=127; + altered=true; + } rightClickable + if (CWSliderInt("Right##EchoVolL",&echoVolR,-128,127)) { + if (echoVolR<-128) echoVolR=-128; + if (echoVolR>127) echoVolR=127; + altered=true; + } rightClickable + + ImGui::Text("Echo filter:"); + for (int i=0; i<8; i++) { + snprintf(temp,63,"%d##FIR%d",i+1,i); + if (CWSliderInt(temp,&echoFilter[i],-128,127)) { + if (echoFilter[i]<-128) echoFilter[i]=-128; + if (echoFilter[i]>127) echoFilter[i]=127; + altered=true; + } rightClickable + } + + if (altered) { + e->lockSave([&]() { + flags.set("volScaleL",127-vsL); + flags.set("volScaleR",127-vsR); + flags.set("echo",echo); + flags.set("echoVolL",echoVolL); + flags.set("echoVolR",echoVolR); + flags.set("echoDelay",echoDelay); + flags.set("echoFeedback",echoFeedback); + flags.set("echoFilter0",echoFilter[0]); + flags.set("echoFilter1",echoFilter[1]); + flags.set("echoFilter2",echoFilter[2]); + flags.set("echoFilter3",echoFilter[3]); + flags.set("echoFilter4",echoFilter[4]); + flags.set("echoFilter5",echoFilter[5]); + flags.set("echoFilter6",echoFilter[6]); + flags.set("echoFilter7",echoFilter[7]); + flags.set("echoMask",echoMask); + }); + } + break; } case DIV_SYSTEM_SWAN: @@ -788,22 +1314,32 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool case DIV_SYSTEM_T6W28: ImGui::Text("nothing to configure"); break; - default: + default: { + bool sysPal=flags.getInt("clockSel",0); + if (ImGui::Checkbox("PAL",&sysPal)) { - copyOfFlags=sysPal; + altered=true; + } + + if (altered) { + e->lockSave([&]() { + flags.set("clockSel",(int)sysPal); + }); } break; + } } - if (copyOfFlags!=flags) { + if (altered) { if (chan>=0) { - e->setSysFlags(chan,copyOfFlags,restart); + e->updateSysFlags(chan,restart); if (e->song.autoSystem) { autoDetectSystem(); } updateWindowTitle(); - } else { - flags=copyOfFlags; } + MARK_MODIFIED; } + + return altered; } diff --git a/src/gui/sysManager.cpp b/src/gui/sysManager.cpp index 5d7a59c73..386d26583 100644 --- a/src/gui/sysManager.cpp +++ b/src/gui/sysManager.cpp @@ -70,7 +70,7 @@ void FurnaceGUI::drawSysManager() { } ImGui::TableNextColumn(); if (ImGui::TreeNode(fmt::sprintf("%d. %s##_SYSM%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { - drawSysConf(i,e->song.system[i],e->song.systemFlagsOld[i],true); + drawSysConf(i,e->song.system[i],e->song.systemFlags[i],true); ImGui::TreePop(); } ImGui::TableNextColumn();