28 Commits
Author SHA1 Message Date
chrisly42 f97f406272 Optimized ping pong some more. 2023-09-05 21:17:11 +02:00
chrisly42 ef1c519a6c Wavegen optimizations, cosmetics and another mystery solved. 2023-08-24 22:07:42 +02:00
chrisly42 b805349bf0 Noise wave generation code optimized. 2023-08-22 22:32:51 +02:00
chrisly42 4461c72eaa Wave generation code path for noise restructured. 2023-08-22 21:06:02 +02:00
chrisly42 1580f0a174 Nosync/sync wave selection optimized among other smaller optimizations. 2023-08-20 21:09:34 +02:00
chrisly42 815d5f6e29 Bugfix for songend detection and more optimizations. 2023-08-19 21:40:08 +02:00
chrisly42 36d435f502 Wave order table filling moved and optimized in SongInit. 2023-08-16 20:35:25 +02:00
chrisly42 e0f7537774 Moved pattern table init from PlayerInit to SongInit, optimized SongInit a bit. 2023-08-16 20:02:41 +02:00
chrisly42 c57f68a505 Track delay completely reworked. 2023-08-13 21:36:49 +02:00
chrisly42 0d3ad4074c Branch optimizations, removed two octave tables and replaced them by a tiny bit of code. 2023-08-10 22:41:52 +02:00
chrisly42 dd8c224199 Replaced the period table by byte-deltas, saved 36 bytes and compression is even better! 2023-08-10 20:27:30 +02:00
chrisly42 40822e295c Cosmetics, doc updates, and optimizations. 2023-08-10 20:24:43 +02:00
chrisly42 d2360ef174 More minor doc updates. 2023-07-26 09:37:31 +02:00
chrisly42 19dd1304ab Minor doc updates. 2023-07-26 09:30:09 +02:00
chrisly42 5d95ed156c Created Presto development branch, committed improvements to Raspberry Casket work-in-progress version. 2023-07-26 09:21:36 +02:00
chrisly42 d62eacf5f8 Minor doc updates. 2023-07-25 18:37:59 +02:00
chrisly42 0496cf73bd 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.
2023-05-30 08:49:04 +02:00
chrisly42 b5478a162c Minor code size optimizations. 2023-05-20 19:33:53 +02:00
chrisly42 6a069ac78a Docu fix. 2022-12-28 15:43:42 +01:00
chrisly42 39d5e5e91e Optimized pattern / song advance code. Prepared release 1.1. 2022-12-28 15:24:03 +01:00
chrisly42 b177277d40 Optimized track delay code further. 2022-12-28 11:58:03 +01:00
chrisly42 2a1d9e9bc1 Rearranged code for more short branches. 2022-12-28 11:51:37 +01:00
chrisly42 7bac794dd8 Optimized speed/shuffle code. 2022-12-28 10:21:48 +01:00
chrisly42 627b388615 Store instrument number * 4 on loading to avoid using two adds every frame 2022-12-27 21:10:27 +01:00
chrisly42 4736b305f9 Bake in this strange vibrato speed multiplication to precalculated vibrato value (where possible) 2022-12-27 20:08:26 +01:00
chrisly42 868747e3c3 Optimized wave loop code 2022-12-27 19:41:17 +01:00
chrisly42 74c2b492f0 Optimized base displacement by reordering variables
Further optimized ADSR code
2022-12-27 19:38:04 +01:00
chrisly42 0d05dbf24c Cosmetics, no code change. 2022-12-26 22:31:02 +01:00
10 changed files with 2580 additions and 2569 deletions
+1 -1
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
+128 -17
View File
@@ -1,7 +1,7 @@
# Raspberry Casket
A fast and small open source Pretracker replayer
## Raspberry Casket Player V1.0 (26-Dec-2022)
## Raspberry Casket Player V2.x (24-Aug-2023)
Provided by Chris 'platon42' Hodges <chrisly@platon42.de>
@@ -15,33 +15,50 @@ 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
The new replayer comes as a drop-in binary replacement if you wish.
In this case you will get faster sample generation (about 12%
faster on 68000) and about 45% less CPU time spent. However, you
faster on 68000) and about 45% less CPU time spent during playback. However, you
won't get stuff as song-end detection and precalc progress this way.
This mode uses the old CPU DMA wait that takes away 8 raster lines.
@@ -54,7 +71,7 @@ during the vertical blank.
Please use the documented sizes for the `MySong` and `MyPlayer` data
structures, which are the symbols `sv_SIZEOF` and `pv_SIZEOF`
respectively (about 2K and 12K with volume table).
respectively (about 2KB and 12KB with volume table).
The source needs two common include files to compile (`custom.i` and
`dmabits.i`). You should leave assembler optimizations enabled.
@@ -69,33 +86,127 @@ The source needs two common include files to compile (`custom.i` and
- a pointer to chip memory sample buffer in `a1`
- the pointer to `MySong` in `a2`
- a pointer to a longword for progress information or null in `a3`
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
6374 bytes and goes down to ~4410 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".
About 2.4 KB of the code (and data) are spent for the sample generation,
the remaining code for playback.
### Timing
#### 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
jitter compared to other standard music replayers.
This means it may take up to 33 raster lines (14-19 on average)
This means it may take up to 32 raster lines (13-18 on average)
which is significant more than a standard Protracker replayer
(the original one could take about 60 raster lines worst case and
about 34 on average!).
Watch out for *Presto*, the [LightSpeedPlayer](https://github.com/arnaud-carre/LSPlayer) variant that should
solve this problem.
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.
- 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.
- Minor code size optimizations.
### V1.1 (28-Dec-22)
- Optimized base displacement by reordering variables.
- Further optimized ADSR code.
- Optimized wave loop code.
- Baked in this strange vibrato speed multiplication to precalculated vibrato value (where possible).
- Various small optimizations.
- Store instrument number * 4 on loading to avoid using two adds every frame.
- Optimized speed/shuffle code. Idea of using xor turned out to make things too complicated for pattern breaks/jumps.
- Rearranged code for more short branches.
- Optimized track delay code further.
- Optimized pattern / song advance code.
- Maximum jitter now about one rasterline less, average about 0.5 rasterlines less (measurements, your mileage may vary).
- Drop-in replacement code size: 6228 bytes.
### V1.0 (26-Dec-22)
- Initial release.
- Drop-in replacement code size: 6446 bytes.
Binary file not shown.
+2 -2
View File
@@ -1,5 +1,5 @@
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.
variables as in the original player (you need only about 2 + 12 KB).
It has been assembled from src/drop_in_replacement.asm.
It has been assembled from src/drop_in_replacement.asm (version V2.0).
Binary file not shown.
+2 -2
View File
@@ -3,7 +3,7 @@ It features Pink's song Plastic Dove (from the Coda Intro).
Even though it features the full replayer code and tune,
the replayer including my demo framework and the song only
takes a mere 6560 bytes (shrinkled), which is even smaller
takes a mere 6448 bytes (shrinkled), which is even smaller
than the new streaming replayer used in Pink's new streaming
player demonstrated (closed source) in
@@ -11,7 +11,7 @@ https://www.pouet.net/prod.php?which=91551
which is 6860 bytes.
The Raspberry Casket replayer takes an average of 14
The Raspberry Casket replayer takes an average of 13.5
rasterlines while Pink's new streaming player takes
only about 10 rasterlines.
+1 -1
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
+810 -2546
View File
File diff suppressed because it is too large Load Diff
+342
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