@@ -63,7 +63,6 @@ ENDR |
| 63 |
|
63 |
|
| 64 |
; Interrupt addresses |
64 |
; Interrupt addresses |
| 65 |
SECTION "Vblank interrupt", ROM0[$0040] |
65 |
SECTION "Vblank interrupt", ROM0[$0040] |
| 66 |
; jp _dosound |
|
|
| 67 |
reti |
66 |
reti |
| 68 |
|
67 |
|
| 69 |
SECTION "LCD controller status interrupt", ROM0[$0048] |
68 |
SECTION "LCD controller status interrupt", ROM0[$0048] |
@@ -71,14 +70,12 @@ SECTION "LCD controller status interrupt", ROM0[$0048] |
| 71 |
reti |
70 |
reti |
| 72 |
|
71 |
|
| 73 |
SECTION "Timer overflow interrupt", ROM0[$0050] |
72 |
SECTION "Timer overflow interrupt", ROM0[$0050] |
| 74 |
; jp _dosound |
|
|
| 75 |
reti |
73 |
reti |
| 76 |
|
74 |
|
| 77 |
SECTION "Serial transfer completion interrupt", ROM0[$0058] |
75 |
SECTION "Serial transfer completion interrupt", ROM0[$0058] |
| 78 |
reti |
76 |
reti |
| 79 |
|
77 |
|
| 80 |
SECTION "P10-P13 signal low edge interrupt", ROM0[$0060] |
78 |
SECTION "P10-P13 signal low edge interrupt", ROM0[$0060] |
| 81 |
; jp _dosound |
|
|
| 82 |
reti |
79 |
reti |
| 83 |
|
80 |
|
| 84 |
; Reserved stack space |
81 |
; Reserved stack space |
@@ -105,7 +102,7 @@ DB "NF" |
| 105 |
SECTION "Song Data", ROM0 |
102 |
SECTION "Song Data", ROM0 |
| 106 |
;; order_cnt is the number of orders times 2 |
103 |
;; order_cnt is the number of orders times 2 |
| 107 |
order_cnt: db 2 |
104 |
order_cnt: db 2 |
| 108 |
order1: dw unreal;, lunawaves, lunawaves, unreal |
105 |
order1: dw unreal ;; unreal;, lunawaves, lunawaves, unreal |
| 109 |
order2: dw empty, unreal, unreal, lunawaves |
106 |
order2: dw empty, unreal, unreal, lunawaves |
| 110 |
order3: dw empty, lunawaves, lunawaves, unreal |
107 |
order3: dw empty, lunawaves, lunawaves, unreal |
| 111 |
order4: dw empty, lunawaves, lunawaves, unreal |
108 |
order4: dw empty, lunawaves, lunawaves, unreal |
@@ -125,6 +122,11 @@ rept 16 |
| 125 |
db 90, 0, 0 |
122 |
db 90, 0, 0 |
| 126 |
db 90, 0, 0 |
123 |
db 90, 0, 0 |
| 127 |
endr |
124 |
endr |
|
|
125 |
slideup: |
|
|
126 |
dn C3, 00, $000 |
|
|
127 |
rept 63 |
|
|
128 |
dn 90, 00, 332 |
|
|
129 |
endr |
| 128 |
|
130 |
|
| 129 |
SECTION "Playback variables", WRAM0 |
131 |
SECTION "Playback variables", WRAM0 |
| 130 |
pattern1: dw |
132 |
pattern1: dw |
@@ -134,6 +136,18 @@ pattern4: dw |
| 134 |
|
136 |
|
| 135 |
current_order: dw |
137 |
current_order: dw |
| 136 |
|
138 |
|
|
|
139 |
channel_periods: |
|
|
140 |
channel_period1: dw |
|
|
141 |
channel_period2: dw |
|
|
142 |
channel_period3: dw |
|
|
143 |
channel_period4: dw |
|
|
144 |
|
|
|
145 |
toneporta_targets: |
|
|
146 |
toneporta_target1: dw |
|
|
147 |
toneporta_target2: dw |
|
|
148 |
toneporta_target3: dw |
|
|
149 |
toneporta_target4: dw |
|
|
150 |
|
| 137 |
row: ds 1 |
151 |
row: ds 1 |
| 138 |
tick: ds 1 |
152 |
tick: ds 1 |
| 139 |
|
153 |
|
@@ -213,7 +227,7 @@ _addr = _addr + 1 |
| 213 |
ld a, 0 |
227 |
ld a, 0 |
| 214 |
ld [rLYC], a |
228 |
ld [rLYC], a |
| 215 |
|
229 |
|
| 216 |
ld a, IEF_VBLANK | IEF_LCDC ; IEF_HILO | IEF_TIMER |
230 |
ld a, IEF_LCDC ; IEF_VBLANK; | IEF_LCDC ; IEF_HILO | IEF_TIMER |
| 217 |
ld [rIE], a |
231 |
ld [rIE], a |
| 218 |
ei |
232 |
ei |
| 219 |
|
233 |
|
@@ -254,15 +268,18 @@ _lookup_note: |
| 254 |
|
268 |
|
| 255 |
ld h, 0 |
269 |
ld h, 0 |
| 256 |
ld l, a |
270 |
ld l, a |
| 257 |
add hl, de |
271 |
inc l |
|
|
272 |
inc l |
|
|
273 |
add hl, de ; HL now points at the 3rd byte of the note |
|
|
274 |
ld a, [hl-] |
|
|
275 |
ld c, a |
|
|
276 |
ld a, [hl-] |
|
|
277 |
ld b, a |
|
|
278 |
|
| 258 |
ld a, [hl] |
279 |
ld a, [hl] |
| 259 |
|
280 |
|
| 260 |
cp LAST_NOTE |
281 |
cp LAST_NOTE |
| 261 |
jp c, .note_exists |
282 |
jp c, .note_exists |
| 262 |
|
|
|
| 263 |
;; Pop the return pointer off the stack and get the one the caller pushed if it's a nonexistent note |
|
|
| 264 |
pop hl |
|
|
| 265 |
ld hl, 0 |
|
|
| 266 |
ret |
283 |
ret |
| 267 |
|
284 |
|
| 268 |
.note_exists: |
285 |
.note_exists: |
@@ -272,31 +289,49 @@ _lookup_note: |
| 272 |
LD L, A |
289 |
LD L, A |
| 273 |
LD DE, note_table |
290 |
LD DE, note_table |
| 274 |
ADD HL, DE |
291 |
ADD HL, DE |
| 275 |
LD A, [HL] |
292 |
LD A, [HL+] |
| 276 |
INC HL |
293 |
;; INC HL |
| 277 |
LD H, [HL] |
294 |
LD H, [HL] |
| 278 |
LD L, A |
295 |
LD L, A |
|
|
296 |
|
|
|
297 |
ccf ;; uh....? |
| 279 |
ret |
298 |
ret |
| 280 |
|
299 |
|
| 281 |
_playnote1: |
300 |
_playnote1: |
| 282 |
;; Call with: |
301 |
;; Call with: |
| 283 |
;; Note value in H and L |
302 |
;; Note value in H and L |
|
|
303 |
;; instrument + effect code in B |
| 284 |
|
304 |
|
| 285 |
;; Play a note on channel 1 (square wave) |
305 |
;; Play a note on channel 1 (square wave) |
| 286 |
|
306 |
|
|
|
307 |
ld a, b |
|
|
308 |
and %00001111 |
|
|
309 |
cp $3 |
|
|
310 |
jp nz, .no_toneporta |
|
|
311 |
ld a, h |
|
|
312 |
ld [toneporta_target1], a |
|
|
313 |
ld a, l |
|
|
314 |
ld [toneporta_target1+1], a |
|
|
315 |
ret |
|
|
316 |
|
|
|
317 |
.no_toneporta: |
| 287 |
; ld a, %01111001 |
318 |
; ld a, %01111001 |
| 288 |
; ld [rAUD1SWEEP], a |
319 |
; ld [rAUD1SWEEP], a |
| 289 |
|
320 |
|
| 290 |
ld a, %11111111 ; $10 |
321 |
ld a, %10111111 ; $10 |
| 291 |
ldh [rAUD1LEN], a |
322 |
ldh [rAUD1LEN], a |
| 292 |
ld a, %11110000 |
323 |
ld a, %11110000 |
| 293 |
ldh [rAUD1ENV], a |
324 |
ldh [rAUD1ENV], a |
| 294 |
|
325 |
|
| 295 |
ld a, l |
326 |
ld a, l |
|
|
327 |
ld [channel_period1+1], a |
| 296 |
ldh [rAUD1LOW], a |
328 |
ldh [rAUD1LOW], a |
|
|
329 |
|
| 297 |
ld a, h |
330 |
ld a, h |
|
|
331 |
ld [channel_period1], a |
| 298 |
or %10000000 |
332 |
or %10000000 |
| 299 |
ldh [rAUD1HIGH], a |
333 |
ldh [rAUD1HIGH], a |
|
|
334 |
|
| 300 |
ret |
335 |
ret |
| 301 |
|
336 |
|
| 302 |
_playnote2: |
337 |
_playnote2: |
@@ -346,6 +381,12 @@ _playnote4: |
| 346 |
|
381 |
|
| 347 |
ret |
382 |
ret |
| 348 |
|
383 |
|
|
|
384 |
cphl: MACRO |
|
|
385 |
or a |
|
|
386 |
sbc hl, \1 |
|
|
387 |
add hl, \1 |
|
|
388 |
ENDM |
|
|
389 |
|
| 349 |
loadShort: MACRO |
390 |
loadShort: MACRO |
| 350 |
ld a, [\1] |
391 |
ld a, [\1] |
| 351 |
ld \3, a |
392 |
ld \3, a |
@@ -353,10 +394,143 @@ loadShort: MACRO |
| 353 |
ld \2, a |
394 |
ld \2, a |
| 354 |
ENDM |
395 |
ENDM |
| 355 |
|
396 |
|
|
|
397 |
_doeffect: |
|
|
398 |
;; Call with: |
|
|
399 |
;; B: instrument nibble + effect type nibble |
|
|
400 |
;; C: effect parameters |
|
|
401 |
;; E: channel |
|
|
402 |
|
|
|
403 |
;; free: A, D, H, L |
|
|
404 |
|
|
|
405 |
;; Strip the instrument bits off leaving only effect code |
|
|
406 |
ld a, b |
|
|
407 |
and %00001111 |
|
|
408 |
ld b, a |
|
|
409 |
|
|
|
410 |
;; Multiply by 3 to get offset into table |
|
|
411 |
ld a, b |
|
|
412 |
add a, b |
|
|
413 |
add a, b |
|
|
414 |
|
|
|
415 |
ld hl, .jump |
|
|
416 |
|
|
|
417 |
add a, l |
|
|
418 |
ld l, a |
|
|
419 |
adc a, h |
|
|
420 |
sub l |
|
|
421 |
ld h, a |
|
|
422 |
|
|
|
423 |
jp hl |
|
|
424 |
|
|
|
425 |
.jump: |
|
|
426 |
;; Jump table for effect |
|
|
427 |
jp fx_no_op ;fx_arpeggio ;0xy |
|
|
428 |
jp fx_no_op ;fx_porta_up ;1xy |
|
|
429 |
jp fx_no_op ;fx_porta_down ;2xy |
|
|
430 |
jp fx_toneporta ;fx_no_op ;3xy |
|
|
431 |
jp fx_no_op ;fx_vibrato ;4xy |
|
|
432 |
jp fx_no_op ;fx_toneporta_volslide ;5xy |
|
|
433 |
jp fx_no_op ;fx_vibrato_volslide ;6xy |
|
|
434 |
jp fx_no_op ;fx_tremolo ;7xy |
|
|
435 |
jp fx_no_op ;fx_set_pan ;8xy |
|
|
436 |
jp fx_no_op ;fx_set_duty ;9xy |
|
|
437 |
jp fx_no_op ;fx_vol_slide ;Axy |
|
|
438 |
jp fx_no_op ;fx_pos_jump ;Bxy |
|
|
439 |
jp fx_no_op ;fx_set_volume ;Cxy |
|
|
440 |
jp fx_no_op ;fx_pattern_break ;Dxy |
|
|
441 |
jp fx_no_op ;fx_note_cut ;Exy |
|
|
442 |
jp fx_no_op ;fx_set_speed ;Fxy |
|
|
443 |
|
|
|
444 |
fx_no_op: |
|
|
445 |
ret |
|
|
446 |
|
|
|
447 |
fx_toneporta: |
|
|
448 |
ld b, e ;; so we have access to DE |
|
|
449 |
;; B: channel |
|
|
450 |
;; C: effect parameters |
|
|
451 |
|
|
|
452 |
;; free registers: A, D, E, H, L |
|
|
453 |
|
|
|
454 |
; Do nothing on the noise channel |
|
|
455 |
; ld a, 4 |
|
|
456 |
; cp e |
|
|
457 |
; ret z |
|
|
458 |
|
|
|
459 |
ld a, [channel_period1+1] |
|
|
460 |
ld l, a |
|
|
461 |
ld a, [channel_period1] |
|
|
462 |
ld h, a |
|
|
463 |
|
|
|
464 |
ld a, [toneporta_target1+1] |
|
|
465 |
ld e, a |
|
|
466 |
ld a, [toneporta_target1] |
|
|
467 |
ld d, a |
|
|
468 |
|
|
|
469 |
;; Comparing which direction to move the current value |
|
|
470 |
;; TODO: Optimize this!!!! |
|
|
471 |
|
|
|
472 |
;; Compare high byte |
|
|
473 |
cp h |
|
|
474 |
jp c, .subtract ; target is less than the current period |
|
|
475 |
jp z, .high_byte_same |
|
|
476 |
jp .add |
|
|
477 |
.high_byte_same: |
|
|
478 |
ld a, e |
|
|
479 |
cp l |
|
|
480 |
jp c, .subtract ; the target is less than the current period |
|
|
481 |
jp z, .done ; both nibbles are the same so no portamento |
|
|
482 |
.add: |
|
|
483 |
ld b, 0 |
|
|
484 |
; ld e, c |
|
|
485 |
|
|
|
486 |
add hl, bc |
|
|
487 |
|
|
|
488 |
ld a, d |
|
|
489 |
cp h |
|
|
490 |
jp c, .set_exact |
|
|
491 |
ld a, e |
|
|
492 |
cp l |
|
|
493 |
jp c, .set_exact |
|
|
494 |
|
|
|
495 |
jp .done |
|
|
496 |
|
|
|
497 |
.subtract: |
|
|
498 |
ld a, l |
|
|
499 |
sub c |
|
|
500 |
ld l, a |
|
|
501 |
|
|
|
502 |
ld a, h |
|
|
503 |
sbc a, 0 |
|
|
504 |
ld h, a |
|
|
505 |
|
|
|
506 |
ld a, d |
|
|
507 |
cp h |
|
|
508 |
jp nc, .set_exact |
|
|
509 |
ld a, e |
|
|
510 |
cp l |
|
|
511 |
jp nc, .set_exact |
|
|
512 |
|
|
|
513 |
jp .done |
|
|
514 |
|
|
|
515 |
.set_exact: |
|
|
516 |
ld h, d |
|
|
517 |
ld l, e |
|
|
518 |
.done: |
|
|
519 |
ld a, l |
|
|
520 |
ld [channel_period1+1], a |
|
|
521 |
ldh [rAUD1LOW], a |
|
|
522 |
|
|
|
523 |
ld a, h |
|
|
524 |
ld [channel_period1], a |
|
|
525 |
ldh [rAUD1HIGH], a |
|
|
526 |
|
|
|
527 |
.do_nothing: |
|
|
528 |
ret |
|
|
529 |
|
| 356 |
_dosound: |
530 |
_dosound: |
| 357 |
ld a, [tick] |
531 |
ld a, [tick] |
| 358 |
cp 0 |
532 |
cp 0 |
| 359 |
jp nz, _process_tick |
533 |
jp nz, .process_effects |
| 360 |
|
534 |
|
| 361 |
;; We're on tick zero, so lookup and play the notes, |
535 |
;; We're on tick zero, so lookup and play the notes, |
| 362 |
;; then continue as usual |
536 |
;; then continue as usual |
@@ -365,41 +539,40 @@ _dosound: |
| 365 |
;; and the procedure will discard its normal return value if it needs to |
539 |
;; and the procedure will discard its normal return value if it needs to |
| 366 |
;; skip a note and use the new value instead. |
540 |
;; skip a note and use the new value instead. |
| 367 |
|
541 |
|
| 368 |
ld hl, _after_note1 |
|
|
| 369 |
push hl |
|
|
| 370 |
loadShort pattern1, d, e |
542 |
loadShort pattern1, d, e |
| 371 |
call _lookup_note |
543 |
call _lookup_note |
| 372 |
pop de |
544 |
jp nc, .after_note1 |
| 373 |
call _playnote1 |
545 |
call _playnote1 |
| 374 |
|
546 |
|
| 375 |
_after_note1: |
547 |
.after_note1: |
| 376 |
ld hl, _after_note2 |
|
|
| 377 |
push hl |
|
|
| 378 |
loadShort pattern2, d, e |
548 |
loadShort pattern2, d, e |
| 379 |
call _lookup_note |
549 |
call _lookup_note |
| 380 |
pop de |
550 |
jp nc, .after_note2 |
| 381 |
call _playnote2 |
551 |
call _playnote2 |
| 382 |
|
552 |
|
| 383 |
_after_note2: |
553 |
.after_note2: |
| 384 |
ld hl, _after_note3 |
|
|
| 385 |
push hl |
|
|
| 386 |
loadShort pattern3, d, e |
554 |
loadShort pattern3, d, e |
| 387 |
call _lookup_note |
555 |
call _lookup_note |
| 388 |
pop de |
556 |
jp nc, .after_note3 |
| 389 |
call _playnote3 |
557 |
call _playnote3 |
| 390 |
|
558 |
|
| 391 |
_after_note3: |
559 |
.after_note3: |
| 392 |
ld hl, _process_tick |
|
|
| 393 |
push hl |
|
|
| 394 |
loadShort pattern4, d, e |
560 |
loadShort pattern4, d, e |
| 395 |
call _lookup_note |
561 |
call _lookup_note |
| 396 |
pop de |
562 |
jp nc, .process_tick |
| 397 |
call _playnote4 |
563 |
call _playnote4 |
| 398 |
|
564 |
|
| 399 |
_process_tick: |
565 |
jp .process_tick |
| 400 |
;; Process effect commands |
566 |
|
|
|
567 |
.process_effects: |
|
|
568 |
;; Only do effects if not on tick zero |
|
|
569 |
loadShort pattern1, d, e |
|
|
570 |
call _lookup_note |
|
|
571 |
ld e, 1 |
|
|
572 |
call _doeffect |
| 401 |
|
573 |
|
| 402 |
|
574 |
|
|
|
575 |
.process_tick: |
| 403 |
ld a, [tick] |
576 |
ld a, [tick] |
| 404 |
inc a |
577 |
inc a |
| 405 |
|
578 |
|