Merge branch 'master' of git://github.com/tildearrow/furnace into tildearrow-master

# Conflicts:
#	src/gui/insEdit.cpp
This commit is contained in:
Waldemar Pawlaszek 2022-02-22 09:13:49 +01:00
commit 79e53cfd10
38 changed files with 537 additions and 98 deletions

BIN
demos/Ice_Wind_OPMSPCM.fur Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -208,13 +208,25 @@ class DivDispatch {
virtual void* getChanState(int chan); virtual void* getChanState(int chan);
/** /**
* get this dispatch's state. * get the register pool of this dispatch.
* @return a pointer, or NULL.
*/
virtual unsigned char* getRegisterPool();
/**
* get the size of the register pool of this dispatch.
* @return the size.
*/
virtual int getRegisterPoolSize();
/**
* get this dispatch's state. DO NOT IMPLEMENT YET.
* @return a pointer to the dispatch's state. must be deallocated manually! * @return a pointer to the dispatch's state. must be deallocated manually!
*/ */
virtual void* getState(); virtual void* getState();
/** /**
* set this dispatch's state. * set this dispatch's state. DO NOT IMPLEMENT YET.
* @param state a pointer to a state pertaining to this dispatch, * @param state a pointer to a state pertaining to this dispatch,
* or NULL if this dispatch does not support state saves. * or NULL if this dispatch does not support state saves.
*/ */

View file

@ -400,6 +400,7 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode)
exportMode=mode; exportMode=mode;
exporting=true; exporting=true;
stop(); stop();
repeatPattern=false;
setOrder(0); setOrder(0);
remainingLoops=loops; remainingLoops=loops;
exportThread=new std::thread(_runExportThread,this); exportThread=new std::thread(_runExportThread,this);
@ -548,9 +549,9 @@ void DivEngine::renderSamples() {
if (diff>=tempstep) encoded|=1; if (diff>=tempstep) encoded|=1;
acc+=jediTable[decstep+encoded]; acc+=jediTable[decstep+encoded];
if (acc>0x7ff || acc<-0x800) { /*if (acc>0x7ff || acc<-0x800) {
logW("clipping! %d\n",acc); logW("clipping! %d\n",acc);
} }*/
acc&=0xfff; acc&=0xfff;
if (acc&0x800) acc|=~0xfff; if (acc&0x800) acc|=~0xfff;
decstep+=adStepSeek[encoded&7]*16; decstep+=adStepSeek[encoded&7]*16;
@ -728,6 +729,13 @@ void* DivEngine::getDispatchChanState(int ch) {
return disCont[dispatchOfChan[ch]].dispatch->getChanState(dispatchChanOfChan[ch]); return disCont[dispatchOfChan[ch]].dispatch->getChanState(dispatchChanOfChan[ch]);
} }
unsigned char* DivEngine::getRegisterPool(int sys, int& size) {
if (sys<0 || sys>=song.systemLen) return NULL;
if (disCont[sys].dispatch==NULL) return NULL;
size=disCont[sys].dispatch->getRegisterPoolSize();
return disCont[sys].dispatch->getRegisterPool();
}
void DivEngine::enableCommandStream(bool enable) { void DivEngine::enableCommandStream(bool enable) {
cmdStreamEnabled=enable; cmdStreamEnabled=enable;
} }

View file

@ -37,8 +37,8 @@
warnings+=(String("\n")+x); \ warnings+=(String("\n")+x); \
} }
#define DIV_VERSION "0.5.7pre4" #define DIV_VERSION "0.5.7"
#define DIV_ENGINE_VERSION 52 #define DIV_ENGINE_VERSION 53
enum DivStatusView { enum DivStatusView {
DIV_STATUS_NOTHING=0, DIV_STATUS_NOTHING=0,
@ -530,6 +530,9 @@ class DivEngine {
// get dispatch channel state // get dispatch channel state
void* getDispatchChanState(int chan); void* getDispatchChanState(int chan);
// get register pool
unsigned char* getRegisterPool(int sys, int& size);
// enable command stream dumping // enable command stream dumping
void enableCommandStream(bool enable); void enableCommandStream(bool enable);

View file

@ -135,6 +135,12 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
ds.brokenShortcutSlides=false; ds.brokenShortcutSlides=false;
ds.ignoreDuplicateSlides=true; ds.ignoreDuplicateSlides=true;
// 1.1 compat flags
if (ds.version>24) {
ds.waveDutyIsVol=true;
ds.legacyVolumeSlides=false;
}
// Neo Geo detune // Neo Geo detune
if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT) { if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT) {
ds.tuning=443.23; ds.tuning=443.23;

View file

@ -29,6 +29,14 @@ void* DivDispatch::getChanState(int chan) {
return NULL; return NULL;
} }
unsigned char* DivDispatch::getRegisterPool() {
return NULL;
}
int DivDispatch::getRegisterPoolSize() {
return 0;
}
void* DivDispatch::getState() { void* DivDispatch::getState() {
return NULL; return NULL;
} }

View file

@ -145,6 +145,7 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si
QueuedWrite& w=writes.front(); QueuedWrite& w=writes.front();
if (w.addrOrVal) { if (w.addrOrVal) {
OPM_Write(&fm,1,w.val); OPM_Write(&fm,1,w.val);
regPool[w.addr&0xff]=w.val;
//printf("write: %x = %.2x\n",w.addr,w.val); //printf("write: %x = %.2x\n",w.addr,w.val);
writes.pop(); writes.pop();
} else { } else {
@ -216,6 +217,7 @@ void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, siz
QueuedWrite& w=writes.front(); QueuedWrite& w=writes.front();
fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr); fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr);
fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val); fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0xff]=w.val;
writes.pop(); writes.pop();
delay=1; delay=1;
} }
@ -877,6 +879,14 @@ void* DivPlatformArcade::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformArcade::getRegisterPool() {
return regPool;
}
int DivPlatformArcade::getRegisterPoolSize() {
return 256;
}
void DivPlatformArcade::poke(unsigned int addr, unsigned short val) { void DivPlatformArcade::poke(unsigned int addr, unsigned short val) {
immWrite(addr,val); immWrite(addr,val);
} }
@ -887,6 +897,7 @@ void DivPlatformArcade::poke(std::vector<DivRegWrite>& wlist) {
void DivPlatformArcade::reset() { void DivPlatformArcade::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
memset(regPool,0,256);
if (useYMFM) { if (useYMFM) {
fm_ymfm->reset(); fm_ymfm->reset();
} else { } else {

View file

@ -71,6 +71,8 @@ class DivPlatformArcade: public DivDispatch {
ymfm::ym2151::output_data out_ymfm; ymfm::ym2151::output_data out_ymfm;
DivArcadeInterface iface; DivArcadeInterface iface;
unsigned char regPool[256];
bool extMode, useYMFM; bool extMode, useYMFM;
bool isMuted[13]; bool isMuted[13];
@ -90,6 +92,8 @@ class DivPlatformArcade: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -94,6 +94,7 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
ay->address_w(w.addr); ay->address_w(w.addr);
ay->data_w(w.val); ay->data_w(w.val);
regPool[w.addr&0x0f]=w.val;
writes.pop(); writes.pop();
} }
ay->sound_stream_update(ayBuf,len); ay->sound_stream_update(ayBuf,len);
@ -400,9 +401,18 @@ void* DivPlatformAY8910::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformAY8910::getRegisterPool() {
return regPool;
}
int DivPlatformAY8910::getRegisterPoolSize() {
return 16;
}
void DivPlatformAY8910::reset() { void DivPlatformAY8910::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
ay->device_reset(); ay->device_reset();
memset(regPool,0,16);
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
chan[i]=DivPlatformAY8910::Channel(); chan[i]=DivPlatformAY8910::Channel();
chan[i].vol=0x0f; chan[i].vol=0x0f;

View file

@ -47,6 +47,7 @@ class DivPlatformAY8910: public DivDispatch {
}; };
std::queue<QueuedWrite> writes; std::queue<QueuedWrite> writes;
ay8910_device* ay; ay8910_device* ay;
unsigned char regPool[16];
unsigned char lastBusy; unsigned char lastBusy;
bool dacMode; bool dacMode;
@ -76,6 +77,8 @@ class DivPlatformAY8910: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -124,6 +124,7 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
} else { } else {
ay->data_w(w.val); ay->data_w(w.val);
} }
regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
ay->sound_stream_update(ayBuf,len); ay->sound_stream_update(ayBuf,len);
@ -462,9 +463,18 @@ void* DivPlatformAY8930::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformAY8930::getRegisterPool() {
return regPool;
}
int DivPlatformAY8930::getRegisterPoolSize() {
return 32;
}
void DivPlatformAY8930::reset() { void DivPlatformAY8930::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
ay->device_reset(); ay->device_reset();
memset(regPool,0,32);
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
chan[i]=DivPlatformAY8930::Channel(); chan[i]=DivPlatformAY8930::Channel();
chan[i].vol=31; chan[i].vol=31;

View file

@ -47,6 +47,7 @@ class DivPlatformAY8930: public DivDispatch {
}; };
std::queue<QueuedWrite> writes; std::queue<QueuedWrite> writes;
ay8930_device* ay; ay8930_device* ay;
unsigned char regPool[32];
unsigned char ayNoiseAnd, ayNoiseOr; unsigned char ayNoiseAnd, ayNoiseOr;
bool bank; bool bank;
@ -69,6 +70,8 @@ class DivPlatformAY8930: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -21,7 +21,7 @@
#include "../engine.h" #include "../engine.h"
#include <math.h> #include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {sid.write(a,v); if (dumpWrites) {addWrite(a,v);} } #define rWrite(a,v) if (!skipRegisterWrites) {sid.write(a,v); regPool[(a)&0x1f]=v; if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 524288 #define CHIP_FREQBASE 524288
@ -467,12 +467,21 @@ void* DivPlatformC64::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformC64::getRegisterPool() {
return regPool;
}
int DivPlatformC64::getRegisterPoolSize() {
return 32;
}
void DivPlatformC64::reset() { void DivPlatformC64::reset() {
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
chan[i]=DivPlatformC64::Channel(); chan[i]=DivPlatformC64::Channel();
} }
sid.reset(); sid.reset();
memset(regPool,0,32);
rWrite(0x18,0x0f); rWrite(0x18,0x0f);

View file

@ -70,6 +70,7 @@ class DivPlatformC64: public DivDispatch {
int filtCut, resetTime; int filtCut, resetTime;
SID sid; SID sid;
unsigned char regPool[32];
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
@ -78,6 +79,8 @@ class DivPlatformC64: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -21,8 +21,8 @@
#include "../engine.h" #include "../engine.h"
#include <math.h> #include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {GB_apu_write(gb,a,v); if (dumpWrites) {addWrite(a,v);} } #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); 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 CHIP_DIVIDER 16 #define CHIP_DIVIDER 16
@ -395,6 +395,14 @@ void* DivPlatformGB::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformGB::getRegisterPool() {
return regPool;
}
int DivPlatformGB::getRegisterPoolSize() {
return 64;
}
void DivPlatformGB::reset() { void DivPlatformGB::reset() {
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
chan[i]=DivPlatformGB::Channel(); chan[i]=DivPlatformGB::Channel();
@ -403,6 +411,7 @@ void DivPlatformGB::reset() {
addWrite(0xffffffff,0); addWrite(0xffffffff,0);
} }
memset(gb,0,sizeof(GB_gameboy_t)); memset(gb,0,sizeof(GB_gameboy_t));
memset(regPool,0,128);
gb->model=GB_MODEL_DMG_B; gb->model=GB_MODEL_DMG_B;
GB_apu_init(gb); GB_apu_init(gb);
GB_set_sample_rate(gb,rate); GB_set_sample_rate(gb,rate);

View file

@ -55,6 +55,8 @@ class DivPlatformGB: public DivDispatch {
unsigned char lastPan; unsigned char lastPan;
GB_gameboy_t* gb; GB_gameboy_t* gb;
unsigned char regPool[128];
unsigned char procMute(); unsigned char procMute();
void updateWave(); void updateWave();
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
@ -62,6 +64,8 @@ class DivPlatformGB: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -121,6 +121,7 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s
OPN2_Write(&fm,0x1+((w.addr>>8)<<1),w.val); OPN2_Write(&fm,0x1+((w.addr>>8)<<1),w.val);
//printf("write: %x = %.2x\n",w.addr,w.val); //printf("write: %x = %.2x\n",w.addr,w.val);
lastBusy=0; lastBusy=0;
regPool[w.addr&0x1ff]=w.val;
writes.pop(); writes.pop();
} else { } else {
lastBusy++; lastBusy++;
@ -190,6 +191,7 @@ void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, si
QueuedWrite& w=writes.front(); QueuedWrite& w=writes.front();
fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr); fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr);
fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val); fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop(); writes.pop();
lastBusy=1; lastBusy=1;
} }
@ -805,8 +807,17 @@ void* DivPlatformGenesis::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformGenesis::getRegisterPool() {
return regPool;
}
int DivPlatformGenesis::getRegisterPoolSize() {
return 512;
}
void DivPlatformGenesis::reset() { void DivPlatformGenesis::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
memset(regPool,0,512);
if (useYMFM) { if (useYMFM) {
fm_ymfm->reset(); fm_ymfm->reset();
} }

View file

@ -79,6 +79,7 @@ class DivPlatformGenesis: public DivDispatch {
ymfm::ym2612* fm_ymfm; ymfm::ym2612* fm_ymfm;
ymfm::ym2612::output_data out_ymfm; ymfm::ym2612::output_data out_ymfm;
DivYM2612Interface iface; DivYM2612Interface iface;
unsigned char regPool[512];
bool dacMode; bool dacMode;
int dacPeriod; int dacPeriod;
@ -106,6 +107,8 @@ class DivPlatformGenesis: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -25,7 +25,7 @@
#define CHIP_DIVIDER 16 #define CHIP_DIVIDER 16
#define rWrite(a,v) if (!skipRegisterWrites) {apu_wr_reg(nes,a,v); if (dumpWrites) {addWrite(a,v);} } #define rWrite(a,v) if (!skipRegisterWrites) {apu_wr_reg(nes,a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
const char* regCheatSheetNES[]={ const char* regCheatSheetNES[]={
"S0Volume", "4000", "S0Volume", "4000",
@ -444,6 +444,14 @@ void* DivPlatformNES::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformNES::getRegisterPool() {
return regPool;
}
int DivPlatformNES::getRegisterPoolSize() {
return 32;
}
void DivPlatformNES::reset() { void DivPlatformNES::reset() {
for (int i=0; i<5; i++) { for (int i=0; i<5; i++) {
chan[i]=DivPlatformNES::Channel(); chan[i]=DivPlatformNES::Channel();
@ -459,6 +467,7 @@ void DivPlatformNES::reset() {
sampleBank=0; sampleBank=0;
apu_turn_on(nes,apuType); apu_turn_on(nes,apuType);
memset(regPool,0,128);
nes->apu.cpu_cycles=0; nes->apu.cpu_cycles=0;
nes->apu.cpu_opcode_cycle=0; nes->apu.cpu_opcode_cycle=0;

View file

@ -59,6 +59,7 @@ class DivPlatformNES: public DivDispatch {
unsigned char sampleBank; unsigned char sampleBank;
unsigned char apuType; unsigned char apuType;
struct NESAPU* nes; struct NESAPU* nes;
unsigned char regPool[128];
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
@ -66,6 +67,8 @@ class DivPlatformNES: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -29,6 +29,7 @@
curChan=c; \ curChan=c; \
rWrite(0,curChan); \ rWrite(0,curChan); \
} \ } \
regPool[16+((c)<<4)+((a)&0x0f)]=v; \
rWrite(a,v); \ rWrite(a,v); \
} }
@ -88,11 +89,12 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
chWrite(i,0x07,0); chWrite(i,0x07,0);
if (s->depth==8) { if (s->depth==8) {
chWrite(i,0x04,0xdf); chWrite(i,0x04,0xdf);
chWrite(i,0x06,(((unsigned char)s->rendData[chan[i].dacPos++]+0x80)>>3)); chWrite(i,0x06,(((unsigned char)s->rendData[chan[i].dacPos]+0x80)>>3));
} else { } else {
chWrite(i,0x04,0xdf); chWrite(i,0x04,0xdf);
chWrite(i,0x06,(((unsigned short)s->rendData[chan[i].dacPos++]+0x8000)>>11)); chWrite(i,0x06,(((unsigned short)s->rendData[chan[i].dacPos]+0x8000)>>11));
} }
chan[i].dacPos++;
if (chan[i].dacPos>=s->rendLength) { if (chan[i].dacPos>=s->rendLength) {
if (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) { if (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) {
chan[i].dacPos=s->loopStart; chan[i].dacPos=s->loopStart;
@ -110,6 +112,7 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
while (!writes.empty() && cycles<24) { while (!writes.empty() && cycles<24) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
pce->Write(cycles,w.addr,w.val); pce->Write(cycles,w.addr,w.val);
regPool[w.addr&0x0f]=w.val;
//cycles+=2; //cycles+=2;
writes.pop(); writes.pop();
} }
@ -442,8 +445,17 @@ void* DivPlatformPCE::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformPCE::getRegisterPool() {
return regPool;
}
int DivPlatformPCE::getRegisterPoolSize() {
return 112;
}
void DivPlatformPCE::reset() { void DivPlatformPCE::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
memset(regPool,0,128);
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
chan[i]=DivPlatformPCE::Channel(); chan[i]=DivPlatformPCE::Channel();
} }

View file

@ -74,12 +74,15 @@ class DivPlatformPCE: public DivDispatch {
int tempR[32]; int tempR[32];
unsigned char sampleBank, lfoMode, lfoSpeed; unsigned char sampleBank, lfoMode, lfoSpeed;
PCE_PSG* pce; PCE_PSG* pce;
unsigned char regPool[128];
void updateWave(int ch); void updateWave(int ch);
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
public: public:
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -83,6 +83,7 @@ void DivPlatformSAA1099::acquire_mame(short* bufL, short* bufR, size_t start, si
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
saa.control_w(w.addr); saa.control_w(w.addr);
saa.data_w(w.val); saa.data_w(w.val);
regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
saa.sound_stream_update(saaBuf,len); saa.sound_stream_update(saaBuf,len);
@ -103,6 +104,7 @@ void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
saa_saaSound->WriteAddressData(w.addr,w.val); saa_saaSound->WriteAddressData(w.addr,w.val);
regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len); saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len);
@ -367,8 +369,17 @@ void* DivPlatformSAA1099::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformSAA1099::getRegisterPool() {
return regPool;
}
int DivPlatformSAA1099::getRegisterPoolSize() {
return 32;
}
void DivPlatformSAA1099::reset() { void DivPlatformSAA1099::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
memset(regPool,0,32);
switch (core) { switch (core) {
case DIV_SAA_CORE_MAME: case DIV_SAA_CORE_MAME:
saa=saa1099_device(); saa=saa1099_device();

View file

@ -56,6 +56,7 @@ class DivPlatformSAA1099: public DivDispatch {
DivSAACores core; DivSAACores core;
saa1099_device saa; saa1099_device saa;
CSAASound* saa_saaSound; CSAASound* saa_saaSound;
unsigned char regPool[32];
unsigned char lastBusy; unsigned char lastBusy;
bool dacMode; bool dacMode;
@ -85,6 +86,8 @@ class DivPlatformSAA1099: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -22,7 +22,7 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {tia.set(a,v); if (dumpWrites) {addWrite(a,v);} } #define rWrite(a,v) if (!skipRegisterWrites) {tia.set(a,v); regPool[((a)-0x15)&0x0f]=v; if (dumpWrites) {addWrite(a,v);} }
const char* regCheatSheetTIA[]={ const char* regCheatSheetTIA[]={
"AUDC0", "15", "AUDC0", "15",
@ -281,8 +281,17 @@ void* DivPlatformTIA::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformTIA::getRegisterPool() {
return regPool;
}
int DivPlatformTIA::getRegisterPoolSize() {
return 6;
}
void DivPlatformTIA::reset() { void DivPlatformTIA::reset() {
tia.reset(); tia.reset();
memset(regPool,0,16);
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
chan[i]=DivPlatformTIA::Channel(); chan[i]=DivPlatformTIA::Channel();
chan[i].vol=0x0f; chan[i].vol=0x0f;

View file

@ -38,6 +38,7 @@ class DivPlatformTIA: public DivDispatch {
Channel chan[2]; Channel chan[2];
bool isMuted[2]; bool isMuted[2];
TIASound tia; TIASound tia;
unsigned char regPool[16];
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
unsigned char dealWithFreq(unsigned char shape, int base, int pitch); unsigned char dealWithFreq(unsigned char shape, int base, int pitch);
@ -46,6 +47,8 @@ class DivPlatformTIA: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -111,6 +111,7 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
QueuedWrite& w=writes.front(); QueuedWrite& w=writes.front();
fm->write(0x0+((w.addr>>8)<<1),w.addr); fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val); fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop(); writes.pop();
delay=4; delay=4;
} }
@ -848,6 +849,14 @@ void* DivPlatformYM2610::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
unsigned char* DivPlatformYM2610::getRegisterPool() {
return regPool;
}
int DivPlatformYM2610::getRegisterPoolSize() {
return 512;
}
void DivPlatformYM2610::poke(unsigned int addr, unsigned short val) { void DivPlatformYM2610::poke(unsigned int addr, unsigned short val) {
immWrite(addr,val); immWrite(addr,val);
} }
@ -858,6 +867,7 @@ void DivPlatformYM2610::poke(std::vector<DivRegWrite>& wlist) {
void DivPlatformYM2610::reset() { void DivPlatformYM2610::reset() {
while (!writes.empty()) writes.pop(); while (!writes.empty()) writes.pop();
memset(regPool,0,512);
if (dumpWrites) { if (dumpWrites) {
addWrite(0xffffffff,0); addWrite(0xffffffff,0);
} }

View file

@ -59,6 +59,7 @@ class DivPlatformYM2610: public DivDispatch {
ymfm::ym2610* fm; ymfm::ym2610* fm;
ymfm::ym2610::output_data fmout; ymfm::ym2610::output_data fmout;
DivYM2610Interface iface; DivYM2610Interface iface;
unsigned char regPool[512];
unsigned char lastBusy; unsigned char lastBusy;
bool dacMode; bool dacMode;
@ -88,6 +89,8 @@ class DivPlatformYM2610: public DivDispatch {
void acquire(short* bufL, short* bufR, size_t start, size_t len); void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset(); void reset();
void forceIns(); void forceIns();
void tick(); void tick();

View file

@ -403,6 +403,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) { SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
stop(); stop();
repeatPattern=false;
setOrder(0); setOrder(0);
isBusy.lock(); isBusy.lock();
double origRate=got.rate; double origRate=got.rate;

View file

@ -154,7 +154,7 @@ bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) {
String FurnaceGUI::encodeKeyMap(std::map<int,int>& map) { String FurnaceGUI::encodeKeyMap(std::map<int,int>& map) {
String ret; String ret;
for (std::map<int,int>::value_type& i: map) { for (std::map<int,int>::value_type& i: map) {
ret+=fmt::printf("%d:%d;",i.first,i.second); ret+=fmt::sprintf("%d:%d;",i.first,i.second);
} }
return ret; return ret;
} }
@ -1383,7 +1383,6 @@ void FurnaceGUI::drawOsc() {
if (!oscOpen) return; if (!oscOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
if (ImGui::Begin("Oscilloscope",&oscOpen)) { if (ImGui::Begin("Oscilloscope",&oscOpen)) {
@ -1397,7 +1396,7 @@ void FurnaceGUI::drawOsc() {
ImGui::PlotLines("##SingleOsc",values,512,0,NULL,-1.0f,1.0f,ImGui::GetContentRegionAvail()); ImGui::PlotLines("##SingleOsc",values,512,0,NULL,-1.0f,1.0f,ImGui::GetContentRegionAvail());
ImGui::EndDisabled(); ImGui::EndDisabled();
} }
ImGui::PopStyleVar(4); ImGui::PopStyleVar(3);
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE; if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE;
ImGui::End(); ImGui::End();
} }
@ -1491,7 +1490,7 @@ void FurnaceGUI::drawVolMeter() {
ImGui::End(); ImGui::End();
} }
const char* aboutLine[57]={ const char* aboutLine[93]={
"tildearrow", "tildearrow",
"is proud to present", "is proud to present",
"", "",
@ -1501,8 +1500,39 @@ const char* aboutLine[57]={
"compatible with DefleMask modules.", "compatible with DefleMask modules.",
"", "",
"zero disassembly.", "zero disassembly.",
"zero reverse-engineering.", "just clean-room design,",
"only time and dedication.", "time and dedication.",
"",
"> CREDITS <",
"",
"-- program --",
"tildearrow",
"",
"-- graphics --",
"tildearrow",
"",
"-- documentation --",
"tildearrow",
"freq-mod",
"nicco1690",
"DeMOSic",
"cam900",
"",
"-- demo songs --",
"0x5066",
"breakthetargets",
"kleeder",
"NikonTeen",
"SuperJet Spade",
"TheDuccinator",
"tildearrow",
"Ultraprogramer",
"",
"-- additional feedback/fixes --",
"fd",
"OPNA2608",
"plane",
"TheEssem",
"", "",
"powered by:", "powered by:",
"Dear ImGui by Omar Cornut", "Dear ImGui by Omar Cornut",
@ -1529,7 +1559,8 @@ const char* aboutLine[57]={
"ILLUMIDARO", "ILLUMIDARO",
"all members of Deflers of Noice!", "all members of Deflers of Noice!",
"", "",
"copyright © 2021-2022 tildearrow.", "copyright © 2021-2022 tildearrow",
"(and contributors).",
"licensed under GPLv2+! see", "licensed under GPLv2+! see",
"LICENSE for more information.", "LICENSE for more information.",
"", "",
@ -1548,7 +1579,11 @@ const char* aboutLine[57]={
"", "",
"it also comes with ABSOLUTELY NO WARRANTY.", "it also comes with ABSOLUTELY NO WARRANTY.",
"", "",
"thanks to all contributors!" "look out for Furnace 0.6 coming somewhere",
"before the equinox with more systems",
"and plenty of other things...",
"",
"thanks to all contributors/bug reporters!"
}; };
void FurnaceGUI::drawAbout() { void FurnaceGUI::drawAbout() {
@ -1590,7 +1625,7 @@ void FurnaceGUI::drawAbout() {
skip=false; skip=false;
skip2=false; skip2=false;
for (int i=(-fmod(160-(aboutSin*2),160))*2; i<scrW; i+=160) { for (int i=(-160+fmod(aboutSin*2,160))*2; i<scrW; i+=160) {
skip2=!skip2; skip2=!skip2;
skip=skip2; skip=skip2;
for (int j=(-240-cos(double(aboutSin*M_PI/300.0))*240.0)*2; j<scrH; j+=160) { for (int j=(-240-cos(double(aboutSin*M_PI/300.0))*240.0)*2; j<scrH; j+=160) {
@ -1600,7 +1635,7 @@ void FurnaceGUI::drawAbout() {
} }
} }
for (int i=0; i<56; i++) { for (int i=0; i<93; i++) {
double posX=(scrW*dpiScale/2.0)+(sin(double(i)*0.5+double(aboutScroll)/90.0)*120*dpiScale)-(ImGui::CalcTextSize(aboutLine[i]).x*0.5); double posX=(scrW*dpiScale/2.0)+(sin(double(i)*0.5+double(aboutScroll)/90.0)*120*dpiScale)-(ImGui::CalcTextSize(aboutLine[i]).x*0.5);
double posY=(scrH-aboutScroll+42*i)*dpiScale; double posY=(scrH-aboutScroll+42*i)*dpiScale;
if (posY<-80*dpiScale || posY>scrH*dpiScale) continue; if (posY<-80*dpiScale || posY>scrH*dpiScale) continue;
@ -1630,7 +1665,7 @@ void FurnaceGUI::drawAbout() {
while (aboutHue>1) aboutHue--; while (aboutHue>1) aboutHue--;
while (aboutSin>=2400) aboutSin-=2400; while (aboutSin>=2400) aboutSin-=2400;
if (aboutScroll>(42*57+scrH)) aboutScroll=-20; if (aboutScroll>(42*93+scrH)) aboutScroll=-20;
} }
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_ABOUT; if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_ABOUT;
ImGui::End(); ImGui::End();
@ -2043,6 +2078,49 @@ void FurnaceGUI::drawChannels() {
ImGui::End(); ImGui::End();
} }
void FurnaceGUI::drawRegView() {
if (nextWindow==GUI_WINDOW_REGISTER_VIEW) {
channelsOpen=true;
ImGui::SetNextWindowFocus();
nextWindow=GUI_WINDOW_NOTHING;
}
if (!regViewOpen) return;
if (ImGui::Begin("Register View",&regViewOpen)) {
for (int i=0; i<e->song.systemLen; i++) {
ImGui::Text("%d. %s",i+1,getSystemName(e->song.system[i]));
int size=0;
unsigned char* regPool=e->getRegisterPool(i,size);
if (regPool==NULL) {
ImGui::Text("- no register pool available");
} else {
ImGui::PushFont(patFont);
if (ImGui::BeginTable("Memory",17)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
for (int i=0; i<16; i++) {
ImGui::TableNextColumn();
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]," %X",i);
}
for (int i=0; i<=((size-1)>>4); i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX],"%.2X",i*16);
for (int j=0; j<16; j++) {
ImGui::TableNextColumn();
if (i*16+j>=size) continue;
ImGui::Text("%.2x",regPool[i*16+j]);
}
}
ImGui::EndTable();
}
ImGui::PopFont();
}
}
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_REGISTER_VIEW;
ImGui::End();
}
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y) { void FurnaceGUI::startSelection(int xCoarse, int xFine, int y) {
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) { if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
curNibble=false; curNibble=false;
@ -2826,6 +2904,7 @@ void FurnaceGUI::doRedo() {
void FurnaceGUI::play(int row) { void FurnaceGUI::play(int row) {
e->walkSong(loopOrder,loopRow,loopEnd); e->walkSong(loopOrder,loopRow,loopEnd);
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
if (row>0) { if (row>0) {
e->playToRow(row); e->playToRow(row);
} else { } else {
@ -3056,6 +3135,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_WINDOW_CHANNELS: case GUI_ACTION_WINDOW_CHANNELS:
nextWindow=GUI_WINDOW_CHANNELS; nextWindow=GUI_WINDOW_CHANNELS;
break; break;
case GUI_ACTION_WINDOW_REGISTER_VIEW:
nextWindow=GUI_WINDOW_REGISTER_VIEW;
break;
case GUI_ACTION_COLLAPSE_WINDOW: case GUI_ACTION_COLLAPSE_WINDOW:
collapseWindow=true; collapseWindow=true;
@ -3125,6 +3207,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_WINDOW_CHANNELS: case GUI_WINDOW_CHANNELS:
channelsOpen=false; channelsOpen=false;
break; break;
case GUI_WINDOW_REGISTER_VIEW:
regViewOpen=false;
break;
default: default:
break; break;
} }
@ -4647,6 +4732,10 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu(); ImGui::EndMenu();
} }
if (ImGui::BeginMenu("settings")) { if (ImGui::BeginMenu("settings")) {
if (ImGui::MenuItem("reset layout")) {
ImGui::LoadIniSettingsFromMemory(defaultLayout);
ImGui::SaveIniSettingsToDisk(finalLayoutPath);
}
if (ImGui::MenuItem("settings...",BIND_FOR(GUI_ACTION_WINDOW_SETTINGS))) { if (ImGui::MenuItem("settings...",BIND_FOR(GUI_ACTION_WINDOW_SETTINGS))) {
syncSettings(); syncSettings();
settingsOpen=true; settingsOpen=true;
@ -4673,6 +4762,7 @@ bool FurnaceGUI::loop() {
if (ImGui::MenuItem("piano/input pad",BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen; if (ImGui::MenuItem("piano/input pad",BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen;
if (ImGui::MenuItem("oscilloscope",BIND_FOR(GUI_ACTION_WINDOW_OSCILLOSCOPE),oscOpen)) oscOpen=!oscOpen; if (ImGui::MenuItem("oscilloscope",BIND_FOR(GUI_ACTION_WINDOW_OSCILLOSCOPE),oscOpen)) oscOpen=!oscOpen;
if (ImGui::MenuItem("volume meter",BIND_FOR(GUI_ACTION_WINDOW_VOL_METER),volMeterOpen)) volMeterOpen=!volMeterOpen; if (ImGui::MenuItem("volume meter",BIND_FOR(GUI_ACTION_WINDOW_VOL_METER),volMeterOpen)) volMeterOpen=!volMeterOpen;
if (ImGui::MenuItem("register view",BIND_FOR(GUI_ACTION_WINDOW_REGISTER_VIEW),regViewOpen)) regViewOpen=!regViewOpen;
if (ImGui::MenuItem("statistics",BIND_FOR(GUI_ACTION_WINDOW_STATS),statsOpen)) statsOpen=!statsOpen; if (ImGui::MenuItem("statistics",BIND_FOR(GUI_ACTION_WINDOW_STATS),statsOpen)) statsOpen=!statsOpen;
ImGui::EndMenu(); ImGui::EndMenu();
@ -4776,6 +4866,7 @@ bool FurnaceGUI::loop() {
drawPiano(); drawPiano();
drawNotes(); drawNotes();
drawChannels(); drawChannels();
drawRegView();
if (ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { if (ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) {
//ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard; //ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard;
@ -5387,6 +5478,7 @@ bool FurnaceGUI::init() {
pianoOpen=e->getConfBool("pianoOpen",false); pianoOpen=e->getConfBool("pianoOpen",false);
notesOpen=e->getConfBool("notesOpen",false); notesOpen=e->getConfBool("notesOpen",false);
channelsOpen=e->getConfBool("channelsOpen",false); channelsOpen=e->getConfBool("channelsOpen",false);
regViewOpen=e->getConfBool("regViewOpen",false);
syncSettings(); syncSettings();
@ -5540,6 +5632,7 @@ bool FurnaceGUI::finish() {
e->setConf("pianoOpen",pianoOpen); e->setConf("pianoOpen",pianoOpen);
e->setConf("notesOpen",notesOpen); e->setConf("notesOpen",notesOpen);
e->setConf("channelsOpen",channelsOpen); e->setConf("channelsOpen",channelsOpen);
e->setConf("regViewOpen",regViewOpen);
// commit last window size // commit last window size
e->setConf("lastWindowWidth",scrW); e->setConf("lastWindowWidth",scrW);
@ -5609,6 +5702,7 @@ FurnaceGUI::FurnaceGUI():
pianoOpen(false), pianoOpen(false),
notesOpen(false), notesOpen(false),
channelsOpen(false), channelsOpen(false),
regViewOpen(false),
selecting(false), selecting(false),
curNibble(false), curNibble(false),
orderNibble(false), orderNibble(false),
@ -5665,6 +5759,7 @@ FurnaceGUI::FurnaceGUI():
oldOrdersLen(0) { oldOrdersLen(0) {
// octave 1 // octave 1
/*
noteKeys[SDL_SCANCODE_Z]=0; noteKeys[SDL_SCANCODE_Z]=0;
noteKeys[SDL_SCANCODE_S]=1; noteKeys[SDL_SCANCODE_S]=1;
noteKeys[SDL_SCANCODE_X]=2; noteKeys[SDL_SCANCODE_X]=2;
@ -5710,6 +5805,7 @@ FurnaceGUI::FurnaceGUI():
// env release // env release
noteKeys[SDL_SCANCODE_GRAVE]=102; noteKeys[SDL_SCANCODE_GRAVE]=102;
*/
// value keys // value keys
valueKeys[SDLK_0]=0; valueKeys[SDLK_0]=0;
@ -5748,4 +5844,5 @@ FurnaceGUI::FurnaceGUI():
memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1)); memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1));
memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1)); memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1));
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
} }

View file

@ -128,6 +128,7 @@ enum FurnaceGUIWindows {
GUI_WINDOW_PIANO, GUI_WINDOW_PIANO,
GUI_WINDOW_NOTES, GUI_WINDOW_NOTES,
GUI_WINDOW_CHANNELS, GUI_WINDOW_CHANNELS,
GUI_WINDOW_REGISTER_VIEW
}; };
enum FurnaceGUIFileDialogs { enum FurnaceGUIFileDialogs {
@ -210,6 +211,7 @@ enum FurnaceGUIActions {
GUI_ACTION_WINDOW_PIANO, GUI_ACTION_WINDOW_PIANO,
GUI_ACTION_WINDOW_NOTES, GUI_ACTION_WINDOW_NOTES,
GUI_ACTION_WINDOW_CHANNELS, GUI_ACTION_WINDOW_CHANNELS,
GUI_ACTION_WINDOW_REGISTER_VIEW,
GUI_ACTION_COLLAPSE_WINDOW, GUI_ACTION_COLLAPSE_WINDOW,
GUI_ACTION_CLOSE_WINDOW, GUI_ACTION_CLOSE_WINDOW,
@ -521,7 +523,7 @@ class FurnaceGUI {
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
bool mixerOpen, debugOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; bool mixerOpen, debugOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
bool pianoOpen, notesOpen, channelsOpen; bool pianoOpen, notesOpen, channelsOpen, regViewOpen;
SelectionPoint selStart, selEnd, cursor; SelectionPoint selStart, selEnd, cursor;
bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders; bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders;
bool collapseWindow, demandScrollX, fancyPattern, wantPatName; bool collapseWindow, demandScrollX, fancyPattern, wantPatName;
@ -568,9 +570,9 @@ class FurnaceGUI {
int samplePreviewNote; int samplePreviewNote;
// SDL_Scancode,int // SDL_Scancode,int
std::map<SDL_Scancode,int> noteKeys; std::map<int,int> noteKeys;
// SDL_Keycode,int // SDL_Keycode,int
std::map<SDL_Keycode,int> valueKeys; std::map<int,int> valueKeys;
int arpMacroScroll; int arpMacroScroll;
@ -621,6 +623,7 @@ class FurnaceGUI {
std::deque<UndoStep> redoHist; std::deque<UndoStep> redoHist;
float keyHit[DIV_MAX_CHANS]; float keyHit[DIV_MAX_CHANS];
int lastIns[DIV_MAX_CHANS];
void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size); void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size);
void drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, const ImVec2& size); void drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, const ImVec2& size);
@ -648,6 +651,7 @@ class FurnaceGUI {
void drawPiano(); void drawPiano();
void drawNotes(); void drawNotes();
void drawChannels(); void drawChannels();
void drawRegView();
void drawAbout(); void drawAbout();
void drawSettings(); void drawSettings();
void drawDebug(); void drawDebug();

View file

@ -480,7 +480,7 @@ void FurnaceGUI::drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r
#define PARAMETER modified=true; e->notifyInsChange(curIns); #define PARAMETER modified=true; e->notifyInsChange(curIns);
#define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax,hoverFunc) \ #define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax,hoverFunc,blockMode) \
ImGui::TableNextRow(); \ ImGui::TableNextRow(); \
ImGui::TableNextColumn(); \ ImGui::TableNextColumn(); \
ImGui::Text("%s",displayName); \ ImGui::Text("%s",displayName); \
@ -517,7 +517,7 @@ void FurnaceGUI::drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r
if (bitfield) { \ if (bitfield) { \
PlotBitfield("##IMacro_" macroName,asInt,totalFit,0,bfVal,macroHeight,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale))); \ PlotBitfield("##IMacro_" macroName,asInt,totalFit,0,bfVal,macroHeight,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale))); \
} else { \ } else { \
PlotCustom("##IMacro_" macroName,asFloat,totalFit,macroDragScroll,NULL,macroDispMin+macroMin,macroHeight+macroDispMin,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale)),sizeof(float),macroColor,macroLen-macroDragScroll,hoverFunc); \ PlotCustom("##IMacro_" macroName,asFloat,totalFit,macroDragScroll,NULL,macroDispMin+macroMin,macroHeight+macroDispMin,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale)),sizeof(float),macroColor,macroLen-macroDragScroll,hoverFunc,blockMode); \
} \ } \
if (displayLoop && ImGui::IsItemClicked(ImGuiMouseButton_Left)) { \ if (displayLoop && ImGui::IsItemClicked(ImGuiMouseButton_Left)) { \
macroDragStart=ImGui::GetItemRectMin(); \ macroDragStart=ImGui::GetItemRectMin(); \
@ -779,15 +779,15 @@ void FurnaceGUI::drawInsEdit() {
} }
if (ImGui::BeginTabItem("Macros (FM)")) { if (ImGui::BeginTabItem("Macros (FM)")) {
MACRO_BEGIN(0); MACRO_BEGIN(0);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7,NULL); NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7,NULL,false);
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7,NULL); NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7,NULL,false);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7,NULL); NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7,NULL,false);
NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3,NULL); NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3,NULL,false);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127,NULL); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127,NULL,false);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127,NULL); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127,NULL,false);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255,NULL); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255,NULL,false);
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3,&macroLFOWaves); NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3,&macroLFOWaves,false);
MACRO_END; MACRO_END;
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
@ -1018,47 +1018,47 @@ void FurnaceGUI::drawInsEdit() {
if (settings.macroView==0) { // modern view if (settings.macroView==0) { // modern view
MACRO_BEGIN(28*dpiScale); MACRO_BEGIN(28*dpiScale);
if (volMax>0) { if (volMax>0) {
NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax,NULL); NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax,NULL,false);
} }
NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94,(ins->std.arpMacroMode?(&macroHoverNote):NULL)); NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94,(ins->std.arpMacroMode?(&macroHoverNote):NULL),true);
if (dutyMax>0) { if (dutyMax>0) {
if (ins->type == DIV_INS_MIKEY) { if (ins->type == DIV_INS_MIKEY) {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,true,mikeyFeedbackBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL); NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,true,mikeyFeedbackBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL,false);
} }
else { else {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL); NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL,false);
} }
} }
if (waveMax>0) { if (waveMax>0) {
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL); NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL,false);
} }
if (ex1Max>0) { if (ex1Max>0) {
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else if (ins->type==DIV_INS_SAA1099) { } else if (ins->type==DIV_INS_SAA1099) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else { } else {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL); NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} }
} }
if (ex2Max>0) { if (ex2Max>0) {
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} else { } else {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL); NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} }
} }
if (ins->type==DIV_INS_C64) { if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL,false);
} }
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) { if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL); NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL,false);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15,NULL); NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15,NULL,false);
} }
if (ins->type==DIV_INS_AY8930) { if (ins->type==DIV_INS_AY8930) {
// oh my i am running out of macros // oh my i am running out of macros
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8,NULL); NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8,NULL,false);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8,NULL); NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8,NULL,false);
} }
MACRO_END; MACRO_END;

