-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudio.asm
343 lines (263 loc) · 5.55 KB
/
audio.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
; this sub routine inits audio
; side effects:
; overwrites a register
init_audio_channels:
; Init $4000-4013
ldy #$13
@loop: lda @regs,y
sta $4000,y
dey
bpl @loop
; We have to skip over $4014 (OAMDMA)
; enable Square 1, Square 2, Triangle and Noise channels. Disable DMC.
lda #$0F
sta $4015
lda #$40
sta $4017
jsr stop_audio
rts
@regs:
.db $30,$08,$00,$00
.db $30,$08,$00,$00
.db $80,$00,$00,$00
.db $30,$00,$00,$00
.db $00,$00,$00,$00
; stops all sounds on all channels
stop_audio:
; set up audio pointers
lda #<no_audio
sta pulse_ptr_1
sta pulse_ptr_2
sta triangle_ptr
sta noise_ptr
lda #>no_audio
sta pulse_ptr_1+1
sta pulse_ptr_2+1
sta triangle_ptr+1
sta noise_ptr+1
rts
; this sub routine update all audio playback
; inputs:
; pulse, triangle and noise_ptrs
; side effects:
; updates audio timer and registers
; user register a, x, y
update_audio:
; pulse 1 code
ldy #$00
lda (pulse_ptr_1), y
cmp #$FF
beq @not_pulse_1 ; no update
ldx pulse_timer_1
dex
stx pulse_timer_1
bne @not_pulse_1 ; if timer is not 0 do not play yet
ldx pulse_periode_1
stx pulse_timer_1 ; store periode again
; skip update
cmp #$FE
beq @skip_note_pulse1
sta $4000 ; store channel settings
iny
lda (pulse_ptr_1), y
tax ; note offset
lda period_table_hi, x
sta $4003
lda period_table_lo, x
sta $4002
lda pulse_sweep_1
sta $4001
@skip_note_pulse1:
lda pulse_ptr_1
clc
adc #$02 ; add 2 for next pair
sta pulse_ptr_1
lda pulse_ptr_1+1
adc #$00
sta pulse_ptr_1+1
@not_pulse_1:
; pulse 2 code
ldy #$00
lda (pulse_ptr_2), y
cmp #$FF
beq @not_pulse_2 ; no update
ldx pulse_timer_2
dex
stx pulse_timer_2
bne @not_pulse_2 ; if timer is not 0 do not play yet
ldx pulse_periode_2
stx pulse_timer_2 ; store periode again
; skip update
cmp #$FE
beq @skip_note_pulse2:
sta $4004 ; store channel settings
iny
lda (pulse_ptr_2), y
tax ; note offset
lda period_table_hi, x
sta $4007
lda period_table_lo, x
sta $4006
lda pulse_sweep_2
sta $4005
@skip_note_pulse2:
lda pulse_ptr_2
clc
adc #$02 ; add 2 for next pair
sta pulse_ptr_2
lda pulse_ptr_2+1
adc #$00
sta pulse_ptr_2+1
@not_pulse_2:
; triangle code
ldy #$00
lda (triangle_ptr), y
cmp #$FF
beq @not_triangle ; no update
ldx triangle_timer
dex
stx triangle_timer
bne @not_triangle ; if timer is not 0 do not play yet
ldx triangle_periode
stx triangle_timer ; store periode again
cmp #$FE
beq @skip_note_triangle:
sta $4008 ; store channel settings
sta $4017
iny
lda (triangle_ptr), y
tax ; note offset
lda period_table_hi+12, x
sta $400B
lda period_table_lo+12, x
sta $400A
@skip_note_triangle:
lda triangle_ptr
clc
adc #$02 ; add 2 for next pair
sta triangle_ptr
lda triangle_ptr+1
adc #$00
sta triangle_ptr+1
@not_triangle:
; triangle code
ldy #$00
lda (noise_ptr), y
cmp #$FF
beq @not_noise ; no update
ldx noise_timer
dex
stx noise_timer
bne @not_noise ; if timer is not 0 do not play yet
ldx noise_periode
stx noise_timer ; store periode again
cmp #$FE
beq @skip_note_noise ; skip note if FE
sta $400C ; store channel settings
iny
lda (noise_ptr), y
sta $400E
iny
lda (noise_ptr), y
sta $400F
@skip_note_noise:
lda noise_ptr
clc
adc #$03 ; add 3 for next pair
sta noise_ptr
lda noise_ptr+1
adc #$00
sta noise_ptr+1
@not_noise:
rts
; this sub routine plays a cursor beep
; noise
; side effects:
; uses a register
; loads sound into noise channel
init_cursor_beep:
lda #<cursor_noise
sta noise_ptr
lda #>cursor_noise
sta noise_ptr+1
lda #10
sta noise_periode ; 10 frames per periode
lda #$01
sta noise_timer
rts
; this sub routine sets up
; the jump sound
; side effects:
; uses A register
; loads sound into noise channel
init_sword_noise:
init_jump_noise:
lda #<jump_noise
sta noise_ptr
lda #>jump_noise
sta noise_ptr+1
lda #$30
sta noise_periode
lda #$01
sta noise_timer
rts
init_hit_noise:
lda #<hit_noise
sta noise_ptr
lda #>hit_noise
sta noise_ptr+1
lda #$30
sta noise_periode
lda #$01
sta noise_timer
rts
init_push_noise:
lda #<push_noise
sta noise_ptr
lda #>push_noise
sta noise_ptr+1
lda #$20
sta noise_periode
lda #$01
sta noise_timer
rts
init_coin_noise:
lda #<coin_noise
sta noise_ptr
lda #>coin_noise
sta noise_ptr+1
lda #$20
sta noise_periode
lda #$01
sta noise_timer
rts
; this sub routine inits the test song
; side effects:
; uses A register
; loads sound into both square wave channels
; and the triangle channel
init_test_song:
lda #$1F ; periode
sta pulse_periode_1
sta pulse_periode_2
sta triangle_periode
lda #$01
sta pulse_timer_1
sta pulse_timer_2
sta triangle_timer
lda #<test_song_square_1
sta pulse_ptr_1
lda #>test_song_square_1
sta pulse_ptr_1+1
lda #<test_song_square_2
sta pulse_ptr_2
lda #>test_song_square_2
sta pulse_ptr_2+1
lda #<test_song_triangle
sta triangle_ptr
lda #>test_song_triangle
sta triangle_ptr+1
lda #%1000000
sta pulse_sweep_1
sta pulse_sweep_2
rts