mirror of
https://github.com/tildearrow/furnace.git
synced 2025-01-06 23:51:21 +00:00
add effects for rear panning
This commit is contained in:
parent
71e40dc015
commit
707bbb54ea
9 changed files with 88 additions and 8 deletions
|
@ -213,6 +213,8 @@ enum DivDispatchCmds {
|
|||
DIV_CMD_MACRO_OFF, // (which)
|
||||
DIV_CMD_MACRO_ON, // (which)
|
||||
|
||||
DIV_CMD_SURROUND_PANNING, // (out, val)
|
||||
|
||||
DIV_ALWAYS_SET_VOLUME, // () -> alwaysSetVol
|
||||
|
||||
DIV_CMD_MAX
|
||||
|
|
|
@ -77,6 +77,15 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
return "81xx: Set panning (left channel)";
|
||||
case 0x82:
|
||||
return "82xx: Set panning (right channel)";
|
||||
case 0x88:
|
||||
return "88xx: Set panning (rear channels; x: left; y: right)";
|
||||
break;
|
||||
case 0x89:
|
||||
return "89xx: Set panning (rear left channel)";
|
||||
break;
|
||||
case 0x8a:
|
||||
return "8Axx: Set panning (rear right channel)";
|
||||
break;
|
||||
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
|
||||
return "Cxxx: Set tick rate (hz)";
|
||||
case 0xe0:
|
||||
|
@ -435,6 +444,7 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
|
|||
case DIV_CMD_FM_FINE:
|
||||
case DIV_CMD_AY_IO_WRITE:
|
||||
case DIV_CMD_AY_AUTO_PWM:
|
||||
case DIV_CMD_SURROUND_PANNING:
|
||||
w->writeC(2); // length
|
||||
w->writeC(c.value);
|
||||
w->writeC(c.value2);
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
|
||||
#define BUSY_END isBusy.unlock(); softLocked=false;
|
||||
|
||||
#define DIV_VERSION "0.6pre3"
|
||||
#define DIV_ENGINE_VERSION 133
|
||||
#define DIV_VERSION "dev134"
|
||||
#define DIV_ENGINE_VERSION 134
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
@ -97,7 +97,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;
|
||||
unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR;
|
||||
bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff;
|
||||
bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp;
|
||||
|
||||
|
@ -135,6 +135,8 @@ struct DivChannelState {
|
|||
arpTicks(1),
|
||||
panL(255),
|
||||
panR(255),
|
||||
panRL(0),
|
||||
panRR(0),
|
||||
doNote(false),
|
||||
legato(false),
|
||||
portaStop(false),
|
||||
|
|
|
@ -2543,6 +2543,16 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
// OPL3 pan compat
|
||||
if (ds.version<134) {
|
||||
for (int i=0; i<ds.systemLen; i++) {
|
||||
if (ds.system[i]==DIV_SYSTEM_OPL3 ||
|
||||
ds.system[i]==DIV_SYSTEM_OPL3_DRUMS) {
|
||||
ds.systemFlags[i].set("compatPan",true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (active) quitDispatch();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
|
|
|
@ -980,7 +980,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
if (oplType!=3) break;
|
||||
if (c.chan==adpcmChan) break;
|
||||
chan[c.chan].pan&=~3;
|
||||
if (c.value==0 && c.value2==0) {
|
||||
if (c.value==0 && c.value2==0 && compatPan) {
|
||||
chan[c.chan].pan|=3;
|
||||
} else {
|
||||
chan[c.chan].pan|=(c.value>0)|((c.value2>0)<<1);
|
||||
|
@ -999,6 +999,33 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_SURROUND_PANNING: {
|
||||
if (oplType!=3) break;
|
||||
if (c.chan==adpcmChan) break;
|
||||
|
||||
if (c.value==2) {
|
||||
chan[c.chan].pan&=3;
|
||||
if (c.value2>0) chan[c.chan].pan|=4;
|
||||
} else if (c.value==3) {
|
||||
if (c.value2>0) chan[c.chan].pan|=8;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1));
|
||||
if (ops==4) {
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1));
|
||||
}
|
||||
} else {
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4));
|
||||
if (ops==4) {
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&15)<<4));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_PITCH: {
|
||||
if (c.chan==adpcmChan) {
|
||||
if (!chan[c.chan].furnacePCM) break;
|
||||
|
@ -1705,6 +1732,8 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) {
|
|||
rate=chipClock/36;
|
||||
}*/
|
||||
|
||||
compatPan=false;
|
||||
|
||||
switch (chipType) {
|
||||
default:
|
||||
case 1: case 2: case 8950:
|
||||
|
@ -1753,6 +1782,7 @@ void DivPlatformOPL::setFlags(const DivConfig& flags) {
|
|||
CHECK_CUSTOM_CLOCK;
|
||||
rate=chipClock/288;
|
||||
chipRateBase=rate;
|
||||
compatPan=flags.getBool("compatPan",false);
|
||||
break;
|
||||
case 4:
|
||||
switch (flags.getInt("clockSel",0)) {
|
||||
|
|
|
@ -92,7 +92,7 @@ class DivPlatformOPL: public DivDispatch {
|
|||
|
||||
unsigned char lfoValue;
|
||||
|
||||
bool useYMFM, update4OpMask, pretendYMU, downsample;
|
||||
bool useYMFM, update4OpMask, pretendYMU, downsample, compatPan;
|
||||
|
||||
short oldWrites[512];
|
||||
short pendingWrites[512];
|
||||
|
|
|
@ -213,6 +213,8 @@ const char* cmdName[]={
|
|||
"MACRO_OFF",
|
||||
"MACRO_ON",
|
||||
|
||||
"SURROUND_PANNING",
|
||||
|
||||
"ALWAYS_SET_VOLUME"
|
||||
};
|
||||
|
||||
|
@ -555,6 +557,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
short lastSlide=-1;
|
||||
bool calledPorta=false;
|
||||
bool panChanged=false;
|
||||
bool surroundPanChanged=false;
|
||||
|
||||
// effects
|
||||
for (int j=0; j<curPat[i].effectCols; j++) {
|
||||
|
@ -585,6 +588,19 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
chan[i].panR=effectVal;
|
||||
panChanged=true;
|
||||
break;
|
||||
case 0x88: // panning rear (split 4-bit)
|
||||
chan[i].panRL=(effectVal>>4)|(effectVal&0xf0);
|
||||
chan[i].panRR=(effectVal&15)|((effectVal&15)<<4);
|
||||
surroundPanChanged=true;
|
||||
break;
|
||||
case 0x89: // panning left (split 8-bit)
|
||||
chan[i].panRL=effectVal;
|
||||
surroundPanChanged=true;
|
||||
break;
|
||||
case 0x8a: // panning right (split 8-bit)
|
||||
chan[i].panRR=effectVal;
|
||||
surroundPanChanged=true;
|
||||
break;
|
||||
case 0x01: // ramp up
|
||||
if (song.ignoreDuplicateSlides && (lastSlide==0x01 || lastSlide==0x1337)) break;
|
||||
lastSlide=0x01;
|
||||
|
@ -866,6 +882,10 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
|||
if (panChanged) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_PANNING,i,chan[i].panL,chan[i].panR));
|
||||
}
|
||||
if (surroundPanChanged) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_SURROUND_PANNING,i,2,chan[i].panRL));
|
||||
dispatchCmd(DivCommand(DIV_CMD_SURROUND_PANNING,i,3,chan[i].panRR));
|
||||
}
|
||||
|
||||
if (insChanged && (chan[i].inPorta || calledPorta) && song.newInsTriggersInPorta) {
|
||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,DIV_NOTE_NULL));
|
||||
|
|
|
@ -319,9 +319,9 @@ const FurnaceGUIColors fxColors[256]={
|
|||
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_INVALID,
|
||||
GUI_COLOR_PATTERN_EFFECT_PANNING,
|
||||
GUI_COLOR_PATTERN_EFFECT_PANNING,
|
||||
GUI_COLOR_PATTERN_EFFECT_PANNING,
|
||||
GUI_COLOR_PATTERN_EFFECT_INVALID,
|
||||
GUI_COLOR_PATTERN_EFFECT_INVALID,
|
||||
GUI_COLOR_PATTERN_EFFECT_INVALID,
|
||||
|
|
|
@ -1182,6 +1182,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
case DIV_SYSTEM_OPL3:
|
||||
case DIV_SYSTEM_OPL3_DRUMS: {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
bool compatPan=flags.getBool("compatPan",false);
|
||||
|
||||
ImGui::Text("Clock rate:");
|
||||
if (ImGui::RadioButton("14.32MHz (NTSC)",clockSel==0)) {
|
||||
|
@ -1205,9 +1206,14 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
altered=true;
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Compatible panning (0800)",&compatPan)) {
|
||||
altered=true;
|
||||
}
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("clockSel",clockSel);
|
||||
flags.set("compatPan",compatPan);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue