dev164 - Namco 163: improvements, part 4

- per-channel wave offset/length
- wave load position/length effects
- global wave load effects that actually make sense
- update doc
This commit is contained in:
tildearrow 2023-07-21 19:54:35 -05:00
parent d411c9caba
commit ad88ce46ab
11 changed files with 172 additions and 159 deletions

View file

@ -173,16 +173,16 @@ enum DivDispatchCmds {
DIV_CMD_N163_WAVE_POSITION,
DIV_CMD_N163_WAVE_LENGTH,
DIV_CMD_N163_WAVE_MODE,
DIV_CMD_N163_WAVE_LOAD,
DIV_CMD_N163_WAVE_UNUSED1,
DIV_CMD_N163_WAVE_UNUSED2,
DIV_CMD_N163_WAVE_LOADPOS,
DIV_CMD_N163_WAVE_LOADLEN,
DIV_CMD_N163_WAVE_LOADMODE,
DIV_CMD_N163_WAVE_UNUSED3,
DIV_CMD_N163_CHANNEL_LIMIT,
DIV_CMD_N163_GLOBAL_WAVE_LOAD,
DIV_CMD_N163_GLOBAL_WAVE_LOADPOS,
DIV_CMD_N163_GLOBAL_WAVE_LOADLEN,
DIV_CMD_N163_GLOBAL_WAVE_LOADMODE,
DIV_CMD_N163_UNUSED4,
DIV_CMD_N163_UNUSED5,
DIV_CMD_SU_SWEEP_PERIOD_LOW, // (which, val)
DIV_CMD_SU_SWEEP_PERIOD_HIGH, // (which, val)

View file

@ -56,8 +56,8 @@
#define DIV_UNSTABLE
#define DIV_VERSION "dev163"
#define DIV_ENGINE_VERSION 163
#define DIV_VERSION "dev164"
#define DIV_ENGINE_VERSION 164
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02

View file

@ -134,7 +134,24 @@ bool DivInstrumentN163::operator==(const DivInstrumentN163& other) {
_C(wave) &&
_C(wavePos) &&
_C(waveLen) &&
_C(waveMode)
_C(waveMode) &&
_C(perChanPos) &&
_C(wavePosCh[0]) &&
_C(wavePosCh[1]) &&
_C(wavePosCh[2]) &&
_C(wavePosCh[3]) &&
_C(wavePosCh[4]) &&
_C(wavePosCh[5]) &&
_C(wavePosCh[6]) &&
_C(wavePosCh[7]) &&
_C(waveLenCh[0]) &&
_C(waveLenCh[1]) &&
_C(waveLenCh[2]) &&
_C(waveLenCh[3]) &&
_C(waveLenCh[4]) &&
_C(waveLenCh[5]) &&
_C(waveLenCh[6]) &&
_C(waveLenCh[7])
);
}
@ -519,6 +536,17 @@ void DivInstrument::writeFeatureN1(SafeWriter* w) {
w->writeC(n163.waveLen);
w->writeC(n163.waveMode);
w->writeC(n163.perChanPos);
if (n163.perChanPos) {
for (int i=0; i<8; i++) {
w->writeC(n163.wavePosCh[i]);
}
for (int i=0; i<8; i++) {
w->writeC(n163.waveLenCh[i]);
}
}
FEATURE_END;
}
@ -2280,6 +2308,18 @@ void DivInstrument::readFeatureN1(SafeReader& reader, short version) {
n163.waveLen=(unsigned char)reader.readC();
n163.waveMode=(unsigned char)reader.readC();
if (version>=164) {
n163.perChanPos=reader.readC();
if (n163.perChanPos) {
for (int i=0; i<8; i++) {
n163.wavePosCh[i]=(unsigned char)reader.readC();
}
for (int i=0; i<8; i++) {
n163.waveLenCh[i]=(unsigned char)reader.readC();
}
}
}
READ_FEAT_END;
}

View file

