prepare for macroInt preview in instrument editor

This commit is contained in:
tildearrow 2022-04-26 15:24:45 -05:00
parent 9eb9561b53
commit e8f29cf122
9 changed files with 467 additions and 57 deletions

View File

@ -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)

View File

@ -29,6 +29,10 @@ void* DivDispatch::getChanState(int chan) {
return NULL;
}
DivMacroInt* DivDispatch::getChanMacroInt(int chan) {
return NULL;
}
unsigned char* DivDispatch::getRegisterPool() {
return NULL;
}

View File

@ -0,0 +1,261 @@
#include "su.h"
#include <string.h>
#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<chan[i].pcmbnd) {
chan[i].pcmpos++;
chan[i].wc++;
if (chan[i].pcmpos==chan[i].pcmbnd) {
if (chan[i].flags.pcmloop) {
chan[i].pcmpos=chan[i].pcmrst;
}
}
chan[i].pcmpos&=(SOUNDCHIP_PCM_SIZE-1);
} else if (chan[i].flags.pcmloop) {
chan[i].pcmpos=chan[i].pcmrst;
}
}
} else {
ocycle[i]=cycle[i];
if (chan[i].flags.shape==5) {
switch ((chan[i].duty>>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<chan[i].swvol.bound && !chan[i].swvol.loop) {
chan[i].vol=chan[i].swvol.bound;
}
}
}
}
if (chan[i].flags.swfreq) {
if (--swfreqt[i]<=0) {
swfreqt[i]=chan[i].swfreq.speed;
if (chan[i].swfreq.dir) {
if (chan[i].freq>(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<chan[i].swfreq.amt) {
chan[i].freq=0;
} else {
chan[i].freq=(chan[i].freq*(0xff-chan[i].swfreq.amt))>>8;
if ((chan[i].freq>>8)<chan[i].swfreq.bound) {
chan[i].freq=chan[i].swfreq.bound<<8;
}
}
}
}
}
if (chan[i].flags.swcut) {
if (--swcutt[i]<=0) {
swcutt[i]=chan[i].swcut.speed;
if (chan[i].swcut.dir) {
if (chan[i].cutoff>(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<chan[i].swcut.amt) {
chan[i].cutoff=0;
} else {
chan[i].cutoff=((2048-(unsigned int)chan[i].swcut.amt)*(unsigned int)chan[i].cutoff)>>11;
if ((chan[i].cutoff>>8)<chan[i].swcut.bound) {
chan[i].cutoff=chan[i].swcut.bound<<8;
}
}
}
}
}
if (chan[i].flags.resosc) {
cycle[i]=0;
rcycle[i]=chan[i].restimer;
ocycle[i]=0;
chan[i].flags.resosc=0;
}
}
tnsL=(nsL[0]+nsL[1]+nsL[2]+nsL[3]+nsL[4]+nsL[5]+nsL[6]+nsL[7])>>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();
}

View File

@ -0,0 +1,93 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#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();
};

View File

@ -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; i<e->song.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),

View File

@ -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];

View File

@ -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,

View File

@ -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; i<GUI_ACTION_MAX; i++) {
@ -1827,6 +1836,7 @@ void FurnaceGUI::commitSettings() {
e->setConf("absorbInsInput",settings.absorbInsInput);
e->setConf("eventDelay",settings.eventDelay);
e->setConf("moveWindowTitle",settings.moveWindowTitle);
e->setConf("hiddenSystems",settings.hiddenSystems);
// colors
for (int i=0; i<GUI_COLOR_MAX; i++) {

View File

@ -41,6 +41,17 @@ void FurnaceGUI::drawSongInfo() {
if (ImGui::InputText("##Name",&e->song.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]<<i;
checker1+=e->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();
}
}