chrisly42
9c48c11cd1
- Bugfix: WaitForFrame was completely broken. Now also caters for race-condition that would have waited one extra frame. - Bugfix: InitPart would overwrite innocent memory (reported by Gigabates and Losso) - Bugfix: Palette LERP had wrong bias. - Removed extra paths in include statement, use default include paths instead - Added Raspberry Casket no-jitter background calc mode (FW_MUSIC_PLAYER_CHOICE = 6) - Updated Raspberry Casket to V2.0 presto branch (WIP) - Removed fw_FrameCounterLong, use fw_FrameCounter-2 for debug purposes - Support for blue noise palette LERPing (like in Is Real). Provide your own blue noise table (4 KB), stuff it into fw_BlueNoiseTablePtr, set FW_PALETTE_LERP_SUPPORT to 2 - Music tick routine is now replaceable during runtime (fw_MusicTickRoutine) - Support for softints and audio interrupts - LMB exit can also be disabled dynamically when using FW_LMB_EXIT_SUPPORT = 2 and fw_DisableLMBExit != 0 - Added LSP Micro support and LSP Nano (custom format that uses note pitches instead of periods) - Minor other things
346 lines
13 KiB
OpenEdge ABL
346 lines
13 KiB
OpenEdge ABL
; 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
|
|
|