diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index 8dcd55d22..db2305c65 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -590,7 +590,9 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { logD("GB data: vol %d dir %d len %d sl %d",ins->gb.envVol,ins->gb.envDir,ins->gb.envLen,ins->gb.soundLen); } else if (ds.system[0]==DIV_SYSTEM_GB) { - // try to convert macro to envelope + // set software envelope flag + ins->gb.softEnv=true; + // try to convert macro to envelope in case the user decides to switch to them if (ins->std.volMacro.len>0) { ins->gb.envVol=ins->std.volMacro.val[0]; if (ins->std.volMacro.val[0]std.volMacro.val[1]) { @@ -600,7 +602,6 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ins->gb.soundLen=ins->std.volMacro.len*2; } } - addWarning("Game Boy volume macros converted to envelopes. may not be perfect!"); } } diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 5b7393ef3..aa95d6cbd 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -160,6 +160,16 @@ void DivPlatformGB::tick(bool sysTick) { for (int i=0; i<4; i++) { chan[i].std.next(); + if (chan[i].softEnv) { + if (chan[i].std.vol.had) { + chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); + if (chan[i].outVol<0) chan[i].outVol=0; + + // temporary until zombie mode is implemented + chan[i].vol=chan[i].outVol; + chan[i].keyOn=true; + } + } if (chan[i].std.arp.had) { if (i==3) { // noise if (chan[i].std.arp.mode) { @@ -189,7 +199,7 @@ void DivPlatformGB::tick(bool sysTick) { chan[i].duty=chan[i].std.duty.val; if (i!=2) { rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(chan[i].soundLen&63))); - } else { + } else if (!chan[i].softEnv) { if (parent->song.waveDutyIsVol) { rWrite(16+i*5+2,gbVolMap[(chan[i].std.duty.val&3)<<2]); } @@ -244,11 +254,13 @@ void DivPlatformGB::tick(bool sysTick) { unsigned short data=ins->gb.hwSeq[chan[i].hwSeqPos].data; switch (ins->gb.hwSeq[chan[i].hwSeqPos].cmd) { case DivInstrumentGB::DIV_GB_HWCMD_ENVELOPE: - chan[i].envLen=data&7; - chan[i].envDir=(data&8)?1:0; - chan[i].envVol=(data>>4)&15; - chan[i].soundLen=data>>8; - chan[i].keyOn=true; + if (!chan[i].softEnv) { + chan[i].envLen=data&7; + chan[i].envDir=(data&8)?1:0; + chan[i].envVol=(data>>4)&15; + chan[i].soundLen=data>>8; + chan[i].keyOn=true; + } break; case DivInstrumentGB::DIV_GB_HWCMD_SWEEP: chan[i].sweep=data; @@ -352,6 +364,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].hwSeqPos=0; chan[c.chan].hwSeqDelay=0; chan[c.chan].released=false; + chan[c.chan].softEnv=ins->gb.softEnv; chan[c.chan].macroInit(ins); if (c.chan==2) { if (chan[c.chan].wave<0) { @@ -387,13 +400,15 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].insChanged=true; if (c.chan!=2) { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_GB); - chan[c.chan].envVol=ins->gb.envVol; - chan[c.chan].envLen=ins->gb.envLen; - chan[c.chan].envDir=ins->gb.envDir; - chan[c.chan].soundLen=ins->gb.soundLen; - chan[c.chan].vol=chan[c.chan].envVol; - if (parent->song.gbInsAffectsEnvelope) { - rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); + if (!ins->gb.softEnv) { + chan[c.chan].envVol=ins->gb.envVol; + chan[c.chan].envLen=ins->gb.envLen; + chan[c.chan].envDir=ins->gb.envDir; + chan[c.chan].soundLen=ins->gb.soundLen; + chan[c.chan].vol=chan[c.chan].envVol; + if (parent->song.gbInsAffectsEnvelope) { + rWrite(16+c.chan*5+2,((chan[c.chan].vol<<4))|(chan[c.chan].envLen&7)|((chan[c.chan].envDir&1)<<3)); + } } } } diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index a4432f1e7..082f33ba9 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -29,7 +29,7 @@ class DivPlatformGB: public DivDispatch { struct Channel { int freq, baseFreq, pitch, pitch2, note, ins; unsigned char duty, sweep; - bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released; + bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, released, softEnv; signed char vol, outVol, wave; unsigned char envVol, envDir, envLen, soundLen; unsigned short hwSeqPos; @@ -56,6 +56,7 @@ class DivPlatformGB: public DivDispatch { keyOff(false), inPorta(false), released(false), + softEnv(false), vol(15), outVol(15), wave(-1),