View file

@ -86,6 +86,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (i<0 || i>=e->song.patLen) { if (i<0 || i>=e->song.patLen) {
return; return;
} }
bool isPushing=false;
// check overflow highlight // check overflow highlight
if (settings.overflowHighlight) { if (settings.overflowHighlight) {
if (edit && cursor.y==i) { if (edit && cursor.y==i) {
@ -97,6 +98,19 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) { } else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1])); ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
} }
} else {
isPushing=true;
if (edit && cursor.y==i) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::PushStyleColor(ImGuiCol_Header,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
} else {
isPushing=false;
}
} }
// row number // row number
if (settings.patRowsBase==1) { if (settings.patRowsBase==1) {
@ -117,19 +131,6 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
ImGui::TableNextColumn(); ImGui::TableNextColumn();
patChanX[j]=ImGui::GetCursorPosX(); patChanX[j]=ImGui::GetCursorPosX();
// check overflow highlight
if (!settings.overflowHighlight) {
if (edit && cursor.y==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
}
// selection highlight flags // selection highlight flags
int sel1XSum=sel1.xCoarse*32+sel1.xFine; int sel1XSum=sel1.xCoarse*32+sel1.xFine;
int sel2XSum=sel2.xCoarse*32+sel2.xFine; int sel2XSum=sel2.xCoarse*32+sel2.xFine;
@ -141,6 +142,8 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
bool cursorIns=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==1); bool cursorIns=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==1);
bool cursorVol=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==2); bool cursorVol=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==2);
// note // note
sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j); sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j);
if (pat->data[i][0]==0 && pat->data[i][1]==0) { if (pat->data[i][0]==0 && pat->data[i][1]==0) {
@ -156,7 +159,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX(); demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} else { } else {
ImGui::Selectable(id,selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars); if (selectedNote) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedNote) ImGui::PopStyleColor();
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(j,0,i); startSelection(j,0,i);
@ -185,7 +190,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX(); demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} else { } else {
ImGui::Selectable(id,selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); if (selectedIns) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedIns) ImGui::PopStyleColor();
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(j,1,i); startSelection(j,1,i);
@ -215,7 +222,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX(); demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} else { } else {
ImGui::Selectable(id,selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); if (selectedVol) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedVol) ImGui::PopStyleColor();
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(j,2,i); startSelection(j,2,i);
@ -268,7 +277,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX(); demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} else { } else {
ImGui::Selectable(id,selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); if (selectedEffect) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffect) ImGui::PopStyleColor();
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(j,index-1,i); startSelection(j,index-1,i);
@ -292,7 +303,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX(); demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3); ImGui::PopStyleColor(3);
} else { } else {
ImGui::Selectable(id,selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars); if (selectedEffectVal) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffectVal) ImGui::PopStyleColor();
} }
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
startSelection(j,index,i); startSelection(j,index,i);
@ -304,6 +317,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
} }
} }
} }
if (isPushing) {
ImGui::PopStyleColor();
}
ImGui::TableNextColumn(); ImGui::TableNextColumn();
patChanX[chans]=ImGui::GetCursorPosX(); patChanX[chans]=ImGui::GetCursorPosX();
} }
@ -315,6 +331,9 @@ void FurnaceGUI::drawPattern() {
nextWindow=GUI_WINDOW_NOTHING; nextWindow=GUI_WINDOW_NOTHING;
} }
if (!patternOpen) return; if (!patternOpen) return;
float scrollX=0;
if (e->isPlaying() && followPattern) cursor.y=oldRow; if (e->isPlaying() && followPattern) cursor.y=oldRow;
demandX=0; demandX=0;
sel1=selStart; sel1=selStart;
@ -381,6 +400,15 @@ void FurnaceGUI::drawPattern() {
if (ImGui::Selectable((extraChannelButtons==2)?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { if (ImGui::Selectable((extraChannelButtons==2)?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) {
if (++extraChannelButtons>2) extraChannelButtons=0; if (++extraChannelButtons>2) extraChannelButtons=0;
} }
if (ImGui::IsItemHovered()) {
if (extraChannelButtons==2) {
ImGui::SetTooltip("Pattern names (click to collapse)\nRight-click for visualizer");
} else if (extraChannelButtons==1) {
ImGui::SetTooltip("Expanded (click for pattern names)\nRight-click for visualizer");
} else {
ImGui::SetTooltip("Compact (click to expand)\nRight-click for visualizer");
}
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
fancyPattern=!fancyPattern; fancyPattern=!fancyPattern;
e->enableCommandStream(fancyPattern); e->enableCommandStream(fancyPattern);
@ -428,7 +456,6 @@ void FurnaceGUI::drawPattern() {
ImGui::PushStyleColor(ImGuiCol_Header,chanHead); ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive); ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover); ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
// help me why is the color leakingggggggg
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead)); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]); if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale)); ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
@ -554,6 +581,7 @@ void FurnaceGUI::drawPattern() {
} }
demandScrollX=false; demandScrollX=false;
} }
scrollX=ImGui::GetScrollX();
ImGui::EndTable(); ImGui::EndTable();
} }
@ -569,7 +597,6 @@ void FurnaceGUI::drawPattern() {
//if (i.cmd==DIV_CMD_NOTE_ON) continue; //if (i.cmd==DIV_CMD_NOTE_ON) continue;
if (i.cmd==DIV_CMD_PRE_PORTA) continue; if (i.cmd==DIV_CMD_PRE_PORTA) continue;
if (i.cmd==DIV_CMD_PRE_NOTE) continue; if (i.cmd==DIV_CMD_PRE_NOTE) continue;
if (i.cmd==DIV_CMD_INSTRUMENT) continue;
if (i.cmd==DIV_CMD_SAMPLE_BANK) continue; if (i.cmd==DIV_CMD_SAMPLE_BANK) continue;
if (i.cmd==DIV_CMD_GET_VOLUME) continue; if (i.cmd==DIV_CMD_GET_VOLUME) continue;
if (i.cmd==DIV_ALWAYS_SET_VOLUME) continue; if (i.cmd==DIV_ALWAYS_SET_VOLUME) continue;
@ -589,8 +616,8 @@ void FurnaceGUI::drawPattern() {
switch (i.cmd) { switch (i.cmd) {
case DIV_CMD_NOTE_ON: case DIV_CMD_NOTE_ON:
partIcon=ICON_FA_ASTERISK; partIcon=ICON_FA_ASTERISK;
life=64.0f; life=96.0f;
lifeSpeed=2.0f; lifeSpeed=3.0f;
break; break;
case DIV_CMD_LEGATO: case DIV_CMD_LEGATO:
partIcon=ICON_FA_COG; partIcon=ICON_FA_COG;
@ -618,6 +645,23 @@ void FurnaceGUI::drawPattern() {
color=volGrad; color=volGrad;
break; break;
} }
case DIV_CMD_INSTRUMENT: {
if (lastIns[i.chan]==i.value) {
num=0;
break;
}
lastIns[i.chan]=i.value;
speedX=0.0f;
speedY=0.0f;
grav=0.0f;
frict=0.98;
spread=30.0f;
life=128.0f;
lifeSpeed=6.0f;
color=insGrad;
num=7+pow(i.value,0.6);
break;
}
case DIV_CMD_PANNING: { case DIV_CMD_PANNING: {
if (i.value==0) { if (i.value==0) {
num=0; num=0;
@ -661,7 +705,7 @@ void FurnaceGUI::drawPattern() {
particles.push_back(Particle( particles.push_back(Particle(
color, color,
partIcon, partIcon,
off.x+patChanX[i.chan]+fmod(rand(),width), off.x+patChanX[i.chan]+fmod(rand(),width)-scrollX,
off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize), off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize),
(speedX+randRange(-spread,spread))*0.5*dpiScale, (speedX+randRange(-spread,spread))*0.5*dpiScale,
(speedY+randRange(-spread,spread))*0.5*dpiScale, (speedY+randRange(-spread,spread))*0.5*dpiScale,
@ -675,31 +719,30 @@ void FurnaceGUI::drawPattern() {
// note slides // note slides
ImVec2 arrowPoints[7]; ImVec2 arrowPoints[7];
for (int i=0; i<chans; i++) { if (e->isPlaying()) for (int i=0; i<chans; i++) {
if (!e->song.chanShow[i]) continue;
DivChannelState* ch=e->getChanState(i); DivChannelState* ch=e->getChanState(i);
if (ch->portaSpeed>0) { if (ch->portaSpeed>0) {
ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH]; ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH];
col.w*=0.2; col.w*=0.2;
float width=patChanX[i+1]-patChanX[i]; float width=patChanX[i+1]-patChanX[i];
if (e->isPlaying()) { particles.push_back(Particle(
particles.push_back(Particle( pitchGrad,
pitchGrad, (ch->portaNote<=ch->note)?ICON_FA_CHEVRON_DOWN:ICON_FA_CHEVRON_UP,
(ch->portaNote<=ch->note)?ICON_FA_CHEVRON_DOWN:ICON_FA_CHEVRON_UP, off.x+patChanX[i]+fmod(rand(),width)-scrollX,
off.x+patChanX[i]+fmod(rand(),width), off.y+fmod(rand(),MAX(1,ImGui::GetWindowHeight())),
off.y+fmod(rand(),MAX(1,ImGui::GetWindowHeight())), 0.0f,
0.0f, (7.0f+(rand()%5)+pow(ch->portaSpeed,0.7f))*((ch->portaNote<=ch->note)?1:-1),
(7.0f+(rand()%5)+pow(ch->portaSpeed,0.7f))*((ch->portaNote<=ch->note)?1:-1), 0.0f,
0.0f, 1.0f,
1.0f, 255.0f,
255.0f, 15.0f
15.0f ));
));
}
for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) { if (width>0.1) for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) {
ImVec2 tMin=ImVec2(off.x+patChanX[i],off.y+j); ImVec2 tMin=ImVec2(off.x+patChanX[i]-scrollX,off.y+j);
ImVec2 tMax=ImVec2(off.x+patChanX[i+1],off.y+j+width*0.6); ImVec2 tMax=ImVec2(off.x+patChanX[i+1]-scrollX,off.y+j+width*0.6);
if (ch->portaNote<=ch->note) { if (ch->portaNote<=ch->note) {
arrowPoints[0]=ImLerp(tMin,tMax,ImVec2(0.1,1.0-0.8)); arrowPoints[0]=ImLerp(tMin,tMax,ImVec2(0.1,1.0-0.8));
arrowPoints[1]=ImLerp(tMin,tMax,ImVec2(0.5,1.0-0.0)); arrowPoints[1]=ImLerp(tMin,tMax,ImVec2(0.5,1.0-0.0));

View file

@ -289,7 +289,7 @@ void PlotBitfield(const char* label, const int* values, int values_count, int va
PlotBitfieldEx(label, &Plot_IntArrayGetter, (void*)&data, values_count, values_offset, overlay_text, bits, graph_size); PlotBitfieldEx(label, &Plot_IntArrayGetter, (void*)&data, values_count, values_offset, overlay_text, bits, graph_size);
} }
int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_display_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float)) int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_display_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float), bool blockMode)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = ImGui::GetCurrentWindow(); ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -384,6 +384,10 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
bgColor); bgColor);
} }
if (blockMode) {
window->DrawList->AddLine(ImLerp(inner_bb.Min,inner_bb.Max,ImVec2(0.0f,histogram_zero_line_t)),ImLerp(inner_bb.Min,inner_bb.Max,ImVec2(1.0f,histogram_zero_line_t)),col_base);
}
for (int n = 0; n < res_w; n++) for (int n = 0; n < res_w; n++)
{ {
const float t1 = t0 + t_step; const float t1 = t0 + t_step;
@ -394,7 +398,7 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
// NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t)); ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, blockMode?tp0.y:histogram_zero_line_t));
if (plot_type == ImGuiPlotType_Lines) if (plot_type == ImGuiPlotType_Lines)
{ {
window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
@ -403,6 +407,10 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
{ {
if (pos1.x >= pos0.x + 2.0f) if (pos1.x >= pos0.x + 2.0f)
pos1.x -= 1.0f; pos1.x -= 1.0f;
if (blockMode) {
pos0.y-=(inner_bb.Max.y-inner_bb.Min.y)*inv_scale;
//pos1.y+=1.0f;
}
window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base); window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
} }
@ -423,8 +431,8 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
return idx_hovered; return idx_hovered;
} }
void PlotCustom(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float)) void PlotCustom(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float), bool blockMode)
{ {
FurnacePlotArrayGetterData data(values, stride); FurnacePlotArrayGetterData data(values, stride);
PlotCustomEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, color, highlight, hoverFunc); PlotCustomEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, color, highlight, hoverFunc, blockMode);
} }

View file

@ -22,4 +22,4 @@
void PlotNoLerp(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); void PlotNoLerp(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
void PlotBitfield(const char* label, const int* values, int values_count, int values_offset = 0, const char** overlay_text = NULL, int bits = 8, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float)); void PlotBitfield(const char* label, const int* values, int values_count, int values_offset = 0, const char** overlay_text = NULL, int bits = 8, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
void PlotCustom(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float), ImVec4 fgColor = ImVec4(1.0f,1.0f,1.0f,1.0f), int highlight = 0, std::string (*hoverFunc)(int,float) = NULL); void PlotCustom(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float), ImVec4 fgColor = ImVec4(1.0f,1.0f,1.0f,1.0f), int highlight = 0, std::string (*hoverFunc)(int,float) = NULL, bool blockMode=false);

View file

@ -22,7 +22,9 @@
#include "util.h" #include "util.h"
#include "IconsFontAwesome4.h" #include "IconsFontAwesome4.h"
#include "misc/cpp/imgui_stdlib.h" #include "misc/cpp/imgui_stdlib.h"
#include <SDL_scancode.h>
#include <fmt/printf.h> #include <fmt/printf.h>
#include <imgui.h>
#ifdef __APPLE__ #ifdef __APPLE__
#define FURKMOD_CMD FURKMOD_META #define FURKMOD_CMD FURKMOD_META
@ -30,6 +32,8 @@
#define FURKMOD_CMD FURKMOD_CTRL #define FURKMOD_CMD FURKMOD_CTRL
#endif #endif
#define DEFAULT_NOTE_KEYS "5:7;6:4;7:3;8:16;10:6;11:8;12:24;13:10;16:11;17:9;18:26;19:28;20:12;21:17;22:1;23:19;24:23;25:5;26:14;27:2;28:21;29:0;30:100;31:13;32:15;34:18;35:20;36:22;38:25;39:27;43:100;46:101;47:29;48:31;53:102;"
const char* mainFonts[]={ const char* mainFonts[]={
"IBM Plex Sans", "IBM Plex Sans",
"Liberation Sans", "Liberation Sans",
@ -113,6 +117,15 @@ void FurnaceGUI::promptKey(int which) {
actionKeys[which]=0; actionKeys[which]=0;
} }
struct MappedInput {
int scan;
int val;
MappedInput():
scan(SDL_SCANCODE_UNKNOWN), val(0) {}
MappedInput(int s, int v):
scan(s), val(v) {}
};
void FurnaceGUI::drawSettings() { void FurnaceGUI::drawSettings() {
if (nextWindow==GUI_WINDOW_SETTINGS) { if (nextWindow==GUI_WINDOW_SETTINGS) {
settingsOpen=true; settingsOpen=true;
@ -564,6 +577,7 @@ void FurnaceGUI::drawSettings() {
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO,"Piano"); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO,"Piano");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES,"Song Comments"); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES,"Song Comments");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHANNELS,"Channels"); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHANNELS,"Channels");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_REGISTER_VIEW,"Register View");
UI_KEYBIND_CONFIG(GUI_ACTION_COLLAPSE_WINDOW,"Collapse/expand current window"); UI_KEYBIND_CONFIG(GUI_ACTION_COLLAPSE_WINDOW,"Collapse/expand current window");
UI_KEYBIND_CONFIG(GUI_ACTION_CLOSE_WINDOW,"Close current window"); UI_KEYBIND_CONFIG(GUI_ACTION_CLOSE_WINDOW,"Close current window");
@ -571,6 +585,89 @@ void FurnaceGUI::drawSettings() {
KEYBIND_CONFIG_END; KEYBIND_CONFIG_END;
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Note input")) {
std::vector<MappedInput> sorted;
if (ImGui::BeginTable("keysNoteInput",4)) {
for (std::map<int,int>::value_type& i: noteKeys) {
std::vector<MappedInput>::iterator j;
for (j=sorted.begin(); j!=sorted.end(); j++) {
if (j->val>i.second) {
break;
}
}
sorted.insert(j,MappedInput(i.first,i.second));
}
static char id[4096];
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::Text("Key");
ImGui::TableNextColumn();
ImGui::Text("Type");
ImGui::TableNextColumn();
ImGui::Text("Value");
ImGui::TableNextColumn();
ImGui::Text("Remove");
for (MappedInput& i: sorted) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s",SDL_GetScancodeName((SDL_Scancode)i.scan));
ImGui::TableNextColumn();
if (i.val==102) {
snprintf(id,4095,"Envelope release##SNType_%d",i.scan);
if (ImGui::Button(id)) {
noteKeys[i.scan]=0;
}
} else if (i.val==101) {
snprintf(id,4095,"Note release##SNType_%d",i.scan);
if (ImGui::Button(id)) {
noteKeys[i.scan]=102;
}
} else if (i.val==100) {
snprintf(id,4095,"Note off##SNType_%d",i.scan);
if (ImGui::Button(id)) {
noteKeys[i.scan]=101;
}
} else {
snprintf(id,4095,"Note##SNType_%d",i.scan);
if (ImGui::Button(id)) {
noteKeys[i.scan]=100;
}
}
ImGui::TableNextColumn();
if (i.val<100) {
snprintf(id,4095,"##SNValue_%d",i.scan);
if (ImGui::InputInt(id,&i.val,1,1)) {
if (i.val<0) i.val=0;
if (i.val>96) i.val=96;
noteKeys[i.scan]=i.val;
}
}
ImGui::TableNextColumn();
snprintf(id,4095,ICON_FA_TIMES "##SNRemove_%d",i.scan);
if (ImGui::Button(id)) {
noteKeys.erase(i.scan);
}
}
ImGui::EndTable();
if (ImGui::BeginCombo("##SNAddNew","Add...")) {
for (int i=0; i<SDL_NUM_SCANCODES; i++) {
const char* sName=SDL_GetScancodeName((SDL_Scancode)i);
if (sName==NULL) continue;
if (sName[0]==0) continue;
snprintf(id,4095,"%s##SNNewKey_%d",sName,i);
if (ImGui::Selectable(id)) {
noteKeys[(SDL_Scancode)i]=0;
}
}
ImGui::EndCombo();
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Pattern")) { if (ImGui::TreeNode("Pattern")) {
KEYBIND_CONFIG_BEGIN("keysPattern"); KEYBIND_CONFIG_BEGIN("keysPattern");
@ -806,6 +903,7 @@ void FurnaceGUI::syncSettings() {
LOAD_KEYBIND(GUI_ACTION_WINDOW_PIANO,0); LOAD_KEYBIND(GUI_ACTION_WINDOW_PIANO,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_NOTES,0); LOAD_KEYBIND(GUI_ACTION_WINDOW_NOTES,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_CHANNELS,0); LOAD_KEYBIND(GUI_ACTION_WINDOW_CHANNELS,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_REGISTER_VIEW,0);
LOAD_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW,0); LOAD_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW,0);
LOAD_KEYBIND(GUI_ACTION_CLOSE_WINDOW,FURKMOD_SHIFT|SDLK_ESCAPE); LOAD_KEYBIND(GUI_ACTION_CLOSE_WINDOW,FURKMOD_SHIFT|SDLK_ESCAPE);
@ -907,6 +1005,8 @@ void FurnaceGUI::syncSettings() {
LOAD_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN,FURKMOD_SHIFT|SDLK_DOWN); LOAD_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN,FURKMOD_SHIFT|SDLK_DOWN);
LOAD_KEYBIND(GUI_ACTION_ORDERS_REPLAY,0); LOAD_KEYBIND(GUI_ACTION_ORDERS_REPLAY,0);
decodeKeyMap(noteKeys,e->getConfString("noteKeys",DEFAULT_NOTE_KEYS));
parseKeybinds(); parseKeybinds();
} }
@ -1072,6 +1172,7 @@ void FurnaceGUI::commitSettings() {
SAVE_KEYBIND(GUI_ACTION_WINDOW_PIANO); SAVE_KEYBIND(GUI_ACTION_WINDOW_PIANO);
SAVE_KEYBIND(GUI_ACTION_WINDOW_NOTES); SAVE_KEYBIND(GUI_ACTION_WINDOW_NOTES);
SAVE_KEYBIND(GUI_ACTION_WINDOW_CHANNELS); SAVE_KEYBIND(GUI_ACTION_WINDOW_CHANNELS);
SAVE_KEYBIND(GUI_ACTION_WINDOW_REGISTER_VIEW);
SAVE_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW); SAVE_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW);
SAVE_KEYBIND(GUI_ACTION_CLOSE_WINDOW); SAVE_KEYBIND(GUI_ACTION_CLOSE_WINDOW);
@ -1173,6 +1274,8 @@ void FurnaceGUI::commitSettings() {
SAVE_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN); SAVE_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN);
SAVE_KEYBIND(GUI_ACTION_ORDERS_REPLAY); SAVE_KEYBIND(GUI_ACTION_ORDERS_REPLAY);
e->setConf("noteKeys",encodeKeyMap(noteKeys));
e->saveConf(); e->saveConf();
if (!e->switchMaster()) { if (!e->switchMaster()) {