Compare commits

...

15 Commits
main ... presto

Author SHA1 Message Date
f97f406272 Optimized ping pong some more. 2023-09-05 21:17:11 +02:00
ef1c519a6c Wavegen optimizations, cosmetics and another mystery solved. 2023-08-24 22:07:42 +02:00
b805349bf0 Noise wave generation code optimized. 2023-08-22 22:32:51 +02:00
4461c72eaa Wave generation code path for noise restructured. 2023-08-22 21:06:02 +02:00
1580f0a174 Nosync/sync wave selection optimized among other smaller optimizations. 2023-08-20 21:09:34 +02:00
815d5f6e29 Bugfix for songend detection and more optimizations. 2023-08-19 21:40:08 +02:00
36d435f502 Wave order table filling moved and optimized in SongInit. 2023-08-16 20:35:25 +02:00
e0f7537774 Moved pattern table init from PlayerInit to SongInit, optimized SongInit a bit. 2023-08-16 20:02:41 +02:00
c57f68a505 Track delay completely reworked. 2023-08-13 21:36:49 +02:00
0d3ad4074c Branch optimizations, removed two octave tables and replaced them by a tiny bit of code. 2023-08-10 22:41:52 +02:00
dd8c224199 Replaced the period table by byte-deltas, saved 36 bytes and compression is even better! 2023-08-10 20:27:30 +02:00
40822e295c Cosmetics, doc updates, and optimizations. 2023-08-10 20:24:43 +02:00
d2360ef174 More minor doc updates. 2023-07-26 09:37:31 +02:00
19dd1304ab Minor doc updates. 2023-07-26 09:30:09 +02:00
5d95ed156c Created Presto development branch, committed improvements to Raspberry Casket work-in-progress version. 2023-07-26 09:21:36 +02:00
8 changed files with 2249 additions and 2225 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022 Chris 'platon42' Hodges <chrisly@platon42.de>
Copyright (c) 2022-2023 Chris 'platon42' Hodges <chrisly@platon42.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,7 +1,7 @@
# Raspberry Casket
A fast and small open source Pretracker replayer
## Raspberry Casket Player V1.1 (28-Dec-2022)
## Raspberry Casket Player V2.x (24-Aug-2023)
Provided by Chris 'platon42' Hodges <chrisly@platon42.de>
@ -15,26 +15,43 @@ surplus code (maybe artefacts from earlier ideas that did nothing),
optimizing the code where possible. This resulted in both reduced
size of the replayer, faster sample calculation and speeding the
tick routine up significantly.
Bugs from the original replayer were fixed.
I also added a few optional features that come in handy, such as
song-end detection and precalc progress support.
It took me more than a month and it was not fun.
Note that this player can be also used for the playback of
Pretracker 1.5 tunes, given you don't use sfx or sub-songs.
Also: Open source. It's 2022, keeping the code closed is just not
Also: Open source. It's 2023, keeping the code closed is just not
part of the demoscene spirit (anymore?), at least for a replayer.
Also note that this is not the final state of the source code.
I could go over many places still and try to rework them.
But I wanted the code to be out in public.
This player is still being optimized and worked on since its
first release in late 2022.
Productions that I know have been using Raspberry Casket so far:
- [Smooth Flowing/Dekadence](https://www.pouet.net/prod.php?which=94347)
- [Cracking Posadas/Software Failure](https://www.pouet.net/prod.php?which=94570)
### Verification
The replayer has been verified on about 60 Pretracker tunes to
create an identical internal state for each tick and identical
samples (if certain optimizations switches are disabled).
The first versions of the replayer had been verified against about
60 Pretracker tunes to create an identical internal state for each
tick and identical samples (if certain optimizations switches are disabled).
I might have introduced bugs though. If you find some problems,
During the process this identical state and identical samples promise
had to be dropped due to bugs in the original player and optimizations.
This is especially the case for the track delay feature of Pretracker
that could in some cases cause odd behaviour and unwanted muting that
has been fixed in Raspberry Casket. So the verification is now heavily
reduced to about 20 songs that still are identical.
I do, however, now also have an emulated Paula output verification that
compares the generated sound between the original code and Raspberry Casket.
Divergences are manually checked from time to time.
If you find some problems,
please let me know under chrisly@platon42.de. Thank you.
### Usage
@ -72,19 +89,19 @@ The source needs two common include files to compile (`custom.i` and
This will create the samples, too.
4. After that, regularly call `pre_PlayerTick` with `MyPlayer` in `a0`
and optionally the copperlist in a1 if you're using that mode).
and optionally the copperlist in `a1` if you're using that mode).
### Size
The original C compiled code was... just bad. The new binary is
about 1/3 of the original one.
less than 1/3 of the original one.
The code has been also optimized in a way that it compresses better.
The original code compressed with *Blueberry's* Shrinkler goes from
18052 bytes down to 9023 bytes.
Raspberry Casket, depending on the features compiled in, is about
6216 bytes and goes down to ~4348 bytes (in isolation).
5716 bytes and shrinkles down to ~4071 bytes (in isolation).
So this means that the optimization is not just "on the outside".
@ -93,8 +110,20 @@ the remaining code for playback.
### Timing
Sample generation is a bit faster (I guess around 10-15%),
but most of the time is spent on `muls` operations, so this is the limiting factor.
#### Sample precalculation
Sample generation is faster than the original 1.0 player and also
faster than the 1.5 player, which got a slightly better performance
than the 1.0 one (compiler change?).
According to my measurements on my set of Pretracker tunes,
Raspberry Casket needs between 10% to 20% less instructions.
Of these instructions, about 5% are `muls` operations and the new
player is only able to shave off between 3% and 8% percent of those,
so this is probably the limiting factor.
#### Playback
Raspberry Casket is about twice as fast as the old replayer for playback.
Unfortunately, the replayer is still pretty slow and has high
@ -108,20 +137,56 @@ about 34 on average!).
Watch out for *Presto*, the [LightSpeedPlayer](https://github.com/arnaud-carre/LSPlayer) variant that should
solve this problem.
### Secrets
- Pink never actually documented how the 0xy command works (2nd instrument, not an ARP!).
It will play the instrument y for x+1 ticks before going to the actual instrument you wanted to trigger in the first place.
This works well, e.g. for bassdrums and other short percussion samples. Note that because y is a 4 bit nibble, you can only
specify the instruments $1-$f this way and not $10-$1f.
### Known issues
- Songs saved with earlier versions of Pretracker than 1.0 (internal version lower than $1b) have stored the ADSR values differently in the file.
There is no provision for fixing these values neither in the original player nor in Raspberry Casket. Loading the file in the tracker and saving
it again will cure this. This is more of a hypothetical problem as you are unlikely to use a Pretracker V0.9 beta version, but it took me quite a
while why Pink's "On and On" has a broken first wave sample in all the replayers but not on the tracker itself. This affects these tunes:
Attack and Release, On and On, Rewind, Cold and Tired, PreFix all by Pink and Cracksteady by Tecon.
- Behaviour for undefined volume slides with both up- and down nibble specified is different (e.g. A9A, hi Rapture!). Don't do that.
- Don't use loops with odd lengths and offsets (even if Pretracker allows this when dragging the loop points).
- Don't stop the music with F00 and use a note delay (EDx) in the same line.
- Don't try to play music with no waves, instruments or patterns.
- Pattern breaks with target row >= $7f will be ignored.
- The original player had the internal state machine running for wave 1 even if no note had been triggered yet on the channel.
This could cause the first instrument using a 4xx command (trigger wave without sync) in the instrument pattern to start at
a more or less random first loop offset instead of from the beginning. This is fixed in Raspberry Casket.
- Shinobi seemed to have used an early beta version of Pretracker where it was possible to specify a Subloop Wait of 0. That's illegal and unsupported.
- Pattern breaks with target row >= $7f will be ignored.
- Pattern break (Dxx) + Song pos (Bxx) on the same line does not work in original Pretracker & Player: New Dxx position is ignored.
There is code to enable it in the player, so you could in theory make backwards running tracks like in Protracker.
But this doesn't make sense as long as the tracker itself does not support it.
- Setting the same track delay multiple times will no longer mute the delayed channel and the new volume will take effect immediately.
- Clearing the track delay (multiple times) will no longer mute the delayed channel nor cause a delay of one tick to the note played in the no-longer delayed channel.
## Changelog
### V2.x (unreleased)
- Split wave generation out of main file, reorganised content into header files.
- Optimized some more code paths for Raspberry Casket replayer.
- In the wave generator optimized away a table (32 words), replacement code is even smaller!
- Replaced the period table by byte-deltas, saved 36 bytes and compression is even better!
- Optimized some code paths for octave selection.
- Removed two 25 bytes tables each, saving another 42 bytes.
- Completely reworked track delay handling, fixed oddities and improved output quality.
- This removes a big source of cpu jitter when track delay is enabled (no longer clearing the track delay buffer).
- This also fixes usages of illegal period 0 in the lead-in that could cause the replay to miss the first trigger.
- Moved pattern table init from PlayerInit to SongInit, optimized SongInit a bit.
- Wave order table filling moved and optimized in SongInit.
- Bugfix: Songend detection for back-jumps was broken since at least V1.1.
- Optimized some more wave selection code.
- Nosync/sync wave selection optimized.
- Optimized wave generation a lot (esp. noise generator).
- Added Presto player draft.
- Drop-in replacement code size: 5716 bytes.
### V1.x (unreleased)
- Fixed a bug regarding the copper output mode with looping waves having a loop-offset.
- Fixed wrong register use on triggering waves regarding the loop offset.
@ -144,4 +209,4 @@ solve this problem.
### V1.0 (26-Dec-22)
- Initial release.
- Drop-in replacement code size: 6446 bytes.
- Drop-in replacement code size: 6446 bytes.

Binary file not shown.

View File

@ -2,4 +2,4 @@ This file "raspberry_casket.bin" can replace the original "player.bin"
provided that you used the 16 KB + 16 KB allocation for player
variables as in the original player (you need only about 2 + 12 KB).
It has been assembled from src/drop_in_replacement.asm (version V1.1).
It has been assembled from src/drop_in_replacement.asm (version V2.0).

View File

@ -1,4 +1,4 @@
; vasmm68k_mot.exe -devpac -Fbin -o ..\binaries\raspberry_casket.bin -opt-allbra drop_in_replacement.asm
; vasmm68k_mot.exe -I..\includes -devpac -Fbin -o ..\binaries\raspberry_casket.bin -opt-allbra drop_in_replacement.asm
PRETRACKER_SUPPORT_V1_5 = 0
PRETRACKER_PARANOIA_MODE = 0

File diff suppressed because it is too large Load Diff

342
src/raspberry_casket.i Normal file
View File

@ -0,0 +1,342 @@
; Pretracker song format description:
;
; $0000 4: PRT<version> ($19/$1a (V0.x), $1b (V1.0), $1e (V1.5))
; $0004 4: File offset to position data (POSD)
; $0008 4: File offset to pattern data (PATT)
; $000C 4: File offset to instruments (INST)
; $0010 4: File offset to waves (WAVE)
; $0014 20: Songname
; $0028 20: Author
; $003C 1: Restart position for song (<=V1.0)
; $003D 1: Number of patterns (<=V1.0)
; $003E 1: Songlength in patterns (<=V1.0)
; $003F 1: Number of steps per pattern (<=V1.0)
; $0040 1: Number of instruments (<=V1.0), $40 for V1.5
; $0041 1: Number of waves
; $0042 24: Wave generation ordering (>=V1.0)
; $005a 1: Number of subsongs (>=V1.5)
; [...]
; Position data (POSD):
; - Per subsong (>=V1.5)
; - 1: Restart pos
; - 1: #patterns
; - 1: #numsteps
; - 1: songlength
; - 4: relative pattern offset in pattern data
; - Positions x 4 x [Pattern number (byte), pitch shift (signed byte)]
;
; Pattern data (PATT):
; Each pattern line consists of three bytes:
; - 1 Bit : Bit 4 of Inst Number
; - 1 Bit : ARP instead of effect
; - 6 Bits: Pitch ($01 is C-0, $3d is NOTE OFF)
;
; - 4 Bits: Bit 0-3 of Inst Number
; - 4 Bits: Effect command
; - 8 Bits: Effect data
; - Patterns x steps x 3 bytes
;
; Unknown data after pattern data: (12 10 00 00 00 00)
;
; Instrument definitions (INST):
; - 32 (!) x Null terminated string (or 23 chars max) (for V1.5 this is 64 strings)
; - For each instrument: Instrument Info (ININ)
; - $00 1: Vibrato Delay
; - $01 1: Vibrato Depth
; - $02 1: Vibrato Speed (-1)
; - $03 1: ADSR Attack
; - $04 1: ADSR Decay
; - $05 1: ADSR Sustain
; - $06 1: ADSR Release
; - $07 1: Number of Inst Pattern steps
;
; - For each instrument:
; - 1 Byte: number of steps
; - 3 Bytes x number of steps: Inst Pattern (IPTT)
;
; Inst pattern data (IPTT):
; Each pattern line consists of three bytes:
; - 1 Bit : Next note stitched to this one
; - 1 Bit : Fixed Pitch Note
; - 6 Bits : Pitch ($01 is C-0)
; - 4 Bits : unused?
; - 12 Bits: Effect
;
; Wave definitions (WAVE):
; - 24 (!) x Null terminated string (or 23 chars max)
; - Optional padding to even address, if necessary
; - For each wave:
; - 42 Bytes: Wave info structure (see definition below)
; ----------------------------------------
; Some constants for clarity
MAX_VOLUME = $40
MAX_SPEED = $2f
MAX_WAVES = 24
MAX_INSTRUMENTS = 32
MAX_TRACK_DELAY = 32
NOTE_OFF_PITCH = $3d
NOTES_IN_OCTAVE = 12
NUM_CHANNELS = 4 ; yes, you can reduce the number of channels if you want
; ----------------------------------------
; Pretracker file structures
; Pattern data (PATT and IPTT)
pdb_pitch_ctrl = 0
pdb_inst_effect = 1 ; for normal pattern data
pdb_effect_cmd = 1 ; for inst pattern
pdb_effect_data = 2
; Pattern pos data (POSD)
ppd_pat_num = 0
ppd_pat_shift = 1
; Instrument Info (ININ)
ii_vibrato_delay = 0
ii_vibrato_depth = 1
ii_vibrato_speed = 2
ii_adsr_attack = 3
ii_adsr_decay = 4
ii_adsr_sustain = 5
ii_adsr_release = 6
ii_pattern_steps = 7
ii_SIZEOF = 8
; Wave Info (WAVE)
wi_loop_start_w = $00
wi_loop_end_w = $02
wi_subloop_len_w = $04
wi_allow_9xx_b = $06 ; 0x00 / 0x01
wi_subloop_wait_b = $07
wi_subloop_step_w = $08
wi_chipram_w = $0a
wi_loop_offset_w = $0c
wi_chord_note1_b = $0e
wi_chord_note2_b = $0f
wi_chord_note3_b = $10
wi_chord_shift_b = $11
wi_osc_unknown_b = $12 ; always $00? (unused in code?)
wi_osc_phase_spd_b = $13
wi_flags_b = $14 ; bit 0/1: osc type, bit 2: needs extra octaves, bit 3: boost, bit 4: pitch linear, bit 5: vol fast
wi_osc_phase_min_b = $15
wi_osc_phase_max_b = $16
wi_osc_basenote_b = $17
wi_osc_gain_b = $18
wi_sam_len_b = $19 ; in multiples of 128, zero-based (0 == 128)
wi_mix_wave_b = $1a
wi_vol_attack_b = $1b
wi_vol_delay_b = $1c
wi_vol_decay_b = $1d
wi_vol_sustain_b = $1e
wi_flt_type_b = $1f ; 1=lowpass, 2=highpass, 3=bandpass, 4=notch
wi_flt_resonance_b = $20
wi_pitch_ramp_b = $21
wi_flt_start_b = $22
wi_flt_min_b = $23
wi_flt_max_b = $24
wi_flt_speed_b = $25
wi_mod_params_l = $26
wi_mod_wetness_b = $26
wi_mod_length_b = $27
wi_mod_predelay_b = $28
wi_mod_density_b = $29 ; (1-7), unisono (bits 3/4) and post bit 5
wi_SIZEOF = $2a
; ----------------------------------------
; Unpacked Instrument Info (addition to player for faster processing)
rsreset
uii_vibrato_delay rs.w 1
uii_vibrato_depth rs.w 1
uii_vibrato_speed rs.w 1
uii_adsr_release rs.b 1
rs.b 1 ; dummy
uii_adsr_attack rs.w 1
uii_adsr_decay rs.w 1
uii_adsr_sustain rs.w 1
uii_pattern_steps rs.b 1
rs.b 1 ; padding
uii_SIZEOF rs.b 0
; ----------------------------------------
; MySong offsets
rsreset
sv_waveinfo_table rs.l MAX_WAVES ; 24 pointers to wave infos to avoid mulu
sv_inst_patterns_table rs.l MAX_INSTRUMENTS ; 32 pointers to pattern data
; --- 127 byte displacement limit ---
sv_wavelength_table rs.l MAX_WAVES ; 24 longwords to sample lengths (standard octave) (NEW)
sv_wavetotal_table rs.l MAX_WAVES ; 24 longwords to sample lengths for all octaves (NEW)
sv_wavegen_order_table rs.b MAX_WAVES ; 24 bytes
sv_num_waves_b rs.b 1
sv_num_steps_b rs.b 1
sv_pat_pos_len_w rs.w 1 ; only byte used
sv_pat_restart_pos_w rs.w 1 ; only byte used
sv_pos_data_adr rs.l 1
sv_waveinfo_ptr rs.l 1 ; base pointer of wave info
sv_inst_infos_table rs.b MAX_INSTRUMENTS*uii_SIZEOF
sv_pattern_table rs.l 256
sv_SIZEOF rs.b 0
; ----------------------------------------
; channel output data (part of pcd structure below) -- FIXED ORDER!
rsreset
ocd_sam_ptr rs.l 1 ; 0
ocd_length rs.w 1 ; 4
ocd_loop_offset rs.w 1 ; 6
ocd_period rs.w 1 ; 8
ocd_volume rs.b 1 ; 10
ocd_trigger rs.b 1 ; 11 needs to be after volume
ocd_unused rs.l 1 ; 12 unused, but makes the structure an even 16 bytes
ocd_SIZEOF rs.b 0
; channel structure (part of pv structure)
rsreset
; DO NOT CHANGE ORDER -- OPTIMIZED CLEARING
pcd_pat_portamento_dest_w rs.w 1 ; portamento destination pitch
pcd_pat_pitch_slide_w rs.w 1
pcd_pat_vol_ramp_speed_b rs.b 1
pcd_pat_2nd_inst_num4_b rs.b 1
pcd_pat_2nd_inst_delay_b rs.b 1
pcd_wave_offset_b rs.b 1
pcd_inst_pitch_slide_w rs.w 1
pcd_inst_sel_arp_note_w rs.w 1
pcd_inst_note_pitch_w rs.w 1
pcd_inst_curr_port_pitch_w rs.w 1
pcd_inst_line_ticks_b rs.b 1
pcd_inst_pitch_pinned_b rs.b 1
pcd_inst_vol_slide_b rs.b 1
pcd_inst_step_pos_b rs.b 1
pcd_inst_wave_num4_w rs.w 1 ; current wave number (1 based, times 4) (lower byte used)
pcd_track_delay_offset_b rs.b 1 ; $ff = no track delay
pcd_inst_speed_stop_b rs.b 1 ; speed byte, $ff stops processing
pcd_inst_pitch_w rs.w 1
pcd_inst_vol_w rs.w 1
pcd_loaded_inst_vol_b rs.b 1
pcd_pat_vol_b rs.b 1 ; Multiplied with volume of instrument.
; DO NOT CHANGE ORDER -- OPTIMIZED CLEARING END
pcd_arp_notes_l rs.b 0
pcd_arp_note_1_b rs.b 1
pcd_arp_note_2_b rs.b 1
pcd_arp_note_3_b rs.b 1
rs.b 1 ; gets cleared
pcd_last_trigger_length_w rs.w 1 ; I think this makes sure that we trigger the note if the length changes
pcd_pat_portamento_speed_b rs.b 1
pcd_pat_adsr_rel_delay_b rs.b 1 ; counts down until adsr release. Seems unused?
pcd_note_off_delay_b rs.b 1 ; time before note is released ($ff = disabled)
pcd_inst_pattern_steps_b rs.b 1 ; number of steps in instrument pattern
pcd_note_delay_b rs.b 1 ; $ff = no note delay
pcd_track_delay_steps_b rs.b 1 ; $00 = no track delay, $xx = track delay xx (this is for the next channel!)
pcd_track_delay_vol16_b rs.b 1 ; needs to be at even address (using word access to shift << 8)
pcd_track_init_delay_b rs.b 1 ; number of frames to ignore the delay
pcd_inst_num4_w rs.w 1 ; current instrument number * 4
pcd_inst_subloop_wait_w rs.w 1
pcd_inst_loop_offset_w rs.w 1
pcd_inst_info_ptr rs.l 1 ; pointer to currently active instrument
pcd_waveinfo_ptr rs.l 1 ; pointer to currently active waveinfo
pcd_channel_mask_b rs.b 1
pcd_channel_num_b rs.b 1
pcd_adsr_phase_w rs.w 1 ; 0=attack, 1=decay, 2=sustain, 3=release ! do not change order
pcd_adsr_volume_w rs.w 1 ; 0 for restart / $400 (word only) ! do not change order
pcd_adsr_phase_speed_b rs.b 1
pcd_inst_ping_pong_dir_b rs.b 1 ; direction of ping-pong (-1 == $00 / +1 = $ff)
pcd_adsr_pos_w rs.w 1 ; pos in adsr curve
pcd_adsr_vol64_w rs.w 1 ; some adsr volume
pcd_new_inst_num_b rs.b 1 ; load new instrument (number) ! do not change order
rs.b 1 ; gets cleared
pcd_vibrato_pos_w rs.w 1 ;
pcd_vibrato_delay_w rs.w 1 ; is a byte value ! do not change order
pcd_vibrato_depth_w rs.w 1 ; is a byte value ! do not change order
pcd_vibrato_speed_w rs.w 1 ; is a byte value ! do not change order
pcd_adsr_release_b rs.b 1 ; is a byte value ! do not change order
rs.b 1 ; padding will be overwritten!
pcd_out_base rs.b ocd_SIZEOF
pcd_track_delay_buffer rs.b MAX_TRACK_DELAY*ocd_SIZEOF
pcd_SIZEOF rs.b 0
pcd_out_ptr_l = pcd_out_base+ocd_sam_ptr
pcd_out_len_w = pcd_out_base+ocd_length
pcd_out_lof_w = pcd_out_base+ocd_loop_offset
pcd_out_per_w = pcd_out_base+ocd_period
pcd_out_vol_b = pcd_out_base+ocd_volume
pcd_out_trg_b = pcd_out_base+ocd_trigger
pcd_out_unused_l = pcd_out_base+ocd_unused ; copied for track delay, but not used?
rsreset
owb_saw_waves rs.b 128
owb_sqr_waves rs.b 128
owb_tri_waves rs.b 128
owb_SIZEOF rs.b 0
; ----------------------------------------
; MyPlayer global variables (not bound to channel)
rsreset
; DO NOT CHANGE ORDER -- OPTIMIZED INIT
pv_pat_curr_row_b rs.b 1 ; current step
pv_next_pat_row_b rs.b 1
pv_next_pat_pos_b rs.b 1
pv_pat_speed_even_b rs.b 1 ; even shuffle speed
pv_pat_speed_odd_b rs.b 1 ; odd shuffle speed
pv_pat_line_ticks_b rs.b 1
pv_pat_stopped_b rs.b 1 ; 0 = stop, $ff = run
pv_songend_detected_b rs.b 1
; DO NOT CHANGE ORDER -- OPTIMIZED INIT END
pv_curr_pat_pos_w rs.w 1 ; only byte used
pv_loop_pattern_b rs.b 1 ; repeat current pattern, do not advance
rs.b 1 ; padding
pv_trigger_mask_w rs.w 1
pv_my_song rs.l 1
pv_copperlist_ptr rs.l 1
pv_wave_sample_table rs.l MAX_WAVES ; 24 pointers to sample starts
pv_period_table rs.w 16*NOTES_IN_OCTAVE*3
; --- 127 byte displacement limit ---
pv_sample_buffer_ptr rs.l 1 ; pointer to start of sample buffer
pv_stop_len_lof rs.l 1 ; $0002 / $0000
pv_stop_per_vol_trg rs.l 1 ; $007b / $00 / $00
pv_channeldata rs.b NUM_CHANNELS*pcd_SIZEOF
IFNE PRETRACKER_VOLUME_TABLE
pv_osc_buffers rs.b 0 ; reuse space of volume_table, which is bigger than NOTES_IN_OCTAVE*owb_SIZEOF
pv_volume_table rs.b (MAX_VOLUME+1)*MAX_VOLUME*2
ELSE
pv_osc_buffers rs.b NOTES_IN_OCTAVE*owb_SIZEOF
ENDC
pv_precalc_sample_size rs.l 1
pv_precalc_progress_ptr rs.l 1
pv_wg_wave_counter_w rs.w 1
IFNE PRETRACKER_PARANOIA_MODE ; same wave for mixing cannot be selected in Pretracker
pv_wg_curr_wave_num_b rs.b 1
rs.b 1
ENDC
pv_wg_curr_sample_ptr rs.l 1
pv_wg_curr_samend_ptr rs.l 1
pv_wg_curr_sample_len_l rs.w 1
pv_wg_curr_sample_len_w rs.w 1
pv_wg_chord_note_num_b rs.b 1 ; don't change order
pv_wg_unisono_run_b rs.b 1 ; don't change order
pv_wg_chord_flag_w rs.w 1
pv_wg_chord_pitches rs.l 1
pv_wg_osc_speed_l rs.l 1
pv_wg_flt_taps rs.w 4
pv_SIZEOF rs.b 0

File diff suppressed because it is too large Load Diff