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 ; The mixer is responsible for outputting proper audio.
29 .
public mixer .mixer_state
33 .if sizeof tonal_state
!= sizeof envelope_state
34 .error
"tonal_state and envelope_state must have the same size"
36 .if sizeof tonal_state
!= sizeof track_state
37 .error
"tonal_state and track_state must have the same size"
41 ;.define NO_MUTABLE_CHANNELS
45 .ifndef NO_MUTABLE_CHANNELS
46 .
public mixer_get_muted_channels
47 .
public mixer_set_muted_channels
49 .
public mixer_get_master_vol
50 .
public mixer_set_master_vol
51 .
public mixer_invalidate_period_save
53 .extrn
envelope_tick:proc
54 .extrn
effect_tick:proc
56 .extrn
volume_table:byte
57 .extrn
sound_status:byte
59 ; Executes one "tick" of the mixer.
60 ; This involves updating volume envelopes, music effects (vibrato, for example),
61 ; and so forth, and most importantly, writing proper values to the audio
63 ; The mixer handles updating of sound effects, and selects the proper "audio
64 ; source" (sound effect or music) depending on whether a sound effect is playing
72 ; update volume envelopes
73 ldx #
3*sizeof envelope_state
77 sbc #sizeof envelope_state
81 ; update tonal effects
82 ldx #
3*sizeof tonal_state
86 sbc #sizeof tonal_state
90 ; update square duties
91 ; ### consider making this a plain effect instead
92 ldx #
1*sizeof tonal_state
93 - lda mixer.tonals.square.counter
,x
95 dec mixer.tonals.square.counter
,x
97 lda mixer.tonals.square.duty_ctrl
,x
101 sta mixer.tonals.square.duty
,x
; set the new duty
104 sbc #sizeof tonal_state
109 ; write to NES audio regs
113 lda mixer.sfx
[0].
ptr.hi
117 ldx #
0*sizeof sfx_state
124 .ifndef NO_MUTABLE_CHANNELS
128 lda mixer.envelopes
[0].master
129 .ifndef NO_MUTABLE_CHANNELS
131 lda #
0 ; the channel is muted
135 ora mixer.envelopes
[0].vol.
int
141 ora mixer.tonals
[0].square.duty
146 lda mixer.tonals
[0].period.lo
148 lda mixer.tonals
[0].period.hi
149 cmp mixer.tonals
[0].square.period_save
152 sta mixer.tonals
[0].square.period_save
157 lda mixer.sfx
[1].
ptr.hi
161 ldx #
1*sizeof sfx_state
168 .ifndef NO_MUTABLE_CHANNELS
173 lda mixer.envelopes
[1].master
174 .ifndef NO_MUTABLE_CHANNELS
176 lda #
0 ; the channel is muted
180 ora mixer.envelopes
[1].vol.
int
186 ora mixer.tonals
[1].square.duty
191 lda mixer.tonals
[1].period.lo
193 lda mixer.tonals
[1].period.hi
194 cmp mixer.tonals
[1].square.period_save
197 sta mixer.tonals
[1].square.period_save
202 lda mixer.sfx
[2].
ptr.hi
206 ldx #
2*sizeof sfx_state
213 .ifndef NO_MUTABLE_CHANNELS
219 lda mixer.envelopes
[2].master
220 .ifndef NO_MUTABLE_CHANNELS
222 lda #
0 ; the channel is muted
226 ora mixer.envelopes
[2].vol.
int
235 lda mixer.tonals
[2].period.lo
237 lda mixer.tonals
[2].period.hi
242 ++ lda mixer.sfx
[3].
ptr.hi
246 ldx #
3*sizeof sfx_state
253 .ifndef NO_MUTABLE_CHANNELS
260 lda mixer.envelopes
[3].master
261 .ifndef NO_MUTABLE_CHANNELS
263 lda #
0 ; the channel is muted
267 ora mixer.envelopes
[3].vol.
int
275 lda mixer.tonals
[3].period.lo
277 lda mixer.tonals
[3].period.hi
279 ora mixer.tonals
[3].square.duty_ctrl
; bit 7 = RNG mode
287 ; It sets important fields of the mixer data structures so that things will
288 ; behave correctly on invocations to mixer_tick().
293 ; zap volume envelopes
294 ldx #
3*sizeof envelope_state
296 sta mixer.envelopes.phase
,x
297 sta mixer.envelopes.vol.
int,x
299 sta mixer.envelopes.master
,x
302 sbc #sizeof envelope_state
306 ldx #
3*sizeof effect_state
308 sta mixer.tonals.effect.kind
,x
309 sta mixer.tonals.period_index
,x
310 sta mixer.tonals.period.lo
,x
311 sta mixer.tonals.period.hi
,x
314 sbc #sizeof effect_state
319 ldx #
3*sizeof sfx_state
321 sta mixer.sfx.
ptr.hi
,x
324 sbc #sizeof sfx_state
328 ; custom channel init
330 sta mixer.tonals
[0].square.period_save
331 sta mixer.tonals
[1].square.period_save
332 ; enable sound hardware channels
338 .ifndef NO_MUTABLE_CHANNELS
339 .
proc mixer_get_muted_channels
345 .
proc mixer_set_muted_channels
358 .
proc mixer_get_master_vol
363 .
proc mixer_set_master_vol
368 .
proc mixer_invalidate_period_save
369 lda mixer.tonals
[0].square.period_save
371 sta mixer.tonals
[0].square.period_save
372 lda mixer.tonals
[1].square.period_save
374 sta mixer.tonals
[1].square.period_save