diff --git a/papers/export-tech.md b/papers/export-tech.md index 88fc13c02..b8d4bfb65 100644 --- a/papers/export-tech.md +++ b/papers/export-tech.md @@ -32,6 +32,21 @@ program follows. ### commands/instructions +command parameters (including their types) are indicated within parentheses. for example, (cs) means "read a char (8-bit) and a short (16-bit)". + +the types are: + +- `c`: signed char +- `s`: signed short (16-bit) +- `i`: signed int (32-bit) +- `b`: unsigned char (byte) +- `S`: unsigned short +- `U`: unsigned int +- `X`: custom (described under the command name) + + +the command list follows. + ``` hex | description ----|------------------------------------ @@ -47,22 +62,28 @@ hex | description b5 | note off b6 | note off env b7 | env release - b8 | instrument // (ins, force) - c0 | pre porta // (inporta, isportaorslide) - c2 | vibrato // (speed, depth) - c3 | vibrato range // (range) - c4 | vibrato shape // (shape) - c5 | pitch // (pitch) - c6 | arpeggio // (note1, note2) - c7 | volume // (vol) - 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) + b8 | instrument (b) + c0 | pre porta (X) + | - bit 7: inPorta + | - bit 6: isPortaOrSlide + c2 | vibrato (bb) // speed, depth + c3 | vibrato range (b) + c4 | vibrato shape (b) + c5 | pitch (c) + c6 | arpeggio (bb) // note1, note2 + c7 | volume (b) + c8 | vol slide (s) + c9 | porta (bb) // target, speed + ca | legato (b) // note... $ff is null note + cb | volume slide with target (sS) // amount, target + cc | tremolo (X) + | - bit 4-7: speed + | - bit 0-3: depth + cd | panbrello (X) + | - bit 4-7: speed + | - bit 0-3: depth + ce | pan slide (c) + cf | panning (bb) // left, right ----|------------------------------------ d0 | speed dial command 0 d1 | speed dial command 1 @@ -97,270 +118,280 @@ hex | description ``` hex | description ----|------------------------------------ - 1c | sample mode - 1d | sample freq - 1e | legacy sample bank - 1f | sample position - 20 | sample direction + 1c | sample mode (b) + 1d | sample freq (b) + 1e | legacy sample bank (b) + 1f | sample position (U) + 20 | sample direction (b) ----|------------------------------------ | **FM commands** - 21 | hard reset - 22 | LFO speed - 23 | LFO waveform - 24 | TL - 25 | AM - 26 | AR - 27 | DR - 28 | SL - 29 | D2R - 2a | RR - 2b | DT - 2c | DT2 - 2d | RS - 2e | KSR - 2f | VIB - 30 | SUS - 31 | WS - 32 | SSG-EG - 33 | REV - 34 | EG-Shift - 35 | FB - 36 | MULT - 37 | FINE - 38 | fixed frequency - 39 | ExtCh - 3a | AM depth - 3b | PM depth - 3c | LFO2 speed - 3d | LFO2 wave + 21 | hard reset (b) + 22 | LFO speed (b) + 23 | LFO waveform (b) + 24 | TL (bb) + 25 | AM (bb) + 26 | AR (bb) + 27 | DR (bb) + 28 | SL (bb) + 29 | D2R (bb) + 2a | RR (bb) + 2b | DT (bb) + 2c | DT2 (bb) + 2d | RS (bb) + 2e | KSR (bb) + 2f | VIB (bb) + 30 | SUS (bb) + 31 | WS (bb) + 32 | SSG-EG (bb) + 33 | REV (bb) + 34 | EG-Shift (bb) + 35 | FB (b) + 36 | MULT (bb) + 37 | FINE (bb) + 38 | fixed frequency (XX) + | - byte 0: frequency low + | - byte 1: + | - bit 4-5: operator + | - bit 0-2: frequency high + 39 | ExtCh (b) + 3a | AM depth (b) + 3b | PM depth (b) + 3c | LFO2 speed (b) + 3d | LFO2 wave (b) ----|------------------------------------ | **PSG commands** - 3e | noise freq - 3f | noise mode/duty/whatever - 40 | waveform + 3e | noise freq (b) + 3f | noise mode/duty/whatever (b) + 40 | waveform (b) ----|------------------------------------ | **Game Boy commands** - 41 | sweep time - 42 | sweep direction + 41 | sweep time (b) + 42 | sweep direction (b) ----|------------------------------------ | **PC Engine commands** - 43 | LFO mode - 44 | LFO speed + 43 | LFO mode (b) + 44 | LFO speed (b) ----|------------------------------------ | **NES commands** - 45 | sweep - 46 | set DMC + 45 | sweep (X) + | - bit 3: on + | - rest of bits: sweep time/amount + 46 | set DMC (b) ----|------------------------------------ | **C64 commands** - 47 | coarse cutoff - 48 | resonance - 49 | filter mode - 4a | reset time - 4b | reset mask - 4c | filter reset - 4d | duty reset - 4e | extended - 4f | duty - 50 | cutoff + 47 | coarse cutoff (b) + 48 | resonance (b) + 49 | filter mode (b) + 4a | reset time (b) + 4b | reset mask (b) + 4c | filter reset (b) + 4d | duty reset (b) + 4e | extended (b) + 4f | duty (S) + 50 | cutoff (S) ----|------------------------------------ | **AY commands** - 51 | set envelope - 52 | envelope freq low - 53 | envelope freq high - 54 | envelope slide - 55 | noise AND mask - 56 | noise OR mask - 57 | auto envelope - 58 | I/O port write - 59 | AutoPWM + 51 | set envelope (b) + 52 | envelope freq low (b) + 53 | envelope freq high (b) + 54 | envelope slide (b) + 55 | noise AND mask (b) + 56 | noise OR mask (b) + 57 | auto envelope (b) + 58 | I/O port write (bb) + 59 | AutoPWM (bb) ----|------------------------------------ | **FDS commands** - 5a | mod depth - 5b | mod speed high - 5c | mod speed low - 5d | mod position - 5e | mod waveform + 5a | mod depth (b) + 5b | mod speed high (b) + 5c | mod speed low (b) + 5d | mod position (b) + 5e | mod waveform (b) ----|------------------------------------ | **SAA1099 commands** - 5f | envelope + 5f | envelope (b) ----|------------------------------------ | **Amiga commands** - 60 | toggle filter - 61 | AM - 62 | period modulation + 60 | toggle filter (b) + 61 | AM (b) + 62 | period modulation (b) ----|------------------------------------ | **Lynx commands** - 63 | load LFSR + 63 | load LFSR (S) ----|------------------------------------ | **QSound commands** - 64 | echo feedback - 65 | echo delay - 66 | echo level - 67 | surround + 64 | echo feedback (b) + 65 | echo delay (S) + 66 | echo level (b) + 67 | surround (b) ----|------------------------------------ | **X1-010 commands** - 68 | envelope shape - 69 | envelope enable - 6a | envelope mode - 6b | envelope period - 6c | envelope slide - 6d | auto envelope - 6e | sample bank slot + 68 | envelope shape (b) + 69 | UNUSED - envelope enable (b) + 6a | envelope mode (b) + 6b | envelope period (b) + 6c | envelope slide (b) + 6d | auto envelope (b) + 6e | sample bank slot (b) ----|------------------------------------ | **WonderSwan commands** - 6f | sweep time - 70 | sweep amount + 6f | sweep time (b) + 70 | sweep amount (b) ----|------------------------------------ | **Namco 163 commands** - 71 | wave position - 72 | wave length - 73 | UNUSED - 74 | UNUSED - 75 | wave load position - 76 | wave load length - 77 | UNUSED - 78 | channel limit - 79 | global wave load - 7a | global wave load position - 7b | UNUSED - 7c | UNUSED + 71 | wave position (b) + 72 | wave length (b) + 73 | UNUSED (b) + 74 | UNUSED (b) + 75 | wave load position (b) + 76 | wave load length (b) + 77 | UNUSED (b) + 78 | channel limit (b) + 79 | global wave load (b) + 7a | global wave load position (b) + 7b | UNUSED (b) + 7c | UNUSED (b) ----|------------------------------------ | **Sound Unit commands** - 7d | sweep period low - 7e | sweep period high - 7f | sweep bound - 80 | sweep enable - 81 | sync period low - 82 | sync period high + 7d | sweep period low (bb) + 7e | sweep period high (bb) + 7f | sweep bound (bb) + 80 | sweep enable (bb) + 81 | sync period low (b) + 82 | sync period high (b) ----|------------------------------------ - 83 | ADPCM-A volume + 83 | ADPCM-A volume (b) ----|------------------------------------ | **SNES commands** - 84 | echo - 85 | pitch mod - 86 | invert - 87 | gain mode - 88 | gain - 89 | echo enable - 8a | echo delay - 8b | echo vol left - 8c | echo vol right - 8d | echo feedback - 8e | echo filter + 84 | echo (b) + 85 | pitch mod (b) + 86 | invert (b) + 87 | gain mode (b) + 88 | gain (b) + 89 | echo enable (b) + 8a | echo delay (b) + 8b | echo vol left (c) + 8c | echo vol right (c) + 8d | echo feedback (c) + 8e | echo filter (bc) ----|------------------------------------ | **NES commands (continued)** - 8f | envelope mode - 90 | length counter - 91 | count mode (?) + 8f | envelope mode (b) + 90 | length counter (b) + 91 | frame counter rate/count mode (b) ----|------------------------------------ | **macro control** - 92 | macro off - 93 | macro on + 92 | macro off (b) + 93 | macro on (b) ----|------------------------------------ - 94 | surround panning + 94 | surround panning (bb) ----|------------------------------------ | **FM commands (continued)** - 95 | AM depth 2 - 96 | PM depth 2 + 95 | AM depth 2 (b) + 96 | PM depth 2 (b) ----|------------------------------------ | **ES5506 commands** - 97 | filter mode - 98 | filter K1 - 99 | filter K2 - 9a | filter K1 slide - 9b | filter K2 slide - 9c | envelope count - 9d | envelope left vol ramp - 9e | envelope right vol ramp - 9f | envelope K1 ramp - a0 | envelope K2 ramp - a1 | pause + 97 | filter mode (b) + 98 | filter K1 (SS) + 99 | filter K2 (SS) + 9a | filter K1 slide (bb) + 9b | filter K2 slide (bb) + 9c | envelope count (S) + 9d | envelope left vol ramp (b) + 9e | envelope right vol ramp (b) + 9f | envelope K1 ramp (bb) + a0 | envelope K2 ramp (bb) + a1 | pause (b) ----|------------------------------------ - a2 | arpeggio speed + a2 | arpeggio speed (b) ----|------------------------------------ | **SNES commands (continued)** - a3 | global vol left - a4 | global vol right + a3 | global vol left (c) + a4 | global vol right (c) ----|------------------------------------ - a5 | NES linear counter length + a5 | NES linear counter length (b) ----|------------------------------------ - a6 | external command + a6 | external command (b) ----|------------------------------------ | **C64 commands (continued)** - a7 | attack/decay - a8 | sustain/release + a7 | attack/decay (X) + | - bit 4-7: attack + | - bit 0-3: decay + a8 | sustain/release (X) + | - bit 4-7: sustain + | - bit 0-3: release ----|------------------------------------ | **ESFM commands** - a9 | operator panning - aa | output level - ab | modulation input - ac | envelope delay + a9 | operator panning (bb) + aa | output level (bb) + ab | modulation input (bb) + ac | envelope delay (bb) ----|------------------------------------ - ad | restart macro + ad | restart macro (b) ----|------------------------------------ | **PowerNoise commands** - ae | load counter - af | I/O write + ae | load counter (bb) + af | I/O write (bb) ----|------------------------------------ | **Dave commands** - b0 | high pass - b1 | ring mod - b2 | swap counters - b3 | low pass - b4 | clock divider + b0 | high pass (b) + b1 | ring mod (b) + b2 | swap counters (b) + b3 | low pass (b) + b4 | clock divider (b) ----|------------------------------------ - b5 | MinMod echo setup + b5 | MinMod echo setup (b) ----|------------------------------------ | **Bifurcator commands** - b6 | state load - b7 | set parameter + b6 | state load (bb) + b7 | set parameter (bb) ----|------------------------------------ - b8 | FDS auto mod + b8 | FDS auto mod (b) ----|------------------------------------ - b9 | FM operator mask + b9 | FM operator mask (b) ----|------------------------------------ | **MultiPCM commands** - ba | mix FM - bb | mix PCM - bc | LFO - bd | VIB - be | AM - bf | AR - c0 | D1R - c1 | DL - c2 | D2R - c3 | RC - c4 | RR - c5 | damp - c6 | pseudo-reverb - c7 | LFO reset - c8 | level direct + ba | mix FM (b) + bb | mix PCM (b) + bc | LFO (b) + bd | VIB (b) + be | AM (b) + bf | AR (b) + c0 | D1R (b) + c1 | DL (b) + c2 | D2R (b) + c3 | RC (b) + c4 | RR (b) + c5 | damp (b) + c6 | pseudo-reverb (b) + c7 | LFO reset (b) + c8 | level direct (b) ----|------------------------------------ | **SID3 commands** - c9 | special wave - ca | ring mod source - cb | hard sync source - cc | phase mod source - cd | wave mix - ce | LFSR feedback bits - cf | 1-bit noise - d0 | filter distortion - d1 | filter output volume - d2 | channel invert - d3 | filter connection - d4 | filter matrix - d5 | filter enable + c9 | special wave (b) + ca | ring mod source (b) + cb | hard sync source (b) + cc | phase mod source (b) + cd | wave mix (b) + ce | LFSR feedback bits (bb) + cf | 1-bit noise (b) + d0 | filter distortion (bb) + d1 | filter output volume (bb) + d2 | channel invert (b) + d3 | filter connection (b) + d4 | filter matrix (b) + d5 | filter enable (b) ----|------------------------------------ | **slide commands** - d6 | pulse width slide - d7 | cutoff slide + d6 | pulse width slide (bc) + d7 | cutoff slide (bc) ----|------------------------------------ | **SID3 commands (continued)** - d8 | phase reset - d9 | noise phase reset - da | envelope reset - db | cutoff scaling - dc | resonance scaling + d8 | phase reset (b) + d9 | noise phase reset (b) + da | envelope reset (b) + db | cutoff scaling (b) + dc | resonance scaling (b) ----|------------------------------------ - dd | WonderSwan speaker volume + dd | WonderSwan speaker volume (b) ``` diff --git a/src/engine/cmdStream.h b/src/engine/cmdStream.h index 58f27a83f..90ba5a0b3 100644 --- a/src/engine/cmdStream.h +++ b/src/engine/cmdStream.h @@ -105,7 +105,8 @@ class DivCSPlayer { // command stream utilities namespace DivCS { - int getInsLength(unsigned char ins, unsigned char ext=0); + int getCmdLength(unsigned char ext); + int getInsLength(unsigned char ins, unsigned char ext=0, unsigned char* speedDial=NULL); }; #endif diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index fed85115a..f508d11c8 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -23,7 +23,216 @@ //#define DISABLE_BLOCK_SEARCH -int DivCS::getInsLength(unsigned char ins, unsigned char ext) { +int DivCS::getCmdLength(unsigned char ext) { + switch (ext) { + case DIV_CMD_SAMPLE_MODE: + case DIV_CMD_SAMPLE_FREQ: + case DIV_CMD_SAMPLE_BANK: + 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: + case DIV_CMD_FM_PM_DEPTH: + case DIV_CMD_STD_NOISE_FREQ: + case DIV_CMD_STD_NOISE_MODE: + case DIV_CMD_WAVE: + case DIV_CMD_GB_SWEEP_TIME: + case DIV_CMD_GB_SWEEP_DIR: + case DIV_CMD_PCE_LFO_MODE: + case DIV_CMD_PCE_LFO_SPEED: + case DIV_CMD_NES_DMC: + case DIV_CMD_C64_CUTOFF: + case DIV_CMD_C64_RESONANCE: + case DIV_CMD_C64_FILTER_MODE: + case DIV_CMD_C64_RESET_TIME: + case DIV_CMD_C64_RESET_MASK: + case DIV_CMD_C64_FILTER_RESET: + case DIV_CMD_C64_DUTY_RESET: + case DIV_CMD_C64_EXTENDED: + case DIV_CMD_AY_ENVELOPE_SET: + case DIV_CMD_AY_ENVELOPE_LOW: + case DIV_CMD_AY_ENVELOPE_HIGH: + case DIV_CMD_AY_ENVELOPE_SLIDE: + case DIV_CMD_AY_NOISE_MASK_AND: + case DIV_CMD_AY_NOISE_MASK_OR: + case DIV_CMD_AY_AUTO_ENVELOPE: + case DIV_CMD_FDS_MOD_DEPTH: + case DIV_CMD_FDS_MOD_HIGH: + case DIV_CMD_FDS_MOD_LOW: + case DIV_CMD_FDS_MOD_POS: + case DIV_CMD_FDS_MOD_WAVE: + case DIV_CMD_SAA_ENVELOPE: + case DIV_CMD_AMIGA_FILTER: + case DIV_CMD_AMIGA_AM: + case DIV_CMD_AMIGA_PM: + 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: + return 1; + case DIV_CMD_FM_TL: + case DIV_CMD_FM_AM: + case DIV_CMD_FM_AR: + case DIV_CMD_FM_DR: + case DIV_CMD_FM_SL: + case DIV_CMD_FM_D2R: + case DIV_CMD_FM_RR: + case DIV_CMD_FM_DT: + case DIV_CMD_FM_DT2: + case DIV_CMD_FM_RS: + case DIV_CMD_FM_KSR: + case DIV_CMD_FM_VIB: + case DIV_CMD_FM_SUS: + case DIV_CMD_FM_WS: + case DIV_CMD_FM_SSG: + case DIV_CMD_FM_REV: + case DIV_CMD_FM_EG_SHIFT: + case DIV_CMD_FM_MULT: + case DIV_CMD_FM_FINE: + 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: + return 2; + 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: + return 2; + case DIV_CMD_ES5506_FILTER_K1: + case DIV_CMD_ES5506_FILTER_K2: + return 4; + case DIV_CMD_FM_FIXFREQ: + return 2; + case DIV_CMD_NES_SWEEP: + return 2; + case DIV_CMD_SAMPLE_POS: + return 4; + default: + return 0; + } + return 0; +} + +int DivCS::getInsLength(unsigned char ins, unsigned char ext, unsigned char* speedDial) { switch (ins) { case 0xb8: // ins case 0xc0: // pre porta @@ -45,14 +254,14 @@ int DivCS::getInsLength(unsigned char ins, unsigned char ext) { 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 0; + if (speedDial==NULL) return 0; + return 1+getCmdLength(speedDial[ins&15]); case 0xf0: // opt return 4; - case 0xf7: { // cmd + case 0xf7: // cmd // determine length from secondary if (ext==0) return 0; - return 0; - } + return 2+getCmdLength(ext); case 0xf8: // call case 0xfc: // waits return 3; @@ -97,7 +306,6 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { w->writeC((unsigned char)c.cmd+0xb4); break; default: - return; w->writeC(0xf7); w->writeC(c.cmd); break; @@ -145,11 +353,12 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { 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: @@ -190,7 +399,97 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { case DIV_CMD_MACRO_ON: case DIV_CMD_MACRO_RESTART: case DIV_CMD_HINT_ARP_TIME: - w->writeC(1); // length + 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: w->writeC(c.value); break; case DIV_CMD_FM_TL: @@ -215,37 +514,66 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { case DIV_CMD_AY_IO_WRITE: case DIV_CMD_AY_AUTO_PWM: case DIV_CMD_SURROUND_PANNING: - w->writeC(2); // length + 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: w->writeC(c.value); w->writeC(c.value2); break; case DIV_CMD_C64_FINE_DUTY: case DIV_CMD_C64_FINE_CUTOFF: case DIV_CMD_LYNX_LFSR_LOAD: - w->writeC(2); // length + case DIV_CMD_QSOUND_ECHO_DELAY: + case DIV_CMD_ES5506_ENVELOPE_COUNT: w->writeS(c.value); break; + case DIV_CMD_ES5506_FILTER_K1: + case DIV_CMD_ES5506_FILTER_K2: + w->writeS(c.value); + w->writeS(c.value2); + break; case DIV_CMD_FM_FIXFREQ: - w->writeC(2); // length w->writeS((c.value<<12)|(c.value2&0x7ff)); break; case DIV_CMD_NES_SWEEP: - w->writeC(1); // length w->writeC((c.value?8:0)|(c.value2&0x77)); break; + case DIV_CMD_SAMPLE_POS: + w->writeI(c.value); + break; default: logW("unimplemented command %s!",cmdName[c.cmd]); - w->writeC(0); // length break; } } +#define _EXT(b,x,l) (((size_t)((x)+1)<(size_t)(l))?(b[(x)+1]):0) + using namespace DivCS; -void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr) { +void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr, unsigned char* speedDial) { unsigned int delta=destAddr-sourceAddr; for (size_t i=0; i addrTable; SafeWriter* oldStream=s; unsigned char* buf=oldStream->getFinalBuf(); @@ -276,7 +604,7 @@ SafeWriter* stripNops(SafeWriter* s) { // prepare address map size_t addr=0; for (size_t i=0; isize();) { - int insLen=getInsLength(buf[i]); + int insLen=getInsLength(buf[i],_EXT(buf,i,oldStream->size()),speedDial); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break; @@ -288,7 +616,7 @@ SafeWriter* stripNops(SafeWriter* s) { // translate addresses for (size_t i=0; isize();) { - int insLen=getInsLength(buf[i]); + int insLen=getInsLength(buf[i],_EXT(buf,i,oldStream->size()),speedDial); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break; @@ -321,7 +649,7 @@ SafeWriter* stripNops(SafeWriter* s) { return s; } -SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlocks) { +SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlocks, unsigned char* speedDial) { unsigned char* buf=stream->getFinalBuf(); for (size_t groupSize=stream->size()>>1; groupSize>=8; groupSize--) { @@ -333,7 +661,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock size_t groupLen=0; size_t groupInsCount=0; size_t subBlockID=subBlocks.size(); - int insLen=getInsLength(buf[searchPos]); + int insLen=getInsLength(buf[searchPos],_EXT(buf,searchPos,stream->size()),speedDial); bool haveSub=false; bool onlyCalls=true; @@ -345,7 +673,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock // register this block for (size_t i=0; isize();) { if (buf[searchPos+i]!=0xf4) onlyCalls=false; - int insLenI=getInsLength(buf[searchPos+i]); + int insLenI=getInsLength(buf[searchPos+i],_EXT(buf,searchPos+i,stream->size()),speedDial); if (insLenI<1) { logE("INS %x NOT IMPLEMENTED...",buf[searchPos+i]); break; @@ -377,7 +705,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock // find identical blocks for (size_t i=searchPos+groupLen; i+groupLensize();) { - int insLenI=getInsLength(buf[i]); + int insLenI=getInsLength(buf[i],_EXT(buf,i,stream->size()),speedDial); if (insLenI<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break; @@ -439,7 +767,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock } } if (foundSomething) { - stream=stripNops(stream); + stream=stripNops(stream,speedDial); buf=stream->getFinalBuf(); } } @@ -591,7 +919,7 @@ SafeWriter* DivEngine::saveCommand() { unsigned char* buf=chanStream[h]->getFinalBuf(); int delayCount=0; for (size_t i=0; isize();) { - int insLen=getInsLength(buf[i]); + int insLen=getInsLength(buf[i],_EXT(buf,i,chanStream[h]->size()),sortedCmd); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break; @@ -638,7 +966,7 @@ SafeWriter* DivEngine::saveCommand() { int delayCount=0; int delayLast=0; for (size_t i=0; isize();) { - int insLen=getInsLength(buf[i]); + int insLen=getInsLength(buf[i],_EXT(buf,i,chanStream[h]->size()),sortedCmd); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[i]); break; @@ -690,7 +1018,7 @@ SafeWriter* DivEngine::saveCommand() { // PASS 2: remove nop's // this includes modifying call addresses to compensate for (int h=0; hgetFinalBuf(); for (size_t j=0; jsize();) { - int insLen=getInsLength(buf[j]); + int insLen=getInsLength(buf[j],_EXT(buf,j,chanStream[h]->size()),sortedCmd); if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[j]); break; @@ -783,7 +1111,7 @@ SafeWriter* DivEngine::saveCommand() { // PASS 4: remove nop's (again) for (int h=0; htell(); logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size()); - reloc(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell()); + reloc(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell(),sortedCmd); w->write(chanStream[i]->getFinalBuf(),chanStream[i]->size()); chanStream[i]->finish(); delete chanStream[i]; diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index 16a019a18..2282cff3e 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -598,6 +598,10 @@ void FurnaceGUI::drawMobileControls() { if (ImGui::Button(_("PatManager"))) { patManagerOpen=!patManagerOpen; } + ImGui::SameLine(); + if (ImGui::Button(_("CSPlayer"))) { + csPlayerOpen=!csPlayerOpen; + } ImGui::Separator();