diff --git a/papers/export-tech.md b/papers/export-tech.md index 44392b8a7..f8673d223 100644 --- a/papers/export-tech.md +++ b/papers/export-tech.md @@ -73,7 +73,9 @@ hex | description | - bit 7: inPorta | - bit 6: isPortaOrSlide c1 | arpeggio speed (b) - c2 | vibrato (bb) // speed, depth + c2 | vibrato (X) + | - bit 4-7: speed + | - bit 0-3: depth c3 | vibrato range (b) c4 | vibrato shape (b) c5 | pitch (c) diff --git a/src/asm/6502/stream.s b/src/asm/6502/stream.s index d68832640..bcfb6bf2b 100644 --- a/src/asm/6502/stream.s +++ b/src/asm/6502/stream.s @@ -46,6 +46,7 @@ fcsTicks=fcsAddrBase+8 ; short ; temporary variables fcsSendVolume=fcsAddrBase+10 ; char fcsSendPitch=fcsAddrBase+11 ; char +fcsArpSpeed=fcsAddrBase+12 ; char fcsCmd=fcsAddrBase+16 ; char[8] fcsTempPtr=fcsZeroPage ; short ; channel state @@ -54,6 +55,14 @@ chanTicks=fcsAddrBase+24 ; short chanStackPtr=fcsAddrBase+24+(FCS_MAX_CHAN*2) ; char chanNote=fcsAddrBase+24+(FCS_MAX_CHAN*2)+1 ; char chanVibratoPos=fcsAddrBase+24+(FCS_MAX_CHAN*4) ; char +chanVibrato=fcsAddrBase+24+(FCS_MAX_CHAN*4)+1 ; char +chanPitch=fcsAddrBase+24+(FCS_MAX_CHAN*6) ; char +chanArp=fcsAddrBase+24+(FCS_MAX_CHAN*6)+1 ; char +chanPortaSpeed=fcsAddrBase+24+(FCS_MAX_CHAN*8) ; char +chanPortaTarget=fcsAddrBase+24+(FCS_MAX_CHAN*8)+1 ; char +chanVol=fcsAddrBase+24+(FCS_MAX_CHAN*10) ; short +chanVolSpeed=fcsAddrBase+24+(FCS_MAX_CHAN*12) ; short +chanPan=fcsAddrBase+24+(FCS_MAX_CHAN*14) ; short ; may be used for driver detection fcsDriverInfo: @@ -94,6 +103,79 @@ fcsPrePorta: jsr fcsDispatchCmd rts +fcsArpTime: + jsr fcsReadNext + sta fcsArpSpeed + rts + +fcsVibrato: + jsr fcsReadNext + sta chanVibrato,x + rts + +; TODO +fcsVibRange: +fcsVibShape: + jsr fcsReadNext + rts + +fcsPitch: + jsr fcsReadNext + sta chanPitch,x + lda #1 + sta fcsSendPitch + rts + +fcsArpeggio: + jsr fcsReadNext + sta chanArp,x + rts + +fcsVolume: + jsr fcsReadNext + sta chanVol+1,x + lda #0 + sta chanVol,x + lda #1 + sta fcsSendVolume + rts + +fcsVolSlide: + jsr fcsReadNext + sta chanVolSpeed,x + jsr fcsReadNext + sta chanVolSpeed+1,x + rts + +fcsPorta: + jsr fcsReadNext + sta chanPortaTarget,x + jsr fcsReadNext + sta chanPortaSpeed,x + rts + +fcsLegato: + jsr fcsReadNext + sta chanNote,x + sta fcsArg0 + ldy #11 + jsr fcsDispatchCmd + rts + +fcsVolSlideTarget: + jsr fcsReadNext + sta chanVolSpeed,x + jsr fcsReadNext + sta chanVolSpeed+1,x + ; TODO: we don't support this yet... + jsr fcsReadNext + jsr fcsReadNext + rts + +fcsNoOpOneByte: + jsr fcsReadNext + rts + fcsNoOp: rts diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index 63c8212fa..f2c51ae39 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -140,11 +140,13 @@ bool DivCSPlayer::tick() { case 0xc1: // arp time arpSpeed=(unsigned char)stream.readC(); break; - case 0xc2: // vibrato - chan[i].vibratoDepth=(signed char)stream.readC(); - chan[i].vibratoRate=(unsigned char)stream.readC(); + case 0xc2: { // vibrato + unsigned char param=stream.readC(); + chan[i].vibratoDepth=param&15; + chan[i].vibratoRate=param>>4; sendPitch=true; break; + } case 0xc3: // vibrato range chan[i].vibratoRange=(unsigned char)stream.readC(); break; diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index e21f9b2fe..ee32d4ff1 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -244,9 +244,9 @@ int DivCS::getInsLength(unsigned char ins, unsigned char ext, unsigned char* spe case 0xcd: // panbrello case 0xce: // pan slide case 0xdd: // waitc + case 0xc2: // vibrato return 2; case 0xcf: // pan - case 0xc2: // vibrato case 0xc8: // vol slide case 0xc9: // porta return 3; @@ -373,10 +373,10 @@ void writeCommandValues(SafeWriter* w, const DivCommand& c, bool bigEndian) { case DIV_CMD_HINT_PAN_SLIDE: case DIV_CMD_HINT_ARPEGGIO: case DIV_CMD_HINT_ARP_TIME: + case DIV_CMD_HINT_VIBRATO: w->writeC(c.value); break; case DIV_CMD_HINT_PANNING: - case DIV_CMD_HINT_VIBRATO: case DIV_CMD_HINT_PORTA: w->writeC(c.value); w->writeC(c.value2); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index cebd9846b..2085f279f 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -870,7 +870,7 @@ void DivEngine::processRow(int i, bool afterDelay) { if (effectVal) chan[i].lastVibrato=effectVal; chan[i].vibratoDepth=effectVal&15; chan[i].vibratoRate=effectVal>>4; - dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate)); + dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,(chan[i].vibratoDepth&15)|(chan[i].vibratoRate<<4))); dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15))); break; case 0x05: // vol slide + vibrato @@ -881,7 +881,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].vibratoDepth=chan[i].lastVibrato&15; chan[i].vibratoRate=chan[i].lastVibrato>>4; } - dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,chan[i].vibratoDepth,chan[i].vibratoRate)); + dispatchCmd(DivCommand(DIV_CMD_HINT_VIBRATO,i,(chan[i].vibratoDepth&15)|(chan[i].vibratoRate<<4))); dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(((chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15))); // TODO: non-0x-or-x0 value should be treated as 00 if (effectVal!=0) { diff --git a/src/gui/csPlayer.cpp b/src/gui/csPlayer.cpp index 95832bed2..fd8234569 100644 --- a/src/gui/csPlayer.cpp +++ b/src/gui/csPlayer.cpp @@ -49,8 +49,8 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr, unsigned return fmt::sprintf("preporta $%.2x",(int)buf[addr+1]); break; case 0xc2: - if (addr+2>=bufLen) return "???"; - return fmt::sprintf("vib %d, %d",(int)buf[addr+1],(int)buf[addr+2]); + if (addr+1>=bufLen) return "???"; + return fmt::sprintf("vib $%.2x",(int)buf[addr+1]); break; case 0xc3: if (addr+1>=bufLen) return "???";