implement all commands

no playback yet!
This commit is contained in:
tildearrow 2025-04-05 18:19:41 -05:00
parent fd9c935fc7
commit d7922baa07
4 changed files with 606 additions and 242 deletions

View file

@ -32,6 +32,21 @@ program follows.
### commands/instructions ### 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 hex | description
----|------------------------------------ ----|------------------------------------
@ -47,22 +62,28 @@ hex | description
b5 | note off b5 | note off
b6 | note off env b6 | note off env
b7 | env release b7 | env release
b8 | instrument // (ins, force) b8 | instrument (b)
c0 | pre porta // (inporta, isportaorslide) c0 | pre porta (X)
c2 | vibrato // (speed, depth) | - bit 7: inPorta
c3 | vibrato range // (range) | - bit 6: isPortaOrSlide
c4 | vibrato shape // (shape) c2 | vibrato (bb) // speed, depth
c5 | pitch // (pitch) c3 | vibrato range (b)
c6 | arpeggio // (note1, note2) c4 | vibrato shape (b)
c7 | volume // (vol) c5 | pitch (c)
c8 | vol slide // (amount) c6 | arpeggio (bb) // note1, note2
c9 | porta // (target, speed) c7 | volume (b)
ca | legato // (note) c8 | vol slide (s)
cb | volume slide with target // (amount, target) c9 | porta (bb) // target, speed
cc | tremolo // (speed/depth) ca | legato (b) // note... $ff is null note
cd | panbrello // (speed/depth) cb | volume slide with target (sS) // amount, target
ce | pan slide // (speed) cc | tremolo (X)
cf | panning // (left, right) | - 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 d0 | speed dial command 0
d1 | speed dial command 1 d1 | speed dial command 1
@ -97,270 +118,280 @@ hex | description
``` ```
hex | description hex | description
----|------------------------------------ ----|------------------------------------
1c | sample mode 1c | sample mode (b)
1d | sample freq 1d | sample freq (b)
1e | legacy sample bank 1e | legacy sample bank (b)
1f | sample position 1f | sample position (U)
20 | sample direction 20 | sample direction (b)
----|------------------------------------ ----|------------------------------------
| **FM commands** | **FM commands**
21 | hard reset 21 | hard reset (b)
22 | LFO speed 22 | LFO speed (b)
23 | LFO waveform 23 | LFO waveform (b)
24 | TL 24 | TL (bb)
25 | AM 25 | AM (bb)
26 | AR 26 | AR (bb)
27 | DR 27 | DR (bb)
28 | SL 28 | SL (bb)
29 | D2R 29 | D2R (bb)
2a | RR 2a | RR (bb)
2b | DT 2b | DT (bb)
2c | DT2 2c | DT2 (bb)
2d | RS 2d | RS (bb)
2e | KSR 2e | KSR (bb)
2f | VIB 2f | VIB (bb)
30 | SUS 30 | SUS (bb)
31 | WS 31 | WS (bb)
32 | SSG-EG 32 | SSG-EG (bb)
33 | REV 33 | REV (bb)
34 | EG-Shift 34 | EG-Shift (bb)
35 | FB 35 | FB (b)
36 | MULT 36 | MULT (bb)
37 | FINE 37 | FINE (bb)
38 | fixed frequency 38 | fixed frequency (XX)
39 | ExtCh | - byte 0: frequency low
3a | AM depth | - byte 1:
3b | PM depth | - bit 4-5: operator
3c | LFO2 speed | - bit 0-2: frequency high
3d | LFO2 wave 39 | ExtCh (b)
3a | AM depth (b)
3b | PM depth (b)
3c | LFO2 speed (b)
3d | LFO2 wave (b)
----|------------------------------------ ----|------------------------------------
| **PSG commands** | **PSG commands**
3e | noise freq 3e | noise freq (b)
3f | noise mode/duty/whatever 3f | noise mode/duty/whatever (b)
40 | waveform 40 | waveform (b)
----|------------------------------------ ----|------------------------------------
| **Game Boy commands** | **Game Boy commands**
41 | sweep time 41 | sweep time (b)
42 | sweep direction 42 | sweep direction (b)
----|------------------------------------ ----|------------------------------------
| **PC Engine commands** | **PC Engine commands**
43 | LFO mode 43 | LFO mode (b)
44 | LFO speed 44 | LFO speed (b)
----|------------------------------------ ----|------------------------------------
| **NES commands** | **NES commands**
45 | sweep 45 | sweep (X)
46 | set DMC | - bit 3: on
| - rest of bits: sweep time/amount
46 | set DMC (b)
----|------------------------------------ ----|------------------------------------
| **C64 commands** | **C64 commands**
47 | coarse cutoff 47 | coarse cutoff (b)
48 | resonance 48 | resonance (b)
49 | filter mode 49 | filter mode (b)
4a | reset time 4a | reset time (b)
4b | reset mask 4b | reset mask (b)
4c | filter reset 4c | filter reset (b)
4d | duty reset 4d | duty reset (b)
4e | extended 4e | extended (b)
4f | duty 4f | duty (S)
50 | cutoff 50 | cutoff (S)
----|------------------------------------ ----|------------------------------------
| **AY commands** | **AY commands**
51 | set envelope 51 | set envelope (b)
52 | envelope freq low 52 | envelope freq low (b)
53 | envelope freq high 53 | envelope freq high (b)
54 | envelope slide 54 | envelope slide (b)
55 | noise AND mask 55 | noise AND mask (b)
56 | noise OR mask 56 | noise OR mask (b)
57 | auto envelope 57 | auto envelope (b)
58 | I/O port write 58 | I/O port write (bb)
59 | AutoPWM 59 | AutoPWM (bb)
----|------------------------------------ ----|------------------------------------
| **FDS commands** | **FDS commands**
5a | mod depth 5a | mod depth (b)
5b | mod speed high 5b | mod speed high (b)
5c | mod speed low 5c | mod speed low (b)
5d | mod position 5d | mod position (b)
5e | mod waveform 5e | mod waveform (b)
----|------------------------------------ ----|------------------------------------
| **SAA1099 commands** | **SAA1099 commands**
5f | envelope 5f | envelope (b)
----|------------------------------------ ----|------------------------------------
| **Amiga commands** | **Amiga commands**
60 | toggle filter 60 | toggle filter (b)
61 | AM 61 | AM (b)
62 | period modulation 62 | period modulation (b)
----|------------------------------------ ----|------------------------------------
| **Lynx commands** | **Lynx commands**
63 | load LFSR 63 | load LFSR (S)
----|------------------------------------ ----|------------------------------------
| **QSound commands** | **QSound commands**
64 | echo feedback 64 | echo feedback (b)
65 | echo delay 65 | echo delay (S)
66 | echo level 66 | echo level (b)
67 | surround 67 | surround (b)
----|------------------------------------ ----|------------------------------------
| **X1-010 commands** | **X1-010 commands**
68 | envelope shape 68 | envelope shape (b)
69 | envelope enable 69 | UNUSED - envelope enable (b)
6a | envelope mode 6a | envelope mode (b)
6b | envelope period 6b | envelope period (b)
6c | envelope slide 6c | envelope slide (b)
6d | auto envelope 6d | auto envelope (b)
6e | sample bank slot 6e | sample bank slot (b)
----|------------------------------------ ----|------------------------------------
| **WonderSwan commands** | **WonderSwan commands**
6f | sweep time 6f | sweep time (b)
70 | sweep amount 70 | sweep amount (b)
----|------------------------------------ ----|------------------------------------
| **Namco 163 commands** | **Namco 163 commands**
71 | wave position 71 | wave position (b)
72 | wave length 72 | wave length (b)
73 | UNUSED 73 | UNUSED (b)
74 | UNUSED 74 | UNUSED (b)
75 | wave load position 75 | wave load position (b)
76 | wave load length 76 | wave load length (b)
77 | UNUSED 77 | UNUSED (b)
78 | channel limit 78 | channel limit (b)
79 | global wave load 79 | global wave load (b)
7a | global wave load position 7a | global wave load position (b)
7b | UNUSED 7b | UNUSED (b)
7c | UNUSED 7c | UNUSED (b)
----|------------------------------------ ----|------------------------------------
| **Sound Unit commands** | **Sound Unit commands**
7d | sweep period low 7d | sweep period low (bb)
7e | sweep period high 7e | sweep period high (bb)
7f | sweep bound 7f | sweep bound (bb)
80 | sweep enable 80 | sweep enable (bb)
81 | sync period low 81 | sync period low (b)
82 | sync period high 82 | sync period high (b)
----|------------------------------------ ----|------------------------------------
83 | ADPCM-A volume 83 | ADPCM-A volume (b)
----|------------------------------------ ----|------------------------------------
| **SNES commands** | **SNES commands**
84 | echo 84 | echo (b)
85 | pitch mod 85 | pitch mod (b)
86 | invert 86 | invert (b)
87 | gain mode 87 | gain mode (b)
88 | gain 88 | gain (b)
89 | echo enable 89 | echo enable (b)
8a | echo delay 8a | echo delay (b)
8b | echo vol left 8b | echo vol left (c)
8c | echo vol right 8c | echo vol right (c)
8d | echo feedback 8d | echo feedback (c)
8e | echo filter 8e | echo filter (bc)
----|------------------------------------ ----|------------------------------------
| **NES commands (continued)** | **NES commands (continued)**
8f | envelope mode 8f | envelope mode (b)
90 | length counter 90 | length counter (b)
91 | count mode (?) 91 | frame counter rate/count mode (b)
----|------------------------------------ ----|------------------------------------
| **macro control** | **macro control**
92 | macro off 92 | macro off (b)
93 | macro on 93 | macro on (b)
----|------------------------------------ ----|------------------------------------
94 | surround panning 94 | surround panning (bb)
----|------------------------------------ ----|------------------------------------
| **FM commands (continued)** | **FM commands (continued)**
95 | AM depth 2 95 | AM depth 2 (b)
96 | PM depth 2 96 | PM depth 2 (b)
----|------------------------------------ ----|------------------------------------
| **ES5506 commands** | **ES5506 commands**
97 | filter mode 97 | filter mode (b)
98 | filter K1 98 | filter K1 (SS)
99 | filter K2 99 | filter K2 (SS)
9a | filter K1 slide 9a | filter K1 slide (bb)
9b | filter K2 slide 9b | filter K2 slide (bb)
9c | envelope count 9c | envelope count (S)
9d | envelope left vol ramp 9d | envelope left vol ramp (b)
9e | envelope right vol ramp 9e | envelope right vol ramp (b)
9f | envelope K1 ramp 9f | envelope K1 ramp (bb)
a0 | envelope K2 ramp a0 | envelope K2 ramp (bb)
a1 | pause a1 | pause (b)
----|------------------------------------ ----|------------------------------------
a2 | arpeggio speed a2 | arpeggio speed (b)
----|------------------------------------ ----|------------------------------------
| **SNES commands (continued)** | **SNES commands (continued)**
a3 | global vol left a3 | global vol left (c)
a4 | global vol right 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)** | **C64 commands (continued)**
a7 | attack/decay a7 | attack/decay (X)
a8 | sustain/release | - bit 4-7: attack
| - bit 0-3: decay
a8 | sustain/release (X)
| - bit 4-7: sustain
| - bit 0-3: release
----|------------------------------------ ----|------------------------------------
| **ESFM commands** | **ESFM commands**
a9 | operator panning a9 | operator panning (bb)
aa | output level aa | output level (bb)
ab | modulation input ab | modulation input (bb)
ac | envelope delay ac | envelope delay (bb)
----|------------------------------------ ----|------------------------------------
ad | restart macro ad | restart macro (b)
----|------------------------------------ ----|------------------------------------
| **PowerNoise commands** | **PowerNoise commands**
ae | load counter ae | load counter (bb)
af | I/O write af | I/O write (bb)
----|------------------------------------ ----|------------------------------------
| **Dave commands** | **Dave commands**
b0 | high pass b0 | high pass (b)
b1 | ring mod b1 | ring mod (b)
b2 | swap counters b2 | swap counters (b)
b3 | low pass b3 | low pass (b)
b4 | clock divider b4 | clock divider (b)
----|------------------------------------ ----|------------------------------------
b5 | MinMod echo setup b5 | MinMod echo setup (b)
----|------------------------------------ ----|------------------------------------
| **Bifurcator commands** | **Bifurcator commands**
b6 | state load b6 | state load (bb)
b7 | set parameter b7 | set parameter (bb)
----|------------------------------------ ----|------------------------------------
b8 | FDS auto mod b8 | FDS auto mod (b)
----|------------------------------------ ----|------------------------------------
b9 | FM operator mask b9 | FM operator mask (b)
----|------------------------------------ ----|------------------------------------
| **MultiPCM commands** | **MultiPCM commands**
ba | mix FM ba | mix FM (b)
bb | mix PCM bb | mix PCM (b)
bc | LFO bc | LFO (b)
bd | VIB bd | VIB (b)
be | AM be | AM (b)
bf | AR bf | AR (b)
c0 | D1R c0 | D1R (b)
c1 | DL c1 | DL (b)
c2 | D2R c2 | D2R (b)
c3 | RC c3 | RC (b)
c4 | RR c4 | RR (b)
c5 | damp c5 | damp (b)
c6 | pseudo-reverb c6 | pseudo-reverb (b)
c7 | LFO reset c7 | LFO reset (b)
c8 | level direct c8 | level direct (b)
----|------------------------------------ ----|------------------------------------
| **SID3 commands** | **SID3 commands**
c9 | special wave c9 | special wave (b)
ca | ring mod source ca | ring mod source (b)
cb | hard sync source cb | hard sync source (b)
cc | phase mod source cc | phase mod source (b)
cd | wave mix cd | wave mix (b)
ce | LFSR feedback bits ce | LFSR feedback bits (bb)
cf | 1-bit noise cf | 1-bit noise (b)
d0 | filter distortion d0 | filter distortion (bb)
d1 | filter output volume d1 | filter output volume (bb)
d2 | channel invert d2 | channel invert (b)
d3 | filter connection d3 | filter connection (b)
d4 | filter matrix d4 | filter matrix (b)
d5 | filter enable d5 | filter enable (b)
----|------------------------------------ ----|------------------------------------
| **slide commands** | **slide commands**
d6 | pulse width slide d6 | pulse width slide (bc)
d7 | cutoff slide d7 | cutoff slide (bc)
----|------------------------------------ ----|------------------------------------
| **SID3 commands (continued)** | **SID3 commands (continued)**
d8 | phase reset d8 | phase reset (b)
d9 | noise phase reset d9 | noise phase reset (b)
da | envelope reset da | envelope reset (b)
db | cutoff scaling db | cutoff scaling (b)
dc | resonance scaling dc | resonance scaling (b)
----|------------------------------------ ----|------------------------------------
dd | WonderSwan speaker volume dd | WonderSwan speaker volume (b)
``` ```

