Merge branch 'master' of https://github.com/tildearrow/furnace into ymf278b

This commit is contained in:
cam900 2024-07-21 18:37:57 +09:00
commit 80faf6cf41
9 changed files with 68 additions and 49 deletions

View file

@ -98,6 +98,12 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
return _("Cxxx: Set tick rate (hz)");
case 0xd8:
return _("D8xx: Set volume slide bottom boundary");
case 0xd9:
return _("D9xx: Set volume slide top boundary");
case 0xdc:
return _("DCxx: Delayed mute");
case 0xe0:
return _("E0xx: Set arp speed");
case 0xe1:
@ -2108,6 +2114,7 @@ void DivEngine::reset() {
chan[i]=DivChannelState();
if (i<chans) chan[i].volMax=(disCont[dispatchOfChan[i]].dispatch->dispatch(DivCommand(DIV_CMD_GET_VOLMAX,dispatchChanOfChan[i]))<<8)|0xff;
chan[i].volume=chan[i].volMax;
chan[i].volTop=chan[i].volMax;
if (song.linearPitch==0) chan[i].vibratoFine=4;
}
extValue=0;

View file

@ -133,7 +133,7 @@ struct DivAudioExportOptions {
struct DivChannelState {
std::vector<DivDelayedCommand> delayed;
int note, oldNote, lastIns, pitch, portaSpeed, portaNote;
int volume, volSpeed, cut, legatoDelay, legatoTarget, rowDelay, volMax;
int volume, volSpeed, cut, volCut, legatoDelay, legatoTarget, rowDelay, volMax, volBottom, volTop;
int delayOrder, delayRow, retrigSpeed, retrigTick;
int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoShape, vibratoFine;
int tremoloDepth, tremoloRate, tremoloPos;
@ -158,10 +158,13 @@ struct DivChannelState {
volume(0x7f00),
volSpeed(0),
cut(-1),
volCut(-1),
legatoDelay(-1),
legatoTarget(0),
rowDelay(0),
volMax(0),
volBottom(0),
volTop(0),
delayOrder(0),
delayRow(0),
retrigSpeed(0),

View file

@ -1077,8 +1077,24 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
p->data[j][effectCol[k]++]=0x0c;
p->data[j][effectCol[k]++]=(effectVal&15);
break;
case 0xa: // vol slide up (fine)
volSlideStatus[k]=((effectVal&15)<<4)|0xf;
volSlideStatusChanged[k]=true;
if (hasNote || hasIns) {
volSlideStatusChanged[k]=true;
}
volSliding[k]=true;
break;
case 0xb: // vol slide down (fine)
volSlideStatus[k]=0xf0|(effectVal&15);
volSlideStatusChanged[k]=true;
if (hasNote || hasIns) {
volSlideStatusChanged[k]=true;
}
volSliding[k]=true;
break;
case 0xc:
p->data[j][effectCol[k]++]=0xec;
p->data[j][effectCol[k]++]=0xdc;
p->data[j][effectCol[k]++]=MAX(1,effectVal&15);
break;
case 0xd:

View file

@ -948,6 +948,20 @@ void DivEngine::processRow(int i, bool afterDelay) {
clockDrift=0;
subticks=0;
break;
case 0xd8: // vol slide bottom
chan[i].volBottom=(effectVal<<8)|0xff;
if (chan[i].volBottom>chan[i].volMax) chan[i].volBottom=chan[i].volMax;
break;
case 0xd9: // vol slide top
chan[i].volTop=(effectVal<<8)|0xff;
if (chan[i].volTop>chan[i].volMax) chan[i].volTop=chan[i].volMax;
break;
case 0xdc: // delayed mute
if (effectVal>0 && (song.delayBehavior==2 || effectVal<nextSpeed)) {
chan[i].volCut=effectVal+1;
chan[i].cutType=0;
}
break;
case 0xe0: // arp speed
if (effectVal>0) {
curSubSong->arpLen=effectVal;
@ -1105,13 +1119,13 @@ void DivEngine::processRow(int i, bool afterDelay) {
break;
case 0xf8: // single volume ramp up
chan[i].volSpeed=0; // add compat flag?
chan[i].volume=MIN(chan[i].volume+effectVal*256,chan[i].volMax);
chan[i].volume=MIN(chan[i].volume+effectVal*256,chan[i].volTop);
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
break;
case 0xf9: // single volume ramp down
chan[i].volSpeed=0; // add compat flag?
chan[i].volume=MAX(chan[i].volume-effectVal*256,0);
chan[i].volume=MAX(chan[i].volume-effectVal*256,chan[i].volBottom);
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
break;
@ -1598,19 +1612,19 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
if (chan[i].volSpeed!=0) {
chan[i].volume=(chan[i].volume&0xff)|(dispatchCmd(DivCommand(DIV_CMD_GET_VOLUME,i))<<8);
chan[i].volume+=chan[i].volSpeed;
if (chan[i].volume>chan[i].volMax) {
chan[i].volume=chan[i].volMax;
if (chan[i].volume>chan[i].volTop) {
chan[i].volume=chan[i].volTop;
chan[i].volSpeed=0;
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,0));
} else if (chan[i].volume<0) {
} else if (chan[i].volume<chan[i].volBottom) {
chan[i].volSpeed=0;
dispatchCmd(DivCommand(DIV_CMD_HINT_VOL_SLIDE,i,0));
if (song.legacyVolumeSlides) {
chan[i].volume=chan[i].volMax+1;
chan[i].volume=chan[i].volTop+1;
} else {
chan[i].volume=0;
chan[i].volume=chan[i].volBottom;
}
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
@ -1628,7 +1642,6 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
if (chan[i].panSpeed!=0) {
int newPanL=chan[i].panL;
int newPanR=chan[i].panR;
logV("panSpeed: %d",chan[i].panSpeed);
if (chan[i].panSpeed>0) { // right
if (newPanR>=0xff) {
newPanL-=chan[i].panSpeed;
@ -1798,6 +1811,15 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
}
}
// volume cut/mute
if (chan[i].volCut>0) {
if (--chan[i].volCut<1) {
chan[i].volume=0;
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
dispatchCmd(DivCommand(DIV_CMD_HINT_VOLUME,i,chan[i].volume>>8));
}
}
// arpeggio
if (chan[i].resetArp) {
dispatchCmd(DivCommand(DIV_CMD_LEGATO,i,chan[i].note));

View file

@ -478,11 +478,11 @@ const FurnaceGUIColors fxColors[256]={
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_VOLUME, // D8
GUI_COLOR_PATTERN_EFFECT_VOLUME, // D9
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_VOLUME, // DC
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_INVALID,
GUI_COLOR_PATTERN_EFFECT_MISC, // DF