From 6fba60818dda13a0d9d8e856783a7d46c1df0b4f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 5 Apr 2025 19:27:44 -0500 Subject: [PATCH] implement command playback - UNTESTED! --- src/engine/cmdStream.cpp | 132 +++++++++++++++++++++++++++++++++++- src/engine/cmdStreamOps.cpp | 60 ++++++++-------- src/gui/csPlayer.cpp | 10 ++- 3 files changed, 169 insertions(+), 33 deletions(-) diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index f948a1ae7..6865adb8e 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -223,7 +223,6 @@ bool DivCSPlayer::tick() { case DIV_CMD_HINT_VIBRATO_RANGE: case DIV_CMD_HINT_VIBRATO_SHAPE: case DIV_CMD_HINT_VOLUME: - case DIV_CMD_HINT_ARP_TIME: arg0=(unsigned char)stream.readC(); break; case DIV_CMD_HINT_PITCH: @@ -259,14 +258,16 @@ bool DivCSPlayer::tick() { arg0-=60; } break; + // ONE BYTE COMMANDS case DIV_CMD_SAMPLE_MODE: case DIV_CMD_SAMPLE_FREQ: case DIV_CMD_SAMPLE_BANK: - case DIV_CMD_SAMPLE_POS: case DIV_CMD_SAMPLE_DIR: case DIV_CMD_FM_HARD_RESET: case DIV_CMD_FM_LFO: case DIV_CMD_FM_LFO_WAVE: + case DIV_CMD_FM_LFO2: + case DIV_CMD_FM_LFO2_WAVE: case DIV_CMD_FM_FB: case DIV_CMD_FM_EXTCH: case DIV_CMD_FM_AM_DEPTH: @@ -306,8 +307,101 @@ bool DivCSPlayer::tick() { case DIV_CMD_MACRO_OFF: case DIV_CMD_MACRO_ON: case DIV_CMD_MACRO_RESTART: + case DIV_CMD_HINT_ARP_TIME: + case DIV_CMD_QSOUND_ECHO_FEEDBACK: + case DIV_CMD_QSOUND_ECHO_LEVEL: + case DIV_CMD_QSOUND_SURROUND: + case DIV_CMD_X1_010_ENVELOPE_SHAPE: + case DIV_CMD_X1_010_ENVELOPE_ENABLE: + case DIV_CMD_X1_010_ENVELOPE_MODE: + case DIV_CMD_X1_010_ENVELOPE_PERIOD: + case DIV_CMD_X1_010_ENVELOPE_SLIDE: + case DIV_CMD_X1_010_AUTO_ENVELOPE: + 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: + case DIV_CMD_N163_WAVE_LOADLEN: + case DIV_CMD_N163_WAVE_UNUSED3: + case DIV_CMD_N163_CHANNEL_LIMIT: + case DIV_CMD_N163_GLOBAL_WAVE_LOAD: + case DIV_CMD_N163_GLOBAL_WAVE_LOADPOS: + case DIV_CMD_N163_UNUSED4: + case DIV_CMD_N163_UNUSED5: + case DIV_CMD_SU_SYNC_PERIOD_LOW: + case DIV_CMD_SU_SYNC_PERIOD_HIGH: + case DIV_CMD_ADPCMA_GLOBAL_VOLUME: + case DIV_CMD_SNES_ECHO: + case DIV_CMD_SNES_PITCH_MOD: + case DIV_CMD_SNES_INVERT: + case DIV_CMD_SNES_GAIN_MODE: + case DIV_CMD_SNES_GAIN: + case DIV_CMD_SNES_ECHO_ENABLE: + case DIV_CMD_SNES_ECHO_DELAY: + case DIV_CMD_SNES_ECHO_VOL_LEFT: + case DIV_CMD_SNES_ECHO_VOL_RIGHT: + case DIV_CMD_SNES_ECHO_FEEDBACK: + case DIV_CMD_NES_ENV_MODE: + case DIV_CMD_NES_LENGTH: + case DIV_CMD_NES_COUNT_MODE: + case DIV_CMD_FM_AM2_DEPTH: + case DIV_CMD_FM_PM2_DEPTH: + case DIV_CMD_ES5506_ENVELOPE_LVRAMP: + case DIV_CMD_ES5506_ENVELOPE_RVRAMP: + case DIV_CMD_ES5506_PAUSE: + case DIV_CMD_ES5506_FILTER_MODE: + case DIV_CMD_SNES_GLOBAL_VOL_LEFT: + case DIV_CMD_SNES_GLOBAL_VOL_RIGHT: + case DIV_CMD_NES_LINEAR_LENGTH: + case DIV_CMD_EXTERNAL: + case DIV_CMD_C64_AD: + case DIV_CMD_C64_SR: + case DIV_CMD_DAVE_HIGH_PASS: + case DIV_CMD_DAVE_RING_MOD: + case DIV_CMD_DAVE_SWAP_COUNTERS: + case DIV_CMD_DAVE_LOW_PASS: + case DIV_CMD_DAVE_CLOCK_DIV: + case DIV_CMD_MINMOD_ECHO: + case DIV_CMD_FDS_MOD_AUTO: + case DIV_CMD_FM_OPMASK: + case DIV_CMD_MULTIPCM_MIX_FM: + case DIV_CMD_MULTIPCM_MIX_PCM: + case DIV_CMD_MULTIPCM_LFO: + case DIV_CMD_MULTIPCM_VIB: + case DIV_CMD_MULTIPCM_AM: + case DIV_CMD_MULTIPCM_AR: + case DIV_CMD_MULTIPCM_D1R: + case DIV_CMD_MULTIPCM_DL: + case DIV_CMD_MULTIPCM_D2R: + case DIV_CMD_MULTIPCM_RC: + case DIV_CMD_MULTIPCM_RR: + case DIV_CMD_MULTIPCM_DAMP: + case DIV_CMD_MULTIPCM_PSEUDO_REVERB: + case DIV_CMD_MULTIPCM_LFO_RESET: + case DIV_CMD_MULTIPCM_LEVEL_DIRECT: + case DIV_CMD_SID3_SPECIAL_WAVE: + case DIV_CMD_SID3_RING_MOD_SRC: + case DIV_CMD_SID3_HARD_SYNC_SRC: + case DIV_CMD_SID3_PHASE_MOD_SRC: + case DIV_CMD_SID3_WAVE_MIX: + case DIV_CMD_SID3_1_BIT_NOISE: + case DIV_CMD_SID3_CHANNEL_INVERSION: + case DIV_CMD_SID3_FILTER_CONNECTION: + case DIV_CMD_SID3_FILTER_MATRIX: + case DIV_CMD_SID3_FILTER_ENABLE: + case DIV_CMD_SID3_PHASE_RESET: + case DIV_CMD_SID3_NOISE_PHASE_RESET: + case DIV_CMD_SID3_ENVELOPE_RESET: + case DIV_CMD_SID3_CUTOFF_SCALING: + case DIV_CMD_SID3_RESONANCE_SCALING: + case DIV_CMD_WS_GLOBAL_SPEAKER_VOLUME: arg0=(unsigned char)stream.readC(); break; + // TWO BYTE COMMANDS case DIV_CMD_FM_TL: case DIV_CMD_FM_AM: case DIV_CMD_FM_AR: @@ -330,14 +424,45 @@ bool DivCSPlayer::tick() { case DIV_CMD_AY_IO_WRITE: case DIV_CMD_AY_AUTO_PWM: case DIV_CMD_SURROUND_PANNING: + case DIV_CMD_SU_SWEEP_PERIOD_LOW: + case DIV_CMD_SU_SWEEP_PERIOD_HIGH: + case DIV_CMD_SU_SWEEP_BOUND: + case DIV_CMD_SU_SWEEP_ENABLE: + case DIV_CMD_SNES_ECHO_FIR: + case DIV_CMD_ES5506_FILTER_K1_SLIDE: + case DIV_CMD_ES5506_FILTER_K2_SLIDE: + case DIV_CMD_ES5506_ENVELOPE_K1RAMP: + case DIV_CMD_ES5506_ENVELOPE_K2RAMP: + case DIV_CMD_ESFM_OP_PANNING: + case DIV_CMD_ESFM_OUTLVL: + case DIV_CMD_ESFM_MODIN: + case DIV_CMD_ESFM_ENV_DELAY: + case DIV_CMD_POWERNOISE_COUNTER_LOAD: + case DIV_CMD_POWERNOISE_IO_WRITE: + case DIV_CMD_BIFURCATOR_STATE_LOAD: + case DIV_CMD_BIFURCATOR_PARAMETER: + case DIV_CMD_SID3_LFSR_FEEDBACK_BITS: + case DIV_CMD_SID3_FILTER_DISTORTION: + case DIV_CMD_SID3_FILTER_OUTPUT_VOLUME: + case DIV_CMD_C64_PW_SLIDE: + case DIV_CMD_C64_CUTOFF_SLIDE: arg0=(unsigned char)stream.readC(); arg1=(unsigned char)stream.readC(); break; + // ONE SHORT COMMANDS case DIV_CMD_C64_FINE_DUTY: case DIV_CMD_C64_FINE_CUTOFF: case DIV_CMD_LYNX_LFSR_LOAD: + case DIV_CMD_QSOUND_ECHO_DELAY: + case DIV_CMD_ES5506_ENVELOPE_COUNT: arg0=(unsigned short)stream.readS(); break; + // TWO SHORT COMMANDS + case DIV_CMD_ES5506_FILTER_K1: + case DIV_CMD_ES5506_FILTER_K2: + arg0=(unsigned short)stream.readS(); + arg1=(unsigned short)stream.readS(); + break; case DIV_CMD_FM_FIXFREQ: arg0=(unsigned short)stream.readS(); arg1=arg0&0x7ff; @@ -348,6 +473,9 @@ bool DivCSPlayer::tick() { arg1=arg0&0x77; arg0=(arg0&8)?1:0; break; + case DIV_CMD_SAMPLE_POS: + arg0=(unsigned int)stream.readI(); + break; } switch (command) { diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index f508d11c8..d09a9801c 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -913,7 +913,32 @@ SafeWriter* DivEngine::saveCommand() { extValuePresent=false; BUSY_END; - // PASS 1: condense delays + // PASS 1: optimize command calls + // calculate command usage + int sortCand=-1; + int sortPos=0; + while (sortPos<16) { + sortCand=-1; + for (int i=DIV_CMD_SAMPLE_MODE; i<256; i++) { + if (cmdPopularity[i]) { + if (sortCand==-1) { + sortCand=i; + } else if (cmdPopularity[sortCand]getFinalBuf(); @@ -937,8 +962,8 @@ SafeWriter* DivEngine::saveCommand() { } // preset delays - int sortCand=-1; - int sortPos=0; + sortCand=-1; + sortPos=0; while (sortPos<16) { sortCand=-1; for (int i=0; i<256; i++) { @@ -1015,14 +1040,14 @@ SafeWriter* DivEngine::saveCommand() { } } - // PASS 2: remove nop's + // PASS 3: remove nop's // this includes modifying call addresses to compensate for (int h=0; h subBlocks; size_t beforeSize=chanStream[h]->size(); @@ -1109,34 +1134,11 @@ SafeWriter* DivEngine::saveCommand() { } #endif - // PASS 4: remove nop's (again) + // PASS 5: remove nop's (again) for (int h=0; htell(); diff --git a/src/gui/csPlayer.cpp b/src/gui/csPlayer.cpp index 842fc1ac0..6f5defc92 100644 --- a/src/gui/csPlayer.cpp +++ b/src/gui/csPlayer.cpp @@ -104,6 +104,12 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) { if (addr+2>=bufLen) return "???"; return fmt::sprintf("pan $%x, $%x",(int)buf[addr+1],(int)buf[addr+2]); break; + case 0xd0: case 0xd1: case 0xd2: case 0xd3: + case 0xd4: case 0xd5: case 0xd6: case 0xd7: + case 0xd8: case 0xd9: case 0xda: case 0xdb: + case 0xdc: case 0xdd: case 0xde: case 0xdf: + return "qcmd"; + 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: @@ -129,7 +135,7 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) { return fmt::sprintf("call %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24))); break; case 0xf7: - return "CMD"; + return "cmd"; break; case 0xf8: if (addr+2>=bufLen) return "???"; @@ -329,7 +335,7 @@ void FurnaceGUI::drawCSPlayer() { csDisAsm.clear(); unsigned char* buf=cs->getData(); for (size_t i=csDisAsmAddr; igetDataLen();) { - int insLen=DivCS::getInsLength(buf[i]); + int insLen=DivCS::getInsLength(buf[i],(((i+1)getDataLen())?buf[i+1]:0),cs->getFastCmds()); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break;