2 ; Copyright (C) 2004, 2005 Kent Hansen.
4 ; This file is part of Neotoxin.
6 ; Neotoxin is free software; you can redistribute it and/or modify
7 ; it under the terms of the GNU General Public License as published by
8 ; the Free Software Foundation; either version 2 of the License, or
9 ; (at your option) any later version.
11 ; Neotoxin is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
16 ; You should have received a copy of the GNU General Public License
17 ; along with this program; if not, write to the Free Software
18 ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 ; Real-time volume envelope processing.
23 ; Only useful for channels 0, 1 and 3.
24 ; Volume envelope format:
25 ; Byte 0: Start volume (0..15)
26 ; Series of 4-byte tuples: 8x8 fixed-point step, hold length, end volume
27 ; Until integer part of step = $FF
28 ; If next byte is also $FF, it's really the end
29 ; Otherwise the envelope is looped from that value
44 .extrn
mixer:mixer_state
46 ; Copies current volume envelope data pointer to local pointer.
47 ; Params: X = channel number
49 lda mixer.envelopes.
ptr.lo
,x
51 lda mixer.envelopes.
ptr.hi
,x
52 sta env.hi
; set pointer to envelope
55 ; Fetches next byte from volume envelope data.
56 ; Params: Y = envelope data offset (auto-incremented)
62 ; Does one tick of envelope processing.
63 ; Params: X = channel number
66 lda mixer.envelopes.phase
,x
67 bmi
@@init ; phase = $80
69 bmi
@@process ; phase = $40
71 bmi
@@sustain ; phase = $20
76 lsr mixer.envelopes.phase
,x
; phase = update envelope
78 sta mixer.envelopes.pos
,x
; reset envelope position
83 sta mixer.envelopes.vol.
int,x
; 1st byte = start volume
84 ; Initialize envelope point
87 cmp #
$FF ; $FF = end of envelope reached
89 ; Point OK, set 4-tuple
90 sta mixer.envelopes.step.
int,x
92 sta mixer.envelopes.step.frac
,x
94 sta mixer.envelopes.hold
,x
96 sta mixer.envelopes.dest
,x
98 sta mixer.envelopes.vol.frac
,x
100 sta mixer.envelopes.pos
,x
102 ; End of envelope reached (step.int = FF)
104 fetch_env_byte
; if FF, definitely end... otherwise loop
107 tay
; loop the envelope
109 ; No more envelope processing
112 sta mixer.envelopes.phase
,x
115 ; Sustain volume until hold == 0.
117 ldy mixer.envelopes.hold
,x
119 beq
- ; sustain forever if length = $FF
120 dec mixer.envelopes.hold
,x
122 asl mixer.envelopes.phase
,x
; back to phase = process
125 ; Update volume according to step
128 lda mixer.envelopes.vol.frac
,x
130 adc mixer.envelopes.step.frac
,x
131 sta mixer.envelopes.vol.frac
,x
134 lda mixer.envelopes.vol.
int,x
135 cmp mixer.envelopes.dest
,x
137 ; CurrentVol < DestVol ==> CurrentVol += StepHi
139 adc mixer.envelopes.step.
int,x
140 cmp mixer.envelopes.dest
,x
142 sta mixer.envelopes.vol.
int,x
144 ; CurrentVol > DestVol ==> CurrentVol -= StepHi
148 eor #
$01 ; toggle carry
150 sbc mixer.envelopes.step.
int,x
152 cmp mixer.envelopes.dest
,x
155 sta mixer.envelopes.vol.
int,x
157 ; Reached point's destination volume
159 lda mixer.envelopes.dest
,x
160 sta mixer.envelopes.vol.
int,x
161 lda mixer.envelopes.hold
,x
163 lsr mixer.envelopes.phase
,x
; phase = sustain
165 ; Start the next envelope point
168 ldy mixer.envelopes.pos
,x