prepare to implement stuff in cmd stream

vol slide with target, tremolo, panbrello and pan slide
This commit is contained in:
tildearrow 2025-04-05 04:33:46 -05:00
parent a49664a3f5
commit 110562c2c4
6 changed files with 80 additions and 160 deletions

View file

@ -28,8 +28,9 @@ size | description
??? | channel data
```
read command and values (if any).
the list of commands follows.
program follows.
### commands/instructions
```
hex | description
@ -47,7 +48,6 @@ hex | description
b6 | note off env
b7 | env release
b8 | instrument // (ins, force)
be | panning // (left, right)
c0 | pre porta // (inporta, isportaorslide)
c2 | vibrato // (speed, depth)
c3 | vibrato range // (range)
@ -55,9 +55,14 @@ hex | description
c5 | pitch // (pitch)
c6 | arpeggio // (note1, note2)
c7 | volume // (vol)
c8 | vol slide // (amount, onetick)
c8 | vol slide // (amount)
c9 | porta // (target, speed)
ca | legato // (note)
cb | volume slide with target // (amount, target)
cc | tremolo // (speed/depth)
cd | panbrello // (speed/depth)
ce | pan slide // (speed)
cf | panning // (left, right)
----|------------------------------------
d0 | speed dial command 0
d1 | speed dial command 1
@ -71,13 +76,13 @@ hex | description
----|------------------------------------
f0 | UNUSED - placeholder used during optimization passes (3-byte nonce follows)
f1 | no operation
f2 | UNUSED - unoptimized extended command
f2 | UNUSED
f3 | loop (negative offset and count follow... both are 8-bit)
f4 | call symbol (32-bit index follows; only used internally)
f5 | jump to sub-block (address follows)
f6 | go to sub-block (32-bit offset follows)
f4 | UNUSED - call symbol (32-bit index follows; only used internally)
f5 | call sub-block (32-bit address follows)
f6 | UNUSED
f7 | full command (command and data follows)
f8 | go to sub-block (16-bit offset follows)
f8 | call sub-block (16-bit address follows)
f9 | return from sub-block
fa | jump (address follows)
fb | set tick rate (4 bytes)
@ -87,3 +92,8 @@ hex | description
ff | stop
```
## full commands
```
```

View file

@ -117,6 +117,8 @@ bool DivCSPlayer::tick() {
case 0xb8: case 0xbe: case 0xc0: case 0xc2:
case 0xc3: case 0xc4: case 0xc5: case 0xc6:
case 0xc7: case 0xc8: case 0xc9: case 0xca:
case 0xcb: case 0xcc: case 0xcd: case 0xce:
case 0xcf:
command=next-0xb4;
break;
case 0xf0: // placeholder
@ -147,19 +149,11 @@ bool DivCSPlayer::tick() {
command=stream.readC();
break;
case 0xf8: {
unsigned int callAddr=chan[i].readPos+2+stream.readS();
unsigned int callAddr=(unsigned short)stream.readS();
chan[i].readPos=stream.tell();
if (!chan[i].doCall(callAddr)) {
logE("%d: (callb16) stack error!",i);
}
mustTell=false;
break;
}
case 0xf6: {
unsigned int callAddr=chan[i].readPos+4+stream.readI();
chan[i].readPos=stream.tell();
if (!chan[i].doCall(callAddr)) {
logE("%d: (callb32) stack error!",i);
logE("%d: (call) stack error!",i);
chan[i].readPos=0;
}
mustTell=false;
break;
@ -168,7 +162,8 @@ bool DivCSPlayer::tick() {
unsigned int callAddr=stream.readI();
chan[i].readPos=stream.tell();
if (!chan[i].doCall(callAddr)) {
logE("%d: (call) stack error!",i);
logE("%d: (calli) stack error!",i);
chan[i].readPos=0;
}
mustTell=false;
break;
@ -208,9 +203,9 @@ bool DivCSPlayer::tick() {
chan[i].lastWaitLen=chan[i].waitTicks;
break;
case 0xff:
chan[i].readPos=chan[i].startPos;
chan[i].readPos=0;
mustTell=false;
logI("%d: stop go back to %x",i,chan[i].readPos);
logI("%d: stop",i,chan[i].readPos);
break;
default:
logE("%d: illegal instruction $%.2x! $%.x",i,next,chan[i].readPos);
@ -240,7 +235,7 @@ bool DivCSPlayer::tick() {
arg0=(signed char)stream.readC();
arg1=(unsigned char)stream.readC();
break;
case DIV_CMD_PANNING:
case DIV_CMD_HINT_PANNING: // TODO: panbrello
arg0=(unsigned char)stream.readC();
arg1=(unsigned char)stream.readC();
break;
@ -391,6 +386,9 @@ bool DivCSPlayer::tick() {
case DIV_CMD_HINT_ARP_TIME:
arpSpeed=arg0;
break;
case DIV_CMD_HINT_PANNING:
e->dispatchCmd(DivCommand(DIV_CMD_PANNING,i,arg0,arg1));
break;
default: // dispatch it
e->dispatchCmd(DivCommand((DivDispatchCmds)command,i,arg0,arg1));
break;

View file

@ -34,7 +34,7 @@ int DivCS::getInsLength(unsigned char ins, unsigned char ext) {
case 0xca: // legato
case 0xfd: // waitc
return 2;
case 0xbe: // pan
case 0xcf: // pan
case 0xc2: // vibrato
case 0xc6: // arpeggio
case 0xc8: // vol slide
@ -48,20 +48,19 @@ int DivCS::getInsLength(unsigned char ins, unsigned char ext) {
return 0;
case 0xf0: // opt
return 4;
case 0xf2: // opt command
case 0xf7: { // cmd
// determine length from secondary
if (ext==0) return 0;
return 0;
}
case 0xf8: // callb16
case 0xf8: // call
case 0xfc: // waits
return 3;
case 0xf4: // callsym
case 0xf5: // call
case 0xf6: // callb32
case 0xf5: // calli
case 0xfa: // jmp
case 0xfb: // rate
case 0xcb: // volporta
return 5;
}
return 1;
@ -80,7 +79,6 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE:
case DIV_CMD_INSTRUMENT:
case DIV_CMD_PANNING:
case DIV_CMD_PRE_PORTA:
case DIV_CMD_HINT_VIBRATO:
case DIV_CMD_HINT_VIBRATO_RANGE:
@ -92,11 +90,15 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
case DIV_CMD_HINT_VOL_SLIDE:
case DIV_CMD_HINT_VOL_SLIDE_TARGET:
case DIV_CMD_HINT_LEGATO:
case DIV_CMD_HINT_TREMOLO:
case DIV_CMD_HINT_PANBRELLO:
case DIV_CMD_HINT_PAN_SLIDE:
case DIV_CMD_HINT_PANNING:
w->writeC((unsigned char)c.cmd+0xb4);
break;
default:
return; // quit for now... we'll implement this later
w->writeC(0xf2); // unoptimized extended command
return;
w->writeC(0xf7);
w->writeC(c.cmd);
break;
}
@ -118,9 +120,12 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
case DIV_CMD_HINT_VIBRATO_SHAPE:
case DIV_CMD_HINT_PITCH:
case DIV_CMD_HINT_VOLUME:
case DIV_CMD_HINT_TREMOLO:
case DIV_CMD_HINT_PANBRELLO:
case DIV_CMD_HINT_PAN_SLIDE:
w->writeC(c.value);
break;
case DIV_CMD_PANNING:
case DIV_CMD_HINT_PANNING:
case DIV_CMD_HINT_VIBRATO:
case DIV_CMD_HINT_ARPEGGIO:
case DIV_CMD_HINT_PORTA:
@ -536,15 +541,11 @@ SafeWriter* DivEngine::saveCommand() {
switch (i.cmd) {
// strip away hinted/useless commands
case DIV_CMD_GET_VOLUME:
break;
case DIV_CMD_VOLUME:
break;
case DIV_CMD_PANNING:
case DIV_CMD_NOTE_PORTA:
break;
case DIV_CMD_LEGATO:
break;
case DIV_CMD_PITCH:
break;
case DIV_CMD_PRE_NOTE:
break;
default:
@ -808,119 +809,6 @@ SafeWriter* DivEngine::saveCommand() {
sortPos++;
}*/
/*
for (int i=0; i<chans; i++) {
// optimize stream
SafeWriter* oldStream=chanStream[i];
SafeReader* reader=oldStream->toReader();
chanStream[i]=new SafeWriter;
chanStream[i]->init();
while (1) {
try {
unsigned char next=reader->readC();
switch (next) {
case 0xb8: // instrument
case 0xc0: // pre porta
case 0xc3: // vibrato range
case 0xc4: // vibrato shape
case 0xc5: // pitch
case 0xc7: // volume
case 0xca: // legato
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
break;
case 0xbe: // panning
case 0xc2: // vibrato
case 0xc6: // arpeggio
case 0xc8: // vol slide
case 0xc9: // porta
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
break;
case 0xf2: { // full command (pre)
unsigned char cmd=reader->readC();
bool foundShort=false;
for (int j=0; j<16; j++) {
if (sortedCmd[j]==cmd) {
chanStream[i]->writeC(0xd0+j);
foundShort=true;
break;
}
}
if (!foundShort) {
chanStream[i]->writeC(0xf7); // full command
chanStream[i]->writeC(cmd);
}
unsigned char cmdLen=reader->readC();
logD("cmdLen: %d",cmdLen);
for (unsigned char j=0; j<cmdLen; j++) {
next=reader->readC();
chanStream[i]->writeC(next);
}
break;
}
case 0xfb: // tick rate
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
next=reader->readC();
chanStream[i]->writeC(next);
break;
case 0xfc: { // 16-bit wait
unsigned short delay=reader->readS();
bool foundShort=false;
for (int j=0; j<16; j++) {
if (sortedDelay[j]==delay) {
chanStream[i]->writeC(0xe0+j);
foundShort=true;
break;
}
}
if (!foundShort) {
chanStream[i]->writeC(next);
chanStream[i]->writeS(delay);
}
break;
}
case 0xfd: { // 8-bit wait
unsigned char delay=reader->readC();
bool foundShort=false;
for (int j=0; j<16; j++) {
if (sortedDelay[j]==delay) {
chanStream[i]->writeC(0xe0+j);
foundShort=true;
break;
}
}
if (!foundShort) {
chanStream[i]->writeC(next);
chanStream[i]->writeC(delay);
}
break;
}
default:
chanStream[i]->writeC(next);
break;
}
} catch (EndOfFileException& e) {
break;
}
}
oldStream->finish();
delete oldStream;
}*/
// write results
for (int i=0; i<chans; i++) {
chanStreamOff[i]=w->tell();

View file

@ -71,6 +71,10 @@ enum DivDispatchCmds {
DIV_CMD_HINT_PORTA, // (target, speed)
DIV_CMD_HINT_LEGATO, // (note)
DIV_CMD_HINT_VOL_SLIDE_TARGET, // (amount, target)
DIV_CMD_HINT_TREMOLO, // (speed/depth as a byte)
DIV_CMD_HINT_PANBRELLO, // (speed/depth as a byte)
DIV_CMD_HINT_PAN_SLIDE, // (speed)
DIV_CMD_HINT_PANNING, // (left, right)
DIV_CMD_SAMPLE_MODE, // (enabled)
DIV_CMD_SAMPLE_FREQ, // (frequency)

View file

@ -68,6 +68,10 @@ const char* cmdName[]={
"HINT_PORTA",
"HINT_LEGATO",
"HINT_VOL_SLIDE_TARGET",
"HINT_TREMOLO",
"HINT_PANBRELLO",
"HINT_PAN_SLIDE",
"HINT_PANNING",
"SAMPLE_MODE",
"SAMPLE_FREQ",
@ -764,6 +768,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
} else {
chan[i].panSpeed=0;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_PAN_SLIDE,i,chan[i].panSpeed&0xff));
break;
case 0x84: // panbrello
if (chan[i].panDepth==0) {
@ -774,6 +779,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
if (chan[i].panDepth!=0) {
chan[i].panSpeed=0;
}
dispatchCmd(DivCommand(DIV_CMD_HINT_PANBRELLO,i,effectVal));
break;
case 0x88: // panning rear (split 4-bit)
chan[i].panRL=(effectVal>>4)|(effectVal&0xf0);
@ -941,6 +947,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
}
chan[i].tremoloDepth=effectVal&15;
chan[i].tremoloRate=effectVal>>4;
dispatchCmd(DivCommand(DIV_CMD_HINT_TREMOLO,i,effectVal));
if (chan[i].tremoloDepth!=0) {
chan[i].volSpeed=0;
chan[i].volSpeedTarget=-1;
@ -1229,6 +1236,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
if (panChanged) {
dispatchCmd(DivCommand(DIV_CMD_PANNING,i,chan[i].panL,chan[i].panR));
dispatchCmd(DivCommand(DIV_CMD_HINT_PANNING,i,chan[i].panL,chan[i].panR));
}
if (surroundPanChanged) {
dispatchCmd(DivCommand(DIV_CMD_SURROUND_PANNING,i,2,chan[i].panRL));

View file

@ -44,10 +44,6 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) {
if (addr+1>=bufLen) return "???";
return fmt::sprintf("ins $%.2x",(int)buf[addr+1]);
break;
case 0xbe:
if (addr+2>=bufLen) return "???";
return fmt::sprintf("pan $%x, $%x",(int)buf[addr+1],(int)buf[addr+2]);
break;
case 0xc0:
if (addr+1>=bufLen) return "???";
return fmt::sprintf("preporta $%.2x",(int)buf[addr+1]);
@ -88,6 +84,26 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) {
if (addr+1>=bufLen) return "???";
return fmt::sprintf("legato %d",(int)buf[addr+1]);
break;
case 0xcb:
if (addr+4>=bufLen) return "???";
return fmt::sprintf("volporta %d, %d",(int)((short)(buf[addr+1]|(buf[addr+2]<<8))),(int)((short)(buf[addr+3]|(buf[addr+4]<<8))));
break;
case 0xcc:
if (addr+1>=bufLen) return "???";
return fmt::sprintf("tremolo $%.2x",(int)buf[addr+1]);
break;
case 0xcd:
if (addr+1>=bufLen) return "???";
return fmt::sprintf("panbrello $%.2x",(int)buf[addr+1]);
break;
case 0xce:
if (addr+1>=bufLen) return "???";
return fmt::sprintf("panslide %d",(signed char)buf[addr+1]);
break;
case 0xcf:
if (addr+2>=bufLen) return "???";
return fmt::sprintf("pan $%x, $%x",(int)buf[addr+1],(int)buf[addr+2]);
break;
case 0xe0: case 0xe1: case 0xe2: case 0xe3:
case 0xe4: case 0xe5: case 0xe6: case 0xe7:
case 0xe8: case 0xe9: case 0xea: case 0xeb:
@ -112,16 +128,12 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) {
if (addr+4>=bufLen) return "???";
return fmt::sprintf("call %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24)));
break;
case 0xf6:
if (addr+4>=bufLen) return "???";
return fmt::sprintf("callb32 %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24)));
break;
case 0xf7:
return "CMD";
break;
case 0xf8:
if (addr+2>=bufLen) return "???";
return fmt::sprintf("callb16 %.4x",(int)(buf[addr+1]|(buf[addr+2]<<8)));
return fmt::sprintf("call %.4x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)));
break;
case 0xf9:
return "ret";