View file

@ -105,7 +105,8 @@ class DivCSPlayer {
// command stream utilities // command stream utilities
namespace DivCS { 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 #endif

View file

@ -23,7 +23,216 @@
//#define DISABLE_BLOCK_SEARCH //#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) { switch (ins) {
case 0xb8: // ins case 0xb8: // ins
case 0xc0: // pre porta 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 0xd4: case 0xd5: case 0xd6: case 0xd7:
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xd8: case 0xd9: case 0xda: case 0xdb:
case 0xdc: case 0xdd: case 0xde: case 0xdf: case 0xdc: case 0xdd: case 0xde: case 0xdf:
return 0; if (speedDial==NULL) return 0;
return 1+getCmdLength(speedDial[ins&15]);
case 0xf0: // opt case 0xf0: // opt
return 4; return 4;
case 0xf7: { // cmd case 0xf7: // cmd
// determine length from secondary // determine length from secondary
if (ext==0) return 0; if (ext==0) return 0;
return 0; return 2+getCmdLength(ext);
}
case 0xf8: // call case 0xf8: // call
case 0xfc: // waits case 0xfc: // waits
return 3; return 3;
@ -97,7 +306,6 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
w->writeC((unsigned char)c.cmd+0xb4); w->writeC((unsigned char)c.cmd+0xb4);
break; break;
default: default:
return;
w->writeC(0xf7); w->writeC(0xf7);
w->writeC(c.cmd); w->writeC(c.cmd);
break; break;
@ -145,11 +353,12 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
case DIV_CMD_SAMPLE_MODE: case DIV_CMD_SAMPLE_MODE:
case DIV_CMD_SAMPLE_FREQ: case DIV_CMD_SAMPLE_FREQ:
case DIV_CMD_SAMPLE_BANK: case DIV_CMD_SAMPLE_BANK:
case DIV_CMD_SAMPLE_POS:
case DIV_CMD_SAMPLE_DIR: case DIV_CMD_SAMPLE_DIR:
case DIV_CMD_FM_HARD_RESET: case DIV_CMD_FM_HARD_RESET:
case DIV_CMD_FM_LFO: case DIV_CMD_FM_LFO:
case DIV_CMD_FM_LFO_WAVE: 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_FB:
case DIV_CMD_FM_EXTCH: case DIV_CMD_FM_EXTCH:
case DIV_CMD_FM_AM_DEPTH: 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_ON:
case DIV_CMD_MACRO_RESTART: case DIV_CMD_MACRO_RESTART:
case DIV_CMD_HINT_ARP_TIME: 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); w->writeC(c.value);
break; break;
case DIV_CMD_FM_TL: 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_IO_WRITE:
case DIV_CMD_AY_AUTO_PWM: case DIV_CMD_AY_AUTO_PWM:
case DIV_CMD_SURROUND_PANNING: 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.value);
w->writeC(c.value2); w->writeC(c.value2);
break; break;
case DIV_CMD_C64_FINE_DUTY: case DIV_CMD_C64_FINE_DUTY:
case DIV_CMD_C64_FINE_CUTOFF: case DIV_CMD_C64_FINE_CUTOFF:
case DIV_CMD_LYNX_LFSR_LOAD: 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); w->writeS(c.value);
break; 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: case DIV_CMD_FM_FIXFREQ:
w->writeC(2); // length
w->writeS((c.value<<12)|(c.value2&0x7ff)); w->writeS((c.value<<12)|(c.value2&0x7ff));
break; break;
case DIV_CMD_NES_SWEEP: case DIV_CMD_NES_SWEEP:
w->writeC(1); // length
w->writeC((c.value?8:0)|(c.value2&0x77)); w->writeC((c.value?8:0)|(c.value2&0x77));
break; break;
case DIV_CMD_SAMPLE_POS:
w->writeI(c.value);
break;
default: default:
logW("unimplemented command %s!",cmdName[c.cmd]); logW("unimplemented command %s!",cmdName[c.cmd]);
w->writeC(0); // length
break; break;
} }
} }
#define _EXT(b,x,l) (((size_t)((x)+1)<(size_t)(l))?(b[(x)+1]):0)
using namespace DivCS; 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; unsigned int delta=destAddr-sourceAddr;
for (size_t i=0; i<len;) { for (size_t i=0; i<len;) {
int insLen=getInsLength(buf[i]); int insLen=getInsLength(buf[i],_EXT(buf,i,len),speedDial);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -266,7 +594,7 @@ void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int
} }
} }
SafeWriter* stripNops(SafeWriter* s) { SafeWriter* stripNops(SafeWriter* s, unsigned char* speedDial) {
std::unordered_map<unsigned int,unsigned int> addrTable; std::unordered_map<unsigned int,unsigned int> addrTable;
SafeWriter* oldStream=s; SafeWriter* oldStream=s;
unsigned char* buf=oldStream->getFinalBuf(); unsigned char* buf=oldStream->getFinalBuf();
@ -276,7 +604,7 @@ SafeWriter* stripNops(SafeWriter* s) {
// prepare address map // prepare address map
size_t addr=0; size_t addr=0;
for (size_t i=0; i<oldStream->size();) { for (size_t i=0; i<oldStream->size();) {
int insLen=getInsLength(buf[i]); int insLen=getInsLength(buf[i],_EXT(buf,i,oldStream->size()),speedDial);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -288,7 +616,7 @@ SafeWriter* stripNops(SafeWriter* s) {
// translate addresses // translate addresses
for (size_t i=0; i<oldStream->size();) { for (size_t i=0; i<oldStream->size();) {
int insLen=getInsLength(buf[i]); int insLen=getInsLength(buf[i],_EXT(buf,i,oldStream->size()),speedDial);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -321,7 +649,7 @@ SafeWriter* stripNops(SafeWriter* s) {
return s; return s;
} }
SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks) { SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks, unsigned char* speedDial) {
unsigned char* buf=stream->getFinalBuf(); unsigned char* buf=stream->getFinalBuf();
for (size_t groupSize=stream->size()>>1; groupSize>=8; groupSize--) { for (size_t groupSize=stream->size()>>1; groupSize>=8; groupSize--) {
@ -333,7 +661,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
size_t groupLen=0; size_t groupLen=0;
size_t groupInsCount=0; size_t groupInsCount=0;
size_t subBlockID=subBlocks.size(); 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 haveSub=false;
bool onlyCalls=true; bool onlyCalls=true;
@ -345,7 +673,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
// register this block // register this block
for (size_t i=0; i<groupSize && i<stream->size();) { for (size_t i=0; i<groupSize && i<stream->size();) {
if (buf[searchPos+i]!=0xf4) onlyCalls=false; 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) { if (insLenI<1) {
logE("INS %x NOT IMPLEMENTED...",buf[searchPos+i]); logE("INS %x NOT IMPLEMENTED...",buf[searchPos+i]);
break; break;
@ -377,7 +705,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
// find identical blocks // find identical blocks
for (size_t i=searchPos+groupLen; i+groupLen<stream->size();) { for (size_t i=searchPos+groupLen; i+groupLen<stream->size();) {
int insLenI=getInsLength(buf[i]); int insLenI=getInsLength(buf[i],_EXT(buf,i,stream->size()),speedDial);
if (insLenI<1) { if (insLenI<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -439,7 +767,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
} }
} }
if (foundSomething) { if (foundSomething) {
stream=stripNops(stream); stream=stripNops(stream,speedDial);
buf=stream->getFinalBuf(); buf=stream->getFinalBuf();
} }
} }
@ -591,7 +919,7 @@ SafeWriter* DivEngine::saveCommand() {
unsigned char* buf=chanStream[h]->getFinalBuf(); unsigned char* buf=chanStream[h]->getFinalBuf();
int delayCount=0; int delayCount=0;
for (size_t i=0; i<chanStream[h]->size();) { for (size_t i=0; i<chanStream[h]->size();) {
int insLen=getInsLength(buf[i]); int insLen=getInsLength(buf[i],_EXT(buf,i,chanStream[h]->size()),sortedCmd);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -638,7 +966,7 @@ SafeWriter* DivEngine::saveCommand() {
int delayCount=0; int delayCount=0;
int delayLast=0; int delayLast=0;
for (size_t i=0; i<chanStream[h]->size();) { for (size_t i=0; i<chanStream[h]->size();) {
int insLen=getInsLength(buf[i]); int insLen=getInsLength(buf[i],_EXT(buf,i,chanStream[h]->size()),sortedCmd);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[i]); logE("INS %x NOT IMPLEMENTED...",buf[i]);
break; break;
@ -690,7 +1018,7 @@ SafeWriter* DivEngine::saveCommand() {
// PASS 2: remove nop's // PASS 2: remove nop's
// this includes modifying call addresses to compensate // this includes modifying call addresses to compensate
for (int h=0; h<chans; h++) { for (int h=0; h<chans; h++) {
chanStream[h]=stripNops(chanStream[h]); chanStream[h]=stripNops(chanStream[h],sortedCmd);
} }
#ifndef DISABLE_BLOCK_SEARCH #ifndef DISABLE_BLOCK_SEARCH
@ -701,7 +1029,7 @@ SafeWriter* DivEngine::saveCommand() {
// 6 is the minimum size that can be reliably optimized // 6 is the minimum size that can be reliably optimized
logI("finding sub-blocks in chan %d",h); logI("finding sub-blocks in chan %d",h);
chanStream[h]=findSubBlocks(chanStream[h],subBlocks); chanStream[h]=findSubBlocks(chanStream[h],subBlocks,sortedCmd);
// find sub-blocks within sub-blocks // find sub-blocks within sub-blocks
size_t subBlocksLast=0; size_t subBlocksLast=0;
size_t subBlocksLen=subBlocks.size(); size_t subBlocksLen=subBlocks.size();
@ -709,7 +1037,7 @@ SafeWriter* DivEngine::saveCommand() {
while (subBlocksLast!=subBlocksLen) { while (subBlocksLast!=subBlocksLen) {
logI("got %d blocks... starting from %d",(int)subBlocksLen,(int)subBlocksLast); logI("got %d blocks... starting from %d",(int)subBlocksLen,(int)subBlocksLast);
for (size_t i=subBlocksLast; i<subBlocksLen; i++) { for (size_t i=subBlocksLast; i<subBlocksLen; i++) {
SafeWriter* newBlock=findSubBlocks(subBlocks[i],subBlocks); SafeWriter* newBlock=findSubBlocks(subBlocks[i],subBlocks,sortedCmd);
subBlocks[i]=newBlock; subBlocks[i]=newBlock;
} }
subBlocksLast=subBlocksLen; subBlocksLast=subBlocksLen;
@ -754,7 +1082,7 @@ SafeWriter* DivEngine::saveCommand() {
// resolve symbols // resolve symbols
unsigned char* buf=chanStream[h]->getFinalBuf(); unsigned char* buf=chanStream[h]->getFinalBuf();
for (size_t j=0; j<chanStream[h]->size();) { for (size_t j=0; j<chanStream[h]->size();) {
int insLen=getInsLength(buf[j]); int insLen=getInsLength(buf[j],_EXT(buf,j,chanStream[h]->size()),sortedCmd);
if (insLen<1) { if (insLen<1) {
logE("INS %x NOT IMPLEMENTED...",buf[j]); logE("INS %x NOT IMPLEMENTED...",buf[j]);
break; break;
@ -783,7 +1111,7 @@ SafeWriter* DivEngine::saveCommand() {
// PASS 4: remove nop's (again) // PASS 4: remove nop's (again)
for (int h=0; h<chans; h++) { for (int h=0; h<chans; h++) {
chanStream[h]=stripNops(chanStream[h]); chanStream[h]=stripNops(chanStream[h],sortedCmd);
} }
// PASS 5: optimize command calls // PASS 5: optimize command calls
@ -813,7 +1141,7 @@ SafeWriter* DivEngine::saveCommand() {
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
chanStreamOff[i]=w->tell(); chanStreamOff[i]=w->tell();
logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size()); 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()); w->write(chanStream[i]->getFinalBuf(),chanStream[i]->size());
chanStream[i]->finish(); chanStream[i]->finish();
delete chanStream[i]; delete chanStream[i];

View file

@ -598,6 +598,10 @@ void FurnaceGUI::drawMobileControls() {
if (ImGui::Button(_("PatManager"))) { if (ImGui::Button(_("PatManager"))) {
patManagerOpen=!patManagerOpen; patManagerOpen=!patManagerOpen;
} }
ImGui::SameLine();
if (ImGui::Button(_("CSPlayer"))) {
csPlayerOpen=!csPlayerOpen;
}
ImGui::Separator(); ImGui::Separator();