Namco 163: add waveform position latch option
for FamiTracker compatibility its default value will be decided by a poll issue #2476
This commit is contained in:
parent
2da316b346
commit
344f8d3a22
4 changed files with 55 additions and 11 deletions
|
|
@ -711,6 +711,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si
|
|||
ds.system[systemID] = DIV_SYSTEM_N163;
|
||||
ds.systemFlags[systemID].set("channels", (int)n163Chans - 1);
|
||||
ds.systemChans[systemID]=CLAMP(n163Chans,1,8);
|
||||
ds.systemFlags[systemID].set("posLatch",true);
|
||||
systemID++;
|
||||
|
||||
for (int ch = 0; ch < (int)n163Chans; ch++) {
|
||||
|
|
@ -1948,8 +1949,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si
|
|||
// - in FamiTracker this is in bytes
|
||||
// - a value of 7F has special meaning
|
||||
if (pat->newData[row][DIV_PAT_FXVAL(j)]==0x7f) {
|
||||
pat->newData[row][DIV_PAT_FX(j)]=-1;
|
||||
pat->newData[row][DIV_PAT_FXVAL(j)]=-1;
|
||||
pat->newData[row][DIV_PAT_FXVAL(j)]=0xff;
|
||||
} else {
|
||||
pat->newData[row][DIV_PAT_FXVAL(j)]=MIN(pat->newData[row][DIV_PAT_FXVAL(j)]<<1,0xff);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "n163.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include "IconsFontAwesome4.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
|
||||
|
|
@ -206,7 +207,7 @@ void DivPlatformN163::tick(bool sysTick) {
|
|||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.duty.had) {
|
||||
if (chan[i].std.duty.had && !chan[i].wavePosLatch) {
|
||||
if (chan[i].curWavePos!=chan[i].std.duty.val) {
|
||||
chan[i].curWavePos=chan[i].std.duty.val;
|
||||
chan[i].waveChanged=true;
|
||||
|
|
@ -230,7 +231,7 @@ void DivPlatformN163::tick(bool sysTick) {
|
|||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.ex1.had) {
|
||||
if (chan[i].std.ex1.had && !chan[i].wavePosLatch) {
|
||||
if (chan[i].curWaveLen!=(chan[i].std.ex1.val&0xfc)) {
|
||||
chan[i].curWaveLen=chan[i].std.ex1.val&0xfc;
|
||||
chan[i].freqChanged=true;
|
||||
|
|
@ -310,11 +311,13 @@ int DivPlatformN163::dispatch(DivCommand c) {
|
|||
if (ins->n163.wave>=0) {
|
||||
chan[c.chan].wave=ins->n163.wave;
|
||||
}
|
||||
chan[c.chan].wavePos=ins->n163.perChanPos?ins->n163.wavePosCh[c.chan&7]:ins->n163.wavePos;
|
||||
chan[c.chan].waveLen=ins->n163.perChanPos?ins->n163.waveLenCh[c.chan&7]:ins->n163.waveLen;
|
||||
chan[c.chan].waveMode=ins->n163.waveMode;
|
||||
chan[c.chan].curWavePos=chan[c.chan].wavePos;
|
||||
chan[c.chan].curWaveLen=chan[c.chan].waveLen;
|
||||
if (!chan[c.chan].wavePosLatch) {
|
||||
chan[c.chan].wavePos=ins->n163.perChanPos?ins->n163.wavePosCh[c.chan&7]:ins->n163.wavePos;
|
||||
chan[c.chan].waveLen=ins->n163.perChanPos?ins->n163.waveLenCh[c.chan&7]:ins->n163.waveLen;
|
||||
chan[c.chan].waveMode=ins->n163.waveMode;
|
||||
chan[c.chan].curWavePos=chan[c.chan].wavePos;
|
||||
chan[c.chan].curWaveLen=chan[c.chan].waveLen;
|
||||
}
|
||||
chan[c.chan].ws.init(NULL,chan[c.chan].waveLen,15,true);
|
||||
if (chan[c.chan].wave<0) {
|
||||
chan[c.chan].wave=0;
|
||||
|
|
@ -425,6 +428,23 @@ int DivPlatformN163::dispatch(DivCommand c) {
|
|||
chan[c.chan].waveUpdated=true;
|
||||
}
|
||||
}
|
||||
|
||||
// wave position latching.
|
||||
// if enabled in chip flags, setting wave pos through effects will "lock" it
|
||||
// to a specific value until a wave pos effect with value FE or FF is used.
|
||||
if (posLatch) {
|
||||
chan[c.chan].wavePosLatch=true;
|
||||
if (c.value>=0xfe) {
|
||||
chan[c.chan].wavePosLatch=false;
|
||||
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_N163);
|
||||
chan[c.chan].wavePos=ins->n163.perChanPos?ins->n163.wavePosCh[c.chan&7]:ins->n163.wavePos;
|
||||
chan[c.chan].waveLen=ins->n163.perChanPos?ins->n163.waveLenCh[c.chan&7]:ins->n163.waveLen;
|
||||
chan[c.chan].waveMode=ins->n163.waveMode;
|
||||
chan[c.chan].curWavePos=chan[c.chan].wavePos;
|
||||
chan[c.chan].curWaveLen=chan[c.chan].waveLen;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_N163_WAVE_LENGTH:
|
||||
if (c.value2&1) {
|
||||
|
|
@ -543,6 +563,20 @@ DivDispatchOscBuffer* DivPlatformN163::getOscBuffer(int ch) {
|
|||
return oscBuf[ch];
|
||||
}
|
||||
|
||||
DivChannelModeHints DivPlatformN163::getModeHints(int ch) {
|
||||
DivChannelModeHints ret;
|
||||
if (!posLatch) return ret;
|
||||
|
||||
ret.count=1;
|
||||
ret.hint[0]=ICON_FA_LOCK;
|
||||
ret.type[0]=0;
|
||||
if (chan[ch].wavePosLatch) {
|
||||
ret.type[0]=21;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformN163::getRegisterPool() {
|
||||
return regPool;
|
||||
}
|
||||
|
|
@ -601,6 +635,7 @@ void DivPlatformN163::setFlags(const DivConfig& flags) {
|
|||
CHECK_CUSTOM_CLOCK;
|
||||
initChanMax=chanMax=flags.getInt("channels",7)&7;
|
||||
multiplex=!flags.getBool("multiplex",false); // not accurate in real hardware
|
||||
posLatch=flags.getBool("posLatch",false);
|
||||
rate=chipClock;
|
||||
rate/=15;
|
||||
n163.set_multiplex(multiplex);
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ class DivPlatformN163: public DivDispatch {
|
|||
short wave, wavePos, waveLen;
|
||||
short curWavePos, curWaveLen;
|
||||
bool waveMode;
|
||||
bool wavePosLatch;
|
||||
bool volumeChanged;
|
||||
bool waveChanged, waveUpdated;
|
||||
DivWaveSynth ws;
|
||||
DivWaveSynth ws;
|
||||
Channel():
|
||||
SharedChannel<signed char>(15),
|
||||
resVol(15),
|
||||
|
|
@ -43,6 +44,7 @@ class DivPlatformN163: public DivDispatch {
|
|||
curWavePos(0),
|
||||
curWaveLen(0),
|
||||
waveMode(0),
|
||||
wavePosLatch(false),
|
||||
volumeChanged(false),
|
||||
waveChanged(false),
|
||||
waveUpdated(false) {}
|
||||
|
|
@ -61,7 +63,7 @@ class DivPlatformN163: public DivDispatch {
|
|||
unsigned char initChanMax;
|
||||
unsigned char chanMax;
|
||||
short loadWave, loadPos;
|
||||
bool multiplex, lenCompensate;
|
||||
bool multiplex, lenCompensate, posLatch;
|
||||
|
||||
n163_core n163;
|
||||
unsigned char regPool[128];
|
||||
|
|
@ -83,6 +85,7 @@ class DivPlatformN163: public DivDispatch {
|
|||
void forceIns();
|
||||
void tick(bool sysTick=true);
|
||||
void muteChannel(int ch, bool mute);
|
||||
DivChannelModeHints getModeHints(int chan);
|
||||
const DivMemoryComposition* getMemCompo(int index);
|
||||
void setFlags(const DivConfig& flags);
|
||||
void notifyWaveChange(int wave);
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
int channels=flags.getInt("channels",7)+1;
|
||||
bool multiplex=flags.getBool("multiplex",false);
|
||||
bool lenCompensate=flags.getBool("lenCompensate",false);
|
||||
bool posLatch=flags.getBool("posLatch",false);
|
||||
|
||||
ImGui::Text(_("Clock rate:"));
|
||||
ImGui::Indent();
|
||||
|
|
@ -1304,6 +1305,10 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
if (ImGui::Checkbox(_("Scale frequency to wave length"),&lenCompensate)) {
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::Checkbox(_("Waveform position latch"),&posLatch)) {
|
||||
altered=true;
|
||||
}
|
||||
ImGui::SetItemTooltip(_("when enabled, a waveform position effect will lock the position, preventing instrument changes from changing it.\nuse a wave position effect with value FE or FF to unlock it."));
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
|
|
@ -1311,6 +1316,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
flags.set("channels",channels-1);
|
||||
flags.set("multiplex",multiplex);
|
||||
flags.set("lenCompensate",lenCompensate);
|
||||
flags.set("posLatch",posLatch);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue