Merge branch 'master' of https://github.com/tildearrow/furnace into k053260
This commit is contained in:
commit
7aaa52297e
36 changed files with 783 additions and 141 deletions
|
|
@ -288,6 +288,9 @@ struct DivRegWrite {
|
|||
* - x is the instance ID
|
||||
* - 0xffffxx04: switch sample bank
|
||||
* - for use in VGM export
|
||||
* - 0xffffxx05: set sample position
|
||||
* - xx is the instance ID
|
||||
* - data is the sample position
|
||||
* - 0xffffffff: reset
|
||||
*/
|
||||
unsigned int addr;
|
||||
|
|
|
|||
|
|
@ -54,8 +54,10 @@
|
|||
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
|
||||
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
|
||||
|
||||
#define DIV_VERSION "0.6pre6"
|
||||
#define DIV_ENGINE_VERSION 161
|
||||
#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "dev163"
|
||||
#define DIV_ENGINE_VERSION 163
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
|
@ -489,7 +491,7 @@ class DivEngine {
|
|||
void processRow(int i, bool afterDelay);
|
||||
void nextOrder();
|
||||
void nextRow();
|
||||
void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, size_t bankOffset, bool directStream);
|
||||
void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream);
|
||||
// returns true if end of song.
|
||||
bool nextTick(bool noAccum=false, bool inhibitLowLat=false);
|
||||
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ void DivPlatformGenesis::processDAC(int iRate) {
|
|||
for (int i=5; i<7; i++) {
|
||||
if (chan[i].dacSample!=-1) {
|
||||
DivSample* s=parent->getSample(chan[i].dacSample);
|
||||
if (!isMuted[i] && s->samples>0) {
|
||||
if (!isMuted[i] && s->samples>0 && chan[i].dacPos<s->samples) {
|
||||
if (parent->song.noOPN2Vol) {
|
||||
chan[i].dacOutput=s->data8[chan[i].dacDirection?(s->samples-chan[i].dacPos-1):chan[i].dacPos];
|
||||
} else {
|
||||
|
|
@ -110,7 +110,7 @@ void DivPlatformGenesis::processDAC(int iRate) {
|
|||
chan[5].dacPeriod+=chan[5].dacRate;
|
||||
if (chan[5].dacPeriod>=iRate) {
|
||||
DivSample* s=parent->getSample(chan[5].dacSample);
|
||||
if (s->samples>0) {
|
||||
if (s->samples>0 && chan[5].dacPos<s->samples) {
|
||||
if (!isMuted[5]) {
|
||||
if (chan[5].dacReady && writes.size()<16) {
|
||||
int sample;
|
||||
|
|
@ -122,10 +122,6 @@ void DivPlatformGenesis::processDAC(int iRate) {
|
|||
urgentWrite(0x2a,(unsigned char)sample+0x80);
|
||||
chan[5].dacReady=false;
|
||||
}
|
||||
} else {
|
||||
if (chan[5].dacReady && writes.size()<16) {
|
||||
urgentWrite(0x2a,0x80);
|
||||
}
|
||||
}
|
||||
chan[5].dacPos++;
|
||||
if (!chan[5].dacDirection && (s->isLoopable() && chan[5].dacPos>=(unsigned int)s->loopEnd)) {
|
||||
|
|
@ -597,6 +593,7 @@ void DivPlatformGenesis::muteChannel(int ch, bool mute) {
|
|||
isMuted[ch]=mute;
|
||||
if (ch>6) return;
|
||||
if (ch<6) {
|
||||
if (ch==5) immWrite(0x2a,0x80);
|
||||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[ch]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[ch].state.op[j];
|
||||
|
|
@ -704,7 +701,11 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
addWrite(0xffff0003,chan[c.chan].dacDirection);
|
||||
}
|
||||
}
|
||||
chan[c.chan].dacPos=0;
|
||||
if (chan[c.chan].setPos) {
|
||||
chan[c.chan].setPos=false;
|
||||
} else {
|
||||
chan[c.chan].dacPos=0;
|
||||
}
|
||||
chan[c.chan].dacPeriod=0;
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
|
||||
|
|
@ -927,6 +928,12 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
if (dumpWrites) addWrite(0xffff0003,chan[c.chan].dacDirection);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SAMPLE_POS:
|
||||
if (c.chan<5) c.chan=5;
|
||||
chan[c.chan].dacPos=c.value;
|
||||
chan[c.chan].setPos=true;
|
||||
if (dumpWrites) addWrite(0xffff0005,chan[c.chan].dacPos);
|
||||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan==csmChan) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
|||
int dacDelay;
|
||||
bool dacReady;
|
||||
bool dacDirection;
|
||||
bool setPos;
|
||||
unsigned char sampleBank;
|
||||
signed char dacOutput;
|
||||
Channel():
|
||||
|
|
@ -70,6 +71,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
|||
dacDelay(0),
|
||||
dacReady(true),
|
||||
dacDirection(false),
|
||||
setPos(false),
|
||||
sampleBank(0),
|
||||
dacOutput(0) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ void DivPlatformPV1000::acquire(short** buf, size_t len) {
|
|||
short samp=d65010g031_sound_tick(&d65010g031,1);
|
||||
buf[0][h]=samp;
|
||||
for (int i=0; i<3; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=d65010g031.out[i]<<1;
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=MAX(d65010g031.out[i]<<2,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ template<bool IsOpnA>
|
|||
bool opn_registers_base<IsOpnA>::write(uint16_t index, uint8_t data, uint32_t &channel, uint32_t &opmask)
|
||||
{
|
||||
assert(index < REGISTERS);
|
||||
if (index >= REGISTERS) return false;
|
||||
|
||||
// writes in the 0xa0-af/0x1a0-af region are handled as latched pairs
|
||||
// borrow unused registers 0xb8-bf/0x1b8-bf as temporary holding locations
|
||||
|
|
|
|||
|
|
@ -236,9 +236,12 @@ void DivPlatformVERA::tick(bool sysTick) {
|
|||
if (s->samples>0) {
|
||||
if (s->isLoopable()) {
|
||||
// Inform the export process of the loop point for this sample
|
||||
addWrite(67,s->loopStart&0xff);
|
||||
addWrite(67,(s->loopStart>>8)&0xff);
|
||||
addWrite(67,(s->loopStart>>16)&0xff);
|
||||
int tmp_ls=(s->loopStart<<1); // for stereo
|
||||
if (chan[16].pcm.depth16)
|
||||
tmp_ls<<=1; // for 16 bit
|
||||
addWrite(67,tmp_ls&0xff);
|
||||
addWrite(67,(tmp_ls>>8)&0xff);
|
||||
addWrite(67,(tmp_ls>>16)&0xff);
|
||||
}
|
||||
while (true) {
|
||||
short tmp_l=0;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
||||
|
||||
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, size_t bankOffset, bool directStream) {
|
||||
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream) {
|
||||
unsigned char baseAddr1=isSecond?0xa0:0x50;
|
||||
unsigned char baseAddr2=isSecond?0x80:0;
|
||||
unsigned short baseAddr2S=isSecond?0x8000:0;
|
||||
|
|
@ -620,15 +620,35 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
pendingFreq[streamID]=write.val;
|
||||
} else {
|
||||
DivSample* sample=song.sample[write.val];
|
||||
w->writeC(0x95);
|
||||
w->writeC(streamID);
|
||||
w->writeS(write.val); // sample number
|
||||
w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())|(sampleDir[streamID]?0x10:0)); // flags
|
||||
int pos=sampleOff8[write.val&0xff]+setPos[streamID];
|
||||
int len=(int)sampleLen8[write.val&0xff]-setPos[streamID];
|
||||
|
||||
if (len<0) len=0;
|
||||
|
||||
if (setPos[streamID]!=0) {
|
||||
if (len<=0) {
|
||||
w->writeC(0x94);
|
||||
w->writeC(streamID);
|
||||
} else {
|
||||
w->writeC(0x93);
|
||||
w->writeC(streamID);
|
||||
w->writeI(pos);
|
||||
w->writeC(1|((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())?0x80:0)|(sampleDir[streamID]?0x10:0)); // flags
|
||||
w->writeI(len);
|
||||
}
|
||||
} else {
|
||||
w->writeC(0x95);
|
||||
w->writeC(streamID);
|
||||
w->writeS(write.val); // sample number
|
||||
w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())|(sampleDir[streamID]?0x10:0)); // flags
|
||||
}
|
||||
|
||||
if (sample->isLoopable() && !sampleDir[streamID]) {
|
||||
loopTimer[streamID]=sample->length8;
|
||||
loopTimer[streamID]=len;
|
||||
loopSample[streamID]=write.val;
|
||||
}
|
||||
playingSample[streamID]=write.val;
|
||||
setPos[streamID]=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -642,16 +662,36 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
loopFreq[streamID]=realFreq;
|
||||
if (pendingFreq[streamID]!=-1) {
|
||||
DivSample* sample=song.sample[pendingFreq[streamID]];
|
||||
w->writeC(0x95);
|
||||
w->writeC(streamID);
|
||||
w->writeS(pendingFreq[streamID]); // sample number
|
||||
w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())|(sampleDir[streamID]?0x10:0)); // flags
|
||||
int pos=sampleOff8[pendingFreq[streamID]&0xff]+setPos[streamID];
|
||||
int len=(int)sampleLen8[pendingFreq[streamID]&0xff]-setPos[streamID];
|
||||
|
||||
if (len<0) len=0;
|
||||
|
||||
if (setPos[streamID]!=0) {
|
||||
if (len<=0) {
|
||||
w->writeC(0x94);
|
||||
w->writeC(streamID);
|
||||
} else {
|
||||
w->writeC(0x93);
|
||||
w->writeC(streamID);
|
||||
w->writeI(pos);
|
||||
w->writeC(1|((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())?0x80:0)|(sampleDir[streamID]?0x10:0)); // flags
|
||||
w->writeI(len);
|
||||
}
|
||||
} else {
|
||||
w->writeC(0x95);
|
||||
w->writeC(streamID);
|
||||
w->writeS(pendingFreq[streamID]); // sample number
|
||||
w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())|(sampleDir[streamID]?0x10:0)); // flags
|
||||
}
|
||||
|
||||
if (sample->isLoopable() && !sampleDir[streamID]) {
|
||||
loopTimer[streamID]=sample->length8;
|
||||
loopTimer[streamID]=len;
|
||||
loopSample[streamID]=pendingFreq[streamID];
|
||||
}
|
||||
playingSample[streamID]=pendingFreq[streamID];
|
||||
pendingFreq[streamID]=-1;
|
||||
setPos[streamID]=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -665,6 +705,41 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
case 3: // set sample direction
|
||||
sampleDir[streamID]=write.val;
|
||||
break;
|
||||
case 5: // set sample pos
|
||||
setPos[streamID]=write.val;
|
||||
|
||||
if (playingSample[streamID]!=-1 && pendingFreq[streamID]==-1) {
|
||||
// play the sample again
|
||||
DivSample* sample=song.sample[playingSample[streamID]];
|
||||
int pos=sampleOff8[playingSample[streamID]&0xff]+setPos[streamID];
|
||||
int len=(int)sampleLen8[playingSample[streamID]&0xff]-setPos[streamID];
|
||||
|
||||
if (len<0) len=0;
|
||||
|
||||
if (setPos[streamID]!=0) {
|
||||
if (len<=0) {
|
||||
w->writeC(0x94);
|
||||
w->writeC(streamID);
|
||||
} else {
|
||||
w->writeC(0x93);
|
||||
w->writeC(streamID);
|
||||
w->writeI(pos);
|
||||
w->writeC(1|((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())?0x80:0)|(sampleDir[streamID]?0x10:0)); // flags
|
||||
w->writeI(len);
|
||||
}
|
||||
} else {
|
||||
w->writeC(0x95);
|
||||
w->writeC(streamID);
|
||||
w->writeS(playingSample[streamID]); // sample number
|
||||
w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0 && sample->isLoopable())|(sampleDir[streamID]?0x10:0)); // flags
|
||||
}
|
||||
|
||||
if (sample->isLoopable() && !sampleDir[streamID]) {
|
||||
loopTimer[streamID]=len;
|
||||
loopSample[streamID]=playingSample[streamID];
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -1082,6 +1157,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
int songTick=0;
|
||||
|
||||
unsigned int sampleOff8[256];
|
||||
unsigned int sampleLen8[256];
|
||||
unsigned int sampleOffSegaPCM[256];
|
||||
|
||||
SafeWriter* w=new SafeWriter;
|
||||
|
|
@ -1102,6 +1178,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
bool sampleDir[DIV_MAX_CHANS];
|
||||
int pendingFreq[DIV_MAX_CHANS];
|
||||
int playingSample[DIV_MAX_CHANS];
|
||||
int setPos[DIV_MAX_CHANS];
|
||||
std::vector<unsigned int> chipVol;
|
||||
std::vector<DivDelayedWrite> delayedWrites[DIV_MAX_CHIPS];
|
||||
std::vector<std::pair<int,DivDelayedWrite>> sortedWrites;
|
||||
|
|
@ -1121,6 +1198,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
loopSample[i]=-1;
|
||||
pendingFreq[i]=-1;
|
||||
playingSample[i]=-1;
|
||||
setPos[i]=0;
|
||||
sampleDir[i]=false;
|
||||
}
|
||||
|
||||
|
|
@ -1379,7 +1457,6 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
willExport[i]=true;
|
||||
CHIP_VOL(6,1.0);
|
||||
CHIP_VOL(0x86,1.7);
|
||||
writeDACSamples=true;
|
||||
} else if (!(hasOPN&0x40000000)) {
|
||||
isSecond[i]=true;
|
||||
willExport[i]=true;
|
||||
|
|
@ -1873,6 +1950,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
|
||||
// initialize sample offsets
|
||||
memset(sampleOff8,0,256*sizeof(unsigned int));
|
||||
memset(sampleLen8,0,256*sizeof(unsigned int));
|
||||
memset(sampleOffSegaPCM,0,256*sizeof(unsigned int));
|
||||
|
||||
// write samples
|
||||
|
|
@ -1881,6 +1959,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
DivSample* sample=song.sample[i];
|
||||
logI("setting seek to %d",sampleSeek);
|
||||
sampleOff8[i]=sampleSeek;
|
||||
sampleLen8[i]=sample->length8;
|
||||
sampleSeek+=sample->length8;
|
||||
}
|
||||
|
||||
|
|
@ -2016,9 +2095,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
w->writeC(0x67);
|
||||
w->writeC(0x66);
|
||||
w->writeC(0xc0+i);
|
||||
w->writeI(writeRF5C68[i]->getSampleMemUsage()+8);
|
||||
w->writeI(writeRF5C68[i]->getSampleMemCapacity());
|
||||
w->writeI(0);
|
||||
w->writeI(writeRF5C68[i]->getSampleMemUsage()+2);
|
||||
w->writeS(0);
|
||||
w->write(writeRF5C68[i]->getSampleMem(),writeRF5C68[i]->getSampleMemUsage());
|
||||
}
|
||||
if (writeMSM6295[i]!=NULL && writeMSM6295[i]->getSampleMemUsage()>0) {
|
||||
|
|
@ -2281,7 +2359,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
for (int i=0; i<song.systemLen; i++) {
|
||||
std::vector<DivRegWrite>& writes=disCont[i].dispatch->getRegisterWrites();
|
||||
for (DivRegWrite& j: writes) {
|
||||
performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,bankOffset[i],directStream);
|
||||
performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i],directStream);
|
||||
writeCount++;
|
||||
}
|
||||
writes.clear();
|
||||
|
|
@ -2321,7 +2399,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
lastOne=i.second.time;
|
||||
}
|
||||
// write write
|
||||
performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,bankOffset[i.first],directStream);
|
||||
performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i.first],directStream);
|
||||
// handle global Furnace commands
|
||||
|
||||
writeCount++;
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ void DivZSM::flushWrites() {
|
|||
}
|
||||
pcmCache.resize(pcmCache.size()>>1);
|
||||
pcmCtrlDCCache&=(unsigned char)~0x10; // clear stereo bit
|
||||
pcmLoopPointCache>>=1; // halve the loop point
|
||||
}
|
||||
}
|
||||
} else { // 8-bit
|
||||
|
|
@ -334,6 +335,7 @@ void DivZSM::flushWrites() {
|
|||
}
|
||||
pcmCache.resize(pcmCache.size()>>1);
|
||||
pcmCtrlDCCache&=(unsigned char)~0x10; // clear stereo bit
|
||||
pcmLoopPointCache>>=1; // halve the loop point
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -365,9 +367,9 @@ void DivZSM::flushWrites() {
|
|||
inst.loopPoint=pcmLoopPointCache;
|
||||
inst.isLooped=pcmIsLooped;
|
||||
pcmInsts.push_back(inst);
|
||||
pcmIsLooped=false;
|
||||
pcmLoopPointCache=0;
|
||||
}
|
||||
pcmIsLooped=false;
|
||||
pcmLoopPointCache=0;
|
||||
}
|
||||
if (extCmd0Len>63) { // this would be bad, but will almost certainly never happen
|
||||
logE("ZSM: extCmd 0 exceeded maximum length of 63: %d",extCmd0Len);
|
||||
|
|
|
|||
|
|
@ -149,6 +149,14 @@ void FurnaceGUI::drawChanOsc() {
|
|||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::Text("Amplitude");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderFloat("##COSAmp",&chanOscAmplify,0.0f,2.0f)) {
|
||||
if (chanOscAmplify<0.0f) chanOscAmplify=0.0f;
|
||||
if (chanOscAmplify>2.0f) chanOscAmplify=2.0f;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Gradient",&chanOscUseGrad);
|
||||
|
||||
if (chanOscUseGrad) {
|
||||
|
|
|
|||
|
|
@ -5759,6 +5759,17 @@ bool FurnaceGUI::loop() {
|
|||
introPos=12.0;
|
||||
}
|
||||
|
||||
#ifdef DIV_UNSTABLE
|
||||
{
|
||||
ImDrawList* dl=ImGui::GetForegroundDrawList();
|
||||
ImVec2 markPos=ImVec2(canvasW-ImGui::CalcTextSize(DIV_VERSION).x-6.0*dpiScale,4.0*dpiScale);
|
||||
ImVec4 markColor=uiColors[GUI_COLOR_TEXT];
|
||||
markColor.w=0.67f;
|
||||
|
||||
dl->AddText(markPos,ImGui::ColorConvertFloat4ToU32(markColor),DIV_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
layoutTimeEnd=SDL_GetPerformanceCounter();
|
||||
|
||||
// backup trigger
|
||||
|
|
@ -6265,14 +6276,14 @@ bool FurnaceGUI::init() {
|
|||
settings.renderBackend="SDL";
|
||||
e->setConf("renderBackend","SDL");
|
||||
e->saveConf();
|
||||
lastError=fmt::sprintf("\r\nthe render backend has been set to a safe value. please restart Furnace.");
|
||||
lastError=fmt::sprintf("could not init renderer!\r\nthe render backend has been set to a safe value. please restart Furnace.");
|
||||
} else {
|
||||
lastError=fmt::sprintf("could not init renderer! %s",SDL_GetError());
|
||||
if (!settings.renderDriver.empty()) {
|
||||
settings.renderDriver="";
|
||||
e->setConf("renderDriver","");
|
||||
e->saveConf();
|
||||
lastError=fmt::sprintf("\r\nthe render driver has been set to a safe value. please restart Furnace.");
|
||||
lastError+=fmt::sprintf("\r\nthe render driver has been set to a safe value. please restart Furnace.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -6362,16 +6373,16 @@ bool FurnaceGUI::init() {
|
|||
if (!rend->init(sdlWin)) {
|
||||
if (settings.renderBackend!="SDL") {
|
||||
settings.renderBackend="SDL";
|
||||
e->setConf("renderBackend","");
|
||||
e->setConf("renderBackend","SDL");
|
||||
e->saveConf();
|
||||
lastError=fmt::sprintf("\r\nthe render backend has been set to a safe value. please restart Furnace.");
|
||||
lastError=fmt::sprintf("could not init renderer!\r\nthe render backend has been set to a safe value. please restart Furnace.");
|
||||
} else {
|
||||
lastError=fmt::sprintf("could not init renderer! %s",SDL_GetError());
|
||||
if (!settings.renderDriver.empty()) {
|
||||
settings.renderDriver="";
|
||||
e->setConf("renderDriver","");
|
||||
e->saveConf();
|
||||
lastError=fmt::sprintf("\r\nthe render driver has been set to a safe value. please restart Furnace.");
|
||||
lastError+=fmt::sprintf("\r\nthe render driver has been set to a safe value. please restart Furnace.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -6666,6 +6677,10 @@ bool FurnaceGUI::finish() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FurnaceGUI::requestQuit() {
|
||||
quit=true;
|
||||
}
|
||||
|
||||
FurnaceGUI::FurnaceGUI():
|
||||
e(NULL),
|
||||
renderBackend(GUI_BACKEND_SDL),
|
||||
|
|
|
|||
|
|
@ -2307,6 +2307,7 @@ class FurnaceGUI {
|
|||
bool loop();
|
||||
bool finish();
|
||||
bool init();
|
||||
void requestQuit();
|
||||
FurnaceGUI();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2378,10 +2378,37 @@ void FurnaceGUI::drawInsEdit() {
|
|||
bool opsAreMutable=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPM);
|
||||
|
||||
if (ImGui::BeginTabItem("FM")) {
|
||||
DivInstrumentFM& fmOrigin=(ins->type==DIV_INS_OPLL && ins->fm.opllPreset>0 && ins->fm.opllPreset<16)?opllPreview:ins->fm;
|
||||
|
||||
bool isPresent[4];
|
||||
int isPresentCount=0;
|
||||
memset(isPresent,0,4*sizeof(bool));
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
if (e->song.system[i]==DIV_SYSTEM_VRC7) {
|
||||
isPresent[3]=true;
|
||||
} else if (e->song.system[i]==DIV_SYSTEM_OPLL || e->song.system[i]==DIV_SYSTEM_OPLL_DRUMS) {
|
||||
isPresent[(e->song.systemFlags[i].getInt("patchSet",0))&3]=true;
|
||||
}
|
||||
}
|
||||
if (!isPresent[0] && !isPresent[1] && !isPresent[2] && !isPresent[3]) {
|
||||
isPresent[0]=true;
|
||||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
if (isPresent[i]) isPresentCount++;
|
||||
}
|
||||
int presentWhich=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
if (isPresent[i]) {
|
||||
presentWhich=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("fmDetails",3,ImGuiTableFlags_SizingStretchSame)) {
|
||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
switch (ins->type) {
|
||||
case DIV_INS_FM:
|
||||
|
|
@ -2453,14 +2480,14 @@ void FurnaceGUI::drawInsEdit() {
|
|||
break;
|
||||
}
|
||||
case DIV_INS_OPLL: {
|
||||
bool dc=ins->fm.fms;
|
||||
bool dm=ins->fm.ams;
|
||||
bool dc=fmOrigin.fms;
|
||||
bool dm=fmOrigin.ams;
|
||||
bool sus=ins->fm.alg;
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::BeginDisabled(ins->fm.opllPreset!=0);
|
||||
P(CWSliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&ins->fm.fb,&_ZERO,&_SEVEN)); rightClickable
|
||||
P(CWSliderScalar(FM_NAME(FM_FB),ImGuiDataType_U8,&fmOrigin.fb,&_ZERO,&_SEVEN)); rightClickable
|
||||
if (ImGui::Checkbox(FM_NAME(FM_DC),&dc)) { PARAMETER
|
||||
ins->fm.fms=dc;
|
||||
fmOrigin.fms=dc;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableNextColumn();
|
||||
|
|
@ -2469,7 +2496,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
ImGui::BeginDisabled(ins->fm.opllPreset!=0);
|
||||
if (ImGui::Checkbox(FM_NAME(FM_DM),&dm)) { PARAMETER
|
||||
ins->fm.ams=dm;
|
||||
fmOrigin.ams=dm;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableNextColumn();
|
||||
|
|
@ -2477,30 +2504,6 @@ void FurnaceGUI::drawInsEdit() {
|
|||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
||||
bool isPresent[4];
|
||||
int isPresentCount=0;
|
||||
memset(isPresent,0,4*sizeof(bool));
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
if (e->song.system[i]==DIV_SYSTEM_VRC7) {
|
||||
isPresent[3]=true;
|
||||
} else if (e->song.system[i]==DIV_SYSTEM_OPLL || e->song.system[i]==DIV_SYSTEM_OPLL_DRUMS) {
|
||||
isPresent[(e->song.systemFlags[i].getInt("patchSet",0))&3]=true;
|
||||
}
|
||||
}
|
||||
if (!isPresent[0] && !isPresent[1] && !isPresent[2] && !isPresent[3]) {
|
||||
isPresent[0]=true;
|
||||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
if (isPresent[i]) isPresentCount++;
|
||||
}
|
||||
int presentWhich=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
if (isPresent[i]) {
|
||||
presentWhich=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo("##LLPreset",opllInsNames[presentWhich][ins->fm.opllPreset])) {
|
||||
if (isPresentCount>1) {
|
||||
if (ImGui::BeginTable("LLPresetList",isPresentCount)) {
|
||||
|
|
@ -2578,11 +2581,26 @@ void FurnaceGUI::drawInsEdit() {
|
|||
|
||||
// update OPLL preset preview
|
||||
if (ins->fm.opllPreset>0 && ins->fm.opllPreset<16) {
|
||||
const opll_patch_t* patchROM=OPLL_GetPatchROM(opll_type_ym2413);
|
||||
const opll_patch_t* patchROM=NULL;
|
||||
|
||||
switch (presentWhich) {
|
||||
case 1:
|
||||
patchROM=OPLL_GetPatchROM(opll_type_ymf281);
|
||||
break;
|
||||
case 2:
|
||||
patchROM=OPLL_GetPatchROM(opll_type_ym2423);
|
||||
break;
|
||||
case 3:
|
||||
patchROM=OPLL_GetPatchROM(opll_type_ds1001);
|
||||
break;
|
||||
default:
|
||||
patchROM=OPLL_GetPatchROM(opll_type_ym2413);
|
||||
break;
|
||||
}
|
||||
|
||||
const opll_patch_t* patch=&patchROM[ins->fm.opllPreset-1];
|
||||
|
||||
opllPreview.alg=0;
|
||||
opllPreview.alg=ins->fm.alg;
|
||||
opllPreview.fb=patch->fb;
|
||||
opllPreview.fms=patch->dm;
|
||||
opllPreview.ams=patch->dc;
|
||||
|
|
@ -2604,8 +2622,6 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
DivInstrumentFM& fmOrigin=(ins->type==DIV_INS_OPLL && ins->fm.opllPreset>0 && ins->fm.opllPreset<16)?opllPreview:ins->fm;
|
||||
|
||||
ImGui::BeginDisabled(!willDisplayOps);
|
||||
if (settings.fmLayout==0) {
|
||||
int numCols=15;
|
||||
|
|
|
|||
|
|
@ -290,8 +290,7 @@ void FurnaceGUIRenderDX11::clear(ImVec4 color) {
|
|||
}
|
||||
|
||||
bool FurnaceGUIRenderDX11::newFrame() {
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
return true;
|
||||
return ImGui_ImplDX11_NewFrame();
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX11::createFontsTexture() {
|
||||
|
|
|
|||
|
|
@ -233,8 +233,7 @@ void FurnaceGUIRenderGL::clear(ImVec4 color) {
|
|||
}
|
||||
|
||||
bool FurnaceGUIRenderGL::newFrame() {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
return true;
|
||||
return ImGui_ImplOpenGL3_NewFrame();
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderGL::createFontsTexture() {
|
||||
|
|
|
|||
18
src/main.cpp
18
src/main.cpp
|
|
@ -36,7 +36,10 @@
|
|||
|
||||
typedef HRESULT (WINAPI *SPDA)(PROCESS_DPI_AWARENESS);
|
||||
#else
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct sigaction termsa;
|
||||
#endif
|
||||
|
||||
#include "cli/cli.h"
|
||||
|
|
@ -356,6 +359,14 @@ void reportError(String what) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifdef HAVE_GUI
|
||||
static void handleTermGUI(int) {
|
||||
g.requestQuit();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// TODO: CoInitializeEx on Windows?
|
||||
// TODO: add crash log
|
||||
int main(int argc, char** argv) {
|
||||
|
|
@ -646,6 +657,13 @@ int main(int argc, char** argv) {
|
|||
g.setFileName(fileName);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
sigemptyset(&termsa.sa_mask);
|
||||
termsa.sa_flags=0;
|
||||
termsa.sa_handler=handleTermGUI;
|
||||
sigaction(SIGTERM,&termsa,NULL);
|
||||
#endif
|
||||
|
||||
g.loop();
|
||||
logI("closing GUI.");
|
||||
g.finish();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue