From 5e61c1830b89343991af559747feac55466cd88a Mon Sep 17 00:00:00 2001 From: dwsJason Date: Fri, 23 Nov 2018 10:20:55 -0500 Subject: [PATCH] import: ninjatrackerplus player, assembled by merlin32 --- asm/merlin/link.s | 16 + asm/merlin/make.bat | 3 + asm/merlin/ninjatrackerplus.s | 2601 +++++++++++++++++++++++++++++++++ asm/merlin/ntpplayer.a | Bin 0 -> 24393 bytes 4 files changed, 2620 insertions(+) create mode 100644 asm/merlin/link.s create mode 100644 asm/merlin/make.bat create mode 100644 asm/merlin/ninjatrackerplus.s create mode 100644 asm/merlin/ntpplayer.a diff --git a/asm/merlin/link.s b/asm/merlin/link.s new file mode 100644 index 0000000..0ba2cb8 --- /dev/null +++ b/asm/merlin/link.s @@ -0,0 +1,16 @@ + + dsk ntpplayer.a ; program name + typ $b1 ; OBJ + ;xpl ; Add Expressload + + +; Segment 1 + + asm ninjatrackerplus.s + ds 0 + knd #$1100 ; Kind + ali None ; alignment + lna ntpplayer ; Load Name + sna ntpplayer ; Segment Name + + diff --git a/asm/merlin/make.bat b/asm/merlin/make.bat new file mode 100644 index 0000000..b5e64ca --- /dev/null +++ b/asm/merlin/make.bat @@ -0,0 +1,3 @@ +merlin32 -V . link.s +iix chtyp -t obj ntpplayer.a + diff --git a/asm/merlin/ninjatrackerplus.s b/asm/merlin/ninjatrackerplus.s new file mode 100644 index 0000000..e9d22a3 --- /dev/null +++ b/asm/merlin/ninjatrackerplus.s @@ -0,0 +1,2601 @@ +***************************** +* NinjaTracker+ Player +* +* by Jesse Blue +* +* thanks to: +* Huibert Aalbers, Olivier Goguel, Jon Christopher Co, John Valdezco, John Brooks +* Brutal Deluxe, Digarok, Saga Musix, yzi, djh0ffman +* +***************************** + +; dsk ntpplayer.a +; typ $b1 +; org $0f0000 + mx %00 + + +; all calls to the player must be JSLs with 16 bit registers +; copy this into your program in order to call the player: + +NinjaTrackerPlus ent +NTPprepare = NinjaTrackerPlus +NTPplay = NinjaTrackerPlus+3 +NTPstop = NinjaTrackerPlus+6 +NTPgetvuptr = NinjaTrackerPlus+9 +NTPgete8ptr = NinjaTrackerPlus+12 +NTPforcesongpos = NinjaTrackerPlus+15 + + + +; prepare +; Prepares music, copies all instruments into sound ram and inits the sound interrupt. +; input: call with X=address low, Y=address high of pointer to the ntp file in memory +; output: X=address low, Y=address high of pointer to instruments (main program can reuse memory from here) +; when carry bit is set, an error occurred. Either the player did not find a NTP module at the given location +; or the version of the NTP module is not supported. + jmp prepare + +; play +; Starts previously prepared music. +; input: call with A=0 loop song, else play song only once +; output: - + jmp play + +; stop +; Stops a currently playing music, turns off all oscillators used by the player and restores the sound interrupt. +; input: - +; outout: - + jmp stop + +; getvuptr +; Returns a pointer to vu data (1 word number of tracks, then one word for every track with its volume). +; input: - +; output: X=address low, Y=address high of pointer + jmp getvuptr + +; gete8ptr +; Returns a pointer to where the player stores information about the last 8xx command found. Can be used for timing purposes. +; input: - +; output: X=address low, Y=address high of pointer + jmp gete8ptr + +; forcesongpos +; Forces the player to jump to a certain pattern (like command B). +; input: A=songpos +; output: carry bit is set when the song position does not exist (error) + jmp forcesongpos + + +*------------------------------- + +; to stay out of the way, do not use the direct page at all +; use DP only for faster access to sound registers +; the assembled code should not be bank relative (meaning: not compiled to a fixed bank) + +sound_control = $3c ;really at $e1c03c +sound_data = $3d ;really at $e1c03d +sound_address = $3e ;really at $e1c03e + +sound_interrupt_ptr = $e1002c +irq_volume = $e100ca + +max_tracks_available = 15 ;the GS has 32 voices = 16 tracks, 1 used for interrupt, so 15 left + +max_pattern_line = 64 ;there are 64 lines in a pattern + +;-------------------------- helper functions + +read_head ldal 0,x + rts + +read_pattern ldal 0,x + rts + +read_instrument ldal 0,x + rts + +;----------------------------------------------------------------------------------------- +; prepare +;----------------------------------------------------------------------------------------- + +prepare = * + sei + phb + phd + phk + plb + + clc + xce + rep #$30 + mx %00 + + lda #$c000 + tcd + + jsr clear_memory + + stx ptr_header + sty ptr_header+2 + + jsr check_header + bcs prepare_1 + + jsr extract_header_info + jsr copy_instruments_to_doc + jsr setup_music + jsr setup_interrupt + jsr setup_master_volume + + ldx ptr_instruments + ldy ptr_instruments+2 + + pld + plb + cli + clc + rtl + +prepare_1 pld + plb + cli + sec + rtl + +;-------------------------- + +clear_memory = * + phx + ldx #zero_out_end-zero_out_begin-2 +]loop stz zero_out_begin,x + dex + dex + bpl ]loop + plx + rts + +;-------------------------- + +header_str asc 'nfc!' + +check_header = * +; patch ptr into header + lda ptr_header + sta read_head+1 + lda ptr_header+1 + sta read_head+2 + +; check header string + ldx #0 + jsr read_head + cmp header_str + bne check_header_1 + + inx + inx + jsr read_head + cmp header_str+2 + bne check_header_1 + +; check version + inx + inx + jsr read_head + and #$ff + bne check_header_1 + + clc + rts + +check_header_1 sec + rts + +;-------------------------- + +extract_header_info = * + +; get basic settings + ldx #5 + jsr read_head + inx + inx + pha + and #$ff + sta number_of_tracks + sta vu_number_of_tracks + asl + sta number_of_tracks2 + asl + sta number_of_tracks4 + pla + xba + and #$ff + sta number_of_instruments + asl + sta number_of_instruments2 + + jsr read_head + inx + and #$ff + sta number_of_patterns + + jsr read_head + inx + and #$ff + sta pattern_order_length + +; get which track uses which output channel + ldy #0 +]loop jsr read_head + inx + and #%111 + asl + asl + asl + asl + sta track_channels,y + iny + iny + cpy number_of_tracks2 + blt ]loop + +; get instrument data + ldy #0 + +]loop jsr read_head + inx + and #$ff + sta instrument_types,y + + jsr read_head + inx + inx + sta instrument_lengths,y + + jsr read_head + inx + and #$ff + sta instrument_volumes,y + + jsr read_head + inx + and #$f + asl + phy + tay + lda note_freq_ptrs_offset,y + ply + sta instrument_finetune,y + + jsr read_head + inx + and #$ff + sta instrument_osc_a_ptr,y + sta instrument_osc_b_ptr,y + + jsr read_head + inx + and #$ff + sta instrument_osc_a_siz,y + sta instrument_osc_b_siz,y + + iny + iny + cpy number_of_instruments2 + blt ]loop + + jsr generate_osc_settings + +; get pattern order + ldy #0 +]loop jsr read_head + inx + and #$ff + sta pattern_order,y + iny + cpy pattern_order_length + blt ]loop + +; calc pointer to notes + txa + clc + adc ptr_header + sta ptr_notes + lda ptr_header+2 + adc #0 + sta ptr_notes+2 + +; patch note ptr + lda ptr_notes + sta read_pattern+1 + lda ptr_notes+1 + sta read_pattern+2 + +; calculate pattern length (= number of tracks x 4 x 64) + lda number_of_tracks + xba + sta pattern_length + +; calculate pattern pointers + phx + lda ptr_notes + sta pattern_pointers + lda ptr_notes+2 + sta pattern_pointers+2 + ldy #0 + ldx #1 +]loop lda pattern_pointers,y + clc + adc pattern_length + sta pattern_pointers+4,y + lda pattern_pointers+2,y + adc #0 + sta pattern_pointers+6,y + iny + iny + iny + iny + inx + cpx number_of_patterns + blt ]loop + plx + +; get ptr to instruments: it's the last calculated pattern pointer plus one pattern length + lda pattern_pointers,y + clc + adc pattern_length + sta ptr_instruments + lda pattern_pointers+2,y + adc #0 + sta ptr_instruments+2 + +; patch instrument ptr + lda ptr_instruments + sta read_instrument+1 + lda ptr_instruments+1 + sta read_instrument+2 + + rts + +;-------------------------- + +generate_osc_opti dw 0 +generate_osc_opti_next dw 0 + +generate_osc_settings = * ;from instruments, generate control bytes for osc A and B + + phx + ldy #0 + +]loop lda instrument_types+2,y ;see if the next instrument has an optimal length + and #%100 + sta generate_osc_opti_next + + lda instrument_types,y + asl + tax + + jsr (generate_osc_sett_tbl,x) + + iny + iny + cpy number_of_instruments2 + blt ]loop + + plx + rts + +generate_osc_sett_tbl dw generate_osc_0,generate_osc_1a,generate_osc_2,generate_osc_3 ;normal samples + dw generate_osc_0,generate_osc_1b,generate_osc_2,generate_osc_3 ;sample has an optimal size + +generate_osc_0 = * + lda #%010 ;type 0: normal sample, use one-shot for osc A + sta instrument_osc_a_ctl,y + lda #%001 ;stop osc B + sta instrument_osc_b_ctl,y + rts + +generate_osc_1a = * + lda #%110 ;type 1a: simple looped sample, use swap mode for osc A + sta instrument_osc_a_ctl,y + lda #%111 ;use swap mode for osc B + sta instrument_osc_b_ctl,y + rts + +generate_osc_1b = * + lda #%000 ;type 1b: simple looped sample with optimal length, use free run mode for osc A + sta instrument_osc_a_ctl,y + lda #%001 ;stop osc B + sta instrument_osc_b_ctl,y + rts + +generate_osc_2 = * + lda generate_osc_opti_next ;type 2: this is the header for the next instrument which is looped + bne generate_osc_2_1 + + lda #%1110 ;loop has no optimal length: use swap mode for osc A with interrupt + sta instrument_osc_a_ctl,y + lda #%0111 ;swap mode for osc B when A is done + sta instrument_osc_b_ctl,y + + bra generate_osc_2_2 + +generate_osc_2_1 = * + lda #%110 ;loop has optimal length: use swap mode for osc A + sta instrument_osc_a_ctl,y + lda #%001 ;use free run mode for osc B when A is done + sta instrument_osc_b_ctl,y + +generate_osc_2_2 = * + lda instrument_osc_a_ptr+2,y ;since osc B plays the loop instrument, copy its ptr and siz parameters + sta instrument_osc_b_ptr,y + + lda instrument_osc_a_siz+2,y + sta instrument_osc_b_siz,y + +generate_osc_3 = * + rts ;type 3: do nothing; it is played via loop header instrument (type 2) + +;-------------------------- + +copy_instruments_to_doc = * + jsr clear_docram + + ldy #0 + +]loop lda instrument_lengths,y + sta copy_instrument_length + + jsr copy_instrument + + lda read_instrument+1 + clc + adc copy_instrument_length + sta read_instrument+1 + bcc copy_instruments_1 + inc read_instrument+3 +copy_instruments_1 = * + + iny + iny + cpy number_of_instruments2 + + blt ]loop + rts + +copy_instrument = * + sep #$20 + mx %10 + +]loop lda sound_control + bmi ]loop + + ora #%01100000 + sta sound_control + + stz sound_address + lda instrument_osc_a_ptr,y + sta sound_address+1 + + ldx #0 +]loop jsr read_instrument + inx + sta sound_data + cpx copy_instrument_length + blt ]loop + + rep #$20 + mx %00 + + rts + +;-------------------------- + +clear_docram = * + sep #$20 + mx %10 + +]loop lda sound_control + bmi ]loop + + ora #%01100000 + sta sound_control + + stz sound_address + stz sound_address+1 + + ldx #0 + lda #0 +]loop sta sound_data + inx + bne ]loop + + rep #$20 + mx %00 + + rts + +;-------------------------- + +setup_music = * + +; reset pointers + stz timer + + lda #6 + sta tempo + + stz ptr_within_pattern + stz pattern_order_ptr + +; get pointer to first pattern to play + ldx pattern_order_ptr + lda pattern_order,x + and #$ff + asl + asl + tax + lda pattern_pointers,x + sta read_pattern+1 + lda pattern_pointers+1,x + sta read_pattern+2 + + rts + +;-------------------------- + +setup_interrupt = * + ldal sound_interrupt_ptr + sta backup_interrupt_ptr + ldal sound_interrupt_ptr+2 + sta backup_interrupt_ptr+2 + + lda #$5c + stal sound_interrupt_ptr + phk + phk + pla + stal sound_interrupt_ptr+2 + lda #interrupt_handler + stal sound_interrupt_ptr+1 + + sep #$20 + mx %10 + +]loop lda sound_control + bmi ]loop + + and #%10011111 ; disable auto-inc. and access DOC reg. + sta sound_control + + ldy #0 +]loop lda timer_sound_settings,y + sta sound_address + iny + lda timer_sound_settings,y + sta sound_data + iny + cpy #7*2 + bne ]loop + + rep #$20 + mx %00 + + lda #reference_freq + sta osc_interrupt_freq + sta new_osc_interrupt_freq + + rts + +reference_freq = 249 ; interrupt frequence +timer_sound_settings = * ; set up oscillator 30 for interrupts + dfb $1e,reference_freq ; frequency low register + dfb $3e,0 ; frequency high register + dfb $5e,0 ; volume register, volume = 0 + dfb $9e,0 ; wavetable pointer register, point to 0 + dfb $de,0 ; wavetable size register, 256 byte length + dfb $e1,$3e ; oscillator enable register + dfb $be,$08 ; mode register, set to free run + +;-------------------------- + +setup_master_volume = * + sep #$20 + mx %10 + + ldal irq_volume + and #%0000_1111 + sta sound_control + + rep #$20 + mx %00 + rts + +;----------------------------------------------------------------------------------------- +; play +;----------------------------------------------------------------------------------------- + +play = * + phb + phk + plb + + sta play_song_once + + lda #1 + sta playing + + plb + clc + rtl + +;----------------------------------------------------------------------------------------- +; stop +;----------------------------------------------------------------------------------------- + +stop = * + sei + phb + phd + phk + plb + + lda #$c000 + tcd + + stz playing ; stop player + + sep #$20 + mx %10 + +]loop lda sound_control ; kill sound + bmi ]loop + and #%10011111 ; disable auto-inc. and access DOC reg. + sta sound_control + + ldx number_of_tracks2 + beq stop_1 + lda #$a0 ; stop all oscillators in use + sta sound_address + lda #1 +]loop sta sound_data + inc sound_address + dex + bne ]loop + +stop_1 = * + lda #$a0+30 ; stop both interrupt oscillators + sta sound_address + lda #1 + sta sound_data + inc sound_address + sta sound_data + + rep #$20 + mx %00 + + lda backup_interrupt_ptr ; restore old interrupt ptr + stal sound_interrupt_ptr + lda backup_interrupt_ptr+2 + stal sound_interrupt_ptr+2 + + cli + pld + plb + clc + rtl + +;----------------------------------------------------------------------------------------- +; getvuptr +;----------------------------------------------------------------------------------------- + +getvuptr = * + phk + phk + pla + + and #$ff + tay + ldx #vu_number_of_tracks + + clc + rtl + +;----------------------------------------------------------------------------------------- +; gete8ptr +;----------------------------------------------------------------------------------------- + +gete8ptr = * + phk + phk + pla + + and #$ff + tay + ldx #last_effect_8_param + + clc + rtl + +;----------------------------------------------------------------------------------------- +; forcesongpos +;----------------------------------------------------------------------------------------- + +forcesongpos = * + sei + phb + + phk + plb + + cmp pattern_order_length + bge forcesongpos_1 + + sta force_pattern_jump_p + lda #1 + sta force_pattern_jump + + plb + cli + clc + rtl + +forcesongpos_1 = * + plb + cli + sec + rtl + +;----------------------------------------------------------------------------------------- +; interupt handler (=the player) +;----------------------------------------------------------------------------------------- + +interrupt_handler = * + phb + phd + + phk + plb + + clc + xce + rep #$30 + mx %00 + + lda #$c000 + tcd + + sep #$20 + mx %10 + +]loop lda sound_control + bmi ]loop + and #%10011111 ; disable auto-inc. and access DOC reg. + sta sound_control + + lda #$e0 + sta sound_address ; reads the interrupt register + lda sound_data ; to know which oscillator generated + lda sound_data ; the interrupt + + and #%00111110 + lsr + cmp #$1e + beq tracker_interrupt ; it's the 50Hz interrupt + + and #%11111110 ; get the track number where the interrupt occured + sta oscillator + + ldy oscillator ; y = track*2 + ldx curr_sample,y + dex + dex ; x = ptr into instrument tables + + lda reg_tbl_ptr,y + sta sound_address + lda instrument_osc_b_ptr,x + sta sound_data + + lda reg_tbl_siz,y + sta sound_address + lda instrument_osc_b_siz,x + sta sound_data + + lda reg_tbl_ctl,y + sta sound_address + lda instrument_osc_b_ctl,x + ora track_channels,y + ora #1 + sta sound_data + + rep #$30 + mx %00 + +jump_to_interrupt_end = * + jmp interrupt_handler_end + + +tracker_interrupt = * ; it's the 50Hz interrupt + rep #$30 + mx %00 + + lda playing + beq jump_to_interrupt_end + + lda timer + beq parse_tracks ;fetch track information only when timer=0 + + inc + cmp tempo + blt tracker_interrupt_1 + lda #0 +tracker_interrupt_1 sta timer + + jsr handle_effects + jmp talk_to_doc + +;-------------------------- + +parse_tracks = * ;fetch track information + inc timer + + lda delay_pattern + beq parse_tracks_2 + + dec delay_pattern + jsr handle_effects + jmp talk_to_doc + +parse_tracks_2 = * + jsr check_pattern_jump ;if we reached the end of the pattern or there was a pattern jump, handle it + + ldy #0 + ldx ptr_within_pattern + lda #$ffff + sta loop_position_jump + +parse_tracks_loop = * + jsr read_pattern + pha + and #$ff + asl + sta note + pla + xba + and #$ff + asl + sta sample + inx + inx + + jsr read_pattern + pha + and #$f + asl + sta effect + pla + xba + and #$ff + sta effect_param + inx + inx + + phx + jsr setup_effect + plx + + iny + iny + + cpy number_of_tracks2 + blt parse_tracks_loop + + lda loop_position_jump ;if there is an active loop, jump + bmi parse_tracks_1 + tax +parse_tracks_1 = * + stx ptr_within_pattern + + + +talk_to_doc = * ;for each track: talk to ensoniq doc + sep #$20 + mx %10 + +]loop lda sound_control + bmi ]loop + and #%10011111 ; DOC reg. + sta sound_control + + ldy #0 +]loop lda what_to_do,y + bne talk_to_doc_0 + +talk_to_doc_loop iny + iny + + cpy number_of_tracks2 + blt ]loop + +talk_to_doc_timer = * + ldy new_osc_interrupt_freq + cpy osc_interrupt_freq + beq talk_to_doc_timer_1 + + sty osc_interrupt_freq ;set new interrupt frequency + + lda #30 + sta sound_address + lda osc_interrupt_freq + sta sound_data + lda #$20+30 + sta sound_address + lda osc_interrupt_freq+1 + sta sound_data +talk_to_doc_timer_1 = * + +interrupt_handler_end = * + sep #$30 + pld + plb + clc + rtl + +talk_to_doc_0 = * + mx %10 +; values can be combined by setting bits +; %10000000 = set control (and turn oscillators off before) +; %00000100 = set wave ptr/size +; %00000010 = set freq +; %00000001 = set volume +; %00000000 = do nothing + bpl talk_to_doc_1 + + lda reg_tbl_ctl,y ;stop + sta sound_address + lda #1 + sta sound_data + inc sound_address + sta sound_data + + lda what_to_do,y +talk_to_doc_1 = * + bit #%00000001 + beq talk_to_doc_2 + + lda reg_tbl_vol,y ;set volume + sta sound_address + lda osc_volume,y + sta sound_data + inc sound_address + sta sound_data + + lda what_to_do,y +talk_to_doc_2 = * + bit #%00000010 + beq talk_to_doc_3 + + tya ;set freq + sta sound_address + lda osc_freq,y + sta sound_data + inc sound_address + sta sound_data + + lda reg_tbl_freqhi,y + sta sound_address + lda osc_freq+1,y + sta sound_data + inc sound_address + sta sound_data + + lda what_to_do,y +talk_to_doc_3 = * + bit #%00000100 + beq talk_to_doc_4 + + ldx osc_instrument,y ;set wave ptr/size via instrument + + lda reg_tbl_ptr,y + sta sound_address + + lda what_to_do,y + bmi talk_to_doc_3_1 + + lda instrument_osc_b_ptr,x ;if we don't set the control byte, make sure we change the instrument + sta sound_data ;in such a way that a looped instrument will play its loop + inc sound_address + sta sound_data + + lda reg_tbl_siz,y + sta sound_address + lda instrument_osc_b_siz,x + sta sound_data + inc sound_address + sta sound_data + + bra talk_to_doc_4 + +talk_to_doc_3_1 = * + lda instrument_osc_a_ptr,x ;if we set the control byte, change the instrument in the normal fashion + sta sound_data + inc sound_address + lda instrument_osc_b_ptr,x + sta sound_data + + lda reg_tbl_siz,y + sta sound_address + lda instrument_osc_a_siz,x + sta sound_data + inc sound_address + lda instrument_osc_b_siz,x + sta sound_data + +talk_to_doc_4 = * + lda what_to_do,y + bpl talk_to_doc_5 + + lda osc_volume,y ;update vu meter + sta vu_data,y + + ldx osc_instrument,y ;set control via instrument + + lda reg_tbl_ctl,y + sta sound_address + lda instrument_osc_a_ctl,x + ora track_channels,y + sta sound_data + inc sound_address + lda instrument_osc_b_ctl,x + ora track_channels,y + sta sound_data + +talk_to_doc_5 = * + jmp talk_to_doc_loop + + mx %00 + +;-------------------------- + +check_pattern_jump = * + ldx pattern_jump + jmp (check_pattern_jump_tbl,x) + +check_pattern_jump_tbl = * + dw check_pattern_end + dw handle_pattern_jump + dw handle_pattern_break + +;-------------------------- + +check_pattern_end = * + lda force_pattern_jump + beq check_pattern_end_0 + + lda force_pattern_jump_p + sta pattern_jump_param + stz force_pattern_jump + bra handle_pattern_jump + +check_pattern_end_0 = * + lda ptr_within_pattern ;check if we're at the end of the pattern + cmp pattern_length + blt check_pattern_end_4 + + stz ptr_within_pattern ;reset pointer within pattern + stz loop_position ;reset loop in pattern + stz loop_position_active + +check_pattern_end_1 = * + ldx pattern_order_ptr ;end of pattern; set next pattern + inx + +check_pattern_end_2 = * + cpx pattern_order_length + blt check_pattern_end_3 + + lda play_song_once + beq check_pattern_end_2_1 + + stz playing ;stop playing after this song + rts + +check_pattern_end_2_1 = * + ldx #0 + +check_pattern_end_3 = * + stx pattern_order_ptr + + lda pattern_order,x ;set new offset position to new pattern + and #$ff + asl + asl + tax + lda pattern_pointers,x + sta read_pattern+1 + lda pattern_pointers+1,x + sta read_pattern+2 + +check_pattern_end_4 = * + rts + +;-------------------------- + +handle_pattern_jump = * ;jump to a specific pattern order position + stz pattern_jump + + stz loop_position ;reset loop in pattern + stz loop_position_active + + ldx pattern_jump_param + jmp check_pattern_end_2 + +;-------------------------- + +handle_pattern_break = * ;stop pattern here and go to next pattern but start at specific line + stz pattern_jump + + ldx pattern_jump_param + lda pattern_break_ptrs,x + and #$ff + beq handle_pattern_break_1 + + tax + lda #0 + clc + +]loop adc number_of_tracks4 ;poor man's multply + dex + bne ]loop + +handle_pattern_break_1 = * + sta ptr_within_pattern + + stz loop_position ;reset loop in pattern + stz loop_position_active + + jmp check_pattern_end_1 + +;-------------------------- + +setup_effect_jump_rts rts +setup_effect_jump_tbl = * + dw setup_arpeggio + dw setup_slide_up + dw setup_slide_down + dw setup_slide_to_note + dw setup_vibrato + dw setup_volslide ;Continue 'Slide to note', but also do Volume slide + dw setup_volslide ;Continue 'Vibrato', but also do Volume slide + dw setup_tremolo + dw setup_gs_panning ;IIGS panning + dw setup_effect_jump_rts ;Not supported: Set sample offset + dw setup_volslide + dw setup_positionjump + dw setup_setvolume + dw setup_patternbreak + dw setup_e_effects + dw setup_setspeed + +setup_e_effect_jump_tbl = * + dw setup_effect_jump_rts ;Not supported: Set filter on/off + dw fineslide_up + dw fineslide_down + dw set_glissando + dw set_vibrato_waveform + dw set_sample_finetune + dw set_loop_pattern + dw set_tremolo_waveform + dw setup_effect_jump_rts ;unused + dw setup_retrigger + dw volslide_up + dw volslide_down + dw setup_note_cut + dw setup_note_delay + dw setup_delay_pattern + dw setup_effect_jump_rts ;Not supported: Invert loop + +setup_effect = * + lda #0 ;by default, do nothing + sta what_to_do,y + sta vu_data,y ;reset vu meter + +; if sample is defined, set it +; and set volume according to instrument + + lda sample + beq setup_effect_2 + +; if sample is defined, always set the volume from the instrument + dec ;the 1st sample is at position 0 in all tables + dec + sta osc_instrument,y ;store which instrument to play + + tax ;use default volume from sample + lda instrument_volumes,x + sta curr_volume,y ;backup volume setting in track + asl + tax + lda volume_lookup,x + sta osc_volume,y ;store volume for osc + + lda what_to_do,y + ora #%00000001 ;mark that we want to set the volume + sta what_to_do,y + + lda sample + cmp curr_sample,y + beq setup_effect_1 + + sta curr_sample,y ;if it's a different sample than before, tell the doc + + lda what_to_do,y + ora #%00000100 ;mark that we want to set the instrument + sta what_to_do,y + +setup_effect_1 = * + lda note ;repeat last note if no note was set + bne setup_effect_2 + lda curr_note,y + beq setup_effect_2 + sta note + + lda what_to_do,y + ora #%00000100 ;mark that we want to set the instrument + sta what_to_do,y + +setup_effect_2 = * + + lda effect + sta curr_effect,y + tax + jsr (setup_effect_jump_tbl,x) + +;if there is no note but a sample, then change the oscillators wavptr and wavsiz, so that an ongoing loop swaps to the new sample + +check_play_note = * + +; if note is defined, play it + + lda note + beq check_play_note_5 ;no note, don't play + + sta curr_note,y ;backup note + + ldx curr_sample,y + beq check_play_note_5 ;no last sample defined, do not play the note + + lda instrument_finetune-2,x ;the 1st sample is at position 0 in all tables + clc + adc note + tax + lda note_freq_ptrs,x ;use note and sample's finetune and look up a frequency + sta curr_ptrfinetune,y + tax + lda freq_finetune,x + sta osc_freq,y ;store freq for osc + + lda what_to_do,y + ora #%10000110 ;store that we want to set frequency, restart the sample and control + sta what_to_do,y + +check_play_note_5 = * + rts + +;-------------------------- + +setup_arpeggio = * + lda effect_param + beq setup_arpeggio_2 ;no arpeggio, turn off if it was running before + + lda note ;if we have a new note, use it + bne setup_arpeggio_1 + lda arpeggio_note1,y ;else use last played + beq setup_arpeggio_2 ;no last note - do nothing + + sta note ;make sure we play the last note again + +setup_arpeggio_1 = * + sta arpeggio_note1,y + + lda effect_param + and #$f0 + lsr + lsr + lsr + clc + adc note + sta arpeggio_note2,y + + lda effect_param + and #$f + asl + clc + adc note + sta arpeggio_note3,y + + lda #$8000 +setup_arpeggio_2 = * + sta arpeggio_ptr,y + + rts + +;-------------------------- + +setup_slide_up = * + lda effect_param + asl + sta slide_delta,y + + lda note ;if there is no note, continue sliding + bne setup_slide_up_1 + + jmp handle_slide_up +setup_slide_up_1 rts + +;-------------------------- + +setup_slide_down = * + lda effect_param + asl + sta slide_delta,y + + lda note ;if there is no note, continue sliding + bne setup_slide_down_1 + + jmp handle_slide_down +setup_slide_down_1 rts + +;-------------------------- + +setup_slide_to_note = * + lda effect_param + beq setup_slide_to_note_1 ;if there is a speed set, use this, else keep whatever is there + asl + sta slide_delta,y +setup_slide_to_note_1 = * + + lda note ;if there is a note set, use this as target, else keep whatever is there + beq setup_slide_to_note_2 + + sta slide_target_note,y ;if a note is set, this is our target to slide to + ldx curr_sample,y + lda instrument_finetune-2,x + clc + adc note + tax + lda note_freq_ptrs,x ;find the target in the freq table to slide to + sta slide_target,y + + stz note ;with this command, the note is a parameter and is not played + lda what_to_do,y + and #%00000101 + sta what_to_do,y +setup_slide_to_note_2 = * + rts + +;-------------------------- + +setup_vibrato = * + lda effect_param + and #$f0 ;If either x or y are 0, then the old vibrato values will be used. + beq setup_vibrato_1 + lsr + lsr + lsr + sta vibrato_rate,y +setup_vibrato_1 = * + + lda effect_param + and #$f + beq setup_vibrato_2 + xba + lsr ;*128 + clc + adc vibrato_tableoffset,y + sta vibrato_table,y +setup_vibrato_2 = * + + lda #0 ;reset position in vibrato table + sta vibrato_pos,y + rts + +;-------------------------- + +setup_tremolo = * + lda effect_param + and #$f0 + beq setup_tremolo_1 + lsr + lsr + lsr + sta tremolo_rate,y +setup_tremolo_1 = * + + lda effect_param + and #$f + beq setup_tremolo_2 + xba + lsr ;*128 + clc + adc tremolo_tableoffset,y + sta tremolo_table,y +setup_tremolo_2 = * + + lda #0 ;reset position in tremolo table: this is actually a bug in protracker + sta tremolo_pos,y + + rts + +;-------------------------- + +setup_gs_panning = * + lda effect_param + cmp #8 + bge setup_gs_panning_1 ;GS panning: if < 8, then we set the channel for this track + asl + asl + asl + asl + sta track_channels,y + rts +setup_gs_panning_1 sta last_effect_8_param ;if it is not a panning effect, store in shared register for timing purposes + rts + +;-------------------------- + +setup_volslide = * + lda effect_param + beq setup_volslide_1 + + cmp #$10 + bge setup_volslide_1 + + lda #0 + sec + sbc effect_param + sta volslide_delta,y + + rts + +setup_volslide_1 = * + and #$f0 ;If both x and y are non-zero, the y value is ignored (assumed to be 0). + lsr + lsr + lsr + lsr + sta volslide_delta,y + + rts + +;-------------------------- + +setup_setvolume = * + lda effect_param + cmp #64 + blt setup_setvolume_1 + lda #64 +setup_setvolume_1 sta curr_volume,y + asl + tax + lda volume_lookup,x + sta osc_volume,y + + lda what_to_do,y + ora #%00000001 ;store that we want to set the volume immediately + sta what_to_do,y + rts + +;-------------------------- + +setup_positionjump = * + lda effect_param ;Legal values are from 0 to 127 + and #$7f + sta pattern_jump_param + + lda #2 + sta pattern_jump + + rts + +;-------------------------- + +setup_patternbreak = * + lda effect_param + sta pattern_jump_param + + lda #4 + sta pattern_jump + + rts + +;-------------------------- + +setup_e_effects = * + lda effect_param + and #$f0 + lsr + lsr + lsr + sta curr_e_effect,y + tax + lda effect_param + and #$f + sta effect_param + jmp (setup_e_effect_jump_tbl,x) + +;-------------------------- + +setup_setspeed = * + lda effect_param + bne setup_setspeed_2 + lda #1 ;when 0, stop music or set to 1 ? + +setup_setspeed_1 = * + sta tempo + rts + +setup_setspeed_2 = * + cmp #$20 ;when < 32, assume set tempo + blt setup_setspeed_1 + + sec ;else interrupt timer + sbc #$20 + asl + tax + lda bpm_to_freq,x + sta new_osc_interrupt_freq + rts + +;-------------------------- + +fineslide_up = * + asl effect_param + + lda curr_ptrfinetune,y + clc + adc effect_param + cmp #max_finetune_ptr + blt fineslide_up_1 + lda #max_finetune_ptr + +fineslide_up_1 sta curr_ptrfinetune,y + + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y + rts + +;-------------------------- + +fineslide_down = * + asl effect_param + + lda curr_ptrfinetune,y + sec + sbc effect_param + bpl fineslide_down_1 + lda #0 + +fineslide_down_1 sta curr_ptrfinetune,y + + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y + rts + +;-------------------------- + +set_glissando = * + lda effect_param ;only 0 and 1 are valid, but PT doesn't check that + sta glissando,y + rts + +;-------------------------- + +set_vibrato_waveform = * + lda effect_param + cmp #8 + bge set_vibrato_waveform_1 + + and #%11 + asl + tax + + lda waveforms,x + sta vibrato_tableoffset,y + + lda effect_param + and #%100 + sta vibrato_retrig,y + +set_vibrato_waveform_1 = * + rts + +;-------------------------- + +set_sample_finetune = * + ldx sample + bne set_sample_finetune_1 + ldx curr_sample,y + beq set_sample_finetune_2 + +set_sample_finetune_1 = * + phx + lda effect_param + asl + tax + lda note_freq_ptrs_offset,x + plx + sta instrument_finetune-2,x + +set_sample_finetune_2 = * + rts + +;-------------------------- + +set_loop_pattern = * + lda effect_param ;0=record position, else loop + bne set_loop_pattern_1 + + lda ptr_within_pattern ;record pattern position + sta loop_position + rts + +set_loop_pattern_1 = * ;start or continue loop + lda loop_position_active + bne set_loop_pattern_2 + + lda #1 ;start loop + sta loop_position_active + lda effect_param + sta loop_repeat_count + lda loop_position + sta loop_position_jump + rts + +set_loop_pattern_2 = * ;continue loop, enough repetitions? + dec loop_repeat_count + beq set_loop_pattern_3 + + lda loop_position + sta loop_position_jump + rts + +set_loop_pattern_3 = * ;loop has ended + stz loop_position_active + rts + +;-------------------------- + +set_tremolo_waveform = * + lda effect_param + cmp #8 + bge set_tremolo_waveform_1 + + and #%11 + asl + tax + + lda waveforms,x + sta tremolo_tableoffset,y + + lda effect_param + and #%100 + sta tremolo_retrig,y + +set_tremolo_waveform_1 = * + rts + +;-------------------------- + +setup_retrigger = * + lda effect_param + sta retrigger_steps,y + lda #0 + sta retrigger_count,y + rts + +;-------------------------- + +volslide_up = * + lda curr_volume,y + clc + adc effect_param + cmp #64 + blt volslide_up_1 + lda #64 + +volslide_up_1 = * + sta curr_volume,y + + asl + tax + lda volume_lookup,x + sta osc_volume,y ;store volume for osc + + lda what_to_do,y + ora #%00000001 ;store that we want to set the volume for this track + sta what_to_do,y + + rts + +;-------------------------- + +volslide_down = * + lda curr_volume,y + sec + sbc effect_param + bpl volslide_up_1 + lda #0 + bra volslide_up_1 + +;-------------------------- + +setup_note_cut = * + lda effect_param + sta note_cut,y + rts + +;-------------------------- + +setup_note_delay = * + lda note + beq setup_note_delay_1 + + sta note_delay_note,y + + lda effect_param + sta note_delay_count,y + + stz note + +setup_note_delay_1 = * + rts + +;-------------------------- + +setup_delay_pattern = * + lda effect_param + sta delay_pattern + rts + +;-------------------------- + +handle_effect_jump_tbl = * + dw handle_arpeggio + dw handle_slide_up + dw handle_slide_down + dw handle_slide_to_note + dw handle_vibrato + dw handle_effect_5 + dw handle_effect_6 + dw handle_tremolo + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_volslide + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + +handle_e_eff_jump_tbl dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_retrigger + dw handle_effect_nothing + dw handle_effect_nothing + dw handle_note_cut + dw handle_note_delay + dw handle_effect_nothing + dw handle_effect_nothing + +handle_effects = * ;when a non-tracker line is encountered, do what the last effect needs to do + ldy #0 + +]loop lda #0 + sta what_to_do,y + + ldx curr_effect,y + jsr (handle_effect_jump_tbl,x) + + iny + iny + cpy number_of_tracks2 + blt ]loop + +handle_effect_nothing rts + +;-------------------------- + +handle_arpeggio = * + lda arpeggio_ptr,y + beq handle_arpeggio_5 + + inc + cmp #$8003 + blt handle_arpeggio_1 + lda #$8000 +handle_arpeggio_1 = * + sta arpeggio_ptr,y + + cmp #$8000 + bne handle_arpeggio_2 + lda arpeggio_note1,y + bra handle_arpeggio_4 + +handle_arpeggio_2 = * + cmp #$8001 + bne handle_arpeggio_3 + lda arpeggio_note2,y + bra handle_arpeggio_4 + +handle_arpeggio_3 = * + lda arpeggio_note3,y + +handle_arpeggio_4 = * + sta note + sta curr_note,y + + lda curr_sample,y + sta sample + + jmp check_play_note + +handle_arpeggio_5 = * + rts + +;-------------------------- + +handle_slide_up = * + lda curr_ptrfinetune,y + clc + adc slide_delta,y + cmp #max_finetune_ptr + blt handle_slide_up_1 + lda #max_finetune_ptr + +handle_slide_up_1 sta curr_ptrfinetune,y + + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y + rts + +;-------------------------- + +handle_slide_down = * + lda curr_ptrfinetune,y + sec + sbc slide_delta,y + cmp #max_finetune_ptr + blt handle_slide_down_1 + lda #0 + +handle_slide_down_1 sta curr_ptrfinetune,y + + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y + rts + +;-------------------------- + +handle_slide_to_note = * + lda glissando,y + beq handle_slide_to_note_0 + +;when glissando is on, we have to slide in semitones + lda curr_note,y + cmp slide_target_note,y + beq handle_slide_to_note_3 + bge handle_slide_to_note_g1 + + inc + inc + bra handle_slide_to_note_g2 + +handle_slide_to_note_g1 = * + dec + dec + +handle_slide_to_note_g2 = * + sta curr_note,y + + ldx curr_sample,y + lda instrument_finetune-2,x + clc + adc curr_note,y + tax + lda note_freq_ptrs,x + bra handle_slide_to_note_2 + +;no glissando + +handle_slide_to_note_0 = * + lda curr_ptrfinetune,y + cmp slide_target,y + beq handle_slide_to_note_3 + bge handle_slide_to_note_4 + + clc + adc slide_delta,y + cmp slide_target,y + blt handle_slide_to_note_2 +handle_slide_to_note_1 = * + lda slide_target,y +handle_slide_to_note_2 = * + sta curr_ptrfinetune,y + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y +handle_slide_to_note_3 = * + rts + +handle_slide_to_note_4 = * + sec + sbc slide_delta,y + cmp slide_target,y + bge handle_slide_to_note_2 + bra handle_slide_to_note_1 + +;-------------------------- + +handle_vibrato = * + lda vibrato_table,y + clc + adc vibrato_pos,y + tax + lda sine_tbl,x + clc + adc curr_ptrfinetune,y + tax + lda freq_finetune,x + sta osc_freq,y + + lda what_to_do,y + ora #%00000010 ;store that we want to set the freq for this track + sta what_to_do,y + + lda vibrato_pos,y + clc + adc vibrato_rate,y + cmp #128 + blt handle_vibrato_1 + + ldx vibrato_retrig,y + bne handle_vibrato_2 + + and #127 +handle_vibrato_1 sta vibrato_pos,y +handle_vibrato_2 rts + +;-------------------------- + +handle_effect_5 = * + jsr handle_slide_to_note ;Continue 'Slide to note', but also do Volume slide + jmp handle_volslide + +;-------------------------- + +handle_effect_6 = * + jsr handle_vibrato ;Continue 'Vibrato', but also do Volume slide + jmp handle_volslide + +;-------------------------- + +handle_tremolo = * + lda tremolo_table,y + clc + adc tremolo_pos,y + tax + lda sine_tbl,x + lsr ;divide by 2 because sine table is factors of 2 + clc + adc curr_volume,y + asl + tax + lda volume_lookup,x + sta osc_volume,y + + lda what_to_do,y + ora #%00000001 ;store that we want to set the vol for this track + sta what_to_do,y + + lda tremolo_pos,y + clc + adc tremolo_rate,y + cmp #128 + blt handle_tremolo_1 + + ldx tremolo_retrig,y + bne handle_tremolo_2 + + and #127 +handle_tremolo_1 sta tremolo_pos,y +handle_tremolo_2 rts + + +;-------------------------- + +handle_volslide = * + ldx #0 + lda curr_volume,y + clc + adc volslide_delta,y + bmi handle_volslide_1 ;when < 0 then 0 + + ldx #64 + cmp #64 + bge handle_volslide_1 ;when > 64 then 64 + + tax + +handle_volslide_1 = * + txa + sta curr_volume,y ;backup volume setting in track + asl + tax + lda volume_lookup,x + sta osc_volume,y ;store volume for osc + + lda what_to_do,y + ora #%00000001 ;store that we want to set the volume for this track + sta what_to_do,y + + rts + +;-------------------------- + +handle_e_effects = * + ldx curr_e_effect,y + jmp (handle_e_eff_jump_tbl,x) + +;-------------------------- + +handle_retrigger = * + lda retrigger_count,y + inc + cmp retrigger_steps,y + blt handle_retrigger_2 + + lda curr_sample,y + beq handle_retrigger_1 + + lda what_to_do,y ;do retrigger + ora #%11000100 + sta what_to_do,y + +handle_retrigger_1 = * + lda #0 +handle_retrigger_2 = * + sta retrigger_count,y + + rts + +;-------------------------- + +handle_note_cut = * + lda note_cut,y + beq handle_note_cut_1 + dec + sta note_cut,y + bne handle_note_cut_1 + + lda #0 + sta curr_volume,y + sta osc_volume,y + + lda what_to_do,y ;store that we want to set the volume + ora #%00000001 + sta what_to_do,y + +handle_note_cut_1 = * + rts + +;-------------------------- + +handle_note_delay = * + lda note_delay_count,y + dec + sta note_delay_count,y + bne handle_note_delay_1 + + lda note_delay_note,y + sta note + + jmp check_play_note + +handle_note_delay_1 = * + rts + +;-------------------------- + +volume_lookup = * + dw 0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60 + dw 64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124 + dw 128,132,136,140,144,148,152,156,160,164,168,172,176,180,184,188 + dw 192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252 + dw 255,255 + +max_finetune_ptr = 3574 +freq_finetune = * + dw 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38 + dw 38,38,38,38,38,38,39,39,39,39,39,39,39,39,39,39 + dw 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39 + dw 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39 + dw 39,39,39,39,40,40,40,40,40,40,40,40,40,40,40,40 + dw 40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40 + dw 40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,41 + dw 41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41 + dw 41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41 + dw 41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42 + dw 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42 + dw 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,43 + dw 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43 + dw 43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43 + dw 43,43,43,43,44,44,44,44,44,44,44,44,44,44,44,44 + dw 44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44 + dw 44,44,44,44,44,44,44,44,45,45,45,45,45,45,45,45 + dw 45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45 + dw 45,45,45,45,45,45,45,45,45,45,46,46,46,46,46,46 + dw 46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46 + dw 46,46,46,46,46,46,46,46,46,46,46,47,47,47,47,47 + dw 47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47 + dw 47,47,47,47,47,47,47,47,47,47,48,48,48,48,48,48 + dw 48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48 + dw 48,48,48,48,48,48,48,48,49,49,49,49,49,49,49,49 + dw 49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49 + dw 49,49,49,49,49,50,50,50,50,50,50,50,50,50,50,50 + dw 50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50 + dw 51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51 + dw 51,51,51,51,51,51,51,51,51,51,51,52,52,52,52,52 + dw 52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52 + dw 52,52,52,52,53,53,53,53,53,53,53,53,53,53,53,53 + dw 53,53,53,53,53,53,53,53,53,53,53,53,53,54,54,54 + dw 54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54 + dw 54,54,54,54,55,55,55,55,55,55,55,55,55,55,55,55 + dw 55,55,55,55,55,55,55,55,55,55,55,56,56,56,56,56 + dw 56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56 + dw 56,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57 + dw 57,57,57,57,57,57,57,58,58,58,58,58,58,58,58,58 + dw 58,58,58,58,58,58,58,58,58,58,58,59,59,59,59,59 + dw 59,59,59,59,59,59,59,59,59,59,59,59,59,59,59,60 + dw 60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60 + dw 60,60,61,61,61,61,61,61,61,61,61,61,61,61,61,61 + dw 61,61,61,61,61,62,62,62,62,62,62,62,62,62,62,62 + dw 62,62,62,62,62,62,62,63,63,63,63,63,63,63,63,63 + dw 63,63,63,63,63,63,63,63,64,64,64,64,64,64,64,64 + dw 64,64,64,64,64,64,64,64,64,65,65,65,65,65,65,65 + dw 65,65,65,65,65,65,65,65,65,66,66,66,66,66,66,66 + dw 66,66,66,66,66,66,66,66,66,67,67,67,67,67,67,67 + dw 67,67,67,67,67,67,67,67,68,68,68,68,68,68,68,68 + dw 68,68,68,68,68,68,68,69,69,69,69,69,69,69,69,69 + dw 69,69,69,69,69,69,70,70,70,70,70,70,70,70,70,70 + dw 70,70,70,70,71,71,71,71,71,71,71,71,71,71,71,71 + dw 71,71,72,72,72,72,72,72,72,72,72,72,72,72,72,73 + dw 73,73,73,73,73,73,73,73,73,73,73,73,74,74,74,74 + dw 74,74,74,74,74,74,74,74,75,75,75,75,75,75,75,75 + dw 75,75,75,75,75,76,76,76,76,76,76,76,76,76,76,76 + dw 76,77,77,77,77,77,77,77,77,77,77,77,78,78,78,78 + dw 78,78,78,78,78,78,78,78,79,79,79,79,79,79,79,79 + dw 79,79,79,80,80,80,80,80,80,80,80,80,80,81,81,81 + dw 81,81,81,81,81,81,81,81,82,82,82,82,82,82,82,82 + dw 82,82,83,83,83,83,83,83,83,83,83,83,84,84,84,84 + dw 84,84,84,84,84,84,85,85,85,85,85,85,85,85,85,85 + dw 86,86,86,86,86,86,86,86,86,87,87,87,87,87,87,87 + dw 87,87,88,88,88,88,88,88,88,88,88,89,89,89,89,89 + dw 89,89,89,89,90,90,90,90,90,90,90,90,91,91,91,91 + dw 91,91,91,91,92,92,92,92,92,92,92,92,92,93,93,93 + dw 93,93,93,93,93,94,94,94,94,94,94,94,95,95,95,95 + dw 95,95,95,95,96,96,96,96,96,96,96,96,97,97,97,97 + dw 97,97,97,98,98,98,98,98,98,98,99,99,99,99,99,99 + dw 99,100,100,100,100,100,100,100,101,101,101,101,101,101,101,102 + dw 102,102,102,102,102,103,103,103,103,103,103,103,104,104,104,104 + dw 104,104,105,105,105,105,105,105,106,106,106,106,106,106,106,107 + dw 107,107,107,107,107,108,108,108,108,108,108,109,109,109,109,109 + dw 110,110,110,110,110,110,111,111,111,111,111,111,112,112,112,112 + dw 112,113,113,113,113,113,113,114,114,114,114,114,115,115,115,115 + dw 115,116,116,116,116,116,117,117,117,117,117,118,118,118,118,118 + dw 119,119,119,119,119,120,120,120,120,120,121,121,121,121,121,122 + dw 122,122,122,123,123,123,123,123,124,124,124,124,125,125,125,125 + dw 125,126,126,126,126,127,127,127,127,128,128,128,128,128,129,129 + dw 129,129,130,130,130,130,131,131,131,131,132,132,132,132,133,133 + dw 133,133,134,134,134,134,135,135,135,136,136,136,136,137,137,137 + dw 137,138,138,138,139,139,139,139,140,140,140,141,141,141,141,142 + dw 142,142,143,143,143,143,144,144,144,145,145,145,146,146,146,146 + dw 147,147,147,148,148,148,149,149,149,150,150,150,151,151,151,152 + dw 152,152,153,153,153,154,154,154,155,155,155,156,156,156,157,157 + dw 158,158,158,159,159,159,160,160,160,161,161,162,162,162,163,163 + dw 164,164,164,165,165,165,166,166,167,167,167,168,168,169,169,170 + dw 170,170,171,171,172,172,172,173,173,174,174,175,175,176,176,176 + dw 177,177,178,178,179,179,180,180,181,181,182,182,183,183,184,184 + dw 184,185,185,186,186,187,187,188,189,189,190,190,191,191,192,192 + dw 193,193,194,194,195,195,196,197,197,198,198,199,199,200,201,201 + dw 202,202,203,204,204,205,205,206,207,207,208,208,209,210,210,211 + dw 212,212,213,214,214,215,216,216,217,218,218,219,220,220,221,222 + dw 223,223,224,225,225,226,227,228,228,229,230,231,232,232,233,234 + dw 235,235,236,237,238,239,240,240,241,242,243,244,245,246,246,247 + dw 248,249,250,251,252,253,254,255,256,256,257,258,259,260,261,262 + dw 263,264,265,266,267,268,270,271,272,273,274,275,276,277,278,279 + dw 280,282,283,284,285,286,287,289,290,291,292,294,295,296,297,299 + dw 300,301,303,304,305,307,308,309,311,312,314,315,317,318,319,321 + dw 322,324,325,327,329,330,332,333,335,337,338,340,342,343,345,347 + dw 348,350,352,354,356,357,359,361,363,365,367,369,371,373,375,377 + dw 379,381,383,385,388,390,392,394,397,399,401,403,406,408,411,413 + dw 416,418,421,423,426,429,431,434,437,439,442,445,448,451,454,457 + dw 460,463,466,469,473,476,479,482,486,489,493,496,500,504,507,511 + dw 515,519,523,527,531,535,539,543,548,552,556,561,566,570,575,580 + dw 585,590,595,600,605,611,616,622,627,633,639,645,651,657,663,670 + dw 676,683,690,697,704,711,719,726,734,742,750,758,767,775,784,793 + dw 802,812,821,831,841,852,862,873,885,896,908,920,932,945,958,972 + dw 986,1000,1015,1030,1045,1061,1078,1095,1113,1131,1150,1169,1190,1210,1232,1254 + dw 1278,1302,1327,1353,1380,1408,1437,1468,1500,1533,1568,1605,1643,1683,1725,1769 + dw 1816,1865,1917,1971,2029,2091,2156,2226,2300,2379,2464,2555 + +note_freq_ptrs = * +note_freq_ptrs_0 = * + dw 0,204,396,578,748,914,1066,1210,1346,1474,1594,1706,1814,1916,2012,2104 + dw 2188,2272,2348,2420,2488,2552,2612,2668,2722,2772,2820,2866,2908,2950,2988,3024 + dw 3058,3090,3120,3148,3176,3200,3224,3248,3268,3288,3308,3326,3342,3358,3374,3388 + dw 3402,3414,3426,3438,3448,3458,3468,3476,3486,3494,3500,3508,3514,3522,3528,3534 + dw 3538,3544,3548,3554,3558,3562,3566,3568,3572 +note_freq_ptrs_1 = * + dw 0,228,420,600,770,930,1082,1224,1360,1488,1608,1720,1828,1928,2024,2114 + dw 2198,2280,2354,2426,2494,2558,2618,2674,2728,2778,2826,2870,2914,2954,2992,3028 + dw 3060,3092,3122,3150,3178,3202,3226,3250,3270,3290,3310,3328,3344,3360,3376,3390 + dw 3402,3416,3428,3440,3450,3460,3470,3478,3488,3496,3502,3510,3516,3522,3528,3534 + dw 3540,3544,3550,3554,3558,3562,3566,3570,3572,3572 +note_freq_ptrs_2 = * + dw 0,252,442,622,790,950,1100,1242,1376,1502,1622,1734,1840,1940,2036,2124 + dw 2210,2288,2364,2434,2502,2564,2624,2680,2734,2784,2832,2876,2918,2958,2996,3032 + dw 3064,3096,3126,3154,3180,3206,3230,3252,3274,3294,3312,3330,3346,3362,3378,3392 + dw 3404,3416,3428,3440,3452,3462,3470,3480,3488,3496,3504,3510,3518,3522,3528,3534 + dw 3540,3546,3550,3554,3558,3562,3566,3570,3572,3572 +note_freq_ptrs_3 = * + dw 0,276,464,642,810,968,1118,1258,1392,1518,1636,1748,1854,1952,2046,2136 + dw 2220,2298,2372,2444,2510,2572,2632,2688,2740,2790,2838,2882,2924,2964,3000,3036 + dw 3068,3100,3130,3158,3184,3210,3232,3254,3276,3296,3314,3332,3348,3364,3378,3392 + dw 3406,3418,3430,3442,3452,3462,3472,3480,3488,3496,3504,3510,3518,3524,3530,3536 + dw 3540,3546,3550,3554,3560,3564,3566,3570,3574,3574 +note_freq_ptrs_4 = * + dw 0,300,488,664,830,988,1136,1276,1408,1532,1650,1762,1866,1964,2058,2146 + dw 2230,2308,2382,2452,2518,2580,2638,2694,2746,2796,2844,2888,2928,2968,3004,3040 + dw 3072,3104,3134,3162,3188,3212,3236,3258,3278,3298,3316,3334,3350,3366,3380,3394 + dw 3408,3420,3432,3444,3454,3464,3472,3482,3490,3498,3504,3512,3518,3524,3530,3536 + dw 3542,3546,3550,3556,3560,3564,3566,3570,3574,3574 +note_freq_ptrs_5 = * + dw 0,324,510,686,850,1006,1154,1292,1424,1548,1664,1774,1878,1976,2070,2156 + dw 2240,2318,2390,2460,2526,2588,2646,2702,2754,2802,2848,2892,2934,2972,3010,3044 + dw 3076,3108,3138,3164,3190,3216,3238,3260,3280,3300,3318,3336,3352,3368,3382,3396 + dw 3410,3422,3434,3444,3454,3464,3474,3482,3490,3498,3506,3512,3520,3526,3532,3536 + dw 3542,3546,3552,3556,3560,3564,3568,3570,3574,3574 +note_freq_ptrs_6 = * + dw 0,348,532,706,870,1026,1172,1310,1440,1562,1678,1788,1892,1988,2080,2168 + dw 2250,2326,2400,2468,2534,2596,2654,2708,2760,2808,2854,2898,2938,2978,3014,3048 + dw 3080,3112,3140,3168,3194,3218,3242,3262,3284,3302,3320,3338,3354,3370,3384,3398 + dw 3410,3424,3436,3446,3456,3466,3474,3484,3492,3500,3506,3514,3520,3526,3532,3538 + dw 3542,3548,3552,3556,3560,3564,3568,3572,3574,3574 +note_freq_ptrs_7 = * + dw 0,372,556,728,892,1044,1190,1326,1456,1578,1692,1802,1904,2000,2092,2178 + dw 2260,2336,2408,2478,2542,2602,2660,2714,2766,2814,2860,2902,2944,2982,3018,3052 + dw 3084,3116,3144,3172,3196,3220,3244,3266,3286,3306,3324,3340,3356,3372,3386,3400 + dw 3412,3424,3436,3448,3458,3468,3476,3484,3492,3500,3508,3514,3520,3526,3532,3538 + dw 3544,3548,3552,3556,3560,3564,3568,3572,3574,3574 +note_freq_ptrs_8 = * + dw 0,0,204,396,578,750,912,1064,1208,1344,1472,1592,1708,1814,1916,2012 + dw 2104,2188,2272,2348,2420,2488,2552,2612,2668,2722,2772,2820,2866,2908,2950,2988 + dw 3024,3058,3090,3120,3148,3176,3200,3224,3248,3268,3288,3308,3326,3342,3358,3374 + dw 3388,3402,3416,3428,3438,3448,3458,3468,3478,3486,3494,3502,3508,3516,3522,3528 + dw 3534,3540,3544,3548,3554,3558,3562,3566,3568,3568 +note_freq_ptrs_9 = * + dw 0,28,230,422,602,772,932,1084,1226,1362,1488,1608,1722,1828,1928,2024 + dw 2114,2198,2278,2356,2426,2494,2558,2618,2674,2728,2778,2826,2870,2914,2954,2992 + dw 3028,3060,3092,3122,3152,3178,3204,3228,3250,3270,3290,3310,3328,3344,3360,3376 + dw 3390,3404,3416,3428,3440,3450,3460,3470,3478,3486,3494,3502,3510,3516,3522,3528 + dw 3534,3540,3544,3550,3554,3558,3562,3566,3568,3568 +note_freq_ptrs_a = * + dw 0,52,254,444,622,810,950,1100,1242,1376,1502,1622,1734,1840,1940,2036 + dw 2124,2210,2288,2364,2434,2502,2564,2624,2680,2734,2784,2832,2876,2918,2958,2996 + dw 3032,3064,3096,3126,3154,3182,3206,3230,3252,3274,3294,3312,3330,3346,3362,3378 + dw 3392,3406,3418,3430,3442,3452,3462,3472,3480,3488,3496,3504,3510,3516,3524,3530 + dw 3536,3540,3546,3550,3554,3558,3562,3566,3570,3570 +note_freq_ptrs_b = * + dw 0,80,280,468,646,812,972,1120,1260,1394,1520,1638,1750,1854,1952,2046 + dw 2136,2220,2298,2372,2444,2510,2572,2632,2688,2740,2790,2838,2882,2924,2964,3000 + dw 3036,3068,3100,3130,3158,3184,3210,3232,3254,3276,3296,3314,3332,3348,3364,3378 + dw 3392,3406,3420,3432,3442,3452,3462,3472,3480,3490,3496,3504,3512,3516,3524,3530 + dw 3536,3540,3546,3550,3554,3560,3562,3566,3570,3570 +note_freq_ptrs_c = * + dw 0,104,302,490,666,832,988,1138,1278,1410,1534,1652,1762,1866,1964,2058 + dw 2146,2230,2308,2382,2452,2518,2580,2640,2694,2746,2796,2844,2888,2928,2968,3004 + dw 3040,3072,3104,3134,3162,3188,3212,3236,3258,3278,3298,3316,3334,3350,3366,3382 + dw 3394,3408,3420,3432,3444,3454,3464,3474,3482,3490,3498,3506,3512,3518,3524,3530 + dw 3536,3542,3546,3552,3556,3560,3564,3568,3570,3570 +note_freq_ptrs_d = * + dw 0,128,326,510,686,852,1006,1154,1294,1424,1548,1664,1774,1878,1976,2070 + dw 2156,2240,2318,2390,2460,2526,2588,2646,2702,2754,2802,2848,2892,2934,2972,3010 + dw 3044,3076,3108,3138,3164,3190,3216,3238,3260,3280,3300,3318,3336,3352,3368,3382 + dw 3396,3410,3422,3434,3444,3454,3464,3474,3482,3490,3498,3506,3512,3518,3526,3532 + dw 3536,3542,3546,3552,3556,3560,3564,3568,3570,3570 +note_freq_ptrs_e = * + dw 0,156,352,536,710,874,1028,1174,1312,1442,1564,1680,1790,1892,1988,2080 + dw 2168,2250,2326,2400,2468,2534,2596,2654,2708,2760,2808,2854,2898,2938,2978,3014 + dw 3048,3080,3112,3140,3168,3194,3218,3242,3262,3284,3302,3320,3338,3354,3370,3384 + dw 3398,3412,3424,3436,3444,3456,3464,3474,3484,3492,3500,3506,3514,3520,3526,3532 + dw 3536,3542,3548,3552,3556,3560,3564,3568,3572,3572 +note_freq_ptrs_f = * + dw 0,180,374,558,730,892,1046,1190,1328,1456,1578,1694,1802,1904,2000,2092 + dw 2178,2260,2336,2408,2478,2542,2602,2660,2714,2766,2814,2860,2902,2944,2982,3018 + dw 3052,3084,3116,3144,3172,3196,3222,3244,3266,3286,3306,3324,3340,3356,3372,3386 + dw 3400,3412,3424,3436,3446,3458,3466,3476,3484,3492,3500,3508,3514,3520,3526,3532 + dw 3538,3544,3548,3552,3556,3560,3564,3568,3572,3572 +max_freq_ptr = 146 +note_freq_ptrs_offset = * + dw note_freq_ptrs_0-note_freq_ptrs + dw note_freq_ptrs_1-note_freq_ptrs + dw note_freq_ptrs_2-note_freq_ptrs + dw note_freq_ptrs_3-note_freq_ptrs + dw note_freq_ptrs_4-note_freq_ptrs + dw note_freq_ptrs_5-note_freq_ptrs + dw note_freq_ptrs_6-note_freq_ptrs + dw note_freq_ptrs_7-note_freq_ptrs + dw note_freq_ptrs_8-note_freq_ptrs + dw note_freq_ptrs_9-note_freq_ptrs + dw note_freq_ptrs_a-note_freq_ptrs + dw note_freq_ptrs_b-note_freq_ptrs + dw note_freq_ptrs_c-note_freq_ptrs + dw note_freq_ptrs_d-note_freq_ptrs + dw note_freq_ptrs_e-note_freq_ptrs + dw note_freq_ptrs_f-note_freq_ptrs + +waveforms dw 0,2048,4096,4096 ;random=square in protracker! + +sine_tbl = * + dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dw 0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,0,0,0,0,0 + dw 0,0,0,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,0,0 + dw 0,0,2,2,2,2,4,4,4,4,4,6,6,6,6,6,6,6,6,6,6,6,4,4,4,4,4,2,2,2,2,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffc,$fffc,$fffc,$fffc,$fffc,$fffe,$fffe,$fffe,$fffe,0 + dw 0,0,2,2,4,4,4,6,6,6,6,8,8,8,8,8,8,8,8,8,8,8,6,6,6,6,4,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fffa,$fffa,$fffa,$fffa,$fffc,$fffc,$fffc,$fffe,$fffe,0 + dw 0,0,2,2,4,4,6,6,8,8,8,8,$a,$a,$a,$a,$a,$a,$a,$a,$a,8,8,8,8,6,6,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff8,$fff8,$fff8,$fff8,$fffa,$fffa,$fffc,$fffc,$fffe,$fffe,0 + dw 0,2,2,4,4,6,6,8,8,$a,$a,$a,$c,$c,$c,$c,$c,$c,$c,$c,$c,$a,$a,$a,8,8,6,6,4,4,2,2,0,$fffe,$fffe,$fffc,$fffc,$fffa,$fffa,$fff8,$fff8,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff6,$fff6,$fff6,$fff8,$fff8,$fffa,$fffa,$fffc,$fffc,$fffe,$fffe + dw 0,2,2,4,6,6,8,8,$a,$a,$c,$c,$c,$e,$e,$e,$e,$e,$e,$e,$c,$c,$c,$a,$a,8,8,6,6,4,2,2,0,$fffe,$fffe,$fffc,$fffa,$fffa,$fff8,$fff8,$fff6,$fff6,$fff4,$fff4,$fff4,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff4,$fff4,$fff4,$fff6,$fff6,$fff8,$fff8,$fffa,$fffa,$fffc,$fffe,$fffe + dw 0,2,4,4,6,8,8,$a,$c,$c,$e,$e,$e,$10,$10,$10,$10,$10,$10,$10,$e,$e,$e,$c,$c,$a,8,8,6,4,4,2,0,$fffe,$fffc,$fffc,$fffa,$fff8,$fff8,$fff6,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff2,$fff2,$fff2,$fff4,$fff4,$fff6,$fff8,$fff8,$fffa,$fffc,$fffc,$fffe + dw 0,2,4,6,6,8,$a,$c,$c,$e,$e,$10,$10,$12,$12,$12,$12,$12,$12,$12,$10,$10,$e,$e,$c,$c,$a,8,6,6,4,2,0,$fffe,$fffc,$fffa,$fffa,$fff8,$fff6,$fff4,$fff4,$fff2,$fff2,$fff0,$fff0,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$fff0,$fff0,$fff2,$fff2,$fff4,$fff4,$fff6,$fff8,$fffa,$fffa,$fffc,$fffe + dw 0,2,4,6,8,$a,$c,$c,$e,$10,$10,$12,$12,$14,$14,$14,$14,$14,$14,$14,$12,$12,$10,$10,$e,$c,$c,$a,8,6,4,2,0,$fffe,$fffc,$fffa,$fff8,$fff6,$fff4,$fff4,$fff2,$fff0,$fff0,$ffee,$ffee,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffee,$ffee,$fff0,$fff0,$fff2,$fff4,$fff4,$fff6,$fff8,$fffa,$fffc,$fffe + dw 0,2,4,6,8,$a,$c,$e,$10,$12,$12,$14,$14,$16,$16,$16,$16,$16,$16,$16,$14,$14,$12,$12,$10,$e,$c,$a,8,6,4,2,0,$fffe,$fffc,$fffa,$fff8,$fff6,$fff4,$fff2,$fff0,$ffee,$ffee,$ffec,$ffec,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffec,$ffec,$ffee,$ffee,$fff0,$fff2,$fff4,$fff6,$fff8,$fffa,$fffc,$fffe + dw 0,2,4,6,$a,$c,$e,$10,$10,$12,$14,$16,$16,$16,$18,$18,$18,$18,$18,$16,$16,$16,$14,$12,$10,$10,$e,$c,$a,6,4,2,0,$fffe,$fffc,$fffa,$fff6,$fff4,$fff2,$fff0,$fff0,$ffee,$ffec,$ffea,$ffea,$ffea,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffea,$ffea,$ffea,$ffec,$ffee,$fff0,$fff0,$fff2,$fff4,$fff6,$fffa,$fffc,$fffe + dw 0,2,6,8,$a,$c,$e,$10,$12,$14,$16,$16,$18,$18,$1a,$1a,$1a,$1a,$1a,$18,$18,$16,$16,$14,$12,$10,$e,$c,$a,8,6,2,0,$fffe,$fffa,$fff8,$fff6,$fff4,$fff2,$fff0,$ffee,$ffec,$ffea,$ffea,$ffe8,$ffe8,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe8,$ffe8,$ffea,$ffea,$ffec,$ffee,$fff0,$fff2,$fff4,$fff6,$fff8,$fffa,$fffe + dw 0,2,6,8,$a,$e,$10,$12,$14,$16,$18,$18,$1a,$1a,$1c,$1c,$1c,$1c,$1c,$1a,$1a,$18,$18,$16,$14,$12,$10,$e,$a,8,6,2,0,$fffe,$fffa,$fff8,$fff6,$fff2,$fff0,$ffee,$ffec,$ffea,$ffe8,$ffe8,$ffe6,$ffe6,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe6,$ffe6,$ffe8,$ffe8,$ffea,$ffec,$ffee,$fff0,$fff2,$fff6,$fff8,$fffa,$fffe + dw 0,2,6,8,$c,$e,$10,$14,$16,$18,$18,$1a,$1c,$1c,$1e,$1e,$1e,$1e,$1e,$1c,$1c,$1a,$18,$18,$16,$14,$10,$e,$c,8,6,2,0,$fffe,$fffa,$fff8,$fff4,$fff2,$fff0,$ffec,$ffea,$ffe8,$ffe8,$ffe6,$ffe4,$ffe4,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe4,$ffe4,$ffe6,$ffe8,$ffe8,$ffea,$ffec,$fff0,$fff2,$fff4,$fff8,$fffa,$fffe + +ramp_tbl = * + dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dw 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe + dw 4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc + dw 6,6,6,6,6,6,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fffa + dw 8,8,8,8,8,6,6,6,6,6,6,6,6,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8 + dw $a,$a,$a,$a,8,8,8,8,8,8,6,6,6,6,6,6,6,4,4,4,4,4,4,2,2,2,2,2,2,0,0,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6 + dw $c,$c,$c,$a,$a,$a,$a,$a,$a,8,8,8,8,8,6,6,6,6,6,4,4,4,4,4,4,2,2,2,2,2,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff4,$fff4 + dw $e,$e,$e,$c,$c,$c,$c,$a,$a,$a,$a,$a,8,8,8,8,8,6,6,6,6,4,4,4,4,4,2,2,2,2,0,0,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff4,$fff2,$fff2 + dw $10,$10,$10,$e,$e,$e,$e,$c,$c,$c,$c,$a,$a,$a,$a,8,8,8,8,6,6,6,6,4,4,4,4,2,2,2,2,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff4,$fff2,$fff2,$fff2,$fff2,$fff0,$fff0 + dw $12,$12,$10,$10,$10,$10,$e,$e,$e,$c,$c,$c,$c,$a,$a,$a,$a,8,8,8,6,6,6,6,4,4,4,2,2,2,2,0,0,0,$fffe,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$fff0,$fff0,$ffee + dw $14,$14,$12,$12,$12,$10,$10,$10,$10,$e,$e,$e,$c,$c,$c,$a,$a,$a,8,8,8,6,6,6,6,4,4,4,2,2,2,0,0,0,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$fff0,$fff0,$ffee,$ffee,$ffee,$ffec + dw $16,$16,$14,$14,$14,$12,$12,$12,$10,$10,$10,$e,$e,$e,$c,$c,$c,$a,$a,8,8,8,6,6,6,4,4,4,2,2,2,0,0,0,$fffe,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fff8,$fff8,$fff8,$fff6,$fff6,$fff4,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$fff0,$ffee,$ffee,$ffee,$ffec,$ffec,$ffec,$ffea + dw $18,$18,$16,$16,$16,$14,$14,$12,$12,$12,$10,$10,$10,$e,$e,$c,$c,$c,$a,$a,$a,8,8,6,6,6,4,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fffa,$fff8,$fff8,$fff6,$fff6,$fff6,$fff4,$fff4,$fff4,$fff2,$fff2,$fff0,$fff0,$fff0,$ffee,$ffee,$ffee,$ffec,$ffec,$ffea,$ffea,$ffea,$ffe8 + dw $1a,$1a,$18,$18,$16,$16,$16,$14,$14,$12,$12,$12,$10,$10,$e,$e,$e,$c,$c,$a,$a,8,8,8,6,6,4,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffc,$fffa,$fffa,$fff8,$fff8,$fff8,$fff6,$fff6,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$ffee,$ffee,$ffee,$ffec,$ffec,$ffea,$ffea,$ffea,$ffe8,$ffe8,$ffe6 + dw $1c,$1c,$1a,$1a,$18,$18,$16,$16,$16,$14,$14,$12,$12,$10,$10,$e,$e,$e,$c,$c,$a,$a,8,8,8,6,6,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffa,$fffa,$fff8,$fff8,$fff8,$fff6,$fff6,$fff4,$fff4,$fff2,$fff2,$fff2,$fff0,$fff0,$ffee,$ffee,$ffec,$ffec,$ffea,$ffea,$ffea,$ffe8,$ffe8,$ffe6,$ffe6,$ffe4 + dw $1e,$1e,$1c,$1c,$1a,$1a,$18,$18,$16,$16,$14,$14,$12,$12,$10,$10,$10,$e,$e,$c,$c,$a,$a,8,8,6,6,4,4,2,2,0,0,0,$fffe,$fffe,$fffc,$fffc,$fffa,$fffa,$fff8,$fff8,$fff6,$fff6,$fff4,$fff4,$fff2,$fff2,$fff0,$fff0,$fff0,$ffee,$ffee,$ffec,$ffec,$ffea,$ffea,$ffe8,$ffe8,$ffe6,$ffe6,$ffe4,$ffe4,$ffe2 + +square_tbl = * + dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dw 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe,$fffe + dw 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc,$fffc + dw 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa,$fffa + dw 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8,$fff8 + dw $a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$a,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6,$fff6 + dw $c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$c,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4,$fff4 + dw $e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$e,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2,$fff2 + dw $10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$10,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0,$fff0 + dw $12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$12,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee,$ffee + dw $14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$14,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec,$ffec + dw $16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$16,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea,$ffea + dw $18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$18,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8,$ffe8 + dw $1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6,$ffe6 + dw $1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4,$ffe4 + dw $1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2,$ffe2 + +pattern_break_ptrs = * + dfb 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0 + dfb 10,11,12,13,14,15,16,17,18,19,0,0,0,0,0,0 + dfb 20,21,22,23,24,25,26,27,28,29,0,0,0,0,0,0 + dfb 30,31,32,33,34,35,36,37,38,39,0,0,0,0,0,0 + dfb 40,41,42,43,44,45,46,47,48,49,0,0,0,0,0,0 + dfb 50,51,52,53,54,55,56,57,58,59,0,0,0,0,0,0 + dfb 60,61,62,63,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + dfb 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + +bpm_to_freq = * + dw 64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94 + dw 96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,125 + dw 127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157 + dw 159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189 + dw 191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221 + dw 223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253 + dw 255,257,259,261,263,265,267,269,271,273,275,277,279,281,283,285 + dw 287,289,291,293,295,297,299,301,303,305,307,309,311,313,315,317 + dw 319,321,323,325,327,329,331,333,335,337,339,341,343,345,347,349 + dw 351,353,355,357,359,361,363,365,367,369,371,372,374,376,378,380 + dw 382,384,386,388,390,392,394,396,398,400,402,404,406,408,410,412 + dw 414,416,418,420,422,424,426,428,430,432,434,436,438,440,442,444 + dw 446,448,450,452,454,456,458,460,462,464,466,468,470,472,474,476 + dw 478,480,482,484,486,488,490,492,494,496,498,500,502,504,506,508 + +reg_tbl_freqhi = * + dw 32,34,36,38,40,42,44,46,48,50,52,54,56,58,60 +reg_tbl_vol = * + dw 64,66,68,70,72,74,76,78,80,82,84,86,88,90,92 +reg_tbl_ptr = * + dw 128,130,132,134,136,138,140,142,144,146,148,150,152,154,156 +reg_tbl_ctl = * + dw 160,162,164,166,168,170,172,174,176,178,180,182,184,186,188 +reg_tbl_siz = * + dw 192,194,196,198,200,202,204,206,208,210,212,214,216,218,220 + +;-------------------------- + +zero_out_begin = * ;for init, we're writing zeros from here + +ptr_header ds 4 ;pointer to file start +ptr_notes ds 4 ;pointer to music notes +ptr_instruments ds 4 ;pointer to instrument start + +play_song_once dw 0 ;0=loop song, else do stop song after one play + +number_of_tracks dw 0 ;1-15 +number_of_instruments dw 0 ;1-255 +number_of_patterns dw 0 ;1-255 +pattern_length dw 0 ;pattern length in bytes (=4 bytes x number_of_tracks x 64, can be 3584 bytes max.) +track_channels ds max_tracks_available*2 ;1 word of stereo setting for each track +pattern_order_length dw 0 ;how many entries there are in pattern_order +pattern_order ds 256 ;in which order the patterns should be played + +instrument_types ds 512 ;1 word per instrument +instrument_lengths ds 512 +instrument_volumes ds 512 +instrument_finetune ds 512 ;instrument finetune value * 2 +instrument_osc_a_ptr ds 512 +instrument_osc_b_ptr ds 512 +instrument_osc_a_siz ds 512 +instrument_osc_b_siz ds 512 +instrument_osc_a_ctl ds 512 +instrument_osc_b_ctl ds 512 + +copy_instrument_length dw 0 + +pattern_pointers ds 1024 ;for every pattern, calculate the offset into memory + +number_of_tracks2 dw 0 ;number of tracks x 2 +number_of_instruments2 dw 0 ;number_of_instruments x 2 +number_of_tracks4 dw 0 ;number of tracks x 4 = number of bytes in a pattern line + +backup_interrupt_ptr ds 4 + +playing dw 0 ;0=not playing, 1=playing +tempo dw 0 +timer dw 0 + +pattern_jump dw 0 ;0=no jump, 2=pattern_jump_param has next songpos, 4=pattern_jump_param has next pointer in pattern +pattern_jump_param dw 0 +force_pattern_jump dw 0 ;0=no jump, else force jump on next occasion +force_pattern_jump_p dw 0 ;jump to this songpos + +loop_position dw 0 ;position where to jump to in the current frame +loop_repeat_count dw 0 ;number of times the loop should be repeated +loop_position_active dw 0 ;0=loop not running, else=loop running +loop_position_jump dw 0 ;$ffff=no position jump, else=jump to this position + +pattern_order_ptr dw 0 ;current position in the pattern order +ptr_within_pattern dw 0 ;offset in bytes to current line in the pattern + +note dw 0 ;read note*2 +sample dw 0 ;read sample*2 +effect dw 0 ;read effect*2 +effect_param dw 0 ;just the effect parameter + +oscillator dw 0 + +osc_interrupt_freq dw 0 +new_osc_interrupt_freq dw 0 + +delay_pattern dw 0 ;after the current line, do a delay of X rows + +what_to_do ds max_tracks_available*2 ;what to send to the shound chip (bit field) + +;the last line that we got from the pattern +curr_note ds max_tracks_available*2 ;note number * 2 +curr_sample ds max_tracks_available*2 ;sample number * 2 +curr_effect ds max_tracks_available*2 ;effect number * 2 +curr_e_effect ds max_tracks_available*2 ;e-effect number * 2 +curr_ptrfinetune ds max_tracks_available*2 ;ptr into the big finetune table +curr_volume ds max_tracks_available*2 ;the volume for this track (0-64) + +arpeggio_ptr ds max_tracks_available*2 ;when 0, arpeggio is off, $8000=note 1, $8001=note 2, $8003=note 3 +arpeggio_note1 ds max_tracks_available*2 +arpeggio_note2 ds max_tracks_available*2 +arpeggio_note3 ds max_tracks_available*2 + +slide_delta ds max_tracks_available*2 +slide_target ds max_tracks_available*2 +slide_target_note ds max_tracks_available*2 + +vibrato_tableoffset ds max_tracks_available*2 +vibrato_table ds max_tracks_available*2 +vibrato_rate ds max_tracks_available*2 +vibrato_pos ds max_tracks_available*2 +vibrato_retrig ds max_tracks_available*2 + +tremolo_tableoffset ds max_tracks_available*2 +tremolo_table ds max_tracks_available*2 +tremolo_rate ds max_tracks_available*2 +tremolo_pos ds max_tracks_available*2 +tremolo_retrig ds max_tracks_available*2 + +volslide_delta ds max_tracks_available*2 + +retrigger_steps ds max_tracks_available*2 +retrigger_count ds max_tracks_available*2 + +note_cut ds max_tracks_available*2 + +note_delay_count ds max_tracks_available*2 +note_delay_note ds max_tracks_available*2 + +osc_freq ds max_tracks_available*2 +osc_volume ds max_tracks_available*2 +osc_instrument ds max_tracks_available*2 + +glissando ds max_tracks_available*2 ;0=no glissando, 1=glissando + +last_effect_8_param dw 0 + +vu_number_of_tracks dw 0 +vu_data ds max_tracks_available*2 + +zero_out_end = * ;for init, we're writing zeros until here diff --git a/asm/merlin/ntpplayer.a b/asm/merlin/ntpplayer.a new file mode 100644 index 0000000000000000000000000000000000000000..57f4822da89c2a97f94bd502b15139662a068453 GIT binary patch literal 24393 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

h;I=4;Q-vD9tx<7SBeKma}eH(o@ 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 UzX03#`G!qj?AWzu|DmJszW{z`rT_o{ literal 0 HcmV?d00001