mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-23 04:55:13 +00:00
parent
78b7049d81
commit
8bc0781f59
3 changed files with 79 additions and 1 deletions
|
@ -55,6 +55,10 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
return "03xx: Portamento";
|
||||
case 0x04:
|
||||
return "04xy: Vibrato (x: speed; y: depth)";
|
||||
case 0x05:
|
||||
return "05xy: Volume slide + vibrato (compatibility only!)";
|
||||
case 0x06:
|
||||
return "06xy: Volume slide + portamento (compatibility only!)";
|
||||
case 0x07:
|
||||
return "07xy: Tremolo (x: speed; y: depth)";
|
||||
case 0x08:
|
||||
|
|
|
@ -105,7 +105,7 @@ struct DivChannelState {
|
|||
int delayOrder, delayRow, retrigSpeed, retrigTick;
|
||||
int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine;
|
||||
int tremoloDepth, tremoloRate, tremoloPos;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR, lastVibrato, lastPorta;
|
||||
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
||||
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp;
|
||||
bool wentThroughNote, goneThroughNote;
|
||||
|
@ -146,6 +146,8 @@ struct DivChannelState {
|
|||
panR(255),
|
||||
panRL(0),
|
||||
panRR(0),
|
||||
lastVibrato(0),
|
||||
lastPorta(0),
|
||||
doNote(false),
|
||||
legato(false),
|
||||
portaStop(false),
|
||||
|
|
|
@ -680,6 +680,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
chan[i].lastPorta=effectVal;
|
||||
calledPorta=true;
|
||||
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
|
@ -700,11 +701,78 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
}
|
||||
break;
|
||||
case 0x04: // vibrato
|
||||
if (effectVal) chan[i].lastVibrato=effectVal;
|
||||
chan[i].vibratoDepth=effectVal&15;
|
||||
chan[i].vibratoRate=effectVal>>4;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
break;
|
||||
case 0x05: // vol slide + vibrato
|
||||
if (effectVal==0) {
|
||||
chan[i].vibratoDepth=0;
|
||||
chan[i].vibratoRate=0;
|
||||
} else {
|
||||
chan[i].vibratoDepth=chan[i].lastVibrato&15;
|
||||
chan[i].vibratoRate=chan[i].lastVibrato>>4;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate));
|
||||
dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15)));
|
||||
// TODO: non-0x-or-x0 value should be treated as 00
|
||||
if (effectVal!=0) {
|
||||
if ((effectVal&15)!=0) {
|
||||
chan[i].volSpeed=-(effectVal&15)*64;
|
||||
} else {
|
||||
chan[i].volSpeed=(effectVal>>4)*64;
|
||||
}
|
||||
// tremolo and vol slides are incompatible
|
||||
chan[i].tremoloDepth=0;
|
||||
chan[i].tremoloRate=0;
|
||||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0x06: // vol slide + porta
|
||||
if (effectVal==0 || chan[i].lastPorta==0) {
|
||||
chan[i].portaNote=-1;
|
||||
chan[i].portaSpeed=-1;
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
|
||||
chan[i].inPorta=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,false,0));
|
||||
} else {
|
||||
calledPorta=true;
|
||||
if (chan[i].note==chan[i].oldNote && !chan[i].inPorta && song.buggyPortaAfterSlide) {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
chan[i].portaSpeed=-1;
|
||||
} else {
|
||||
chan[i].portaNote=chan[i].note;
|
||||
chan[i].portaSpeed=chan[i].lastPorta;
|
||||
chan[i].inPorta=true;
|
||||
chan[i].wasShorthandPorta=false;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_PORTA,i,CLAMP(chan[i].portaNote,-128,127),MAX(chan[i].portaSpeed,0)));
|
||||
chan[i].portaStop=true;
|
||||
if (chan[i].keyOn) chan[i].doNote=false;
|
||||
chan[i].stopOnOff=song.stopPortaOnNoteOff; // what?!
|
||||
chan[i].scheduledSlideReset=false;
|
||||
dispatchCmd(DivCommand(DIV_CMD_PRE_PORTA,i,true,1));
|
||||
lastSlide=0x1337; // i hate this so much
|
||||
}
|
||||
// TODO: non-0x-or-x0 value should be treated as 00
|
||||
if (effectVal!=0) {
|
||||
if ((effectVal&15)!=0) {
|
||||
chan[i].volSpeed=-(effectVal&15)*64;
|
||||
} else {
|
||||
chan[i].volSpeed=(effectVal>>4)*64;
|
||||
}
|
||||
// tremolo and vol slides are incompatible
|
||||
chan[i].tremoloDepth=0;
|
||||
chan[i].tremoloRate=0;
|
||||
} else {
|
||||
chan[i].volSpeed=0;
|
||||
}
|
||||
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,chan[i].volSpeed));
|
||||
break;
|
||||
case 0x07: // tremolo
|
||||
// TODO
|
||||
// this effect is really weird. i thought it would alter the tremolo depth but turns out it's completely different
|
||||
|
@ -1148,6 +1216,10 @@ void DivEngine::nextRow() {
|
|||
doPrepareCut=false;
|
||||
break;
|
||||
}
|
||||
if (pat->data[curRow][4+(j<<1)]==0x06) {
|
||||
doPrepareCut=false;
|
||||
break;
|
||||
}
|
||||
if (pat->data[curRow][4+(j<<1)]==0xea) {
|
||||
if (pat->data[curRow][5+(j<<1)]>0) {
|
||||
doPrepareCut=false;
|
||||
|
|
Loading…
Reference in a new issue