; 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_clone_wave_b    = $12 ; only used by tracker itself
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_last_wave_was_looping_b rs.b    1 ; -1 if the last wave was a looping one so no-sync is actually allowed
pcd_wave_nosync             rs.b    1 ; For Presto (otherwise padding): Store if the wave currently uses nosync or not

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_wave_ptr           rs.l    1
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