prepare to implement stuff in cmd stream
vol slide with target, tremolo, panbrello and pan slide
This commit is contained in:
parent
a49664a3f5
commit
110562c2c4
|
@ -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
|
||||
|
||||
```
|
||||
|
||||
```
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in a new issue