From 28698beaf3cad3abb11c77c84da28acf7354921d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 01:55:44 -0500 Subject: [PATCH 01/15] dev106 - Game Boy: implement hw seq and prepare for software envelope maybe --- TODO.md | 1 - papers/format.md | 6 +++- src/engine/engine.h | 4 +-- src/engine/instrument.cpp | 10 +++++++ src/engine/instrument.h | 5 +++- src/engine/platform/gb.cpp | 57 +++++++++++++++++++++++++++++++++++++- src/engine/platform/gb.h | 6 ++-- src/gui/insEdit.cpp | 17 ++++++++---- 8 files changed, 93 insertions(+), 13 deletions(-) diff --git a/TODO.md b/TODO.md index 46773705a..13f31300e 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ # to-do for 0.6pre1.5-0.6pre2 -- Game Boy envelope macro/sequence - volume commands should work on Game Boy - ability to customize `OFF`, `===` and `REL` - stereo separation control for AY diff --git a/papers/format.md b/papers/format.md index 263955022..1a8cd7219 100644 --- a/papers/format.md +++ b/papers/format.md @@ -32,7 +32,8 @@ these fields are 0 in format versions prior to 100 (0.6pre1). the format versions are: -- 105: Furance dev105 +- 106: Furnace dev106 +- 105: Furnace dev105 - 104: Furnace dev104 - 103: Furnace dev103 - 102: Furnace 0.6pre1 (dev102) @@ -846,6 +847,9 @@ size | description | - 2 bytes: nothing | - for loop/loop until release: | - 2 bytes: position + --- | **Game Boy extra flags** (>=106) + 1 | use software envelope + 1 | always init hard env on new note ``` # wavetable diff --git a/src/engine/engine.h b/src/engine/engine.h index 001ea1941..483ebcf0d 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -45,8 +45,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev105" -#define DIV_ENGINE_VERSION 105 +#define DIV_VERSION "dev106" +#define DIV_ENGINE_VERSION 106 // for imports #define DIV_VERSION_MOD 0xff01 diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index b1afc3953..555d7d17f 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -539,6 +539,10 @@ void DivInstrument::putInsData(SafeWriter* w) { w->writeS(gb.hwSeq[i].data); } + // GB additional flags + w->writeC(gb.softEnv); + w->writeC(gb.alwaysInit); + blockEndSeek=w->tell(); w->seek(blockStartSeek,SEEK_SET); w->writeI(blockEndSeek-blockStartSeek-4); @@ -1101,6 +1105,12 @@ DivDataErrors DivInstrument::readInsData(SafeReader& reader, short version) { } } + // GB additional flags + if (version>=106) { + gb.softEnv=reader.readC(); + gb.alwaysInit=reader.readC(); + } + return DIV_DATA_SUCCESS; } diff --git a/src/engine/instrument.h b/src/engine/instrument.h index eddf9f79e..df7a6b361 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -262,6 +262,7 @@ struct DivInstrumentSTD { struct DivInstrumentGB { unsigned char envVol, envDir, envLen, soundLen, hwSeqLen; + bool softEnv, alwaysInit; enum HWSeqCommands: unsigned char { DIV_GB_HWCMD_ENVELOPE=0, DIV_GB_HWCMD_SWEEP, @@ -281,7 +282,9 @@ struct DivInstrumentGB { envDir(0), envLen(2), soundLen(64), - hwSeqLen(0) { + hwSeqLen(0), + softEnv(false), + alwaysInit(false) { memset(hwSeq,0,256*sizeof(int)); } }; diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 2ec9bfdf9..5b7393ef3 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -233,12 +233,61 @@ void DivPlatformGB::tick(bool sysTick) { } } } + // run hardware sequence + if (chan[i].active) { + if (--chan[i].hwSeqDelay<=0) { + chan[i].hwSeqDelay=0; + DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_GB); + int hwSeqCount=0; + while (chan[i].hwSeqPosgb.hwSeqLen && hwSeqCount<4) { + bool leave=false; + unsigned short data=ins->gb.hwSeq[chan[i].hwSeqPos].data; + switch (ins->gb.hwSeq[chan[i].hwSeqPos].cmd) { + case DivInstrumentGB::DIV_GB_HWCMD_ENVELOPE: + chan[i].envLen=data&7; + chan[i].envDir=(data&8)?1:0; + chan[i].envVol=(data>>4)&15; + chan[i].soundLen=data>>8; + chan[i].keyOn=true; + break; + case DivInstrumentGB::DIV_GB_HWCMD_SWEEP: + chan[i].sweep=data; + chan[i].sweepChanged=true; + break; + case DivInstrumentGB::DIV_GB_HWCMD_WAIT: + chan[i].hwSeqDelay=data+1; + leave=true; + break; + case DivInstrumentGB::DIV_GB_HWCMD_WAIT_REL: + if (!chan[i].released) { + chan[i].hwSeqPos--; + leave=true; + } + break; + case DivInstrumentGB::DIV_GB_HWCMD_LOOP: + chan[i].hwSeqPos=data-1; + break; + case DivInstrumentGB::DIV_GB_HWCMD_LOOP_REL: + if (!chan[i].released) { + chan[i].hwSeqPos=data-1; + } + break; + } + + chan[i].hwSeqPos++; + if (leave) break; + hwSeqCount++; + } + } + } + if (chan[i].sweepChanged) { chan[i].sweepChanged=false; if (i==0) { rWrite(16+i*5,chan[i].sweep); } } + if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { if (i==3) { // noise int ntPos=chan[i].baseFreq; @@ -300,6 +349,9 @@ int DivPlatformGB::dispatch(DivCommand c) { } chan[c.chan].active=true; chan[c.chan].keyOn=true; + chan[c.chan].hwSeqPos=0; + chan[c.chan].hwSeqDelay=0; + chan[c.chan].released=false; chan[c.chan].macroInit(ins); if (c.chan==2) { if (chan[c.chan].wave<0) { @@ -308,7 +360,7 @@ int DivPlatformGB::dispatch(DivCommand c) { } ws.init(ins,32,15,chan[c.chan].insChanged); } - if (chan[c.chan].insChanged) { + if (chan[c.chan].insChanged || ins->gb.alwaysInit) { chan[c.chan].envVol=ins->gb.envVol; chan[c.chan].envLen=ins->gb.envLen; chan[c.chan].envDir=ins->gb.envDir; @@ -320,11 +372,14 @@ int DivPlatformGB::dispatch(DivCommand c) { case DIV_CMD_NOTE_OFF: chan[c.chan].active=false; chan[c.chan].keyOff=true; + chan[c.chan].hwSeqPos=0; + chan[c.chan].hwSeqDelay=0; chan[c.chan].macroInit(NULL); break; case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_ENV_RELEASE: chan[c.chan].std.release(); + chan[c.chan].released=true; break; case DIV_CMD_INSTRUMENT: if (chan[c.chan].ins!=c.value || c.value2==1) { diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 58cce8805..a4432f1e7 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -29,10 +29,11 @@ class DivPlatformGB: public DivDispatch { struct Channel { int freq, baseFreq, pitch, pitch2, note, ins; unsigned char duty, sweep; - bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta; + bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released; signed char vol, outVol, wave; unsigned char envVol, envDir, envLen, soundLen; - unsigned short hwSeqPos, hwSeqDelay; + unsigned short hwSeqPos; + short hwSeqDelay; DivMacroInt std; void macroInit(DivInstrument* which) { std.init(which); @@ -54,6 +55,7 @@ class DivPlatformGB: public DivDispatch { keyOn(false), keyOff(false), inPorta(false), + released(false), vol(15), outVol(15), wave(-1), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index e0c18b6c1..ce9406ba1 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2965,6 +2965,10 @@ void FurnaceGUI::drawInsEdit() { } } if (ins->type==DIV_INS_GB) if (ImGui::BeginTabItem("Game Boy")) { + P(ImGui::Checkbox("Use software envelope",&ins->gb.softEnv)); + P(ImGui::Checkbox("Initialize envelope on every note",&ins->gb.alwaysInit)); + + ImGui::BeginDisabled(ins->gb.softEnv); P(CWSliderScalar("Volume",ImGuiDataType_U8,&ins->gb.envVol,&_ZERO,&_FIFTEEN)); rightClickable P(CWSliderScalar("Envelope Length",ImGuiDataType_U8,&ins->gb.envLen,&_ZERO,&_SEVEN)); rightClickable P(CWSliderScalar("Sound Length",ImGuiDataType_U8,&ins->gb.soundLen,&_ZERO,&_SIXTY_FOUR,ins->gb.soundLen>63?"Infinity":"%d")); rightClickable @@ -3060,13 +3064,13 @@ void FurnaceGUI::drawInsEdit() { somethingChanged=true; } - if (ImGui::RadioButton("Up",hwsDir)) { PARAMETER - hwsDir=true; + if (ImGui::RadioButton("Up",!hwsDir)) { PARAMETER + hwsDir=false; somethingChanged=true; } ImGui::SameLine(); - if (ImGui::RadioButton("Down",!hwsDir)) { PARAMETER - hwsDir=false; + if (ImGui::RadioButton("Down",hwsDir)) { PARAMETER + hwsDir=true; somethingChanged=true; } @@ -3128,6 +3132,7 @@ void FurnaceGUI::drawInsEdit() { } ImGui::EndChild(); + ImGui::EndDisabled(); } ImGui::EndTabItem(); } @@ -3689,8 +3694,10 @@ void FurnaceGUI::drawInsEdit() { if (ins->type==DIV_INS_FM || ins->type==DIV_INS_MIKEY || ins->type==DIV_INS_MULTIPCM || ins->type==DIV_INS_SU) { volMax=127; } - if (ins->type==DIV_INS_GB) { + if (ins->type==DIV_INS_GB && !ins->gb.softEnv) { volMax=0; + } else { + volMax=15; } if (ins->type==DIV_INS_PET || ins->type==DIV_INS_BEEPER) { volMax=1; From df10b6cc5952926e4a1c81dcd87fc58d0b074392 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 14:16:26 -0500 Subject: [PATCH 02/15] Game Boy: hardware sequences, part 3 the previous commit was part 2 --- src/gui/insEdit.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index ce9406ba1..0d90e3733 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2993,15 +2993,18 @@ void FurnaceGUI::drawInsEdit() { ImGui::Text("Hardware Sequence"); ImGui::EndMenuBar(); - if (ins->gb.hwSeqLen>0) if (ImGui::BeginTable("HWSeqList",2)) { + if (ins->gb.hwSeqLen>0) if (ImGui::BeginTable("HWSeqList",3)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); int curFrame=0; ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextColumn(); ImGui::Text("Tick"); ImGui::TableNextColumn(); ImGui::Text("Command"); + ImGui::TableNextColumn(); + ImGui::Text("Move/Remove"); for (int i=0; igb.hwSeqLen; i++) { ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -3119,6 +3122,46 @@ void FurnaceGUI::drawInsEdit() { break; } ImGui::PopID(); + ImGui::TableNextColumn(); + ImGui::PushID(i+512); + if (ImGui::Button(ICON_FA_CHEVRON_UP "##HWCmdUp")) { + if (i>0) { + e->lockEngine([ins,i]() { + ins->gb.hwSeq[i-1].cmd^=ins->gb.hwSeq[i].cmd; + ins->gb.hwSeq[i].cmd^=ins->gb.hwSeq[i-1].cmd; + ins->gb.hwSeq[i-1].cmd^=ins->gb.hwSeq[i].cmd; + + ins->gb.hwSeq[i-1].data^=ins->gb.hwSeq[i].data; + ins->gb.hwSeq[i].data^=ins->gb.hwSeq[i-1].data; + ins->gb.hwSeq[i-1].data^=ins->gb.hwSeq[i].data; + }); + } + MARK_MODIFIED; + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_CHEVRON_DOWN "##HWCmdDown")) { + if (igb.hwSeqLen-1) { + e->lockEngine([ins,i]() { + ins->gb.hwSeq[i-1].cmd^=ins->gb.hwSeq[i].cmd; + ins->gb.hwSeq[i].cmd^=ins->gb.hwSeq[i-1].cmd; + ins->gb.hwSeq[i-1].cmd^=ins->gb.hwSeq[i].cmd; + + ins->gb.hwSeq[i-1].data^=ins->gb.hwSeq[i].data; + ins->gb.hwSeq[i].data^=ins->gb.hwSeq[i-1].data; + ins->gb.hwSeq[i-1].data^=ins->gb.hwSeq[i].data; + }); + } + MARK_MODIFIED; + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_TIMES "##HWCmdDel")) { + for (int j=i; jgb.hwSeqLen-1; j++) { + ins->gb.hwSeq[j].cmd=ins->gb.hwSeq[j+1].cmd; + ins->gb.hwSeq[j].data=ins->gb.hwSeq[j+1].data; + } + ins->gb.hwSeqLen--; + } + ImGui::PopID(); } ImGui::EndTable(); } From 6bcb3063a59f40df4cfbe3d350c67d57b016ad71 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 15:41:52 -0500 Subject: [PATCH 03/15] add OPZ disclaimer in docs --- papers/doc/7-systems/opz.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/papers/doc/7-systems/opz.md b/papers/doc/7-systems/opz.md index 61e931394..c7952a55b 100644 --- a/papers/doc/7-systems/opz.md +++ b/papers/doc/7-systems/opz.md @@ -1,5 +1,7 @@ # Yamaha OPZ (YM2414) +**disclaimer: despite the name, this has nothing to do with teenage engineering's OP-Z synth!** + this is the YM2151's little-known successor, used in the Yamaha TX81Z and a few other Yamaha synthesizers. oh, and the Korg Z3 too. it adds these features on top of the YM2151: From bccecc4c07ba59eee23507590ba627e720795588 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 16:27:29 -0500 Subject: [PATCH 04/15] Game Boy: software envelopes, part 1 --- src/engine/fileOps.cpp | 5 +++-- src/engine/platform/gb.cpp | 41 ++++++++++++++++++++++++++------------ src/engine/platform/gb.h | 3 ++- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 8dcd55d22..db2305c65 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -590,7 +590,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { logD("GB data: vol %d dir %d len %d sl %d",ins->gb.envVol,ins->gb.envDir,ins->gb.envLen,ins->gb.soundLen); } else if (ds.system[0]==DIV_SYSTEM_GB) { - // try to convert macro to envelope + // set software envelope flag + ins->gb.softEnv=true; + // try to convert macro to envelope in case the user decides to switch to them if (ins->std.volMacro.len>0) { ins->gb.envVol=ins->std.volMacro.val[0]; if (ins->std.volMacro.val[0]std.volMacro.val[1]) { @@ -600,7 +602,6 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ins->gb.soundLen=ins->std.volMacro.len*2; } } - addWarning("Game Boy volume macros converted to envelopes. may not be perfect!"); } } diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 5b7393ef3..aa95d6cbd 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -160,6 +160,16 @@ void DivPlatformGB::tick(bool sysTick) { for (int i=0; i<4; i++) { chan[i].std.next(); + if (chan[i].softEnv) { + if (chan[i].std.vol.had) { + chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); + if (chan[i].outVol<0) chan[i].outVol=0; + + // temporary until zombie mode is implemented + chan[i].vol=chan[i].outVol; + chan[i].keyOn=true; + } + } if (chan[i].std.arp.had) { if (i==3) { // noise if (chan[i].std.arp.mode) { @@ -189,7 +199,7 @@ void DivPlatformGB::tick(bool sysTick) { chan[i].duty=chan[i].std.duty.val; if (i!=2) { rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); - } else { + } else if (!chan[i].softEnv) { if (parent->song.waveDutyIsVol) { rWrite(16+i*5+2,gbVolMap[(chan[i].std.duty.val&3)<<2]); } @@ -244,11 +254,13 @@ void DivPlatformGB::tick(bool sysTick) { unsigned short data=ins->gb.hwSeq[chan[i].hwSeqPos].data; switch (ins->gb.hwSeq[chan[i].hwSeqPos].cmd) { case DivInstrumentGB::DIV_GB_HWCMD_ENVELOPE: - chan[i].envLen=data&7; - chan[i].envDir=(data&8)?1:0; - chan[i].envVol=(data>>4)&15; - chan[i].soundLen=data>>8; - chan[i].keyOn=true; + if (!chan[i].softEnv) { + chan[i].envLen=data&7; + chan[i].envDir=(data&8)?1:0; + chan[i].envVol=(data>>4)&15; + chan[i].soundLen=data>>8; + chan[i].keyOn=true; + } break; case DivInstrumentGB::DIV_GB_HWCMD_SWEEP: chan[i].sweep=data; @@ -352,6 +364,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].hwSeqPos=0; chan[c.chan].hwSeqDelay=0; chan[c.chan].released=false; + chan[c.chan].softEnv=ins->gb.softEnv; chan[c.chan].macroInit(ins); if (c.chan==2) { if (chan[c.chan].wave<0) { @@ -387,13 +400,15 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].insChanged=true; if (c.chan!=2) { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_GB); - chan[c.chan].envVol=ins->gb.envVol; - chan[c.chan].envLen=ins->gb.envLen; - chan[c.chan].envDir=ins->gb.envDir; - chan[c.chan].soundLen=ins->gb.soundLen; - chan[c.chan].vol=chan[c.chan].envVol; - if (parent->song.gbInsAffectsEnvelope) { - rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); + if (!ins->gb.softEnv) { + chan[c.chan].envVol=ins->gb.envVol; + chan[c.chan].envLen=ins->gb.envLen; + chan[c.chan].envDir=ins->gb.envDir; + chan[c.chan].soundLen=ins->gb.soundLen; + chan[c.chan].vol=chan[c.chan].envVol; + if (parent->song.gbInsAffectsEnvelope) { + rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); + } } } } diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index a4432f1e7..082f33ba9 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -29,7 +29,7 @@ class DivPlatformGB: public DivDispatch { struct Channel { int freq, baseFreq, pitch, pitch2, note, ins; unsigned char duty, sweep; - bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released; + bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released, softEnv; signed char vol, outVol, wave; unsigned char envVol, envDir, envLen, soundLen; unsigned short hwSeqPos; @@ -56,6 +56,7 @@ class DivPlatformGB: public DivDispatch { keyOff(false), inPorta(false), released(false), + softEnv(false), vol(15), outVol(15), wave(-1), From 4b18d0920bbde8e0887beab27c302a24026bcfd0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 17:02:45 -0500 Subject: [PATCH 05/15] Game Boy: software envelopes, part 2 --- src/engine/platform/gb.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index aa95d6cbd..875304023 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -166,7 +166,10 @@ void DivPlatformGB::tick(bool sysTick) { if (chan[i].outVol<0) chan[i].outVol=0; // temporary until zombie mode is implemented - chan[i].vol=chan[i].outVol; + chan[i].envLen=0; + chan[i].envDir=0; + chan[i].envVol=chan[i].outVol; + chan[i].soundLen=64; chan[i].keyOn=true; } } @@ -314,10 +317,10 @@ void DivPlatformGB::tick(bool sysTick) { if (chan[i].keyOn) { if (i==2) { // wave rWrite(16+i*5,0x80); - rWrite(16+i*5+2,gbVolMap[chan[i].vol]); + rWrite(16+i*5+2,gbVolMap[chan[i].outVol]); } else { rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); - rWrite(16+i*5+2,((chan[i].vol<<4))|(chan[i].envLen&7)|((chan[i].envDir&1)<<3)); + rWrite(16+i*5+2,((chan[i].envVol<<4))|(chan[i].envLen&7)|((chan[i].envDir&1)<<3)); } } if (chan[i].keyOff) { @@ -406,6 +409,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].envDir=ins->gb.envDir; chan[c.chan].soundLen=ins->gb.soundLen; chan[c.chan].vol=chan[c.chan].envVol; + chan[c.chan].outVol=chan[c.chan].vol; if (parent->song.gbInsAffectsEnvelope) { rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); } @@ -415,8 +419,9 @@ int DivPlatformGB::dispatch(DivCommand c) { break; case DIV_CMD_VOLUME: chan[c.chan].vol=c.value; + chan[c.chan].outVol=c.value; if (c.chan==2) { - rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].vol]); + rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].outVol]); } break; case DIV_CMD_GET_VOLUME: From 51db06298bfcdbcb4e197407e00d6510e2585d43 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 23:53:47 -0500 Subject: [PATCH 06/15] Game Boy: fix volume regression --- src/engine/platform/gb.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 875304023..abbb19336 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -423,6 +423,9 @@ int DivPlatformGB::dispatch(DivCommand c) { if (c.chan==2) { rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].outVol]); } + if (!chan[c.chan].softEnv) { + chan[c.chan].envVol=chan[c.chan].vol; + } break; case DIV_CMD_GET_VOLUME: return chan[c.chan].vol; From 92f40774e4c87675a659c931cb74001bafc9ef01 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 10 Aug 2022 23:56:25 -0500 Subject: [PATCH 07/15] Game Boy: I hate your artificial limitations fixes a DefleMask demo module --- src/engine/platform/gb.cpp | 4 ++++ src/engine/platform/gb.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index abbb19336..31ce24240 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -573,6 +573,10 @@ void DivPlatformGB::reset() { antiClickWavePos=0; } +int DivPlatformGB::getPortaFloor(int ch) { + return 24; +} + bool DivPlatformGB::isStereo() { return true; } diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 082f33ba9..e4b8568b1 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -94,6 +94,7 @@ class DivPlatformGB: public DivDispatch { void forceIns(); void tick(bool sysTick=true); void muteChannel(int ch, bool mute); + int getPortaFloor(int ch); bool isStereo(); void notifyInsChange(int ins); void notifyWaveChange(int wave); From 340052cf0a50f6a848d5c545df4ada5a6c077283 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 00:46:15 -0500 Subject: [PATCH 08/15] Game Boy: add chip revision flag --- src/engine/platform/gb.cpp | 35 ++++++++++++++++++++++++++++++----- src/engine/platform/gb.h | 9 +++++++++ src/gui/sysConf.cpp | 13 +++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 31ce24240..39ccaf56c 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -21,8 +21,8 @@ #include "../engine.h" #include -#define rWrite(a,v) if (!skipRegisterWrites) {GB_apu_write(gb,a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} } -#define immWrite(a,v) {GB_apu_write(gb,a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} } +#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} } +#define immWrite(a,v) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} } #define CHIP_DIVIDER 16 @@ -84,6 +84,12 @@ const char* DivPlatformGB::getEffectName(unsigned char effect) { void DivPlatformGB::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; iapu_output.final_sample.left; bufR[i]=gb->apu_output.final_sample.right; @@ -97,8 +103,8 @@ void DivPlatformGB::acquire(short* bufL, short* bufR, size_t start, size_t len) void DivPlatformGB::updateWave() { rWrite(0x1a,0); for (int i=0; i<16; i++) { - int nibble1=15-ws.output[((i<<1)+antiClickWavePos)&31]; - int nibble2=15-ws.output[((1+(i<<1))+antiClickWavePos)&31]; + int nibble1=15-ws.output[((i<<1)+antiClickWavePos-1)&31]; + int nibble2=15-ws.output[((1+(i<<1))+antiClickWavePos-1)&31]; rWrite(0x30+i,(nibble1<<4)|nibble2); } antiClickWavePos&=31; @@ -559,7 +565,7 @@ void DivPlatformGB::reset() { } memset(gb,0,sizeof(GB_gameboy_t)); memset(regPool,0,128); - gb->model=GB_MODEL_DMG_B; + gb->model=model; GB_apu_init(gb); GB_set_sample_rate(gb,rate); // enable all channels @@ -581,6 +587,10 @@ bool DivPlatformGB::isStereo() { return true; } +bool DivPlatformGB::getDCOffRequired() { + return (model==GB_MODEL_AGB); +} + void DivPlatformGB::notifyInsChange(int ins) { for (int i=0; i<4; i++) { if (chan[i].ins==ins) { @@ -613,6 +623,20 @@ void DivPlatformGB::poke(std::vector& wlist) { void DivPlatformGB::setFlags(unsigned int flags) { antiClickEnabled=!(flags&8); + switch (flags&3) { + case 0: + model=GB_MODEL_DMG_B; + break; + case 1: + model=GB_MODEL_CGB_C; + break; + case 2: + model=GB_MODEL_CGB_E; + break; + case 3: + model=GB_MODEL_AGB; + break; + } } int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { @@ -626,6 +650,7 @@ int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int fl parent=p; dumpWrites=false; skipRegisterWrites=false; + model=GB_MODEL_DMG_B; gb=new GB_gameboy_t; setFlags(flags); reset(); diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index e4b8568b1..ce582979f 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -24,6 +24,7 @@ #include "../macroInt.h" #include "../waveSynth.h" #include "sound/gb/gb.h" +#include class DivPlatformGB: public DivDispatch { struct Channel { @@ -73,10 +74,17 @@ class DivPlatformGB: public DivDispatch { bool antiClickEnabled; unsigned char lastPan; DivWaveSynth ws; + struct QueuedWrite { + unsigned char addr; + unsigned char val; + QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {} + }; + std::queue writes; int antiClickPeriodCount, antiClickWavePos; GB_gameboy_t* gb; + GB_model_t model; unsigned char regPool[128]; unsigned char procMute(); @@ -96,6 +104,7 @@ class DivPlatformGB: public DivDispatch { void muteChannel(int ch, bool mute); int getPortaFloor(int ch); bool isStereo(); + bool getDCOffRequired(); void notifyInsChange(int ins); void notifyWaveChange(int wave); void notifyInsDeletion(void* ins); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 3259f00c0..484490348 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -185,6 +185,19 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool if (ImGui::Checkbox("Disable anti-click",&antiClick)) { copyOfFlags=(flags&(~8))|(antiClick<<3); } + ImGui::Text("Chip revision:"); + if (ImGui::RadioButton("Original (DMG)",(flags&7)==0)) { + copyOfFlags=(flags&(~7))|0; + } + if (ImGui::RadioButton("Game Boy Color (rev C)",(flags&7)==1)) { + copyOfFlags=(flags&(~7))|1; + } + if (ImGui::RadioButton("Game Boy Color (rev E)",(flags&7)==2)) { + copyOfFlags=(flags&(~7))|2; + } + if (ImGui::RadioButton("Game Boy Advance",(flags&7)==3)) { + copyOfFlags=(flags&(~7))|3; + } break; } case DIV_SYSTEM_OPLL: From d30f9bc8a02f80d337ba6239b7d1a38d8152c96b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 01:24:53 -0500 Subject: [PATCH 09/15] Game Boy: software envelopes, part 3 zombie mode --- src/engine/platform/gb.cpp | 29 +++++++++++++++++++++++++---- src/engine/platform/gb.h | 6 ++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 39ccaf56c..2fad226ae 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -171,12 +171,13 @@ void DivPlatformGB::tick(bool sysTick) { chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); if (chan[i].outVol<0) chan[i].outVol=0; - // temporary until zombie mode is implemented chan[i].envLen=0; - chan[i].envDir=0; + chan[i].envDir=1; chan[i].envVol=chan[i].outVol; chan[i].soundLen=64; - chan[i].keyOn=true; + + if (!chan[i].keyOn) chan[i].killIt=true; + chan[i].freqChanged=true; } } if (chan[i].std.arp.had) { @@ -327,6 +328,7 @@ void DivPlatformGB::tick(bool sysTick) { } else { rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); rWrite(16+i*5+2,((chan[i].envVol<<4))|(chan[i].envLen&7)|((chan[i].envDir&1)<<3)); + chan[i].lastKill=chan[i].envVol; } } if (chan[i].keyOff) { @@ -346,6 +348,25 @@ void DivPlatformGB::tick(bool sysTick) { if (chan[i].keyOn) chan[i].keyOn=false; if (chan[i].keyOff) chan[i].keyOff=false; chan[i].freqChanged=false; + + if (chan[i].killIt) { + if (i!=2) { + //rWrite(16+i*5+2,8); + int killDelta=chan[i].lastKill-chan[i].outVol+1; + if (killDelta<0) killDelta+=16; + chan[i].lastKill=chan[i].outVol; + + if (killDelta!=1) { + rWrite(16+i*5+2,((chan[i].envVol<<4))|8); + for (int j=0; jgb.alwaysInit) { + if ((chan[c.chan].insChanged || ins->gb.alwaysInit) && !chan[c.chan].softEnv) { chan[c.chan].envVol=ins->gb.envVol; chan[c.chan].envLen=ins->gb.envLen; chan[c.chan].envDir=ins->gb.envDir; diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index ce582979f..9498317bd 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -30,8 +30,8 @@ class DivPlatformGB: public DivDispatch { struct Channel { int freq, baseFreq, pitch, pitch2, note, ins; unsigned char duty, sweep; - bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released, softEnv; - signed char vol, outVol, wave; + bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released, softEnv, killIt; + signed char vol, outVol, wave, lastKill; unsigned char envVol, envDir, envLen, soundLen; unsigned short hwSeqPos; short hwSeqDelay; @@ -58,9 +58,11 @@ class DivPlatformGB: public DivDispatch { inPorta(false), released(false), softEnv(false), + killIt(false), vol(15), outVol(15), wave(-1), + lastKill(0), envVol(0), envDir(0), envLen(0), From 7e7a5a8e3037cdf0415a1db3adb512ad04a4fc9e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 01:34:18 -0500 Subject: [PATCH 10/15] Game Boy: software envelopes, part 4 fixes --- src/engine/platform/gb.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 2fad226ae..3797d5bca 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -171,13 +171,17 @@ void DivPlatformGB::tick(bool sysTick) { chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); if (chan[i].outVol<0) chan[i].outVol=0; - chan[i].envLen=0; - chan[i].envDir=1; - chan[i].envVol=chan[i].outVol; - chan[i].soundLen=64; + if (i==2) { + rWrite(16+i*5+2,gbVolMap[chan[i].outVol]); + } else { + chan[i].envLen=0; + chan[i].envDir=1; + chan[i].envVol=chan[i].outVol; + chan[i].soundLen=64; - if (!chan[i].keyOn) chan[i].killIt=true; - chan[i].freqChanged=true; + if (!chan[i].keyOn) chan[i].killIt=true; + chan[i].freqChanged=true; + } } } if (chan[i].std.arp.had) { @@ -452,6 +456,10 @@ int DivPlatformGB::dispatch(DivCommand c) { } if (!chan[c.chan].softEnv) { chan[c.chan].envVol=chan[c.chan].vol; + } else if (c.chan!=2) { + chan[c.chan].envVol=chan[c.chan].vol; + if (!chan[c.chan].keyOn) chan[c.chan].killIt=true; + chan[c.chan].freqChanged=true; } break; case DIV_CMD_GET_VOLUME: From ed98df91d284b0c9d37515ac54d80c6fa8eb7ee4 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 02:05:05 -0500 Subject: [PATCH 11/15] turn on proper noise layout by default --- src/engine/song.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/song.h b/src/engine/song.h index 8375fc561..8b7eaa59f 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -562,7 +562,7 @@ struct DivSong { linearPitch(2), pitchSlideSpeed(4), loopModality(0), - properNoiseLayout(false), + properNoiseLayout(true), waveDutyIsVol(false), resetMacroOnPorta(false), legacyVolumeSlides(false), From 762b3b292845cea80acbdb8b22c1bef2bc2a1ce5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 02:08:24 -0500 Subject: [PATCH 12/15] PCE: per-chan osc DAC mode overflow fix --- src/engine/platform/pce.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 5d9a0de88..3fc7a05bd 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -115,7 +115,7 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len) pce->ResetTS(0); for (int i=0; i<6; i++) { - oscBuf[i]->data[oscBuf[i]->needle++]=(pce->channel[i].blip_prev_samp[0]+pce->channel[i].blip_prev_samp[1])<<1; + oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP((pce->channel[i].blip_prev_samp[0]+pce->channel[i].blip_prev_samp[1])<<1,-32768,32767); } tempL[0]=(tempL[0]>>1)+(tempL[0]>>2); From 81482c2f2be021b58f605c49060500e9646c6613 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 04:50:16 -0500 Subject: [PATCH 13/15] QSound: SAMPLE LOOP BUG DEBUG BEGIN --- src/engine/platform/qsound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 6bc88dbf0..ca6a794cd 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -365,7 +365,7 @@ void DivPlatformQSound::tick(bool sysTick) { rWrite(q1_reg_map[Q1V_LOOP][i], qsound_loop); rWrite(q1_reg_map[Q1V_START][i], qsound_addr); rWrite(q1_reg_map[Q1V_PHASE][i], 0x8000); - //logV("ch %d bank=%04x, addr=%04x, end=%04x, loop=%04x!",i,qsound_bank,qsound_addr,qsound_end,qsound_loop); + logV("ch %d bank=%04x, addr=%04x, end=%04x, loop=%04x!",i,qsound_bank,qsound_addr,qsound_end,qsound_loop); // Write sample address. Enable volume if (!chan[i].std.vol.had) { rWrite(q1_reg_map[Q1V_VOL][i], chan[i].vol << 4); From 0528f4e7bde0d04609d37ed0d6a3f9205de7f2d8 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 05:04:35 -0500 Subject: [PATCH 14/15] Game Boy: possibly fix wave soft env --- src/engine/platform/gb.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 3797d5bca..0a8b624c9 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -173,6 +173,7 @@ void DivPlatformGB::tick(bool sysTick) { if (i==2) { rWrite(16+i*5+2,gbVolMap[chan[i].outVol]); + chan[i].soundLen=64; } else { chan[i].envLen=0; chan[i].envDir=1; @@ -413,6 +414,9 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].envDir=ins->gb.envDir; chan[c.chan].soundLen=ins->gb.soundLen; } + if (c.chan==2 && chan[c.chan].softEnv) { + chan[c.chan].soundLen=64; + } chan[c.chan].insChanged=false; break; } From 01d1556fb496675927a8c4b1fd5e1ee694b792e2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 11 Aug 2022 05:38:31 -0500 Subject: [PATCH 15/15] GUI: rename "system" to "chip" "system" made sense when Furnace was a .dmf tracker and had compound setups like Genesis (YM2612+SN) however, it doesn't make too much sense now when compared to "chip" --- src/gui/debug.cpp | 2 +- src/gui/debugWindow.cpp | 4 ++-- src/gui/gui.cpp | 22 +++++++++++----------- src/gui/settings.cpp | 11 +++-------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/gui/debug.cpp b/src/gui/debug.cpp index f1c974e8b..5ae596bcd 100644 --- a/src/gui/debug.cpp +++ b/src/gui/debug.cpp @@ -334,7 +334,7 @@ void putDispatchChan(void* data, int chanNum, int type) { break; } default: - ImGui::Text("Unknown system! Help!"); + ImGui::Text("Unimplemented chip! Help!"); break; } } diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 6ad2ddddf..8fe02b116 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -297,7 +297,7 @@ void FurnaceGUI::drawDebug() { } if (ImGui::TreeNode("Playground")) { if (pgSys<0 || pgSys>=e->song.systemLen) pgSys=0; - if (ImGui::BeginCombo("System",fmt::sprintf("%d. %s",pgSys+1,e->getSystemName(e->song.system[pgSys])).c_str())) { + if (ImGui::BeginCombo("Chip",fmt::sprintf("%d. %s",pgSys+1,e->getSystemName(e->song.system[pgSys])).c_str())) { for (int i=0; isong.systemLen; i++) { if (ImGui::Selectable(fmt::sprintf("%d. %s",i+1,e->getSystemName(e->song.system[i])).c_str())) { pgSys=i; @@ -358,7 +358,7 @@ void FurnaceGUI::drawDebug() { if (ImGui::TreeNode("Register Cheatsheet")) { const char** sheet=e->getRegisterSheet(pgSys); if (sheet==NULL) { - ImGui::Text("no cheatsheet available for this system."); + ImGui::Text("no cheatsheet available for this chip."); } else { if (ImGui::BeginTable("RegisterSheet",2,ImGuiTableFlags_SizingFixedSame)) { ImGui::TableNextRow(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index c1cd7f076..8ee6c60b9 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1879,7 +1879,7 @@ void FurnaceGUI::processDrags(int dragX, int dragY) { #define sysAddOption(x) \ if (ImGui::MenuItem(getSystemName(x))) { \ if (!e->addSystem(x)) { \ - showError("cannot add system! ("+e->getLastError()+")"); \ + showError("cannot add chip! ("+e->getLastError()+")"); \ } \ updateWindowTitle(); \ } @@ -2887,7 +2887,7 @@ bool FurnaceGUI::loop() { if (ImGui::MenuItem("one file")) { openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE); } - if (ImGui::MenuItem("multiple files (one per system)")) { + if (ImGui::MenuItem("multiple files (one per chip)")) { openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS); } if (ImGui::MenuItem("multiple files (one per channel)")) { @@ -2928,7 +2928,7 @@ bool FurnaceGUI::loop() { "pattern indexes are ordered as they appear in the song." ); } - ImGui::Text("systems to export:"); + ImGui::Text("chips to export:"); bool hasOneAtLeast=false; for (int i=0; isong.systemLen; i++) { int minVersion=e->minVGMVersion(e->song.system[i]); @@ -2937,17 +2937,17 @@ bool FurnaceGUI::loop() { ImGui::EndDisabled(); if (minVersion>vgmExportVersion) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { - ImGui::SetTooltip("this system is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff); + ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff); } } else if (minVersion==0) { if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { - ImGui::SetTooltip("this system is not supported by the VGM format!"); + ImGui::SetTooltip("this chip is not supported by the VGM format!"); } } else { if (willExport[i]) hasOneAtLeast=true; } } - ImGui::Text("select the systems you wish to export,"); + ImGui::Text("select the chip you wish to export,"); ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1); if (hasOneAtLeast) { if (ImGui::MenuItem("click to export")) { @@ -2972,14 +2972,14 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } ImGui::Separator(); - if (ImGui::BeginMenu("add system...")) { + if (ImGui::BeginMenu("add chip...")) { for (int j=0; availableSystems[j]; j++) { if (!settings.hiddenSystems && (availableSystems[j]==DIV_SYSTEM_YMU759 || availableSystems[j]==DIV_SYSTEM_DUMMY)) continue; sysAddOption((DivSystem)availableSystems[j]); } ImGui::EndMenu(); } - if (ImGui::BeginMenu("configure system...")) { + 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.systemFlags[i],true); @@ -2988,7 +2988,7 @@ bool FurnaceGUI::loop() { } ImGui::EndMenu(); } - if (ImGui::BeginMenu("change system...")) { + if (ImGui::BeginMenu("change chip...")) { ImGui::Checkbox("Preserve channel positions",&preserveChanPos); for (int i=0; isong.systemLen; i++) { if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { @@ -3001,12 +3001,12 @@ bool FurnaceGUI::loop() { } ImGui::EndMenu(); } - if (ImGui::BeginMenu("remove system...")) { + if (ImGui::BeginMenu("remove chip...")) { ImGui::Checkbox("Preserve channel positions",&preserveChanPos); for (int i=0; isong.systemLen; i++) { if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { if (!e->removeSystem(i,preserveChanPos)) { - showError("cannot remove system! ("+e->getLastError()+")"); + showError("cannot remove chip! ("+e->getLastError()+")"); } } } diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 73e9d2333..37d4bfecf 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -468,7 +468,7 @@ void FurnaceGUI::drawSettings() { } bool restartOnFlagChangeB=settings.restartOnFlagChange; - if (ImGui::Checkbox("Restart song when changing system properties",&restartOnFlagChangeB)) { + if (ImGui::Checkbox("Restart song when changing chip properties",&restartOnFlagChangeB)) { settings.restartOnFlagChange=restartOnFlagChangeB; } @@ -1232,11 +1232,6 @@ void FurnaceGUI::drawSettings() { } ImGui::EndDisabled(); - bool chipNamesB=settings.chipNames; - if (ImGui::Checkbox("Use chip names instead of system names",&chipNamesB)) { - settings.chipNames=chipNamesB; - } - bool oplStandardWaveNamesB=settings.oplStandardWaveNames; if (ImGui::Checkbox("Use standard OPL waveform names",&oplStandardWaveNamesB)) { settings.oplStandardWaveNames=oplStandardWaveNamesB; @@ -1567,8 +1562,8 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SONG,"Song effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_TIME,"Time effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SPEED,"Speed effect"); - UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY,"Primary system effect"); - UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY,"Secondary system effect"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY,"Primary specific effect"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY,"Secondary specific effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_MISC,"Miscellaneous"); UI_COLOR_CONFIG(GUI_COLOR_EE_VALUE,"External command output"); ImGui::TreePop();