PUSHS "Sound Variables", WRAM0[AUDIO_VARS_START] ordersStart: dw println "orders start is ", ordersStart ordersLength: db ; audio player state currentOrderNumber: db currentRowNumber: db println "currentRowNumber is ", currentRowNumber currentTickNumber: db currentPattern: dw println "current pattern is ", currentPattern audioReadHead: dw AUDIO_VARIABLES_BEGIN: speed: db macro channel ; macro to define all the channell data in parallel channel_\1_note: db channel_\1_duty: db channel_\1_volume: db channel_\1_slide: db channel_\1_arp: db channel_\1_pan: db channel_\1_vibrato: db channel_\1_trigger: db endm channel 1 channel 2 channel 3 channel 4 println "channel 1 note is ", channel_1_note AUDIO_VARIABLES_END: POPS SoundSetup: ld a, LOW(gbtarottheme) ld [ordersStart], a ld a, HIGH(gbtarottheme) ld [ordersStart+1], a ld a, 0 ld [currentOrderNumber], a ld [currentRowNumber], a ld [currentTickNumber], a ld a, $FF ld [currentRowNumber], a ld a, [ordersStart] ld l, a ld a, [ordersStart+1] ld h, a inc hl ld a, [hl+] ld [currentPattern], a ld [audioReadHead], a ld a, [hl+] ld [currentPattern+1], a ld [audioReadHead+1], a ld hl, ZEROES ld de, AUDIO_VARIABLES_BEGIN ld bc, AUDIO_VARIABLES_END - AUDIO_VARIABLES_BEGIN call CopyRange ld a, 6 ld [speed], a ld a, %1000_1111 ld [rNR52], a ld a, $ff ld [rNR51], a ld a, $11 ld [rNR50], a ret SoundUpdate: ld a, [speed] ld b, a ld a, [currentTickNumber] inc a call ArrayClampLoopingB ld [currentTickNumber], a cp a, 0 jp nz, .doneAllPackets ; if we're not zero, then just update the things ld b, 64 ld a, [currentRowNumber] inc a call ArrayClampLoopingB ld [currentRowNumber], a cp a, 0 jp nz, :+ ; if the new row number is zero, then we go to the next pattern. ld a, AUDHIGH_RESTART ld [rNR14], a ; TODO: update for song orders ld a, [currentPattern] ld [audioReadHead], a ld a, [currentPattern+1] ld [audioReadHead+1], a : ld a, [audioReadHead] ld l, a ld a, [audioReadHead+1] ld h, a ld a, [currentRowNumber] ld b, a ld a, [hl+] and a, $F0 cp a, 0 ret nz ld a, [hl+] cp a, b jp nz, .doneAllPackets ; return if the current row doesn't equal the row we're looking at ; else we're looking at packets .packetExamine ld a, l ld [audioReadHead], a ld a, h ld [audioReadHead+1], a ld d, h ld e, l ld hl, channel_1_note ld a, [de] and a, $0F cp a, 1 jp nz, :+ ld hl, channel_1_note : cp a, 2 jp nz, :+ ld hl, channel_2_note : cp a, 3 jp nz, :+ ld hl, channel_3_note : cp a, 4 jp nz, :+ ld hl, channel_4_note : ld a, [de] and a, $F0 ; grab the top nibble of [hl], which holds the effect. ; if nibble is zero, then update our read head (already done) and return. cp a, $00 jp z, .doneAllPackets ld bc, channel_1_note - channel_1_note cp a, $10 jp z, .updateValue ld bc, channel_1_volume - channel_1_note cp a, $20 jp z, .updateVolume ld bc, channel_1_duty - channel_1_note cp a, $30 jp z, .updateValue ld bc, channel_1_pan - channel_1_note cp a, $40 jp z, .updateValue ld bc, channel_1_arp - channel_1_note cp a, $50 jp z, .updateValue ld bc, channel_1_vibrato - channel_1_note cp a, $60 jp z, .updateValue ld bc, channel_1_slide - channel_1_note cp a, $70 jp z, .updateValue ld bc, channel_1_volume - channel_1_note cp a, $80 jp z, .noteCut cp a, $90 jp z, .patternJump cp a, $a0 jp z, .breakSetStep cp a, $b0 jp z, .setSpeed cp a, $c0 jp z, .event ; and now a bunch of code for handling all those cases! .updateVolume: inc de add hl, bc ld a, 0 ld [channel_1_trigger], a ld a, [hl] cp a, 0 jp nz, :+ ; if the volume is zero to start with, ; and the new volume is nonzero, ld a, [de] ; set the trigger flag cp a, 0 jp z, :+ ld a, AUDHIGH_RESTART ld [channel_1_trigger], a : ld a, [de] ld [hl], a inc de ld h, d ld l, e jp .packetExamine .updateValue: inc de add hl, bc : ld a, [de] ld [hl], a inc de ld h, d ld l, e jp .packetExamine .noteCut: inc de add hl, bc ld [hl], 0 ld a, AUDHIGH_RESTART ld [channel_1_trigger], a inc de ld h, d ld l, e jp .packetExamine .patternJump: ; TODO inc de inc de ld h, d ld l, e jp .packetExamine .breakSetStep: ; TODO inc de inc de ld h, d ld l, e jp .packetExamine .setSpeed: inc de ld a, [de] ld [speed], a inc de ld h, d ld l, e jp .packetExamine .event: ; TODO inc de inc de ld h, d ld l, e jp .packetExamine .doneAllPackets: call Channel_1_Update call Channel_2_Update call Channel_3_Update call Channel_4_Update ret Channel_1_Update: ld a, [channel_1_duty] or a, $0a ld [rNR11], a ld a, [channel_1_volume] sla a sla a sla a sla a and a, $F0 ld [rNR12], a ld a, [channel_1_note] ld hl, note_periods ld b, 0 ld c, a add hl, bc add hl, bc ; double width values ld a, [hl+] ld [rNR13], a ld a, [channel_1_trigger] or a, [hl] or a, AUDHIGH_LENGTH_OFF ld [rNR14], a ld a, 0 ld [channel_1_trigger], a ret Channel_2_Update: Channel_3_Update: Channel_4_Update: ret note_periods: dw 44, 156, 262, 363, 457, 547, 631, 710, 786, 854, 923, 986, ; C3 to B3 dw 1046,1102,1155,1205,1253,1297,1339,1379,1417,1452,1486,1517, ; C4 to B4 dw 1546,1575,1602,1627,1650,1673,1694,1714,1732,1750,1767,1783, ; C5 to B5 dw 1798,1812,1825,1837,1849,1860,1871,1881,1890,1899,1907,1915, ; C6 to B6 dw 1923,1930,1936,1943,1949,1954,1959,1964,1969,1974,1978,1982, ; C7 to B7 dw 1985,1988,1992,1995,1998,2001,2004,2006,2009,2011,2013,2015 ; C8 to B8 INCLUDE "theme.inc"