Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
f97f406272 | |||
ef1c519a6c | |||
b805349bf0 | |||
4461c72eaa | |||
1580f0a174 | |||
815d5f6e29 | |||
36d435f502 | |||
e0f7537774 | |||
c57f68a505 | |||
0d3ad4074c | |||
dd8c224199 | |||
40822e295c | |||
d2360ef174 | |||
19dd1304ab | |||
5d95ed156c |
2
LICENSE
2
LICENSE
@ -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
|
||||
|
99
README.md
99
README.md
@ -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.
@ -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).
|
@ -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
342
src/raspberry_casket.i
Normal 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
|
||||
|
1294
src/raspberry_casket_wavegen.asm
Normal file
1294
src/raspberry_casket_wavegen.asm
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user