@ -446,6 +446,9 @@ struct DivInstrumentX1_010 {
struct DivInstrumentN163 {
int wave, wavePos, waveLen;
unsigned char waveMode;
bool perChanPos;
int wavePosCh[8];
int waveLenCh[8];
bool operator==(const DivInstrumentN163& other);
bool operator!=(const DivInstrumentN163& other) {
@ -456,7 +459,13 @@ struct DivInstrumentN163 {
wave(-1),
wavePos(0),
waveLen(32),
waveMode(3) {}
waveMode(3),
perChanPos(false) {
for (int i=0; i<8; i++) {
wavePosCh[i]=(i&3)<<5;
waveLenCh[i]=32;
}
}
};
struct DivInstrumentFDS {

View file

@ -146,7 +146,7 @@ void DivPlatformN163::updateWave(int ch, int wave, int pos, int len) {
} else {
// load from custom
DivWavetable* wt=parent->getWave(wave);
for (int i=0; i<len; i++) {
for (int i=0; i<wt->len; i++) {
unsigned char addr=(pos+i); // address (nibble each)
if (addr>=((0x78-(chanMax<<3))<<1)) { // avoid conflict with channel register area
break;
@ -155,7 +155,7 @@ void DivPlatformN163::updateWave(int ch, int wave, int pos, int len) {
if (wt->max<1 || wt->len<1) {
rWriteMask(addr>>1,0,mask);
} else {
int data=wt->data[i*wt->len/len]*15/wt->max;
int data=wt->data[i]*15/wt->max;
if (data<0) data=0;
if (data>15) data=15;
rWriteMask(addr>>1,(addr&1)?(data<<4):(data&0xf),mask);
@ -282,8 +282,8 @@ int DivPlatformN163::dispatch(DivCommand c) {
if (ins->n163.wave>=0) {
chan[c.chan].wave=ins->n163.wave;
}
chan[c.chan].wavePos=ins->n163.wavePos;
chan[c.chan].waveLen=ins->n163.waveLen;
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;
@ -393,9 +393,23 @@ int DivPlatformN163::dispatch(DivCommand c) {
chan[c.chan].curWaveLen=c.value&0xfc;
chan[c.chan].freqChanged=true;
break;
case DIV_CMD_N163_WAVE_LOADPOS:
chan[c.chan].wavePos=c.value;
if (chan[c.chan].waveMode) {
chan[c.chan].waveUpdated=true;
}
break;
case DIV_CMD_N163_WAVE_LOADLEN:
chan[c.chan].waveLen=c.value&0xfc;
if (chan[c.chan].waveMode) {
chan[c.chan].waveUpdated=true;
}
break;
case DIV_CMD_N163_GLOBAL_WAVE_LOAD:
loadWave=c.value;
// TODO: load wave here
if (loadWave>=0 && loadWave<parent->song.waveLen) {
updateWave(-1,loadWave,loadPos,-1);
}
break;
case DIV_CMD_N163_GLOBAL_WAVE_LOADPOS:
loadPos=c.value;

View file

@ -995,15 +995,16 @@ void DivEngine::registerSystems() {
{DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163, DIV_INS_N163},
{},
{
{0x18, {DIV_CMD_N163_CHANNEL_LIMIT, "180x: Change channel limits (0 to 7, x + 1)"}}
{0x18, {DIV_CMD_N163_CHANNEL_LIMIT, "18xx: Change channel limits (0 to 7, x + 1)"}},
{0x20, {DIV_CMD_N163_GLOBAL_WAVE_LOAD, "20xx: Load a waveform into memory"}},
{0x21, {DIV_CMD_N163_GLOBAL_WAVE_LOADPOS, "21xx: Set position for wave load"}}
},
{
{0x10, {DIV_CMD_WAVE, "10xx: Select waveform"}},
{0x11, {DIV_CMD_N163_WAVE_POSITION, "11xx: Set waveform position in RAM (single nibble unit)"}},
{0x12, {DIV_CMD_N163_WAVE_LENGTH, "12xx: Set waveform length in RAM (04 to FC, 4 nibble unit)"}},
{0x13, {DIV_CMD_N163_WAVE_MODE, "130x: Change waveform update mode (0: off; bit 0: update now; bit 1: update when every waveform changes)"}},
{0x20, {DIV_CMD_N163_GLOBAL_WAVE_LOAD, "20xx: Load a waveform into memory"}},
{0x21, {DIV_CMD_N163_GLOBAL_WAVE_LOADPOS, "21xx: Set position for wave load"}},
{0x11, {DIV_CMD_N163_WAVE_POSITION, "11xx: Set waveform position in RAM"}},
{0x12, {DIV_CMD_N163_WAVE_LENGTH, "12xx: Set waveform length in RAM (04 to FC in steps of 4)"}},
{0x15, {DIV_CMD_N163_WAVE_LOADPOS, "15xx: Set waveform load position"}},
{0x16, {DIV_CMD_N163_WAVE_LOADLEN, "16xx: Set waveform load length (04 to FC in steps of 4)"}},
}
);

View file

@ -4681,14 +4681,62 @@ void FurnaceGUI::drawInsEdit() {
if (ins->n163.wave>=e->song.waveLen) ins->n163.wave=e->song.waveLen-1;
}
}
if (ImGui::InputInt("Offset##WAVEPOS",&ins->n163.wavePos,1,16)) { PARAMETER
if (ins->n163.wavePos<0) ins->n163.wavePos=0;
if (ins->n163.wavePos>255) ins->n163.wavePos=255;
}
if (ImGui::InputInt("Length##WAVELEN",&ins->n163.waveLen,4,16)) { PARAMETER
if (ins->n163.waveLen<0) ins->n163.waveLen=0;
if (ins->n163.waveLen>252) ins->n163.waveLen=252;
ins->n163.waveLen&=0xfc;
ImGui::Separator();
P(ImGui::Checkbox("Per-channel wave offset/length",&ins->n163.perChanPos));
if (ins->n163.perChanPos) {
if (ImGui::BeginTable("N1PerChPos",3)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5f);
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5f);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn();
ImGui::Text("Ch");
ImGui::TableNextColumn();
ImGui::Text("Offset");
ImGui::TableNextColumn();
ImGui::Text("Length");
for (int i=0; i<8; i++) {
ImGui::PushID(64+i);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Dummy(ImVec2(dpiScale,ImGui::GetFrameHeightWithSpacing()));
ImGui::SameLine();
ImGui::Text("%d",i+1);
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt("##pcOff",&ins->n163.wavePosCh[i],1,16)) { PARAMETER
if (ins->n163.wavePosCh[i]<0) ins->n163.wavePosCh[i]=0;
if (ins->n163.wavePosCh[i]>255) ins->n163.wavePosCh[i]=255;
}
ImGui::TableNextColumn();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt("##pcLen",&ins->n163.waveLenCh[i],4,16)) { PARAMETER
if (ins->n163.waveLenCh[i]<0) ins->n163.waveLenCh[i]=0;
if (ins->n163.waveLenCh[i]>252) ins->n163.waveLenCh[i]=252;
ins->n163.waveLenCh[i]&=0xfc;
}
ImGui::PopID();
}
ImGui::EndTable();
}
} else {
if (ImGui::InputInt("Offset##WAVEPOS",&ins->n163.wavePos,1,16)) { PARAMETER
if (ins->n163.wavePos<0) ins->n163.wavePos=0;
if (ins->n163.wavePos>255) ins->n163.wavePos=255;
}
if (ImGui::InputInt("Length##WAVELEN",&ins->n163.waveLen,4,16)) { PARAMETER
if (ins->n163.waveLen<0) ins->n163.waveLen=0;
if (ins->n163.waveLen>252) ins->n163.waveLen=252;
ins->n163.waveLen&=0xfc;
}
}
ImGui::EndTabItem();
}