dev243 - N163: add convenience effects - READ

two effects for convenience and .ftm import:

- 1Axx: set wave load and play pos (equivalent to 11xx 15xx)
- 1Bxx: set wave load and play length (equivalent to 12xx 16xx)

*** Developer Information ***

a small change to the command stream format has been made. the commands for N163 loadpos/loadlen have been retired, and the commands for N163 wave position/length now take in 2 bytes instead of 1.
the first byte is the position/length.
the second byte is a bitset. if bit 0 is set, update playback state. if bit 1 is set, update load state.
This commit is contained in:
tildearrow 2026-01-18 17:26:20 -05:00
parent 6294431945
commit 2da316b346
7 changed files with 42 additions and 30 deletions

View file

@ -26,13 +26,19 @@ if the waveform changes (e.g. ins change, wave macro or wave synth), or the **lo
- `10xx`: **set waveform for playback.**
- `11xx`: **set waveform position in RAM for playback.**
- position is in nibbles.
- `12xx`: **set waveform length in RAM for playback.**
- `x` goes from `04` to `FC` in steps of 4.
- `15xx`: **set waveform load position.**
- position is in nibbles.
- `16xx`: **set waveform load length.**
- `x` goes from `04` to `FC` in steps of 4.
- `180x`: **set channel limit.**
- range of `x` is `0` to `7`. 1 is added to get results of 1 through 8.
- `1Axx`: **set waveform load and playback position.**
- position is in nibbles.
- `1Bxx`: **set waveform load and playback length.**
- `x` goes from `04` to `FC` in steps of 4.
- `20xx`: **load a waveform to RAM.**
- `x` is the waveform.
- the length is determined by the wave's width (it will be snapped to a multiple of 4 if it isn't).

View file

@ -268,12 +268,12 @@ hex | description
70 | sweep amount (b)
----|------------------------------------
| **Namco 163 commands**
71 | wave position (b)
72 | wave length (b)
71 | wave position (bb)
72 | wave length (bb)
73 | UNUSED (b)
74 | UNUSED (b)
75 | wave load position (b)
76 | wave load length (b)
75 | UNUSED (b)
76 | UNUSED (b)
77 | UNUSED (b)
78 | channel limit (b)
79 | global wave load (b)

View file

@ -402,8 +402,6 @@ bool DivCSPlayer::tick() {
case DIV_CMD_X1_010_SAMPLE_BANK_SLOT:
case DIV_CMD_WS_SWEEP_TIME:
case DIV_CMD_WS_SWEEP_AMOUNT:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
case DIV_CMD_N163_WAVE_UNUSED1:
case DIV_CMD_N163_WAVE_UNUSED2:
case DIV_CMD_N163_WAVE_LOADPOS:
@ -533,6 +531,8 @@ bool DivCSPlayer::tick() {
case DIV_CMD_SID3_FILTER_OUTPUT_VOLUME:
case DIV_CMD_C64_PW_SLIDE:
case DIV_CMD_C64_CUTOFF_SLIDE:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
arg0=(unsigned char)stream.readC();
arg1=(unsigned char)stream.readC();
break;

View file

@ -84,8 +84,6 @@ int DivCS::getCmdLength(unsigned char ext) {
case DIV_CMD_X1_010_SAMPLE_BANK_SLOT:
case DIV_CMD_WS_SWEEP_TIME:
case DIV_CMD_WS_SWEEP_AMOUNT:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
case DIV_CMD_N163_WAVE_UNUSED1:
case DIV_CMD_N163_WAVE_UNUSED2:
case DIV_CMD_N163_WAVE_LOADPOS:
@ -213,6 +211,8 @@ int DivCS::getCmdLength(unsigned char ext) {
case DIV_CMD_SID3_FILTER_OUTPUT_VOLUME:
case DIV_CMD_C64_PW_SLIDE:
case DIV_CMD_C64_CUTOFF_SLIDE:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
return 2;
case DIV_CMD_C64_FINE_DUTY:
case DIV_CMD_C64_FINE_CUTOFF:
@ -472,8 +472,6 @@ void writeCommandValues(SafeWriter* w, const DivCommand& c, bool bigEndian) {
case DIV_CMD_X1_010_SAMPLE_BANK_SLOT:
case DIV_CMD_WS_SWEEP_TIME:
case DIV_CMD_WS_SWEEP_AMOUNT:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
case DIV_CMD_N163_WAVE_UNUSED1:
case DIV_CMD_N163_WAVE_UNUSED2:
case DIV_CMD_N163_WAVE_LOADPOS:
@ -602,6 +600,8 @@ void writeCommandValues(SafeWriter* w, const DivCommand& c, bool bigEndian) {
case DIV_CMD_SID3_FILTER_OUTPUT_VOLUME:
case DIV_CMD_C64_PW_SLIDE:
case DIV_CMD_C64_CUTOFF_SLIDE:
case DIV_CMD_N163_WAVE_POSITION:
case DIV_CMD_N163_WAVE_LENGTH:
w->writeC(c.value);
w->writeC(c.value2);
break;

View file

@ -56,8 +56,8 @@ class DivWorkPool;
#define DIV_UNSTABLE
#define DIV_VERSION "dev242"
#define DIV_ENGINE_VERSION 242
#define DIV_VERSION "dev243"
#define DIV_ENGINE_VERSION 243
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02

View file

@ -113,7 +113,7 @@ const int ftEffectMap[]={
0xfc, // delayed release
0x09, // select groove
0xe6, // delayed note transpose
0x11, // Namco 163 wave RAM offset
0x1a, // Namco 163 wave RAM offset
-1, // FDS vol env - not supported
-1, // FDS auto FM - not supported yet
-1, // phase reset - not supported
@ -227,7 +227,7 @@ const int eftEffectMap[] = {
0xfc, // delayed release
0x09, // select groove
0xe6, // delayed note transpose
0x11, // Namco 163 wave RAM offset
0x1a, // Namco 163 wave RAM offset
-1, // FDS vol env - not supported
-1, // FDS auto FM - not supported yet
-1, // phase reset - not supported
@ -1943,7 +1943,7 @@ bool DivEngine::loadFTM(unsigned char* file, size_t len, bool dnft, bool dnft_si
if (map_channels[ch] == n163_chans[v]) {
if (pat->newData[row][DIV_PAT_FX(j)] == 0x12) {
pat->newData[row][DIV_PAT_FX(j)] = 0x110; // N163 wave change (we'll map this later)
} else if (pat->newData[row][DIV_PAT_FX(j)] == 0x11) {
} else if (pat->newData[row][DIV_PAT_FX(j)] == 0x1a) {
// wave position:
// - in FamiTracker this is in bytes
// - a value of 7F has special meaning

View file

@ -414,23 +414,29 @@ int DivPlatformN163::dispatch(DivCommand c) {
chan[c.chan].keyOn=true;
break;
case DIV_CMD_N163_WAVE_POSITION:
chan[c.chan].curWavePos=c.value;
chan[c.chan].waveChanged=true;
break;
case DIV_CMD_N163_WAVE_LENGTH:
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;
if (c.value2&1) {
chan[c.chan].curWavePos=c.value;
chan[c.chan].waveChanged=true;
}
if (c.value2&2) {
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;
case DIV_CMD_N163_WAVE_LENGTH:
if (c.value2&1) {
chan[c.chan].curWaveLen=c.value&0xfc;
chan[c.chan].freqChanged=true;
}
if (c.value2&2) {
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: