mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-15 17:25:06 +00:00
Merge branch 'master' of git://github.com/tildearrow/furnace into tildearrow-master
# Conflicts: # src/gui/insEdit.cpp
This commit is contained in:
commit
79e53cfd10
38 changed files with 537 additions and 98 deletions
BIN
demos/Ice_Wind_OPMSPCM.fur
Normal file
BIN
demos/Ice_Wind_OPMSPCM.fur
Normal file
Binary file not shown.
BIN
demos/Jet_Pack_Adventure_GBAesque.fur
Normal file
BIN
demos/Jet_Pack_Adventure_GBAesque.fur
Normal file
Binary file not shown.
BIN
demos/Tubelectric_Fictional_Arcade.fur
Normal file
BIN
demos/Tubelectric_Fictional_Arcade.fur
Normal file
Binary file not shown.
|
@ -208,13 +208,25 @@ class DivDispatch {
|
|||
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!
|
||||
*/
|
||||
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,
|
||||
* or NULL if this dispatch does not support state saves.
|
||||
*/
|
||||
|
|
|
@ -400,6 +400,7 @@ bool DivEngine::saveAudio(const char* path, int loops, DivAudioExportModes mode)
|
|||
exportMode=mode;
|
||||
exporting=true;
|
||||
stop();
|
||||
repeatPattern=false;
|
||||
setOrder(0);
|
||||
remainingLoops=loops;
|
||||
exportThread=new std::thread(_runExportThread,this);
|
||||
|
@ -548,9 +549,9 @@ void DivEngine::renderSamples() {
|
|||
if (diff>=tempstep) encoded|=1;
|
||||
|
||||
acc+=jediTable[decstep+encoded];
|
||||
if (acc>0x7ff || acc<-0x800) {
|
||||
/*if (acc>0x7ff || acc<-0x800) {
|
||||
logW("clipping! %d\n",acc);
|
||||
}
|
||||
}*/
|
||||
acc&=0xfff;
|
||||
if (acc&0x800) acc|=~0xfff;
|
||||
decstep+=adStepSeek[encoded&7]*16;
|
||||
|
@ -728,6 +729,13 @@ void* DivEngine::getDispatchChanState(int 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) {
|
||||
cmdStreamEnabled=enable;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
warnings+=(String("\n")+x); \
|
||||
}
|
||||
|
||||
#define DIV_VERSION "0.5.7pre4"
|
||||
#define DIV_ENGINE_VERSION 52
|
||||
#define DIV_VERSION "0.5.7"
|
||||
#define DIV_ENGINE_VERSION 53
|
||||
|
||||
enum DivStatusView {
|
||||
DIV_STATUS_NOTHING=0,
|
||||
|
@ -530,6 +530,9 @@ class DivEngine {
|
|||
// get dispatch channel state
|
||||
void* getDispatchChanState(int chan);
|
||||
|
||||
// get register pool
|
||||
unsigned char* getRegisterPool(int sys, int& size);
|
||||
|
||||
// enable command stream dumping
|
||||
void enableCommandStream(bool enable);
|
||||
|
||||
|
|
|
@ -135,6 +135,12 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
ds.brokenShortcutSlides=false;
|
||||
ds.ignoreDuplicateSlides=true;
|
||||
|
||||
// 1.1 compat flags
|
||||
if (ds.version>24) {
|
||||
ds.waveDutyIsVol=true;
|
||||
ds.legacyVolumeSlides=false;
|
||||
}
|
||||
|
||||
// Neo Geo detune
|
||||
if (ds.system[0]==DIV_SYSTEM_YM2610 || ds.system[0]==DIV_SYSTEM_YM2610_EXT) {
|
||||
ds.tuning=443.23;
|
||||
|
|
|
@ -29,6 +29,14 @@ void* DivDispatch::getChanState(int chan) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char* DivDispatch::getRegisterPool() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int DivDispatch::getRegisterPoolSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* DivDispatch::getState() {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -145,6 +145,7 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si
|
|||
QueuedWrite& w=writes.front();
|
||||
if (w.addrOrVal) {
|
||||
OPM_Write(&fm,1,w.val);
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
//printf("write: %x = %.2x\n",w.addr,w.val);
|
||||
writes.pop();
|
||||
} else {
|
||||
|
@ -216,6 +217,7 @@ void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, siz
|
|||
QueuedWrite& w=writes.front();
|
||||
fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0xff]=w.val;
|
||||
writes.pop();
|
||||
delay=1;
|
||||
}
|
||||
|
@ -877,6 +879,14 @@ void* DivPlatformArcade::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformArcade::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformArcade::getRegisterPoolSize() {
|
||||
return 256;
|
||||
}
|
||||
|
||||
void DivPlatformArcade::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
@ -887,6 +897,7 @@ void DivPlatformArcade::poke(std::vector<DivRegWrite>& wlist) {
|
|||
|
||||
void DivPlatformArcade::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,256);
|
||||
if (useYMFM) {
|
||||
fm_ymfm->reset();
|
||||
} else {
|
||||
|
|
|
@ -71,6 +71,8 @@ class DivPlatformArcade: public DivDispatch {
|
|||
ymfm::ym2151::output_data out_ymfm;
|
||||
DivArcadeInterface iface;
|
||||
|
||||
unsigned char regPool[256];
|
||||
|
||||
bool extMode, useYMFM;
|
||||
|
||||
bool isMuted[13];
|
||||
|
@ -90,6 +92,8 @@ class DivPlatformArcade: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -94,6 +94,7 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
QueuedWrite w=writes.front();
|
||||
ay->address_w(w.addr);
|
||||
ay->data_w(w.val);
|
||||
regPool[w.addr&0x0f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
ay->sound_stream_update(ayBuf,len);
|
||||
|
@ -400,9 +401,18 @@ void* DivPlatformAY8910::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformAY8910::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformAY8910::getRegisterPoolSize() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
ay->device_reset();
|
||||
memset(regPool,0,16);
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i]=DivPlatformAY8910::Channel();
|
||||
chan[i].vol=0x0f;
|
||||
|
|
|
@ -47,6 +47,7 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
};
|
||||
std::queue<QueuedWrite> writes;
|
||||
ay8910_device* ay;
|
||||
unsigned char regPool[16];
|
||||
unsigned char lastBusy;
|
||||
|
||||
bool dacMode;
|
||||
|
@ -76,6 +77,8 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -124,6 +124,7 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
} else {
|
||||
ay->data_w(w.val);
|
||||
}
|
||||
regPool[w.addr&0x1f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
ay->sound_stream_update(ayBuf,len);
|
||||
|
@ -462,9 +463,18 @@ void* DivPlatformAY8930::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformAY8930::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformAY8930::getRegisterPoolSize() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
ay->device_reset();
|
||||
memset(regPool,0,32);
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i]=DivPlatformAY8930::Channel();
|
||||
chan[i].vol=31;
|
||||
|
|
|
@ -47,6 +47,7 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
};
|
||||
std::queue<QueuedWrite> writes;
|
||||
ay8930_device* ay;
|
||||
unsigned char regPool[32];
|
||||
unsigned char ayNoiseAnd, ayNoiseOr;
|
||||
bool bank;
|
||||
|
||||
|
@ -69,6 +70,8 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "../engine.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
|
||||
|
||||
|
@ -467,12 +467,21 @@ void* DivPlatformC64::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformC64::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformC64::getRegisterPoolSize() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
void DivPlatformC64::reset() {
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i]=DivPlatformC64::Channel();
|
||||
}
|
||||
|
||||
sid.reset();
|
||||
memset(regPool,0,32);
|
||||
|
||||
rWrite(0x18,0x0f);
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
int filtCut, resetTime;
|
||||
|
||||
SID sid;
|
||||
unsigned char regPool[32];
|
||||
|
||||
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);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include "../engine.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {GB_apu_write(gb,a,v); if (dumpWrites) {addWrite(a,v);} }
|
||||
#define immWrite(a,v) {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); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
|
||||
|
||||
#define CHIP_DIVIDER 16
|
||||
|
||||
|
@ -395,6 +395,14 @@ void* DivPlatformGB::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformGB::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformGB::getRegisterPoolSize() {
|
||||
return 64;
|
||||
}
|
||||
|
||||
void DivPlatformGB::reset() {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i]=DivPlatformGB::Channel();
|
||||
|
@ -403,6 +411,7 @@ void DivPlatformGB::reset() {
|
|||
addWrite(0xffffffff,0);
|
||||
}
|
||||
memset(gb,0,sizeof(GB_gameboy_t));
|
||||
memset(regPool,0,128);
|
||||
gb->model=GB_MODEL_DMG_B;
|
||||
GB_apu_init(gb);
|
||||
GB_set_sample_rate(gb,rate);
|
||||
|
|
|
@ -55,6 +55,8 @@ class DivPlatformGB: public DivDispatch {
|
|||
unsigned char lastPan;
|
||||
|
||||
GB_gameboy_t* gb;
|
||||
unsigned char regPool[128];
|
||||
|
||||
unsigned char procMute();
|
||||
void updateWave();
|
||||
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);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -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);
|
||||
//printf("write: %x = %.2x\n",w.addr,w.val);
|
||||
lastBusy=0;
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop();
|
||||
} else {
|
||||
lastBusy++;
|
||||
|
@ -190,6 +191,7 @@ void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, si
|
|||
QueuedWrite& w=writes.front();
|
||||
fm_ymfm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm_ymfm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop();
|
||||
lastBusy=1;
|
||||
}
|
||||
|
@ -805,8 +807,17 @@ void* DivPlatformGenesis::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformGenesis::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformGenesis::getRegisterPoolSize() {
|
||||
return 512;
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,512);
|
||||
if (useYMFM) {
|
||||
fm_ymfm->reset();
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
ymfm::ym2612* fm_ymfm;
|
||||
ymfm::ym2612::output_data out_ymfm;
|
||||
DivYM2612Interface iface;
|
||||
unsigned char regPool[512];
|
||||
|
||||
bool dacMode;
|
||||
int dacPeriod;
|
||||
|
@ -106,6 +107,8 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#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[]={
|
||||
"S0Volume", "4000",
|
||||
|
@ -444,6 +444,14 @@ void* DivPlatformNES::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformNES::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformNES::getRegisterPoolSize() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
void DivPlatformNES::reset() {
|
||||
for (int i=0; i<5; i++) {
|
||||
chan[i]=DivPlatformNES::Channel();
|
||||
|
@ -459,6 +467,7 @@ void DivPlatformNES::reset() {
|
|||
sampleBank=0;
|
||||
|
||||
apu_turn_on(nes,apuType);
|
||||
memset(regPool,0,128);
|
||||
nes->apu.cpu_cycles=0;
|
||||
nes->apu.cpu_opcode_cycle=0;
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ class DivPlatformNES: public DivDispatch {
|
|||
unsigned char sampleBank;
|
||||
unsigned char apuType;
|
||||
struct NESAPU* nes;
|
||||
unsigned char regPool[128];
|
||||
|
||||
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);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
curChan=c; \
|
||||
rWrite(0,curChan); \
|
||||
} \
|
||||
regPool[16+((c)<<4)+((a)&0x0f)]=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);
|
||||
if (s->depth==8) {
|
||||
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 {
|
||||
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 (s->loopStart>=0 && s->loopStart<=(int)s->rendLength) {
|
||||
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) {
|
||||
QueuedWrite w=writes.front();
|
||||
pce->Write(cycles,w.addr,w.val);
|
||||
regPool[w.addr&0x0f]=w.val;
|
||||
//cycles+=2;
|
||||
writes.pop();
|
||||
}
|
||||
|
@ -442,8 +445,17 @@ void* DivPlatformPCE::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformPCE::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformPCE::getRegisterPoolSize() {
|
||||
return 112;
|
||||
}
|
||||
|
||||
void DivPlatformPCE::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,128);
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i]=DivPlatformPCE::Channel();
|
||||
}
|
||||
|
|
|
@ -74,12 +74,15 @@ class DivPlatformPCE: public DivDispatch {
|
|||
int tempR[32];
|
||||
unsigned char sampleBank, lfoMode, lfoSpeed;
|
||||
PCE_PSG* pce;
|
||||
unsigned char regPool[128];
|
||||
void updateWave(int ch);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -83,6 +83,7 @@ void DivPlatformSAA1099::acquire_mame(short* bufL, short* bufR, size_t start, si
|
|||
QueuedWrite w=writes.front();
|
||||
saa.control_w(w.addr);
|
||||
saa.data_w(w.val);
|
||||
regPool[w.addr&0x1f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
saa.sound_stream_update(saaBuf,len);
|
||||
|
@ -103,6 +104,7 @@ void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start
|
|||
while (!writes.empty()) {
|
||||
QueuedWrite w=writes.front();
|
||||
saa_saaSound->WriteAddressData(w.addr,w.val);
|
||||
regPool[w.addr&0x1f]=w.val;
|
||||
writes.pop();
|
||||
}
|
||||
saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len);
|
||||
|
@ -367,8 +369,17 @@ void* DivPlatformSAA1099::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformSAA1099::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformSAA1099::getRegisterPoolSize() {
|
||||
return 32;
|
||||
}
|
||||
|
||||
void DivPlatformSAA1099::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,32);
|
||||
switch (core) {
|
||||
case DIV_SAA_CORE_MAME:
|
||||
saa=saa1099_device();
|
||||
|
|
|
@ -56,6 +56,7 @@ class DivPlatformSAA1099: public DivDispatch {
|
|||
DivSAACores core;
|
||||
saa1099_device saa;
|
||||
CSAASound* saa_saaSound;
|
||||
unsigned char regPool[32];
|
||||
unsigned char lastBusy;
|
||||
|
||||
bool dacMode;
|
||||
|
@ -85,6 +86,8 @@ class DivPlatformSAA1099: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <string.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[]={
|
||||
"AUDC0", "15",
|
||||
|
@ -281,8 +281,17 @@ void* DivPlatformTIA::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformTIA::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformTIA::getRegisterPoolSize() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
void DivPlatformTIA::reset() {
|
||||
tia.reset();
|
||||
memset(regPool,0,16);
|
||||
for (int i=0; i<2; i++) {
|
||||
chan[i]=DivPlatformTIA::Channel();
|
||||
chan[i].vol=0x0f;
|
||||
|
|
|
@ -38,6 +38,7 @@ class DivPlatformTIA: public DivDispatch {
|
|||
Channel chan[2];
|
||||
bool isMuted[2];
|
||||
TIASound tia;
|
||||
unsigned char regPool[16];
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
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);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -111,6 +111,7 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
|
|||
QueuedWrite& w=writes.front();
|
||||
fm->write(0x0+((w.addr>>8)<<1),w.addr);
|
||||
fm->write(0x1+((w.addr>>8)<<1),w.val);
|
||||
regPool[w.addr&0x1ff]=w.val;
|
||||
writes.pop();
|
||||
delay=4;
|
||||
}
|
||||
|
@ -848,6 +849,14 @@ void* DivPlatformYM2610::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformYM2610::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformYM2610::getRegisterPoolSize() {
|
||||
return 512;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
@ -858,6 +867,7 @@ void DivPlatformYM2610::poke(std::vector<DivRegWrite>& wlist) {
|
|||
|
||||
void DivPlatformYM2610::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
memset(regPool,0,512);
|
||||
if (dumpWrites) {
|
||||
addWrite(0xffffffff,0);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
ymfm::ym2610* fm;
|
||||
ymfm::ym2610::output_data fmout;
|
||||
DivYM2610Interface iface;
|
||||
unsigned char regPool[512];
|
||||
unsigned char lastBusy;
|
||||
|
||||
bool dacMode;
|
||||
|
@ -88,6 +89,8 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
unsigned char* getRegisterPool();
|
||||
int getRegisterPoolSize();
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
|
|
|
@ -403,6 +403,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
|
||||
SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
||||
stop();
|
||||
repeatPattern=false;
|
||||
setOrder(0);
|
||||
isBusy.lock();
|
||||
double origRate=got.rate;
|
||||
|
|
119
src/gui/gui.cpp
119
src/gui/gui.cpp
|
@ -154,7 +154,7 @@ bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) {
|
|||
String FurnaceGUI::encodeKeyMap(std::map<int,int>& map) {
|
||||
String ret;
|
||||
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;
|
||||
}
|
||||
|
@ -1383,7 +1383,6 @@ void FurnaceGUI::drawOsc() {
|
|||
if (!oscOpen) return;
|
||||
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0,0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
|
||||
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::EndDisabled();
|
||||
}
|
||||
ImGui::PopStyleVar(4);
|
||||
ImGui::PopStyleVar(3);
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE;
|
||||
ImGui::End();
|
||||
}
|
||||
|
@ -1491,7 +1490,7 @@ void FurnaceGUI::drawVolMeter() {
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
const char* aboutLine[57]={
|
||||
const char* aboutLine[93]={
|
||||
"tildearrow",
|
||||
"is proud to present",
|
||||
"",
|
||||
|
@ -1501,8 +1500,39 @@ const char* aboutLine[57]={
|
|||
"compatible with DefleMask modules.",
|
||||
"",
|
||||
"zero disassembly.",
|
||||
"zero reverse-engineering.",
|
||||
"only time and dedication.",
|
||||
"just clean-room design,",
|
||||
"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:",
|
||||
"Dear ImGui by Omar Cornut",
|
||||
|
@ -1529,7 +1559,8 @@ const char* aboutLine[57]={
|
|||
"ILLUMIDARO",
|
||||
"all members of Deflers of Noice!",
|
||||
"",
|
||||
"copyright © 2021-2022 tildearrow.",
|
||||
"copyright © 2021-2022 tildearrow",
|
||||
"(and contributors).",
|
||||
"licensed under GPLv2+! see",
|
||||
"LICENSE for more information.",
|
||||
"",
|
||||
|
@ -1548,7 +1579,11 @@ const char* aboutLine[57]={
|
|||
"",
|
||||
"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() {
|
||||
|
@ -1590,7 +1625,7 @@ void FurnaceGUI::drawAbout() {
|
|||
|
||||
skip=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;
|
||||
skip=skip2;
|
||||
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 posY=(scrH-aboutScroll+42*i)*dpiScale;
|
||||
if (posY<-80*dpiScale || posY>scrH*dpiScale) continue;
|
||||
|
@ -1630,7 +1665,7 @@ void FurnaceGUI::drawAbout() {
|
|||
|
||||
while (aboutHue>1) aboutHue--;
|
||||
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;
|
||||
ImGui::End();
|
||||
|
@ -2043,6 +2078,49 @@ void FurnaceGUI::drawChannels() {
|
|||
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",®ViewOpen)) {
|
||||
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) {
|
||||
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
|
||||
curNibble=false;
|
||||
|
@ -2826,6 +2904,7 @@ void FurnaceGUI::doRedo() {
|
|||
|
||||
void FurnaceGUI::play(int row) {
|
||||
e->walkSong(loopOrder,loopRow,loopEnd);
|
||||
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
|
||||
if (row>0) {
|
||||
e->playToRow(row);
|
||||
} else {
|
||||
|
@ -3056,6 +3135,9 @@ void FurnaceGUI::doAction(int what) {
|
|||
case GUI_ACTION_WINDOW_CHANNELS:
|
||||
nextWindow=GUI_WINDOW_CHANNELS;
|
||||
break;
|
||||
case GUI_ACTION_WINDOW_REGISTER_VIEW:
|
||||
nextWindow=GUI_WINDOW_REGISTER_VIEW;
|
||||
break;
|
||||
|
||||
case GUI_ACTION_COLLAPSE_WINDOW:
|
||||
collapseWindow=true;
|
||||
|
@ -3125,6 +3207,9 @@ void FurnaceGUI::doAction(int what) {
|
|||
case GUI_WINDOW_CHANNELS:
|
||||
channelsOpen=false;
|
||||
break;
|
||||
case GUI_WINDOW_REGISTER_VIEW:
|
||||
regViewOpen=false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4647,6 +4732,10 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
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))) {
|
||||
syncSettings();
|
||||
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("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("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;
|
||||
|
||||
ImGui::EndMenu();
|
||||
|
@ -4776,6 +4866,7 @@ bool FurnaceGUI::loop() {
|
|||
drawPiano();
|
||||
drawNotes();
|
||||
drawChannels();
|
||||
drawRegView();
|
||||
|
||||
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;
|
||||
|
@ -5387,6 +5478,7 @@ bool FurnaceGUI::init() {
|
|||
pianoOpen=e->getConfBool("pianoOpen",false);
|
||||
notesOpen=e->getConfBool("notesOpen",false);
|
||||
channelsOpen=e->getConfBool("channelsOpen",false);
|
||||
regViewOpen=e->getConfBool("regViewOpen",false);
|
||||
|
||||
syncSettings();
|
||||
|
||||
|
@ -5540,6 +5632,7 @@ bool FurnaceGUI::finish() {
|
|||
e->setConf("pianoOpen",pianoOpen);
|
||||
e->setConf("notesOpen",notesOpen);
|
||||
e->setConf("channelsOpen",channelsOpen);
|
||||
e->setConf("regViewOpen",regViewOpen);
|
||||
|
||||
// commit last window size
|
||||
e->setConf("lastWindowWidth",scrW);
|
||||
|
@ -5609,6 +5702,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
pianoOpen(false),
|
||||
notesOpen(false),
|
||||
channelsOpen(false),
|
||||
regViewOpen(false),
|
||||
selecting(false),
|
||||
curNibble(false),
|
||||
orderNibble(false),
|
||||
|
@ -5665,6 +5759,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
oldOrdersLen(0) {
|
||||
|
||||
// octave 1
|
||||
/*
|
||||
noteKeys[SDL_SCANCODE_Z]=0;
|
||||
noteKeys[SDL_SCANCODE_S]=1;
|
||||
noteKeys[SDL_SCANCODE_X]=2;
|
||||
|
@ -5710,6 +5805,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
|
||||
// env release
|
||||
noteKeys[SDL_SCANCODE_GRAVE]=102;
|
||||
*/
|
||||
|
||||
// value keys
|
||||
valueKeys[SDLK_0]=0;
|
||||
|
@ -5748,4 +5844,5 @@ FurnaceGUI::FurnaceGUI():
|
|||
|
||||
memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
||||
memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1));
|
||||
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
|
||||
}
|
||||
|
|
|
@ -128,6 +128,7 @@ enum FurnaceGUIWindows {
|
|||
GUI_WINDOW_PIANO,
|
||||
GUI_WINDOW_NOTES,
|
||||
GUI_WINDOW_CHANNELS,
|
||||
GUI_WINDOW_REGISTER_VIEW
|
||||
};
|
||||
|
||||
enum FurnaceGUIFileDialogs {
|
||||
|
@ -210,6 +211,7 @@ enum FurnaceGUIActions {
|
|||
GUI_ACTION_WINDOW_PIANO,
|
||||
GUI_ACTION_WINDOW_NOTES,
|
||||
GUI_ACTION_WINDOW_CHANNELS,
|
||||
GUI_ACTION_WINDOW_REGISTER_VIEW,
|
||||
|
||||
GUI_ACTION_COLLAPSE_WINDOW,
|
||||
GUI_ACTION_CLOSE_WINDOW,
|
||||
|
@ -521,7 +523,7 @@ class FurnaceGUI {
|
|||
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
||||
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
|
||||
bool mixerOpen, debugOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
|
||||
bool pianoOpen, notesOpen, channelsOpen;
|
||||
bool pianoOpen, notesOpen, channelsOpen, regViewOpen;
|
||||
SelectionPoint selStart, selEnd, cursor;
|
||||
bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders;
|
||||
bool collapseWindow, demandScrollX, fancyPattern, wantPatName;
|
||||
|
@ -568,9 +570,9 @@ class FurnaceGUI {
|
|||
int samplePreviewNote;
|
||||
|
||||
// SDL_Scancode,int
|
||||
std::map<SDL_Scancode,int> noteKeys;
|
||||
std::map<int,int> noteKeys;
|
||||
// SDL_Keycode,int
|
||||
std::map<SDL_Keycode,int> valueKeys;
|
||||
std::map<int,int> valueKeys;
|
||||
|
||||
int arpMacroScroll;
|
||||
|
||||
|
@ -621,6 +623,7 @@ class FurnaceGUI {
|
|||
std::deque<UndoStep> redoHist;
|
||||
|
||||
float keyHit[DIV_MAX_CHANS];
|
||||
int lastIns[DIV_MAX_CHANS];
|
||||
|
||||
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);
|
||||
|
@ -648,6 +651,7 @@ class FurnaceGUI {
|
|||
void drawPiano();
|
||||
void drawNotes();
|
||||
void drawChannels();
|
||||
void drawRegView();
|
||||
void drawAbout();
|
||||
void drawSettings();
|
||||
void drawDebug();
|
||||
|
|
|
@ -480,7 +480,7 @@ void FurnaceGUI::drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r
|
|||
|
||||
#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::TableNextColumn(); \
|
||||
ImGui::Text("%s",displayName); \
|
||||
|
@ -517,7 +517,7 @@ void FurnaceGUI::drawFMEnv(unsigned char ar, unsigned char dr, unsigned char d2r
|
|||
if (bitfield) { \
|
||||
PlotBitfield("##IMacro_" macroName,asInt,totalFit,0,bfVal,macroHeight,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale))); \
|
||||
} 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)) { \
|
||||
macroDragStart=ImGui::GetItemRectMin(); \
|
||||
|
@ -779,15 +779,15 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
if (ImGui::BeginTabItem("Macros (FM)")) {
|
||||
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.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.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.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.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,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,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,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.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.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.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,¯oLFOWaves);
|
||||
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,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,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,¯oLFOWaves,false);
|
||||
MACRO_END;
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
@ -1018,47 +1018,47 @@ void FurnaceGUI::drawInsEdit() {
|
|||
if (settings.macroView==0) { // modern view
|
||||
MACRO_BEGIN(28*dpiScale);
|
||||
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?(¯oHoverNote):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?(¯oHoverNote):NULL),true);
|
||||
if (dutyMax>0) {
|
||||
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 {
|
||||
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) {
|
||||
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 (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) {
|
||||
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 {
|
||||
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 (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 {
|
||||
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) {
|
||||
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) {
|
||||
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.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.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,false);
|
||||
}
|
||||
if (ins->type==DIV_INS_AY8930) {
|
||||
// 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.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.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,false);
|
||||
}
|
||||
|
||||
MACRO_END;
|
||||
|
|
|
@ -86,6 +86,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
if (i<0 || i>=e->song.patLen) {
|
||||
return;
|
||||
}
|
||||
bool isPushing=false;
|
||||
// check overflow highlight
|
||||
if (settings.overflowHighlight) {
|
||||
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)) {
|
||||
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
|
||||
if (settings.patRowsBase==1) {
|
||||
|
@ -117,19 +131,6 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
ImGui::TableNextColumn();
|
||||
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
|
||||
int sel1XSum=sel1.xCoarse*32+sel1.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 cursorVol=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==2);
|
||||
|
||||
|
||||
|
||||
// note
|
||||
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) {
|
||||
|
@ -156,7 +159,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
demandX=ImGui::GetCursorPosX();
|
||||
ImGui::PopStyleColor(3);
|
||||
} 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()) {
|
||||
startSelection(j,0,i);
|
||||
|
@ -185,7 +190,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
demandX=ImGui::GetCursorPosX();
|
||||
ImGui::PopStyleColor(3);
|
||||
} 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()) {
|
||||
startSelection(j,1,i);
|
||||
|
@ -215,7 +222,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
demandX=ImGui::GetCursorPosX();
|
||||
ImGui::PopStyleColor(3);
|
||||
} 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()) {
|
||||
startSelection(j,2,i);
|
||||
|
@ -268,7 +277,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
demandX=ImGui::GetCursorPosX();
|
||||
ImGui::PopStyleColor(3);
|
||||
} 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()) {
|
||||
startSelection(j,index-1,i);
|
||||
|
@ -292,7 +303,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
|
|||
demandX=ImGui::GetCursorPosX();
|
||||
ImGui::PopStyleColor(3);
|
||||
} 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()) {
|
||||
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();
|
||||
patChanX[chans]=ImGui::GetCursorPosX();
|
||||
}
|
||||
|
@ -315,6 +331,9 @@ void FurnaceGUI::drawPattern() {
|
|||
nextWindow=GUI_WINDOW_NOTHING;
|
||||
}
|
||||
if (!patternOpen) return;
|
||||
|
||||
float scrollX=0;
|
||||
|
||||
if (e->isPlaying() && followPattern) cursor.y=oldRow;
|
||||
demandX=0;
|
||||
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 (++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)) {
|
||||
fancyPattern=!fancyPattern;
|
||||
e->enableCommandStream(fancyPattern);
|
||||
|
@ -428,7 +456,6 @@ void FurnaceGUI::drawPattern() {
|
|||
ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
|
||||
// help me why is the color leakingggggggg
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
|
||||
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
|
||||
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
|
||||
|
@ -554,6 +581,7 @@ void FurnaceGUI::drawPattern() {
|
|||
}
|
||||
demandScrollX=false;
|
||||
}
|
||||
scrollX=ImGui::GetScrollX();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
|
@ -569,7 +597,6 @@ void FurnaceGUI::drawPattern() {
|
|||
//if (i.cmd==DIV_CMD_NOTE_ON) continue;
|
||||
if (i.cmd==DIV_CMD_PRE_PORTA) 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_GET_VOLUME) continue;
|
||||
if (i.cmd==DIV_ALWAYS_SET_VOLUME) continue;
|
||||
|
@ -589,8 +616,8 @@ void FurnaceGUI::drawPattern() {
|
|||
switch (i.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
partIcon=ICON_FA_ASTERISK;
|
||||
life=64.0f;
|
||||
lifeSpeed=2.0f;
|
||||
life=96.0f;
|
||||
lifeSpeed=3.0f;
|
||||
break;
|
||||
case DIV_CMD_LEGATO:
|
||||
partIcon=ICON_FA_COG;
|
||||
|
@ -618,6 +645,23 @@ void FurnaceGUI::drawPattern() {
|
|||
color=volGrad;
|
||||
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: {
|
||||
if (i.value==0) {
|
||||
num=0;
|
||||
|
@ -661,7 +705,7 @@ void FurnaceGUI::drawPattern() {
|
|||
particles.push_back(Particle(
|
||||
color,
|
||||
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),
|
||||
(speedX+randRange(-spread,spread))*0.5*dpiScale,
|
||||
(speedY+randRange(-spread,spread))*0.5*dpiScale,
|
||||
|
@ -675,18 +719,18 @@ void FurnaceGUI::drawPattern() {
|
|||
|
||||
// note slides
|
||||
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);
|
||||
if (ch->portaSpeed>0) {
|
||||
ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH];
|
||||
col.w*=0.2;
|
||||
float width=patChanX[i+1]-patChanX[i];
|
||||
|
||||
if (e->isPlaying()) {
|
||||
particles.push_back(Particle(
|
||||
pitchGrad,
|
||||
(ch->portaNote<=ch->note)?ICON_FA_CHEVRON_DOWN:ICON_FA_CHEVRON_UP,
|
||||
off.x+patChanX[i]+fmod(rand(),width),
|
||||
off.x+patChanX[i]+fmod(rand(),width)-scrollX,
|
||||
off.y+fmod(rand(),MAX(1,ImGui::GetWindowHeight())),
|
||||
0.0f,
|
||||
(7.0f+(rand()%5)+pow(ch->portaSpeed,0.7f))*((ch->portaNote<=ch->note)?1:-1),
|
||||
|
@ -695,11 +739,10 @@ void FurnaceGUI::drawPattern() {
|
|||
255.0f,
|
||||
15.0f
|
||||
));
|
||||
}
|
||||
|
||||
for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) {
|
||||
ImVec2 tMin=ImVec2(off.x+patChanX[i],off.y+j);
|
||||
ImVec2 tMax=ImVec2(off.x+patChanX[i+1],off.y+j+width*0.6);
|
||||
if (width>0.1) for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) {
|
||||
ImVec2 tMin=ImVec2(off.x+patChanX[i]-scrollX,off.y+j);
|
||||
ImVec2 tMax=ImVec2(off.x+patChanX[i+1]-scrollX,off.y+j+width*0.6);
|
||||
if (ch->portaNote<=ch->note) {
|
||||
arrowPoints[0]=ImLerp(tMin,tMax,ImVec2(0.1,1.0-0.8));
|
||||
arrowPoints[1]=ImLerp(tMin,tMax,ImVec2(0.5,1.0-0.0));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
|
@ -384,6 +384,10 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
|
|||
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++)
|
||||
{
|
||||
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.
|
||||
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)
|
||||
{
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -423,8 +431,8 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
|
|||
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);
|
||||
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);
|
||||
}
|
|
@ -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 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);
|
|
@ -22,7 +22,9 @@
|
|||
#include "util.h"
|
||||
#include "IconsFontAwesome4.h"
|
||||
#include "misc/cpp/imgui_stdlib.h"
|
||||
#include <SDL_scancode.h>
|
||||
#include <fmt/printf.h>
|
||||
#include <imgui.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define FURKMOD_CMD FURKMOD_META
|
||||
|
@ -30,6 +32,8 @@
|
|||
#define FURKMOD_CMD FURKMOD_CTRL
|
||||
#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[]={
|
||||
"IBM Plex Sans",
|
||||
"Liberation Sans",
|
||||
|
@ -113,6 +117,15 @@ void FurnaceGUI::promptKey(int which) {
|
|||
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() {
|
||||
if (nextWindow==GUI_WINDOW_SETTINGS) {
|
||||
settingsOpen=true;
|
||||
|
@ -564,6 +577,7 @@ void FurnaceGUI::drawSettings() {
|
|||
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO,"Piano");
|
||||
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES,"Song Comments");
|
||||
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_CLOSE_WINDOW,"Close current window");
|
||||
|
@ -571,6 +585,89 @@ void FurnaceGUI::drawSettings() {
|
|||
KEYBIND_CONFIG_END;
|
||||
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")) {
|
||||
KEYBIND_CONFIG_BEGIN("keysPattern");
|
||||
|
||||
|
@ -806,6 +903,7 @@ void FurnaceGUI::syncSettings() {
|
|||
LOAD_KEYBIND(GUI_ACTION_WINDOW_PIANO,0);
|
||||
LOAD_KEYBIND(GUI_ACTION_WINDOW_NOTES,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_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_REPLAY,0);
|
||||
|
||||
decodeKeyMap(noteKeys,e->getConfString("noteKeys",DEFAULT_NOTE_KEYS));
|
||||
|
||||
parseKeybinds();
|
||||
}
|
||||
|
||||
|
@ -1072,6 +1172,7 @@ void FurnaceGUI::commitSettings() {
|
|||
SAVE_KEYBIND(GUI_ACTION_WINDOW_PIANO);
|
||||
SAVE_KEYBIND(GUI_ACTION_WINDOW_NOTES);
|
||||
SAVE_KEYBIND(GUI_ACTION_WINDOW_CHANNELS);
|
||||
SAVE_KEYBIND(GUI_ACTION_WINDOW_REGISTER_VIEW);
|
||||
|
||||
SAVE_KEYBIND(GUI_ACTION_COLLAPSE_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_REPLAY);
|
||||
|
||||
e->setConf("noteKeys",encodeKeyMap(noteKeys));
|
||||
|
||||
e->saveConf();
|
||||
|
||||
if (!e->switchMaster()) {
|
||||
|
|
Loading…
Reference in a new issue