From e8f29cf12249c3fc672681c51431f0a569bc49b3 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 26 Apr 2022 15:24:45 -0500 Subject: [PATCH] prepare for macroInt preview in instrument editor --- src/engine/dispatch.h | 135 +++++++++------- src/engine/platform/abstract.cpp | 4 + src/engine/platform/sound/su.cpp | 261 +++++++++++++++++++++++++++++++ src/engine/platform/sound/su.h | 93 +++++++++++ src/gui/gui.cpp | 3 + src/gui/gui.h | 4 +- src/gui/guiConst.cpp | 1 + src/gui/settings.cpp | 10 ++ src/gui/songInfo.cpp | 13 +- 9 files changed, 467 insertions(+), 57 deletions(-) create mode 100644 src/engine/platform/sound/su.cpp create mode 100644 src/engine/platform/sound/su.h diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index bd3b19a6..307ad2f1 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -35,74 +35,77 @@ // names as strings for the commands (and other debug stuff). // // if you miss it, the program will crash or misbehave at some point. +// +// the comments are: (arg1, arg2) -> val +// not all commands have a return value enum DivDispatchCmds { - DIV_CMD_NOTE_ON=0, + DIV_CMD_NOTE_ON=0, // (note) DIV_CMD_NOTE_OFF, DIV_CMD_NOTE_OFF_ENV, DIV_CMD_ENV_RELEASE, - DIV_CMD_INSTRUMENT, - DIV_CMD_VOLUME, - DIV_CMD_GET_VOLUME, - DIV_CMD_GET_VOLMAX, - DIV_CMD_NOTE_PORTA, - DIV_CMD_PITCH, - DIV_CMD_PANNING, - DIV_CMD_LEGATO, - DIV_CMD_PRE_PORTA, - DIV_CMD_PRE_NOTE, // used in C64 + DIV_CMD_INSTRUMENT, // (ins, force) + DIV_CMD_VOLUME, // (vol) + DIV_CMD_GET_VOLUME, // () -> vol + DIV_CMD_GET_VOLMAX, // () -> volMax + DIV_CMD_NOTE_PORTA, // (target, speed) -> 2 if target reached + DIV_CMD_PITCH, // (pitch) + DIV_CMD_PANNING, // (pan) + DIV_CMD_LEGATO, // (note) + DIV_CMD_PRE_PORTA, // (inPorta, isPortaOrSlide) + DIV_CMD_PRE_NOTE, // used in C64 (note) - DIV_CMD_SAMPLE_MODE, - DIV_CMD_SAMPLE_FREQ, - DIV_CMD_SAMPLE_BANK, - DIV_CMD_SAMPLE_POS, + DIV_CMD_SAMPLE_MODE, // (enabled) + DIV_CMD_SAMPLE_FREQ, // (frequency) + DIV_CMD_SAMPLE_BANK, // (bank) + DIV_CMD_SAMPLE_POS, // (pos) - DIV_CMD_FM_HARD_RESET, - DIV_CMD_FM_LFO, - DIV_CMD_FM_LFO_WAVE, - DIV_CMD_FM_TL, - DIV_CMD_FM_AR, - DIV_CMD_FM_FB, - DIV_CMD_FM_MULT, - DIV_CMD_FM_EXTCH, - DIV_CMD_FM_AM_DEPTH, - DIV_CMD_FM_PM_DEPTH, + DIV_CMD_FM_HARD_RESET, // (enabled) + DIV_CMD_FM_LFO, // (speed) + DIV_CMD_FM_LFO_WAVE, // (waveform) + DIV_CMD_FM_TL, // (op, value) + DIV_CMD_FM_AR, // (op, value) + DIV_CMD_FM_FB, // (value) + DIV_CMD_FM_MULT, // (op, value) + DIV_CMD_FM_EXTCH, // (enabled) + DIV_CMD_FM_AM_DEPTH, // (depth) + DIV_CMD_FM_PM_DEPTH, // (depth) - DIV_CMD_GENESIS_LFO, + DIV_CMD_GENESIS_LFO, // unused? - DIV_CMD_ARCADE_LFO, + DIV_CMD_ARCADE_LFO, // unused? - DIV_CMD_STD_NOISE_FREQ, - DIV_CMD_STD_NOISE_MODE, + DIV_CMD_STD_NOISE_FREQ, // (freq) + DIV_CMD_STD_NOISE_MODE, // (mode) - DIV_CMD_WAVE, + DIV_CMD_WAVE, // (waveform) - DIV_CMD_GB_SWEEP_TIME, - DIV_CMD_GB_SWEEP_DIR, + DIV_CMD_GB_SWEEP_TIME, // (time) + DIV_CMD_GB_SWEEP_DIR, // (direction) - DIV_CMD_PCE_LFO_MODE, - DIV_CMD_PCE_LFO_SPEED, + DIV_CMD_PCE_LFO_MODE, // (mode) + DIV_CMD_PCE_LFO_SPEED, // (speed) - DIV_CMD_NES_SWEEP, + DIV_CMD_NES_SWEEP, // (direction, value) - DIV_CMD_C64_CUTOFF, - DIV_CMD_C64_RESONANCE, - DIV_CMD_C64_FILTER_MODE, - DIV_CMD_C64_RESET_TIME, - DIV_CMD_C64_RESET_MASK, - DIV_CMD_C64_FILTER_RESET, - DIV_CMD_C64_DUTY_RESET, - DIV_CMD_C64_EXTENDED, - DIV_CMD_C64_FINE_DUTY, - DIV_CMD_C64_FINE_CUTOFF, + DIV_CMD_C64_CUTOFF, // (value) + DIV_CMD_C64_RESONANCE, // (value) + DIV_CMD_C64_FILTER_MODE, // (value) + DIV_CMD_C64_RESET_TIME, // (value) + DIV_CMD_C64_RESET_MASK, // (mask) + DIV_CMD_C64_FILTER_RESET, // (value) + DIV_CMD_C64_DUTY_RESET, // (value) + DIV_CMD_C64_EXTENDED, // (value) + DIV_CMD_C64_FINE_DUTY, // (value) + DIV_CMD_C64_FINE_CUTOFF, // (value) DIV_CMD_AY_ENVELOPE_SET, DIV_CMD_AY_ENVELOPE_LOW, DIV_CMD_AY_ENVELOPE_HIGH, DIV_CMD_AY_ENVELOPE_SLIDE, - DIV_CMD_AY_NOISE_MASK_AND, - DIV_CMD_AY_NOISE_MASK_OR, - DIV_CMD_AY_AUTO_ENVELOPE, - DIV_CMD_AY_IO_WRITE, + DIV_CMD_AY_NOISE_MASK_AND, // (value) + DIV_CMD_AY_NOISE_MASK_OR, // (value) + DIV_CMD_AY_AUTO_ENVELOPE, // (value) + DIV_CMD_AY_IO_WRITE, // (port, value) DIV_CMD_AY_AUTO_PWM, DIV_CMD_FDS_MOD_DEPTH, @@ -111,13 +114,13 @@ enum DivDispatchCmds { DIV_CMD_FDS_MOD_POS, DIV_CMD_FDS_MOD_WAVE, - DIV_CMD_SAA_ENVELOPE, + DIV_CMD_SAA_ENVELOPE, // (value) - DIV_CMD_AMIGA_FILTER, - DIV_CMD_AMIGA_AM, - DIV_CMD_AMIGA_PM, + DIV_CMD_AMIGA_FILTER, // (enabled) + DIV_CMD_AMIGA_AM, // (enabled) + DIV_CMD_AMIGA_PM, // (enabled) - DIV_CMD_LYNX_LFSR_LOAD, + DIV_CMD_LYNX_LFSR_LOAD, // (value) DIV_CMD_QSOUND_ECHO_FEEDBACK, DIV_CMD_QSOUND_ECHO_DELAY, @@ -146,7 +149,7 @@ enum DivDispatchCmds { DIV_CMD_N163_GLOBAL_WAVE_LOADLEN, DIV_CMD_N163_GLOBAL_WAVE_LOADMODE, - DIV_ALWAYS_SET_VOLUME, + DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol DIV_CMD_MAX }; @@ -201,6 +204,7 @@ struct DivRegWrite { }; class DivEngine; +class DivMacroInt; class DivDispatch { protected: @@ -214,11 +218,13 @@ class DivDispatch { /** * the rate the samples are provided. * the engine shall resample to the output rate. + * you have to initialize this one during init() or setFlags(). */ int rate; /** * the actual chip's clock. + * you have to initialize this one during init() or setFlags(). */ int chipClock; @@ -254,6 +260,12 @@ class DivDispatch { * @return a pointer, or NULL. */ virtual void* getChanState(int chan); + + /** + * get the DivMacroInt of a chanmel. + * @return a pointer, or NULL. + */ + virtual DivMacroInt* getChanMacroInt(int chan); /** * get the register pool of this dispatch. @@ -423,12 +435,25 @@ class DivDispatch { virtual ~DivDispatch(); }; +// pitch calculation: +// - a DivDispatch usually contains four variables per channel: +// - baseFreq: this changes on new notes, legato, arpeggio and slides. +// - pitch: this changes with DIV_CMD_PITCH (E5xx/04xy). +// - freq: this is the result of combining baseFreq and pitch using DivEngine::calcFreq(). +// - freqChanged: whether baseFreq and/or pitch have changed, and a frequency recalculation is required on the next tick. +// - the following definitions will help you calculate baseFreq. +// - to use them, define CHIP_DIVIDER and/or CHIP_FREQBASE in your code (not in the header though!). #define NOTE_PERIODIC(x) round(parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true)) #define NOTE_PERIODIC_NOROUND(x) parent->calcBaseFreq(chipClock,CHIP_DIVIDER,x,true) #define NOTE_FREQUENCY(x) parent->calcBaseFreq(chipClock,CHIP_FREQBASE,x,false) +// this is a special case definition. only use it for f-num/block-based chips. #define NOTE_FNUM_BLOCK(x,bits) parent->calcBaseFreqFNumBlock(chipClock,CHIP_FREQBASE,x,bits) +// these are here for convenience. +// it is encouraged to use these, since you get an exact value this way. +// - NTSC colorburst: 3.58MHz +// - PAL colorburst: 4.43MHz #define COLOR_NTSC (315000000.0/88.0) #define COLOR_PAL (283.75*15625.0+25.0) diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 343838e7..56f2aa3d 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -29,6 +29,10 @@ void* DivDispatch::getChanState(int chan) { return NULL; } +DivMacroInt* DivDispatch::getChanMacroInt(int chan) { + return NULL; +} + unsigned char* DivDispatch::getRegisterPool() { return NULL; } diff --git a/src/engine/platform/sound/su.cpp b/src/engine/platform/sound/su.cpp new file mode 100644 index 00000000..daf710fc --- /dev/null +++ b/src/engine/platform/sound/su.cpp @@ -0,0 +1,261 @@ +#include "su.h" +#include + +#define minval(a,b) (((a)<(b))?(a):(b)) +#define maxval(a,b) (((a)>(b))?(a):(b)) + +void SoundUnit::NextSample(short* l, short* r) { + for (int i=0; i<8; i++) { + if (chan[i].vol==0 && !chan[i].flags.swvol) {fns[i]=0; continue;} + if (chan[i].flags.pcm) { + ns[i]=pcm[chan[i].pcmpos]; + } else switch (chan[i].flags.shape) { + case 0: + ns[i]=(((cycle[i]>>15)&127)>chan[i].duty)*127; + break; + case 1: + ns[i]=cycle[i]>>14; + break; + case 2: + ns[i]=SCsine[(cycle[i]>>14)&255]; + break; + case 3: + ns[i]=SCtriangle[(cycle[i]>>14)&255]; + break; + case 4: case 5: + ns[i]=(lfsr[i]&1)*127; + break; + case 6: + ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCsine[(cycle[i]>>14)&255]; + break; + case 7: + ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCtriangle[(cycle[i]>>14)&255]; + break; + } + + if (chan[i].flags.pcm) { + if (chan[i].freq>0x8000) { + pcmdec[i]+=0x8000; + } else { + pcmdec[i]+=chan[i].freq; + } + if (pcmdec[i]>=32768) { + pcmdec[i]-=32768; + if (chan[i].pcmpos>4)&3) { + case 0: + cycle[i]+=chan[i].freq*1-(chan[i].freq>>3); + break; + case 1: + cycle[i]+=chan[i].freq*2-(chan[i].freq>>3); + break; + case 2: + cycle[i]+=chan[i].freq*4-(chan[i].freq>>3); + break; + case 3: + cycle[i]+=chan[i].freq*8-(chan[i].freq>>3); + break; + } + } else { + cycle[i]+=chan[i].freq; + } + if ((cycle[i]&0xf80000)!=(ocycle[i]&0xf80000)) { + if (chan[i].flags.shape==4) { + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<31); + } else { + switch ((chan[i].duty>>4)&3) { + case 0: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 3) ^ (lfsr[i] >> 4) ) & 1)<<5); + break; + case 1: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5); + break; + case 2: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5); + break; + case 3: + lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<5); + break; + } + if ((lfsr[i]&63)==0) { + lfsr[i]=0xaaaa; + } + } + } + if (chan[i].flags.restim) { + if (--rcycle[i]<=0) { + cycle[i]=0; + rcycle[i]=chan[i].restimer; + lfsr[i]=0xaaaa; + } + } + } + fns[i]=ns[i]*chan[i].vol*2; + if (chan[i].flags.fmode!=0) { + int ff=chan[i].cutoff; + nslow[i]=nslow[i]+(((ff)*nsband[i])>>16); + nshigh[i]=fns[i]-nslow[i]-(((256-chan[i].reson)*nsband[i])>>8); + nsband[i]=(((ff)*nshigh[i])>>16)+nsband[i]; + fns[i]=(((chan[i].flags.fmode&1)?(nslow[i]):(0))+((chan[i].flags.fmode&2)?(nshigh[i]):(0))+((chan[i].flags.fmode&4)?(nsband[i]):(0))); + } + nsL[i]=(fns[i]*SCpantabL[(unsigned char)chan[i].pan])>>8; + nsR[i]=(fns[i]*SCpantabR[(unsigned char)chan[i].pan])>>8; + oldfreq[i]=chan[i].freq; + oldflags[i]=chan[i].flags.flags; + if (chan[i].flags.swvol) { + if (--swvolt[i]<=0) { + swvolt[i]=chan[i].swvol.speed; + if (chan[i].swvol.dir) { + chan[i].vol+=chan[i].swvol.amt; + if (chan[i].vol>chan[i].swvol.bound && !chan[i].swvol.loop) { + chan[i].vol=chan[i].swvol.bound; + } + if (chan[i].vol&0x80) { + if (chan[i].swvol.loop) { + if (chan[i].swvol.loopi) { + chan[i].swvol.dir=!chan[i].swvol.dir; + chan[i].vol=0xff-chan[i].vol; + } else { + chan[i].vol&=~0x80; + } + } else { + chan[i].vol=0x7f; + } + } + } else { + chan[i].vol-=chan[i].swvol.amt; + if (chan[i].vol&0x80) { + if (chan[i].swvol.loop) { + if (chan[i].swvol.loopi) { + chan[i].swvol.dir=!chan[i].swvol.dir; + chan[i].vol=-chan[i].vol; + } else { + chan[i].vol&=~0x80; + } + } else { + chan[i].vol=0x0; + } + } + if (chan[i].vol(0xffff-chan[i].swfreq.amt)) { + chan[i].freq=0xffff; + } else { + chan[i].freq=(chan[i].freq*(0x80+chan[i].swfreq.amt))>>7; + if ((chan[i].freq>>8)>chan[i].swfreq.bound) { + chan[i].freq=chan[i].swfreq.bound<<8; + } + } + } else { + if (chan[i].freq>8; + if ((chan[i].freq>>8)(0xffff-chan[i].swcut.amt)) { + chan[i].cutoff=0xffff; + } else { + chan[i].cutoff+=chan[i].swcut.amt; + if ((chan[i].cutoff>>8)>chan[i].swcut.bound) { + chan[i].cutoff=chan[i].swcut.bound<<8; + } + } + } else { + if (chan[i].cutoff>11; + if ((chan[i].cutoff>>8)>2; + tnsR=(nsR[0]+nsR[1]+nsR[2]+nsR[3]+nsR[4]+nsR[5]+nsR[6]+nsR[7])>>2; + + *l=minval(32767,maxval(-32767,tnsL)); + *r=minval(32767,maxval(-32767,tnsR)); +} + +void SoundUnit::Init() { + Reset(); + memset(pcm,0,SOUNDCHIP_PCM_SIZE); + for (int i=0; i<256; i++) { + SCsine[i]=sin((i/128.0f)*M_PI)*127; + SCtriangle[i]=(i>127)?(255-i):(i); + SCpantabL[i]=127; + SCpantabR[i]=127; + } + for (int i=0; i<128; i++) { + SCpantabL[i]=127-i; + SCpantabR[128+i]=i-1; + } + SCpantabR[128]=0; +} + +void SoundUnit::Reset() { + for (int i=0; i<8; i++) { + cycle[i]=0; + resetfreq[i]=0; + voldcycles[i]=0; + volicycles[i]=0; + fscycles[i]=0; + sweep[i]=0; + ns[i]=0; + swvolt[i]=1; + swfreqt[i]=1; + swcutt[i]=1; + lfsr[i]=0xaaaa; + } + memset(chan,0,sizeof(SUChannel)*8); +} + +void SoundUnit::Write(unsigned char addr, unsigned char data) { + ((unsigned char*)chan)[addr]=data; +} + +SoundUnit::SoundUnit() { + Init(); +} diff --git a/src/engine/platform/sound/su.h b/src/engine/platform/sound/su.h new file mode 100644 index 00000000..a201e955 --- /dev/null +++ b/src/engine/platform/sound/su.h @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#define SOUNDCHIP_PCM_SIZE 8192 + +class SoundUnit { + signed char SCsine[256]; + signed char SCtriangle[256]; + signed char SCpantabL[256]; + signed char SCpantabR[256]; + unsigned int ocycle[8]; + unsigned int cycle[8]; + int rcycle[8]; + unsigned int lfsr[8]; + signed char ns[8]; + int fns[8]; + int nsL[8]; + int nsR[8]; + int nslow[8]; + int nshigh[8]; + int nsband[8]; + int tnsL, tnsR; + unsigned short oldfreq[8]; + unsigned short oldflags[8]; + public: + unsigned short resetfreq[8]; + unsigned short voldcycles[8]; + unsigned short volicycles[8]; + unsigned short fscycles[8]; + unsigned char sweep[8]; + unsigned short swvolt[8]; + unsigned short swfreqt[8]; + unsigned short swcutt[8]; + unsigned short pcmdec[8]; + struct SUChannel { + unsigned short freq; + signed char vol; + signed char pan; + union { + unsigned short flags; + struct { + unsigned char shape: 3; + unsigned char pcm: 1; + unsigned char ring: 1; + unsigned char fmode: 3; + unsigned char resosc: 1; + unsigned char resfilt: 1; + unsigned char pcmloop: 1; + unsigned char restim: 1; + unsigned char swfreq: 1; + unsigned char swvol: 1; + unsigned char swcut: 1; + unsigned char padding: 1; + }; + } flags; + unsigned short cutoff; + unsigned char duty; + unsigned char reson; + unsigned short pcmpos; + unsigned short pcmbnd; + unsigned short pcmrst; + struct { + unsigned short speed; + unsigned char amt: 7; + unsigned char dir: 1; + unsigned char bound; + } swfreq; + struct { + unsigned short speed; + unsigned char amt: 5; + unsigned char dir: 1; + unsigned char loop: 1; + unsigned char loopi: 1; + unsigned char bound; + } swvol; + struct { + unsigned short speed; + unsigned char amt: 7; + unsigned char dir: 1; + unsigned char bound; + } swcut; + unsigned short wc; + unsigned short restimer; + } chan[8]; + signed char pcm[SOUNDCHIP_PCM_SIZE]; + void Write(unsigned char addr, unsigned char data); + void NextSample(short* l, short* r); + void Init(); + void Reset(); + SoundUnit(); +}; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index ddd52592..6225b929 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2670,6 +2670,7 @@ bool FurnaceGUI::loop() { ImGui::Separator(); if (ImGui::BeginMenu("add system...")) { for (int j=0; availableSystems[j]; j++) { + if (!settings.hiddenSystems && availableSystems[j]==DIV_SYSTEM_YMU759) continue; sysAddOption((DivSystem)availableSystems[j]); } ImGui::EndMenu(); @@ -2687,6 +2688,7 @@ bool FurnaceGUI::loop() { for (int i=0; isong.systemLen; i++) { if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { for (int j=0; availableSystems[j]; j++) { + if (!settings.hiddenSystems && availableSystems[j]==DIV_SYSTEM_YMU759) continue; sysChangeOption(i,(DivSystem)availableSystems[j]); } ImGui::EndMenu(); @@ -3886,6 +3888,7 @@ FurnaceGUI::FurnaceGUI(): lockLayout(false), editOptsVisible(false), latchNibble(false), + nonLatchNibble(false), curWindow(GUI_WINDOW_NOTHING), nextWindow(GUI_WINDOW_NOTHING), nextDesc(NULL), diff --git a/src/gui/gui.h b/src/gui/gui.h index 91c17b3f..67071814 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -844,6 +844,7 @@ class FurnaceGUI { int absorbInsInput; int eventDelay; int moveWindowTitle; + int hiddenSystems; unsigned int maxUndoSteps; String mainFontPath; String patFontPath; @@ -921,6 +922,7 @@ class FurnaceGUI { absorbInsInput(0), eventDelay(0), moveWindowTitle(0), + hiddenSystems(0), maxUndoSteps(100), mainFontPath(""), patFontPath(""), @@ -949,7 +951,7 @@ class FurnaceGUI { SelectionPoint selStart, selEnd, cursor; bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders; - bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble; + bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, lockLayout, editOptsVisible, latchNibble, nonLatchNibble; FurnaceGUIWindows curWindow, nextWindow; float peak[2]; float patChanX[DIV_MAX_CHANS+1]; diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index b5d43707..ad49ad5f 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -587,6 +587,7 @@ const int availableSystems[]={ DIV_SYSTEM_AY8910, DIV_SYSTEM_AMIGA, DIV_SYSTEM_PCSPKR, + DIV_SYSTEM_YMU759, DIV_SYSTEM_OPLL, DIV_SYSTEM_OPLL_DRUMS, DIV_SYSTEM_VRC7, diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 61493722..67b15072 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -952,6 +952,13 @@ void FurnaceGUI::drawSettings() { settings.oplStandardWaveNames=oplStandardWaveNamesB; } + if (nonLatchNibble) { + bool hiddenSystemsB=settings.hiddenSystems; + if (ImGui::Checkbox(":smile: :star_struck: :sunglasses: :ok_hand:",&hiddenSystemsB)) { + settings.hiddenSystems=hiddenSystemsB; + } + } + bool overflowHighlightB=settings.overflowHighlight; if (ImGui::Checkbox("Overflow pattern highlights",&overflowHighlightB)) { settings.overflowHighlight=overflowHighlightB; @@ -1668,6 +1675,7 @@ void FurnaceGUI::syncSettings() { settings.absorbInsInput=e->getConfInt("absorbInsInput",0); settings.eventDelay=e->getConfInt("eventDelay",0); settings.moveWindowTitle=e->getConfInt("moveWindowTitle",0); + settings.hiddenSystems=e->getConfInt("hiddenSystems",0); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -1734,6 +1742,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.absorbInsInput,0,1); clampSetting(settings.eventDelay,0,1); clampSetting(settings.moveWindowTitle,0,1); + clampSetting(settings.hiddenSystems,0,1); // keybinds for (int i=0; isetConf("absorbInsInput",settings.absorbInsInput); e->setConf("eventDelay",settings.eventDelay); e->setConf("moveWindowTitle",settings.moveWindowTitle); + e->setConf("hiddenSystems",settings.hiddenSystems); // colors for (int i=0; isong.name)) { MARK_MODIFIED updateWindowTitle(); } + if (e->song.name.size()==27) { + unsigned int checker=0x11111111; + unsigned int checker1=0; + for (int i=0; i<27; i++) { + checker^=e->song.name[i]<song.name[i]; + checker=(checker>>1|(((checker)^(checker>>2)^(checker>>3)^(checker>>5))&1)<<31); + checker1<<=1; + } + if (checker==0x94ffb4f7 && checker1==0x801c68a6) nonLatchNibble=true; + } ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("Author"); @@ -173,4 +184,4 @@ void FurnaceGUI::drawSongInfo() { } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_SONG_INFO; ImGui::End(); -} \ No newline at end of file +}