From 283279506ed314f0b46a3849e47811463bc57bdc Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 11 Sep 2019 16:08:36 -0400 Subject: [PATCH] pt3: create combined version for pt3_lib and pt3_player keeping separate versions was a pain --- pt3_lib/Makefile | 4 +- pt3_lib/gr_offsets.s | 5 + pt3_lib/interrupt_handler.s | 107 +-- .../pt3_lib.s => pt3_lib/pt3_lib_core.s | 590 +----------- pt3_lib/pt3_lib_init.s | 575 ++++++++++++ pt3_lib/pt3_lib_irq_handler.s | 109 +++ pt3_lib/pt3_test.s | 63 +- pt3_lib/text_print.s | 142 +++ pt3_lib/zp.inc | 5 + pt3_player/Makefile | 13 +- pt3_player/interrupt_handler.s | 113 +-- pt3_player/pt3_dumper.s | 52 +- .../pt3_lib.s => pt3_player/pt3_lib_core.s | 864 +++++------------- pt3_player/pt3_lib_init.s | 575 ++++++++++++ pt3_player/pt3_lib_irq_handler.s | 109 +++ pt3_player/pt3_player.s | 10 +- pt3_player/pt3_table_test.s | 3 +- pt3_player/pt3_timer.s | 31 +- 18 files changed, 1865 insertions(+), 1505 deletions(-) create mode 100644 pt3_lib/gr_offsets.s rename pt3_player/pt3_lib.s => pt3_lib/pt3_lib_core.s (77%) create mode 100644 pt3_lib/pt3_lib_init.s create mode 100644 pt3_lib/pt3_lib_irq_handler.s create mode 100644 pt3_lib/text_print.s rename pt3_lib/pt3_lib.s => pt3_player/pt3_lib_core.s (75%) create mode 100644 pt3_player/pt3_lib_init.s create mode 100644 pt3_player/pt3_lib_irq_handler.s diff --git a/pt3_lib/Makefile b/pt3_lib/Makefile index ac2b44dd..3600bb13 100644 --- a/pt3_lib/Makefile +++ b/pt3_lib/Makefile @@ -21,7 +21,9 @@ HELLO: hello.bas PT3_TEST: pt3_test.o ld65 -o PT3_TEST pt3_test.o -C ../linker_scripts/apple2_1000.inc -pt3_test.o: pt3_test.s pt3_lib.s interrupt_handler.s zp.inc +pt3_test.o: pt3_test.s \ + pt3_lib_init.s pt3_lib_core.s interrupt_handler.s \ + zp.inc ca65 -o pt3_test.o pt3_test.s -l pt3_test.lst # diff --git a/pt3_lib/gr_offsets.s b/pt3_lib/gr_offsets.s new file mode 100644 index 00000000..d3af91f7 --- /dev/null +++ b/pt3_lib/gr_offsets.s @@ -0,0 +1,5 @@ +gr_offsets: + .word $400,$480,$500,$580,$600,$680,$700,$780 + .word $428,$4a8,$528,$5a8,$628,$6a8,$728,$7a8 + .word $450,$4d0,$550,$5d0,$650,$6d0,$750,$7d0 + diff --git a/pt3_lib/interrupt_handler.s b/pt3_lib/interrupt_handler.s index e836df2d..e80581ad 100644 --- a/pt3_lib/interrupt_handler.s +++ b/pt3_lib/interrupt_handler.s @@ -30,104 +30,8 @@ interrupt_handler: ; inc $0404 ; debug (flashes char onscreen) - bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 - - lda DONE_PLAYING ; 3 - beq pt3_play_music ; if song done, don't play music ; 3/2nt - jmp exit_interrupt ; 3 - ;============ - ; 13 - -pt3_play_music: - - ; decode a frame of music - - jsr pt3_make_frame - - ; handle song over condition - lda DONE_SONG - beq mb_write_frame ; if not done, continue - - lda LOOP ; see if looping - beq move_to_next - -pt3_loop_smc: - lda #0 ; looping, move to loop location - sta current_pattern - lda #$0 - sta current_line - sta current_subframe - sta DONE_SONG ; undo the next song - - beq done_interrupt ; branch always - -move_to_next: - ; same as "press right" - ldx #$20 - jmp quiet_exit - - ;====================================== - ; Write frames to Mockingboard - ;====================================== - ; for speed could merge this into - ; the decode code - -mb_write_frame: - - - tax ; set up reg count ; 2 - ;============ - ; 2 - - ;================================== - ; loop through the 14 registers - ; reading the value, then write out - ;================================== - -mb_write_loop: - lda AY_REGISTERS,X ; load register value ; 4 - - ; special case R13. If it is 0xff, then don't update - ; otherwise might spuriously reset the envelope settings - - cpx #13 ; 2 - bne mb_not_13 ; 3/2nt - cmp #$ff ; 2 - beq mb_skip_13 ; 3/2nt - ;============ - ; typ 5 -mb_not_13: - - - ; address - stx MOCK_6522_ORA1 ; put address on PA1 ; 4 - stx MOCK_6522_ORA2 ; put address on PA2 ; 4 - lda #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 - sta MOCK_6522_ORB1 ; latch_address on PB1 ; 4 - sta MOCK_6522_ORB2 ; latch_address on PB2 ; 4 - ldy #MOCK_AY_INACTIVE ; go inactive ; 2 - sty MOCK_6522_ORB1 ; 4 - sty MOCK_6522_ORB2 ; 4 - - ; value - lda AY_REGISTERS,X ; load register value ; 4 - sta MOCK_6522_ORA1 ; put value on PA1 ; 4 - sta MOCK_6522_ORA2 ; put value on PA2 ; 4 - lda #MOCK_AY_WRITE ; ; 2 - sta MOCK_6522_ORB1 ; write on PB1 ; 4 - sta MOCK_6522_ORB2 ; write on PB2 ; 4 - sty MOCK_6522_ORB1 ; 4 - sty MOCK_6522_ORB2 ; 4 - ;=========== - ; 60 -mb_no_write: - inx ; point to next register ; 2 - cpx #14 ; if 14 we're done ; 2 - bmi mb_write_loop ; otherwise, loop ; 3/2nt - ;============ - ; 7 -mb_skip_13: +.include "pt3_lib_irq_handler.s" jmp exit_interrupt @@ -135,16 +39,14 @@ mb_skip_13: ; Finally done with this interrupt ;================================= -done_interrupt: - quiet_exit: stx DONE_PLAYING jsr clear_ay_both - ;ldx #$ff ; also mute the channel - stx AY_REGISTERS+7 ; just in case + ldx #$ff ; also mute the channel + stx AY_REGISTERS+7 ; just in case + -done_key: exit_interrupt: pla @@ -164,4 +66,3 @@ interrupt_smc: ; typical ; ???? cycles - diff --git a/pt3_player/pt3_lib.s b/pt3_lib/pt3_lib_core.s similarity index 77% rename from pt3_player/pt3_lib.s rename to pt3_lib/pt3_lib_core.s index d2f6be8d..fed1de16 100644 --- a/pt3_player/pt3_lib.s +++ b/pt3_lib/pt3_lib_core.s @@ -91,6 +91,7 @@ NOTE_TONE_SLIDE_TO_STEP =39 NOTE_STRUCT_SIZE=40 +.ifdef USE_ZERO_PAGE note_a = $80 note_b = $80+(NOTE_STRUCT_SIZE*1) note_c = $80+(NOTE_STRUCT_SIZE*2) @@ -98,7 +99,8 @@ note_c = $80+(NOTE_STRUCT_SIZE*2) begin_vars=$80 end_vars=$80+(NOTE_STRUCT_SIZE*3) -.if 0 + +.else ; !USE_ZERO_PAGE begin_vars: note_a: ; reset? @@ -383,438 +385,6 @@ load_ornament: - ;==================================== - ; pt3_init_song - ;==================================== - ; -pt3_init_song: - - lda #$0 - sta DONE_SONG ; 3 - ldx #(end_vars-begin_vars) -zero_song_structs_loop: - dex - sta note_a,X - bne zero_song_structs_loop - - sta pt3_noise_period_smc+1 ; 4 - sta pt3_noise_add_smc+1 ; 4 - - sta pt3_envelope_period_l_smc+1 ; 4 - sta pt3_envelope_period_h_smc+1 ; 4 - sta pt3_envelope_slide_l_smc+1 ; 4 - sta pt3_envelope_slide_h_smc+1 ; 4 - sta pt3_envelope_slide_add_l_smc+1 ; 4 - sta pt3_envelope_slide_add_h_smc+1 ; 4 - sta pt3_envelope_add_smc+1 ; 4 - sta pt3_envelope_type_smc+1 ; 4 - sta pt3_envelope_type_old_smc+1 ; 4 - sta pt3_envelope_delay_smc+1 ; 4 - sta pt3_envelope_delay_orig_smc+1 ; 4 - - sta PT3_MIXER_VAL ; 3 - - sta current_pattern_smc+1 ; 4 - sta current_line_smc+1 ; 4 - sta current_subframe_smc+1 ; 4 - - lda #$f ; 2 - sta note_a+NOTE_VOLUME ; 4 - sta note_b+NOTE_VOLUME ; 4 - sta note_c+NOTE_VOLUME ; 4 - - ; default ornament/sample in A - ; X is zero coming in here - ;ldx #(NOTE_STRUCT_SIZE*0) ; 2 - jsr load_ornament0_sample1 ; 6+93 - - ; default ornament/sample in B - ldx #(NOTE_STRUCT_SIZE*1) ; 2 - jsr load_ornament0_sample1 ; 6+93 - - ; default ornament/sample in C - ldx #(NOTE_STRUCT_SIZE*2) ; 2 - jsr load_ornament0_sample1 ; 6+93 - - ;======================= - ; load default speed - - lda PT3_LOC+PT3_SPEED ; 4 - sta pt3_speed_smc+1 ; 4 - - ;======================= - ; load loop - - lda PT3_LOC+PT3_LOOP ; 4 - sta pt3_loop_smc+1 ; 4 - - - ;======================== - ;======================== - ; set up note/freq table - ; this saves some space and makes things marginally faster longrun - ;======================== - ;======================== - ; note (heh) that there are separate tables if version 3.3 - ; but we are going to assume we are only going to be playing - ; newer 3.4+ version files so only need the newer tables - - ldx PT3_LOC+PT3_HEADER_FREQUENCY ; 4 - beq use_freq_table_0 - dex - beq use_freq_table_1 - dex - beq use_freq_table_2 - ; fallthrough (freq table 3) - -use_freq_table_3: - ;================================================= - ; Create Table #3, v4+, "PT3NoteTable_REAL_34_35" - ;================================================= - - ldy #11 ; !2 -freq_table_3_copy_loop: - ; note, high lookup almost same as 2v4, just need to adjust one value - - lda base2_v4_high,Y ; !3 - sta NoteTable_high,Y ; !3 - lda base3_low,Y ; !3 - sta NoteTable_low,Y ; !3 - dey ; !1 - bpl freq_table_3_copy_loop ; !2 - - dec NoteTable_high ; adjust to right value - - jsr NoteTablePropogate ; !3 - - lda #table3_v4_adjust - sta note_table_adjust_smc+2 - - jsr NoteTableAdjust - - jmp done_set_freq_table - - - -use_freq_table_2: - ;================================================= - ; Create Table #2, v4+, "PT3NoteTable_ASM_34_35" - ;================================================= - - ldy #11 -freq_table_2_copy_loop: - lda base2_v4_high,Y - sta NoteTable_high,Y - lda base2_v4_low,Y - sta NoteTable_low,Y - dey - bpl freq_table_2_copy_loop - - jsr NoteTablePropogate ; !3 - - lda #table2_v4_adjust - sta note_table_adjust_smc+2 - - jsr NoteTableAdjust - - jmp done_set_freq_table - -use_freq_table_1: - ;================================================= - ; Create Table #1, "PT3NoteTable_ST" - ;================================================= - - ldy #11 -freq_table_1_copy_loop: - lda base1_high,Y - sta NoteTable_high,Y - lda base1_low,Y - sta NoteTable_low,Y - dey - bpl freq_table_1_copy_loop - - jsr NoteTablePropogate ; !3 - - ; last adjustments - lda #$FD ; Tone[23]=$3FD - sta NoteTable_low+23 - dec NoteTable_low+46 ; Tone[46]-=1; - - - jmp done_set_freq_table - - -use_freq_table_0: - ;================================================= - ; Create Table #0, "PT3NoteTable_PT_34_35" - ;================================================= - - ldy #11 -freq_table_0_copy_loop: - lda base0_v4_high,Y - sta NoteTable_high,Y - lda base0_v4_low,Y - sta NoteTable_low,Y - dey - bpl freq_table_0_copy_loop - - jsr NoteTablePropogate ; !3 - - lda #table0_v4_adjust - sta note_table_adjust_smc+2 - - jsr NoteTableAdjust - - -done_set_freq_table: - - - ;====================== - ; calculate version - ldx #6 ; 2 - lda PT3_LOC+PT3_VERSION ; 4 - sec ; 2 - sbc #'0' ; 2 - cmp #9 ; 2 - bcs not_ascii_number ; bge ; 2/3 - tax ; 2 - -not_ascii_number: - - ; adjust version<6 SMC code in the slide code - - ; FIXME: I am sure there's a more clever way to do this - - lda #$2C ; BIT ; 2 - cpx #$6 ; 2 - bcs version_greater_than_or_equal_6 ; bgt ; 3 - ; less than 6, jump - ; also carry is known to be clear - adc #$20 ; BIT->JMP 2C->4C ; 2 -version_greater_than_or_equal_6: - sta version_smc ; 4 - -pick_volume_table: - - ;======================= - ; Pick which volume number, based on version - - ; if (PlParams.PT3.PT3_Version <= 4) - - cpx #5 ; 2 - - ; carry clear = 3.3/3.4 table - ; carry set = 3.5 table - - ;========================== - ; VolTableCreator - ;========================== - ; Creates the appropriate volume table - ; based on z80 code by Ivan Roshin ZXAYHOBETA/VTII10bG.asm - ; - - ; Called with carry==0 for 3.3/3.4 table - ; Called with carry==1 for 3.5 table - - ; 177f-1932 = 435 bytes, not that much better than 512 of lookup - - -VolTableCreator: - - ; Init initial variables - lda #$0 - sta z80_d_smc+1 - ldy #$11 - - ; Set up self modify - - ldx #$2A ; ROL for self-modify - bcs vol_type_35 - -vol_type_33: - - ; For older table, we set initial conditions a bit - ; different - - dey - tya - - ldx #$ea ; NOP for self modify - -vol_type_35: - sty z80_l_smc+1 ; l=16 or 17 - sta z80_e_smc+1 ; e=16 or 0 - stx vol_smc ; set the self-modify code - - ldy #16 ; skip first row, all zeros - ldx #16 ; c=16 -vol_outer: - clc ; add HL,DE -z80_l_smc: - lda #$d1 -z80_e_smc: - adc #$d1 - sta z80_e_smc+1 - lda #0 -z80_d_smc: - adc #$d1 - sta z80_d_smc+1 ; carry is important - - ; sbc hl,hl - lda #0 - adc #$ff - eor #$ff - -vol_write: - sta z80_h_smc+1 - pha - -vol_inner: - pla - pha - -vol_smc: - nop ; nop or ROL depending - -z80_h_smc: - lda #$d1 - - adc #$0 ; a=a+carry; - - sta VolumeTable,Y - iny - - pla ; add HL,DE - adc z80_e_smc+1 - pha - lda z80_h_smc+1 - adc z80_d_smc+1 - sta z80_h_smc+1 - - inx ; inc C - txa ; a=c - and #$f - bne vol_inner - - - pla - - lda z80_e_smc+1 ; a=e - cmp #$77 - bne vol_m3 - - inc z80_e_smc+1 - -vol_m3: - txa ; a=c - bne vol_outer - -vol_done: - rts - - - ;========================================= - ; copy note table seed to proper location - ;========================================= - -; faster inlined - -;NoteTableCopy: - -; ldy #11 ; !2 -;note_table_copy_loop: -;ntc_smc1: -; lda base1_high,Y ; !3 -; sta NoteTable_high,Y ; !3 -;ntc_smc2: -; lda base1_low,Y ; !3 -; sta NoteTable_low,Y ; !3 -; dey ; !1 -; bpl note_table_copy_loop ; !2 -; rts ; !1 - - - ;========================================== - ; propogate the freq down, dividing by two - ;========================================== -NoteTablePropogate: - - ldy #0 -note_table_propogate_loop: - clc - lda NoteTable_high,Y - ror - sta NoteTable_high+12,Y - - lda NoteTable_low,Y - ror - sta NoteTable_low+12,Y - - iny - cpy #84 - bne note_table_propogate_loop - - rts - - - ;================================================ - ; propogation isn't enough, various values - ; are ofte off by one, so adjust using a bitmask - ;================================================ -NoteTableAdjust: - - ldx #0 -note_table_adjust_outer: - -note_table_adjust_smc: - lda table0_v4_adjust,X - sta TEMP - - ; reset smc - lda #NoteTable_low - sta ntl_smc+2 - - - ldy #7 -note_table_adjust_inner: - ror TEMP - bcc note_table_skip_adjust - -ntl_smc: - inc NoteTable_low,X - -note_table_skip_adjust: - clc - lda #12 - adc ntl_smc+1 - sta ntl_smc+1 - lda #0 - adc ntl_smc+2 ; unnecessary if aligned - sta ntl_smc+2 - -skip_adjust_done: - dey - bpl note_table_adjust_inner - - inx - cpx #12 - bne note_table_adjust_outer - - rts - - - - - - ;===================================== ; Calculate Note ;===================================== @@ -1259,7 +829,12 @@ do_onoff: do_offon: ldy note_a+NOTE_OFFON_DELAY,X ; else a->onoff=a->offon_delay; put_offon: +.ifdef USE_ZERO_PAGE sty note_a+NOTE_ONOFF,X +.else + lda note_a+NOTE_ONOFF,X + tay +.endif done_onoff: @@ -1701,7 +1276,7 @@ skip_step_inc1: ; a->tone_delta=GetNoteFreq(a->note,pt3)- ; GetNoteFreq(prev_note,pt3); - sty TEMP ; save Y + sty PT3_TEMP ; save Y prev_note_smc: ldy #$d1 lda NoteTable_low,Y ; GetNoteFreq @@ -1725,7 +1300,7 @@ temp_word_h2_smc: lda note_a+NOTE_NOTE,X sta note_a+NOTE_SLIDE_TO_NOTE,X - ldy TEMP ; restore Y + ldy PT3_TEMP ; restore Y ; a->note=prev_note; lda prev_note_smc+1 @@ -2403,51 +1978,8 @@ done_do_frame: rts ; 6 - -;base0_v3_high: -;.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 -;base0_v3_low: -;.byte $21,$73,$CE,$33,$A0,$16,$93,$18,$A4,$36,$CE,$6D - -; note: same as base0_v3_high -base0_v4_high: -.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 -base0_v4_low: -.byte $22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF,$6D - -base1_high: -.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07 -base1_low: -.byte $F8,$10,$60,$80,$D8,$28,$88,$F0,$60,$E0,$58,$E0 - -;base2_v3_high: -;.byte $0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07,$07,$07 -;base2_v3_low: -;.byte $3E,$80,$CC,$22,$82,$EC,$5C,$D6,$58,$E0,$6E,$04 - -; note almost same as above -base2_v4_high: -.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 -base2_v4_low: -.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8,$3B,$C5,$55,$EC - -; note almost same as above -;base3_high: -;.byte $0C,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 -base3_low: -.byte $DA,$22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF - - -; Adjustment factors -table0_v4_adjust: -.byte $40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c,$5a - -table2_v4_adjust: -.byte $20,$a8,$40,$f8,$bc,$90,$78,$70,$74,$08,$2a,$50 - -table3_v4_adjust: -.byte $B4,$40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c - +; note, you might have slightly better performance if these are aligned +; so that loads don't have to cross page boundaries NoteTable_high: .res 96,0 @@ -2459,101 +1991,3 @@ VolumeTable: pt3_lib_end: - - - -; Table #1 of Pro Tracker 3.3x - 3.5x -;PT3NoteTable_ST_high: -;.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09 -;.byte $09,$08,$08,$07,$07,$07,$06,$06 -;.byte $05,$05,$05,$04,$04,$04,$04,$03 -;.byte $03,$03,$03,$03,$02,$02,$02,$02 -;.byte $02,$02,$02,$01,$01,$01,$01,$01 -;.byte $01,$01,$01,$01,$01,$01,$01,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 - -;PT3NoteTable_ST_low: -;.byte $F8,$10,$60,$80,$D8,$28,$88,$F0 -;.byte $60,$E0,$58,$E0,$7C,$08,$B0,$40 -;.byte $EC,$94,$44,$F8,$B0,$70,$2C,$FD -;.byte $BE,$84,$58,$20,$F6,$CA,$A2,$7C -;.byte $58,$38,$16,$F8,$DF,$C2,$AC,$90 -;.byte $7B,$65,$51,$3E,$2C,$1C,$0A,$FC -;.byte $EF,$E1,$D6,$C8,$BD,$B2,$A8,$9F -;.byte $96,$8E,$85,$7E,$77,$70,$6B,$64 -;.byte $5E,$59,$54,$4F,$4B,$47,$42,$3F -;.byte $3B,$38,$35,$32,$2F,$2C,$2A,$27 -;.byte $25,$23,$21,$1F,$1D,$1C,$1A,$19 -;.byte $17,$16,$15,$13,$12,$11,$10,$0F - - -; Table #2 of Pro Tracker 3.4x - 3.5x -;PT3NoteTable_ASM_34_35_high: -;.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08 -;.byte $08,$07,$07,$06,$06,$06,$05,$05 -;.byte $05,$04,$04,$04,$04,$03,$03,$03 -;.byte $03,$03,$02,$02,$02,$02,$02,$02 -;.byte $02,$01,$01,$01,$01,$01,$01,$01 -;.byte $01,$01,$01,$01,$01,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 -;.byte $00,$00,$00,$00,$00,$00,$00,$00 - -;PT3NoteTable_ASM_34_35_low: -;.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8 -;.byte $3B,$C5,$55,$EC,$88,$2A,$D2,$7E -;.byte $2F,$E5,$9E,$5C,$1D,$E2,$AB,$76 -;.byte $44,$15,$E9,$BF,$98,$72,$4F,$2E -;.byte $0F,$F1,$D5,$BB,$A2,$8B,$74,$60 -;.byte $4C,$39,$28,$17,$07,$F9,$EB,$DD -;.byte $D1,$C5,$BA,$B0,$A6,$9D,$94,$8C -;.byte $84,$7C,$75,$6F,$69,$63,$5D,$58 -;.byte $53,$4E,$4A,$46,$42,$3E,$3B,$37 -;.byte $34,$31,$2F,$2C,$29,$27,$25,$23 -;.byte $21,$1F,$1D,$1C,$1A,$19,$17,$16 -;.byte $15,$14,$12,$11,$10,$0F,$0E,$0D - - -;PT3VolumeTable_33_34: -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 -;.byte $0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2 -;.byte $0,$0,$0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3 -;.byte $0,$0,$0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4 -;.byte $0,$0,$0,$1,$1,$1,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 -;.byte $0,$0,$0,$1,$1,$2,$2,$3,$3,$3,$4,$4,$5,$5,$6,$6 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$5,$5,$6,$6,$7,$7,$8 -;.byte $0,$0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$6,$7,$8,$8,$9 -;.byte $0,$0,$1,$2,$2,$3,$4,$4,$5,$6,$6,$7,$8,$8,$9,$A -;.byte $0,$0,$1,$2,$3,$3,$4,$5,$6,$6,$7,$8,$9,$9,$A,$B -;.byte $0,$0,$1,$2,$3,$4,$4,$5,$6,$7,$8,$8,$9,$A,$B,$C -;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D -;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F - -;PT3VolumeTable_35: -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 -;.byte $0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1,$2,$2,$2,$2 -;.byte $0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2,$3,$3,$3 -;.byte $0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3,$4,$4 -;.byte $0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 -;.byte $0,$0,$1,$1,$2,$2,$2,$3,$3,$4,$4,$4,$5,$5,$6,$6 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 -;.byte $0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7,$8 -;.byte $0,$1,$1,$2,$2,$3,$4,$4,$5,$5,$6,$7,$7,$8,$8,$9 -;.byte $0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$7,$7,$8,$9,$9,$A -;.byte $0,$1,$1,$2,$3,$4,$4,$5,$6,$7,$7,$8,$9,$A,$A,$B -;.byte $0,$1,$2,$2,$3,$4,$5,$6,$6,$7,$8,$9,$A,$A,$B,$C -;.byte $0,$1,$2,$3,$3,$4,$5,$6,$7,$8,$9,$A,$A,$B,$C,$D -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D,$E -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F diff --git a/pt3_lib/pt3_lib_init.s b/pt3_lib/pt3_lib_init.s new file mode 100644 index 00000000..e2f7e448 --- /dev/null +++ b/pt3_lib/pt3_lib_init.s @@ -0,0 +1,575 @@ +; pt3_lib_init.s + +; Initialize a song + +; this is done before song starts playing so it is not +; as performance / timing critical + + ;==================================== + ; pt3_init_song + ;==================================== + ; +pt3_init_song: + + lda #$0 + sta DONE_SONG ; 3 + ldx #(end_vars-begin_vars) +zero_song_structs_loop: + dex + sta note_a,X + bne zero_song_structs_loop + + sta pt3_noise_period_smc+1 ; 4 + sta pt3_noise_add_smc+1 ; 4 + + sta pt3_envelope_period_l_smc+1 ; 4 + sta pt3_envelope_period_h_smc+1 ; 4 + sta pt3_envelope_slide_l_smc+1 ; 4 + sta pt3_envelope_slide_h_smc+1 ; 4 + sta pt3_envelope_slide_add_l_smc+1 ; 4 + sta pt3_envelope_slide_add_h_smc+1 ; 4 + sta pt3_envelope_add_smc+1 ; 4 + sta pt3_envelope_type_smc+1 ; 4 + sta pt3_envelope_type_old_smc+1 ; 4 + sta pt3_envelope_delay_smc+1 ; 4 + sta pt3_envelope_delay_orig_smc+1 ; 4 + + sta PT3_MIXER_VAL ; 3 + + sta current_pattern_smc+1 ; 4 + sta current_line_smc+1 ; 4 + sta current_subframe_smc+1 ; 4 + + lda #$f ; 2 + sta note_a+NOTE_VOLUME ; 4 + sta note_b+NOTE_VOLUME ; 4 + sta note_c+NOTE_VOLUME ; 4 + + ; default ornament/sample in A + ; X is zero coming in here + ;ldx #(NOTE_STRUCT_SIZE*0) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ; default ornament/sample in B + ldx #(NOTE_STRUCT_SIZE*1) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ; default ornament/sample in C + ldx #(NOTE_STRUCT_SIZE*2) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ;======================= + ; load default speed + + lda PT3_LOC+PT3_SPEED ; 4 + sta pt3_speed_smc+1 ; 4 + + ;======================= + ; load loop + + lda PT3_LOC+PT3_LOOP ; 4 + sta pt3_loop_smc+1 ; 4 + + + ;======================== + ;======================== + ; set up note/freq table + ; this saves some space and makes things marginally faster longrun + ;======================== + ;======================== + ; note (heh) that there are separate tables if version 3.3 + ; but we are going to assume we are only going to be playing + ; newer 3.4+ version files so only need the newer tables + + ldx PT3_LOC+PT3_HEADER_FREQUENCY ; 4 + beq use_freq_table_0 + dex + beq use_freq_table_1 + dex + beq use_freq_table_2 + ; fallthrough (freq table 3) + +use_freq_table_3: + ;================================================= + ; Create Table #3, v4+, "PT3NoteTable_REAL_34_35" + ;================================================= + + ldy #11 ; !2 +freq_table_3_copy_loop: + ; note, high lookup almost same as 2v4, just need to adjust one value + + lda base2_v4_high,Y ; !3 + sta NoteTable_high,Y ; !3 + lda base3_low,Y ; !3 + sta NoteTable_low,Y ; !3 + dey ; !1 + bpl freq_table_3_copy_loop ; !2 + + dec NoteTable_high ; adjust to right value + + jsr NoteTablePropogate ; !3 + + lda #table3_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + jmp done_set_freq_table + + + +use_freq_table_2: + ;================================================= + ; Create Table #2, v4+, "PT3NoteTable_ASM_34_35" + ;================================================= + + ldy #11 +freq_table_2_copy_loop: + lda base2_v4_high,Y + sta NoteTable_high,Y + lda base2_v4_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_2_copy_loop + + jsr NoteTablePropogate ; !3 + + lda #table2_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + jmp done_set_freq_table + +use_freq_table_1: + ;================================================= + ; Create Table #1, "PT3NoteTable_ST" + ;================================================= + + ldy #11 +freq_table_1_copy_loop: + lda base1_high,Y + sta NoteTable_high,Y + lda base1_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_1_copy_loop + + jsr NoteTablePropogate ; !3 + + ; last adjustments + lda #$FD ; Tone[23]=$3FD + sta NoteTable_low+23 + dec NoteTable_low+46 ; Tone[46]-=1; + + + jmp done_set_freq_table + + +use_freq_table_0: + ;================================================= + ; Create Table #0, "PT3NoteTable_PT_34_35" + ;================================================= + + ldy #11 +freq_table_0_copy_loop: + lda base0_v4_high,Y + sta NoteTable_high,Y + lda base0_v4_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_0_copy_loop + + jsr NoteTablePropogate ; !3 + + lda #table0_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + +done_set_freq_table: + + + ;====================== + ; calculate version + ldx #6 ; 2 + lda PT3_LOC+PT3_VERSION ; 4 + sec ; 2 + sbc #'0' ; 2 + cmp #9 ; 2 + bcs not_ascii_number ; bge ; 2/3 + tax ; 2 + +not_ascii_number: + + ; adjust version<6 SMC code in the slide code + + ; FIXME: I am sure there's a more clever way to do this + + lda #$2C ; BIT ; 2 + cpx #$6 ; 2 + bcs version_greater_than_or_equal_6 ; bgt ; 3 + ; less than 6, jump + ; also carry is known to be clear + adc #$20 ; BIT->JMP 2C->4C ; 2 +version_greater_than_or_equal_6: + sta version_smc ; 4 + +pick_volume_table: + + ;======================= + ; Pick which volume number, based on version + + ; if (PlParams.PT3.PT3_Version <= 4) + + cpx #5 ; 2 + + ; carry clear = 3.3/3.4 table + ; carry set = 3.5 table + + ;========================== + ; VolTableCreator + ;========================== + ; Creates the appropriate volume table + ; based on z80 code by Ivan Roshin ZXAYHOBETA/VTII10bG.asm + ; + + ; Called with carry==0 for 3.3/3.4 table + ; Called with carry==1 for 3.5 table + + ; 177f-1932 = 435 bytes, not that much better than 512 of lookup + + +VolTableCreator: + + ; Init initial variables + lda #$0 + sta z80_d_smc+1 + ldy #$11 + + ; Set up self modify + + ldx #$2A ; ROL for self-modify + bcs vol_type_35 + +vol_type_33: + + ; For older table, we set initial conditions a bit + ; different + + dey + tya + + ldx #$ea ; NOP for self modify + +vol_type_35: + sty z80_l_smc+1 ; l=16 or 17 + sta z80_e_smc+1 ; e=16 or 0 + stx vol_smc ; set the self-modify code + + ldy #16 ; skip first row, all zeros + ldx #16 ; c=16 +vol_outer: + clc ; add HL,DE +z80_l_smc: + lda #$d1 +z80_e_smc: + adc #$d1 + sta z80_e_smc+1 + lda #0 +z80_d_smc: + adc #$d1 + sta z80_d_smc+1 ; carry is important + + ; sbc hl,hl + lda #0 + adc #$ff + eor #$ff + +vol_write: + sta z80_h_smc+1 + pha + +vol_inner: + pla + pha + +vol_smc: + nop ; nop or ROL depending + +z80_h_smc: + lda #$d1 + + adc #$0 ; a=a+carry; + + sta VolumeTable,Y + iny + + pla ; add HL,DE + adc z80_e_smc+1 + pha + lda z80_h_smc+1 + adc z80_d_smc+1 + sta z80_h_smc+1 + + inx ; inc C + txa ; a=c + and #$f + bne vol_inner + + + pla + + lda z80_e_smc+1 ; a=e + cmp #$77 + bne vol_m3 + + inc z80_e_smc+1 + +vol_m3: + txa ; a=c + bne vol_outer + +vol_done: + rts + + + ;========================================= + ; copy note table seed to proper location + ;========================================= + +; faster inlined + +;NoteTableCopy: + +; ldy #11 ; !2 +;note_table_copy_loop: +;ntc_smc1: +; lda base1_high,Y ; !3 +; sta NoteTable_high,Y ; !3 +;ntc_smc2: +; lda base1_low,Y ; !3 +; sta NoteTable_low,Y ; !3 +; dey ; !1 +; bpl note_table_copy_loop ; !2 +; rts ; !1 + + + ;========================================== + ; propogate the freq down, dividing by two + ;========================================== +NoteTablePropogate: + + ldy #0 +note_table_propogate_loop: + clc + lda NoteTable_high,Y + ror + sta NoteTable_high+12,Y + + lda NoteTable_low,Y + ror + sta NoteTable_low+12,Y + + iny + cpy #84 + bne note_table_propogate_loop + + rts + + + ;================================================ + ; propogation isn't enough, various values + ; are ofte off by one, so adjust using a bitmask + ;================================================ +NoteTableAdjust: + + ldx #0 +note_table_adjust_outer: + +note_table_adjust_smc: + lda table0_v4_adjust,X + sta PT3_TEMP + + ; reset smc + lda #NoteTable_low + sta ntl_smc+2 + + + ldy #7 +note_table_adjust_inner: + ror PT3_TEMP + bcc note_table_skip_adjust + +ntl_smc: + inc NoteTable_low,X + +note_table_skip_adjust: + clc + lda #12 + adc ntl_smc+1 + sta ntl_smc+1 + lda #0 + adc ntl_smc+2 ; unnecessary if aligned + sta ntl_smc+2 + +skip_adjust_done: + dey + bpl note_table_adjust_inner + + inx + cpx #12 + bne note_table_adjust_outer + + rts + + +;base0_v3_high: +;.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 +;base0_v3_low: +;.byte $21,$73,$CE,$33,$A0,$16,$93,$18,$A4,$36,$CE,$6D + +; note: same as base0_v3_high +base0_v4_high: +.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 +base0_v4_low: +.byte $22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF,$6D + +base1_high: +.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07 +base1_low: +.byte $F8,$10,$60,$80,$D8,$28,$88,$F0,$60,$E0,$58,$E0 + +;base2_v3_high: +;.byte $0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07,$07,$07 +;base2_v3_low: +;.byte $3E,$80,$CC,$22,$82,$EC,$5C,$D6,$58,$E0,$6E,$04 + +; note almost same as above +base2_v4_high: +.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 +base2_v4_low: +.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8,$3B,$C5,$55,$EC + +; note almost same as above +;base3_high: +;.byte $0C,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 +base3_low: +.byte $DA,$22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF + + +; Adjustment factors +table0_v4_adjust: +.byte $40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c,$5a + +table2_v4_adjust: +.byte $20,$a8,$40,$f8,$bc,$90,$78,$70,$74,$08,$2a,$50 + +table3_v4_adjust: +.byte $B4,$40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c + + +; Table #1 of Pro Tracker 3.3x - 3.5x +;PT3NoteTable_ST_high: +;.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09 +;.byte $09,$08,$08,$07,$07,$07,$06,$06 +;.byte $05,$05,$05,$04,$04,$04,$04,$03 +;.byte $03,$03,$03,$03,$02,$02,$02,$02 +;.byte $02,$02,$02,$01,$01,$01,$01,$01 +;.byte $01,$01,$01,$01,$01,$01,$01,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 + +;PT3NoteTable_ST_low: +;.byte $F8,$10,$60,$80,$D8,$28,$88,$F0 +;.byte $60,$E0,$58,$E0,$7C,$08,$B0,$40 +;.byte $EC,$94,$44,$F8,$B0,$70,$2C,$FD +;.byte $BE,$84,$58,$20,$F6,$CA,$A2,$7C +;.byte $58,$38,$16,$F8,$DF,$C2,$AC,$90 +;.byte $7B,$65,$51,$3E,$2C,$1C,$0A,$FC +;.byte $EF,$E1,$D6,$C8,$BD,$B2,$A8,$9F +;.byte $96,$8E,$85,$7E,$77,$70,$6B,$64 +;.byte $5E,$59,$54,$4F,$4B,$47,$42,$3F +;.byte $3B,$38,$35,$32,$2F,$2C,$2A,$27 +;.byte $25,$23,$21,$1F,$1D,$1C,$1A,$19 +;.byte $17,$16,$15,$13,$12,$11,$10,$0F + + +; Table #2 of Pro Tracker 3.4x - 3.5x +;PT3NoteTable_ASM_34_35_high: +;.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08 +;.byte $08,$07,$07,$06,$06,$06,$05,$05 +;.byte $05,$04,$04,$04,$04,$03,$03,$03 +;.byte $03,$03,$02,$02,$02,$02,$02,$02 +;.byte $02,$01,$01,$01,$01,$01,$01,$01 +;.byte $01,$01,$01,$01,$01,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 + +;PT3NoteTable_ASM_34_35_low: +;.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8 +;.byte $3B,$C5,$55,$EC,$88,$2A,$D2,$7E +;.byte $2F,$E5,$9E,$5C,$1D,$E2,$AB,$76 +;.byte $44,$15,$E9,$BF,$98,$72,$4F,$2E +;.byte $0F,$F1,$D5,$BB,$A2,$8B,$74,$60 +;.byte $4C,$39,$28,$17,$07,$F9,$EB,$DD +;.byte $D1,$C5,$BA,$B0,$A6,$9D,$94,$8C +;.byte $84,$7C,$75,$6F,$69,$63,$5D,$58 +;.byte $53,$4E,$4A,$46,$42,$3E,$3B,$37 +;.byte $34,$31,$2F,$2C,$29,$27,$25,$23 +;.byte $21,$1F,$1D,$1C,$1A,$19,$17,$16 +;.byte $15,$14,$12,$11,$10,$0F,$0E,$0D + + +;PT3VolumeTable_33_34: +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 +;.byte $0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2 +;.byte $0,$0,$0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3 +;.byte $0,$0,$0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4 +;.byte $0,$0,$0,$1,$1,$1,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 +;.byte $0,$0,$0,$1,$1,$2,$2,$3,$3,$3,$4,$4,$5,$5,$6,$6 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$5,$5,$6,$6,$7,$7,$8 +;.byte $0,$0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$6,$7,$8,$8,$9 +;.byte $0,$0,$1,$2,$2,$3,$4,$4,$5,$6,$6,$7,$8,$8,$9,$A +;.byte $0,$0,$1,$2,$3,$3,$4,$5,$6,$6,$7,$8,$9,$9,$A,$B +;.byte $0,$0,$1,$2,$3,$4,$4,$5,$6,$7,$8,$8,$9,$A,$B,$C +;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D +;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F + +;PT3VolumeTable_35: +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 +;.byte $0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1,$2,$2,$2,$2 +;.byte $0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2,$3,$3,$3 +;.byte $0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3,$4,$4 +;.byte $0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 +;.byte $0,$0,$1,$1,$2,$2,$2,$3,$3,$4,$4,$4,$5,$5,$6,$6 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 +;.byte $0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7,$8 +;.byte $0,$1,$1,$2,$2,$3,$4,$4,$5,$5,$6,$7,$7,$8,$8,$9 +;.byte $0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$7,$7,$8,$9,$9,$A +;.byte $0,$1,$1,$2,$3,$4,$4,$5,$6,$7,$7,$8,$9,$A,$A,$B +;.byte $0,$1,$2,$2,$3,$4,$5,$6,$6,$7,$8,$9,$A,$A,$B,$C +;.byte $0,$1,$2,$3,$3,$4,$5,$6,$7,$8,$9,$A,$A,$B,$C,$D +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D,$E +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F diff --git a/pt3_lib/pt3_lib_irq_handler.s b/pt3_lib/pt3_lib_irq_handler.s new file mode 100644 index 00000000..10899c88 --- /dev/null +++ b/pt3_lib/pt3_lib_irq_handler.s @@ -0,0 +1,109 @@ + + +pt3_irq_handler: + + bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 + + lda DONE_PLAYING ; 3 + beq pt3_play_music ; if song done, don't play music ; 3/2nt + jmp done_pt3_irq_handler ; 3 + ;============ + ; 13 + +pt3_play_music: + + ; decode a frame of music + + jsr pt3_make_frame + + ; handle song over condition + lda DONE_SONG + beq mb_write_frame ; if not done, continue + + lda LOOP ; see if looping + beq move_to_next + +pt3_loop_smc: + lda #$d1 ; looping, move to loop location + ; non-zero to avoid the temptation + ; to merge with following lda #$0 + sta current_pattern_smc+1 + lda #$0 + sta current_line_smc+1 + sta current_subframe_smc+1 + sta DONE_SONG ; undo the next song + + beq done_pt3_irq_handler ; branch always + +move_to_next: + ; same as "press right" + ldx #$20 + jmp quiet_exit + + ;====================================== + ; Write frames to Mockingboard + ;====================================== + ; for speed could merge this into + ; the decode code + +mb_write_frame: + + + tax ; set up reg count ; 2 + ;============ + ; 2 + + ;================================== + ; loop through the 14 registers + ; reading the value, then write out + ;================================== + +mb_write_loop: + lda AY_REGISTERS,X ; load register value ; 4 + + ; special case R13. If it is 0xff, then don't update + ; otherwise might spuriously reset the envelope settings + + cpx #13 ; 2 + bne mb_not_13 ; 3/2nt + cmp #$ff ; 2 + beq mb_skip_13 ; 3/2nt + ;============ + ; typ 5 +mb_not_13: + + + ; address + stx MOCK_6522_ORA1 ; put address on PA1 ; 4 + stx MOCK_6522_ORA2 ; put address on PA2 ; 4 + ldy #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 + sty MOCK_6522_ORB1 ; latch_address on PB1 ; 4 + sty MOCK_6522_ORB2 ; latch_address on PB2 ; 4 + ldy #MOCK_AY_INACTIVE ; go inactive ; 2 + sty MOCK_6522_ORB1 ; 4 + sty MOCK_6522_ORB2 ; 4 + + ; value + sta MOCK_6522_ORA1 ; put value on PA1 ; 4 + sta MOCK_6522_ORA2 ; put value on PA2 ; 4 + lda #MOCK_AY_WRITE ; ; 2 + sta MOCK_6522_ORB1 ; write on PB1 ; 4 + sta MOCK_6522_ORB2 ; write on PB2 ; 4 + sty MOCK_6522_ORB1 ; 4 + sty MOCK_6522_ORB2 ; 4 + ;=========== + ; 56 +mb_no_write: + inx ; point to next register ; 2 + cpx #14 ; if 14 we're done ; 2 + bmi mb_write_loop ; otherwise, loop ; 3/2nt + ;============ + ; 7 +mb_skip_13: + + + ;================================= + ; Finally done with this interrupt + ;================================= + +done_pt3_irq_handler: diff --git a/pt3_lib/pt3_test.s b/pt3_lib/pt3_test.s index 8d24d52d..e2216d02 100644 --- a/pt3_lib/pt3_test.s +++ b/pt3_lib/pt3_test.s @@ -32,8 +32,8 @@ pt3_setup: cmp #6 beq apple_iie_or_newer - lda #1 ; set if older than a IIe - sta apple_ii + ;lda #$d0 ; set if older than a IIe + ;sta apple_ii_smc jmp done_apple_detect apple_iie_or_newer: lda $FBC0 ; 0 on a IIc @@ -69,9 +69,11 @@ done_apple_detect: ;=============== lda #0 + sta DRAW_PAGE sta DONE_PLAYING sta LOOP + ;======================= ; Detect mockingboard ;======================== @@ -83,32 +85,32 @@ done_apple_detect: ; print detection message -; lda #mocking_message -; sta OUTH -; jsr move_and_print ; print it + lda #mocking_message + sta OUTH + jsr move_and_print ; print it jsr mockingboard_detect_slot4 ; call detection routine cpx #$1 beq mockingboard_found -; lda #not_message -; sta OUTH -; inc CV -; jsr move_and_print + lda #not_message + sta OUTH + inc CV + jsr move_and_print -; jmp forever_loop ; and wait forever + jmp forever_loop ; and wait forever mockingboard_found: -; lda #found_message -; sta OUTH -; inc CV -; jsr move_and_print + lda #found_message + sta OUTH + inc CV + jsr move_and_print ;============================ ; Init the Mockingboard @@ -170,8 +172,8 @@ start_interrupts: ;============================ ; Loop forever ;============================ +forever_loop: main_loop: - jmp main_loop @@ -187,23 +189,26 @@ main_loop: ; vars ;========= -time_frame: .byte $0 -apple_ii: .byte $0 - ;========= ;routines ;========= .include "mockingboard_a.s" .include "interrupt_handler.s" -.include "pt3_lib.s" +.include "pt3_lib_core.s" +.include "pt3_lib_init.s" + +.include "text_print.s" +.include "gr_offsets.s" ;========= ; strings ;========= -;mocking_message: .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" -not_message: .byte "NOT " -found_message: .asciiz "FOUND" -;done_message: .asciiz "DONE PLAYING" +mocking_message: .byte $0,$0 + .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" +not_message: .byte $0,$1 + .asciiz "+ NOT FOUND" +found_message: .byte $0,$1 + .asciiz "+ FOUND" ;============= ; include song diff --git a/pt3_lib/text_print.s b/pt3_lib/text_print.s new file mode 100644 index 00000000..2a090799 --- /dev/null +++ b/pt3_lib/text_print.s @@ -0,0 +1,142 @@ + + ;================================ + ; move_and_print + ;================================ + ; get X,Y from OUTL/OUTH + ; then print following string to that address + ; stop at NUL + ; convert to APPLE ASCII (or with 0x80) + ; leave OUTL/OUTH pointing to next string + +move_and_print: + ldy #0 + lda (OUTL),Y + sta CH + iny + lda (OUTL),Y + asl + tay + lda gr_offsets,Y ; lookup low-res memory address + clc + adc CH ; add in xpos + sta BASL ; store out low byte of addy + + lda gr_offsets+1,Y ; look up high byte + adc DRAW_PAGE ; + sta BASH ; and store it out + ; BASH:BASL now points at right place + + clc + lda OUTL + adc #2 + sta OUTL + lda OUTH + adc #0 + sta OUTH + + ;================================ + ; print_string + ;================================ + +print_string: + ldy #0 +print_string_loop: + lda (OUTL),Y + beq done_print_string + eor #$80 ; flip from ASCII to text char + sta (BASL),Y + iny + bne print_string_loop +done_print_string: + iny + clc + tya + adc OUTL + sta OUTL + lda OUTH + adc #0 + sta OUTH + + rts + + + ;================================ + ; move and print a list of lines + ;================================ +move_and_print_list: + jsr move_and_print + ldy #0 + lda (OUTL),Y + bpl move_and_print_list + + rts + + + + ;================================ + ; move and print a list of lines + ;================================ +move_and_print_list_both_pages: + lda DRAW_PAGE + pha + + lda OUTL + pha + lda OUTH + pha + + lda #0 + sta DRAW_PAGE + + jsr move_and_print_list + + pla + sta OUTH + pla + sta OUTL + + lda #4 + sta DRAW_PAGE + + jsr move_and_print_list + + pla + sta DRAW_PAGE + + + rts + + + + ;======================= + ; print to both pages + ;======================= +print_both_pages: + lda DRAW_PAGE + pha + + lda OUTL + pha + lda OUTH + pha + + lda #0 + sta DRAW_PAGE + + jsr move_and_print + + pla + sta OUTH + pla + sta OUTL + + lda #4 + sta DRAW_PAGE + + jsr move_and_print + + pla + sta DRAW_PAGE + + + rts diff --git a/pt3_lib/zp.inc b/pt3_lib/zp.inc index 50c8a909..06d21117 100644 --- a/pt3_lib/zp.inc +++ b/pt3_lib/zp.inc @@ -34,6 +34,10 @@ SEEDH = $4F ; dos33 zero page = 26-2f, 35-38, 3e 3f 40-4d ; overlap applesoft 67-6a,6f,70,af,b0,ca-cd,d8 +DRAW_PAGE = $6D +OUTL = $6E +OUTH = $6F + AY_REGISTERS = $70 A_FINE_TONE = $70 A_COARSE_TONE = $71 @@ -43,6 +47,7 @@ C_FINE_TONE = $74 C_COARSE_TONE = $75 NOISE = $76 ENABLE = $77 +PT3_MIXER_VAL = $77 A_VOLUME = $78 B_VOLUME = $79 C_VOLUME = $7A diff --git a/pt3_player/Makefile b/pt3_player/Makefile index 6bc4d320..93bf4598 100644 --- a/pt3_player/Makefile +++ b/pt3_player/Makefile @@ -78,8 +78,9 @@ PT3_PLAYER: pt3_player.o ld65 -o PT3_PLAYER pt3_player.o -C ../linker_scripts/apple2_1000.inc pt3_player.o: pt3_player.s \ - gr_fast_clear.s pt3_lib.s interrupt_handler.s random16.s fire.s \ - gr_putsprite.s put_letters.s zp.inc + gr_fast_clear.s random16.s fire.s \ + gr_putsprite.s put_letters.s zp.inc \ + pt3_lib_init.s pt3_lib_core.s interrupt_handler.s ca65 -o pt3_player.o pt3_player.s -l pt3_player.lst # @@ -88,7 +89,8 @@ PT3_TIMER: pt3_timer.o ld65 -o PT3_TIMER pt3_timer.o -C ../linker_scripts/apple2_1000.inc pt3_timer.o: pt3_timer.s \ - gr_fast_clear.s pt3_lib.s interrupt_handler.s zp.inc + gr_fast_clear.s zp.inc \ + pt3_lib_init.s pt3_lib_core.s ca65 -o pt3_timer.o pt3_timer.s -l pt3_timer.lst # @@ -97,7 +99,8 @@ PT3_DUMPER: pt3_dumper.o ld65 -o PT3_DUMPER pt3_dumper.o -C ../linker_scripts/apple2_1000.inc pt3_dumper.o: pt3_dumper.s \ - gr_fast_clear.s pt3_lib.s interrupt_handler.s zp.inc + gr_fast_clear.s zp.inc \ + pt3_lib_init.s pt3_lib_core.s ca65 -o pt3_dumper.o pt3_dumper.s -l pt3_dumper.lst # @@ -106,7 +109,7 @@ PT3_TABLE_TEST: pt3_table_test.o ld65 -o PT3_TABLE_TEST pt3_table_test.o -C ../linker_scripts/apple2_1000.inc pt3_table_test.o: pt3_table_test.s \ - gr_fast_clear.s pt3_lib.s interrupt_handler.s zp.inc + gr_fast_clear.s pt3_lib_core.s pt3_lib_init.s zp.inc ca65 -o pt3_table_test.o pt3_table_test.s -l pt3_table_test.lst # diff --git a/pt3_player/interrupt_handler.s b/pt3_player/interrupt_handler.s index 0ceb5cca..c427ed50 100644 --- a/pt3_player/interrupt_handler.s +++ b/pt3_player/interrupt_handler.s @@ -29,116 +29,17 @@ interrupt_handler: tya pha ; save Y - - ; inc $0404 ; debug (flashes char onscreen) - bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 + +.include "pt3_lib_irq_handler.s" + + ;============================================== + ; only update time counter if not done playing + ;============================================== lda DONE_PLAYING ; 3 - beq pt3_play_music ; if song done, don't play music ; 3/2nt - jmp check_keyboard ; 3 - ;============ - ; 13 - -pt3_play_music: - - ; decode a frame of music - - jsr pt3_make_frame - - ; handle song over condition - lda DONE_SONG - beq mb_write_frame ; if not done, continue - - lda LOOP ; see if looping - beq move_to_next - -pt3_loop_smc: - lda #$d1 ; looping, move to loop location - ; non-zero to avoid the temptation - ; to merge with following lda #$0 - sta current_pattern_smc+1 - lda #$0 - sta current_line_smc+1 - sta current_subframe_smc+1 - sta DONE_SONG ; undo the next song - - beq done_interrupt ; branch always - -move_to_next: - ; same as "press right" - ldx #$20 - jmp quiet_exit - - ;====================================== - ; Write frames to Mockingboard - ;====================================== - ; for speed could merge this into - ; the decode code - -mb_write_frame: - - - tax ; set up reg count ; 2 - ;============ - ; 2 - - ;================================== - ; loop through the 14 registers - ; reading the value, then write out - ;================================== - -mb_write_loop: - lda AY_REGISTERS,X ; load register value ; 4 - - ; special case R13. If it is 0xff, then don't update - ; otherwise might spuriously reset the envelope settings - - cpx #13 ; 2 - bne mb_not_13 ; 3/2nt - cmp #$ff ; 2 - beq mb_skip_13 ; 3/2nt - ;============ - ; typ 5 -mb_not_13: - - - ; address - stx MOCK_6522_ORA1 ; put address on PA1 ; 4 - stx MOCK_6522_ORA2 ; put address on PA2 ; 4 - ldy #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 - sty MOCK_6522_ORB1 ; latch_address on PB1 ; 4 - sty MOCK_6522_ORB2 ; latch_address on PB2 ; 4 - ldy #MOCK_AY_INACTIVE ; go inactive ; 2 - sty MOCK_6522_ORB1 ; 4 - sty MOCK_6522_ORB2 ; 4 - - ; value - sta MOCK_6522_ORA1 ; put value on PA1 ; 4 - sta MOCK_6522_ORA2 ; put value on PA2 ; 4 - lda #MOCK_AY_WRITE ; ; 2 - sta MOCK_6522_ORB1 ; write on PB1 ; 4 - sta MOCK_6522_ORB2 ; write on PB2 ; 4 - sty MOCK_6522_ORB1 ; 4 - sty MOCK_6522_ORB2 ; 4 - ;=========== - ; 56 -mb_no_write: - inx ; point to next register ; 2 - cpx #14 ; if 14 we're done ; 2 - bmi mb_write_loop ; otherwise, loop ; 3/2nt - ;============ - ; 7 -mb_skip_13: - - - ;================================= - ; Finally done with this interrupt - ;================================= - -done_interrupt: - + bne check_keyboard ;===================== ; Update time counter diff --git a/pt3_player/pt3_dumper.s b/pt3_player/pt3_dumper.s index 839d3a83..1edf4a24 100644 --- a/pt3_player/pt3_dumper.s +++ b/pt3_player/pt3_dumper.s @@ -8,8 +8,7 @@ PT3_LOC = $4000 -NUM_FILES = 15 - +PT3_USE_ZERO_PAGE = 1 ;============================= ; Setup @@ -231,20 +230,6 @@ new_song: ; Init Variables ;========================= - ; ? - - - ;=========================== - ; Print loading message - ;=========================== - -; lda #loading_message -; sta OUTH -; jsr print_cout - - ;=========================== ; Load in PT3 file ;=========================== @@ -365,30 +350,6 @@ filename_found: rts - ;=============================== - ; Increment file we want to load - ;=============================== -increment_file: - inc WHICH_FILE - lda WHICH_FILE - cmp #NUM_FILES - bne done_increment - lda #0 - sta WHICH_FILE -done_increment: - rts - - ;=============================== - ; Decrement file we want to load - ;=============================== -decrement_file: - dec WHICH_FILE - bpl done_decrement - lda #(NUM_FILES-1) - sta WHICH_FILE -done_decrement: - rts - ;=============== ; print cout @@ -422,21 +383,26 @@ FRAMEH: .byte $00 song_list: -; .asciiz "IT.PT3" ; ST + .asciiz "IT.PT3" ; ST ; .asciiz "CR.PT3" ; ST ; .asciiz "EA.PT3" ; ST ; .asciiz "RI.PT3" ; ST ; .asciiz "OO.PT3" ; ASM_34_35 ; .asciiz "DY.PT3" ; ASM_34_35 ; .asciiz "BH.PT3" ; PT_34_35 - .asciiz "CH.PT3" ; REAL_34_35 +; .asciiz "CH.PT3" ; REAL_34_35 ;========= ;routines ;========= .include "qkumba_rts.s" ;.include "../pt3_lib/pt3_lib.s" -.include "pt3_lib.s" + +.include "pt3_lib_core.s" +.include "pt3_lib_init.s" + + + ;============ ; dummy vars diff --git a/pt3_lib/pt3_lib.s b/pt3_player/pt3_lib_core.s similarity index 75% rename from pt3_lib/pt3_lib.s rename to pt3_player/pt3_lib_core.s index 416f9bad..1118b5ae 100644 --- a/pt3_lib/pt3_lib.s +++ b/pt3_player/pt3_lib_core.s @@ -21,7 +21,11 @@ ; + 2817 bytes -- eliminate pt3_version. Slighly faster but also bigger ; + 2828 bytes -- fix some correctness issues ; + 2776 bytes -- init vars with loop (slower, but more correct and smaller) -; + 2783 bytes -- fix vibrato code to work again +; + 2739 bytes -- qkumba's crazy SMC everywhere patch +; + 2418+143 = 2561 bytes -- move NOTE structs to page0 +; + 2423+143 = 2566 bytes -- fix vibrato code +; + 2554+143 = 2697 bytes -- generate all four tone tables +; + 2537+143 = 2680 bytes -- inline GetNoteFreq ; TODO ; move some of these flags to be bits rather than bytes? @@ -87,9 +91,20 @@ NOTE_TONE_SLIDE_TO_STEP =39 NOTE_STRUCT_SIZE=40 +.ifdef PT3_USE_ZERO_PAGE +note_a = $80 +note_b = $80+(NOTE_STRUCT_SIZE*1) +note_c = $80+(NOTE_STRUCT_SIZE*2) + +begin_vars=$80 +end_vars=$80+(NOTE_STRUCT_SIZE*3) + + +.else ; !PT3_USE_ZERO_PAGE begin_vars: note_a: ; reset? + .byte $0 ; NOTE_VOLUME ; 0 ; Y .byte $0 ; NOTE_TONE_SLIDING_L ; 1 ; Y .byte $0 ; NOTE_TONE_SLIDING_H ; 2 ; Y @@ -214,141 +229,13 @@ note_c: .byte $0 ; NOTE_TONE_DELTA_L .byte $0 ; NOTE_TONE_DELTA_H .byte $0 ; NOTE_TONE_SLIDE_TO_STEP - - -;==================================== -; Global vars that must be preserved - -current_subframe: .byte $0 -current_line: .byte $0 -current_pattern: .byte $0 -pt3_pattern_done: .byte $0 - -pt3_noise_period: .byte $0 ; Y -pt3_noise_add: .byte $0 ; Y - -pt3_envelope_period_l: .byte $0 ; Y -pt3_envelope_period_h: .byte $0 ; Y -pt3_envelope_slide_l: .byte $0 -pt3_envelope_slide_h: .byte $0 -pt3_envelope_slide_add_l:.byte $0 -pt3_envelope_slide_add_h:.byte $0 -pt3_envelope_add: .byte $0 -pt3_envelope_type: .byte $0 ; Y -pt3_envelope_type_old: .byte $0 -pt3_envelope_delay: .byte $0 -pt3_envelope_delay_orig:.byte $0 - -pt3_mixer_value: .byte $0 - end_vars: +.endif -;========================== -; local variables - -note_command: ; shared space with sample_b0 -sample_b0: .byte $0 -note_command_bottom: ; shared space with sample_b1 -sample_b1: .byte $0 - -temp_word_l: .byte $0 -temp_word_h: .byte $0 - -spec_command: .byte $0 - -freq_l: .byte $00 -freq_h: .byte $00 - -e_slide_amount: .byte $0 - -prev_note: .byte $0 -prev_sliding_l: .byte $0 -prev_sliding_h: .byte $0 - -z80_h: .byte $0 -z80_l: .byte $0 -z80_d: .byte $0 -z80_e: .byte $0 - - - - - ;=========================== - ; Load Ornament - ;=========================== - ; ornament value in A - ; note offset in X - - ; Ornament table pointers are 16-bits little endian - ; There are 16 of these pointers starting at $aa:$a9 - ; Our ornament starts at address (A*2)+that pointer - ; We point ORNAMENT_H:ORNAMENT_L to this - ; then we load the length/data values - ; and then leave ORNAMENT_H:ORNAMENT_L pointing to begnning of - ; the ornament data - - ; Optimization: - ; Loop and length only used once, can be located negative - ; from the pointer, but 6502 doesn't make addressing like that - ; easy. Can't self modify as channels A/B/C have own copies - ; of the var. - -load_ornament0: +load_ornament0_sample1: lda #0 ; 2 - -load_ornament: - - sty PT3_TEMP ; save Y value ; 3 - - ;pt3->ornament_patterns[i]= - ; (pt3->data[0xaa+(i*2)]<<8)|pt3->data[0xa9+(i*2)]; - - asl ; A*2 ; 2 - tay ; 2 - - ; a->ornament_pointer=pt3->ornament_patterns[a->ornament]; - - lda PT3_LOC+PT3_ORNAMENT_LOC_L,Y ; 4+ - sta ORNAMENT_L ; 3 - - lda PT3_LOC+PT3_ORNAMENT_LOC_L+1,Y ; 4+ - - ; we're assuming PT3 is loaded to a page boundary - - adc #>PT3_LOC ; 2 - sta ORNAMENT_H ; 3 - - lda #0 ; 2 - sta note_a+NOTE_ORNAMENT_POSITION,X ; 5 - - tay ; 2 - - ; Set the loop value - ; a->ornament_loop=pt3->data[a->ornament_pointer]; - lda (ORNAMENT_L),Y ; 5+ - sta note_a+NOTE_ORNAMENT_LOOP,X ; 5 - - ; Set the length value - ; a->ornament_length=pt3->data[a->ornament_pointer]; - iny ; 2 - lda (ORNAMENT_L),Y ; 5+ - sta note_a+NOTE_ORNAMENT_LENGTH,X ; 5 - - ; Set the pointer to the value past the length - - lda ORNAMENT_L ; 3 - adc #$2 ; 2 - sta note_a+NOTE_ORNAMENT_POINTER_L,X ; 5 - lda ORNAMENT_H ; 3 - adc #$0 ; 2 - sta note_a+NOTE_ORNAMENT_POINTER_H,X ; 5 - - ldy PT3_TEMP ; restore Y value ; 3 - - rts ; 6 - - ;============ - ; 83 + jsr load_ornament ; 6 + ; fall through ;=========================== ; Load Sample @@ -421,225 +308,80 @@ load_sample: ;============ ; 76 - ;==================================== - ; pt3_init_song - ;==================================== - ; -pt3_init_song: + ;=========================== + ; Load Ornament + ;=========================== + ; ornament value in A + ; note offset in X - lda #$0 - sta DONE_SONG - ; 3 - ldx #(end_vars-begin_vars) -zero_song_structs_loop: - dex - sta note_a,X - bne zero_song_structs_loop + ; Ornament table pointers are 16-bits little endian + ; There are 16 of these pointers starting at $aa:$a9 + ; Our ornament starts at address (A*2)+that pointer + ; We point ORNAMENT_H:ORNAMENT_L to this + ; then we load the length/data values + ; and then leave ORNAMENT_H:ORNAMENT_L pointing to begnning of + ; the ornament data + ; Optimization: + ; Loop and length only used once, can be located negative + ; from the pointer, but 6502 doesn't make addressing like that + ; easy. Can't self modify as channels A/B/C have own copies + ; of the var. - lda #$f ; 2 - sta note_a+NOTE_VOLUME ; 4 - sta note_b+NOTE_VOLUME ; 4 - sta note_c+NOTE_VOLUME ; 4 +load_ornament: -.if 0 - lda #$0 ; 2 - sta note_a+NOTE_TONE_SLIDING_L ; 4 - sta note_b+NOTE_TONE_SLIDING_L ; 4 - sta note_c+NOTE_TONE_SLIDING_L ; 4 - sta note_a+NOTE_TONE_SLIDING_H ; 4 - sta note_b+NOTE_TONE_SLIDING_H ; 4 - sta note_c+NOTE_TONE_SLIDING_H ; 4 - sta note_a+NOTE_ENABLED ; 4 - sta note_b+NOTE_ENABLED ; 4 - sta note_c+NOTE_ENABLED ; 4 - sta note_a+NOTE_ENVELOPE_ENABLED ; 4 - sta note_b+NOTE_ENVELOPE_ENABLED ; 4 - sta note_c+NOTE_ENVELOPE_ENABLED ; 4 - sta note_a+NOTE_SAMPLE_POSITION ; 4 - sta note_b+NOTE_SAMPLE_POSITION ; 4 - sta note_c+NOTE_SAMPLE_POSITION ; 4 + sty PT3_TEMP ; save Y value ; 3 - sta pt3_noise_period ; 4 - sta pt3_noise_add ; 4 - sta pt3_envelope_period_l ; 4 - sta pt3_envelope_period_h ; 4 - sta pt3_envelope_type ; 4 -.endif - lda #0 - ; default ornament/sample in A - ldx #(NOTE_STRUCT_SIZE*0) ; 2 - jsr load_ornament ; 6+93 - jsr load_sample1 ; 6+86 + ;pt3->ornament_patterns[i]= + ; (pt3->data[0xaa+(i*2)]<<8)|pt3->data[0xa9+(i*2)]; - ; default ornament/sample in B - ldx #(NOTE_STRUCT_SIZE*1) ; 2 - jsr load_ornament0 ; 6+93 - jsr load_sample1 ; 6+86 + asl ; A*2 ; 2 + tay ; 2 - ; default ornament/sample in C - ldx #(NOTE_STRUCT_SIZE*2) ; 2 - jsr load_ornament0 ; 6+93 - jsr load_sample1 ; 6+86 + ; a->ornament_pointer=pt3->ornament_patterns[a->ornament]; - ;======================= - ; load default speed + lda PT3_LOC+PT3_ORNAMENT_LOC_L,Y ; 4+ + sta ORNAMENT_L ; 3 - lda PT3_LOC+PT3_SPEED ; 4 - sta pt3_speed_smc+1 ; 4 + lda PT3_LOC+PT3_ORNAMENT_LOC_L+1,Y ; 4+ - ;======================= - ; load loop + ; we're assuming PT3 is loaded to a page boundary - lda PT3_LOC+PT3_LOOP ; 4 - sta pt3_loop_smc+1 ; 4 + adc #>PT3_LOC ; 2 + sta ORNAMENT_H ; 3 + lda #0 ; 2 + sta note_a+NOTE_ORNAMENT_POSITION,X ; 5 - ;====================== - ; calculate version - ldx #6 ; 2 - lda PT3_LOC+PT3_VERSION ; 4 - sec ; 2 - sbc #'0' ; 2 - cmp #9 ; 2 - bcs not_ascii_number ; bge ; 2/3 - tax ; 2 - -not_ascii_number: - - ; adjust version<6 SMC code in the slide code - - ; FIXME: I am sure there's a more clever way to do this - - lda #$2C ; BIT ; 2 - cpx #$6 ; 2 - bcc version_less_than_6 ; blt ; 3 - ; carry is set - adc #$1F ; BIT->JMP 2C->4C ; 2 -version_less_than_6: - sta version_smc ; 4 - -pick_volume_table: - - ;======================= - ; Pick which volume number, based on version - - ; if (PlParams.PT3.PT3_Version <= 4) - - cpx #5 ; 2 - - ; carry clear = 3.3/3.4 table - ; carry set = 3.5 table - - ;========================== - ; VolTableCreator - ;========================== - ; Creates the appropriate volume table - ; based on z80 code by Ivan Roshin ZXAYHOBETA/VTII10bG.asm - ; - - ; Called with carry==0 for 3.3/3.4 table - ; Called with carry==1 for 3.5 table - - ; 177f-1932 = 435 bytes, not that much better than 512 of lookup - - -VolTableCreator: - - ; Init initial variables - lda #$0 - sta z80_d - ldy #$11 - - ; Set up self modify - - ldx #$2A ; ROL for self-modify - bcs vol_type_35 - -vol_type_33: - - ; For older table, we set initial conditions a bit - ; different - - dey - tya - - ldx #$ea ; NOP for self modify - -vol_type_35: - sty z80_l ; l=16 or 17 - sta z80_e ; e=16 or 0 - stx vol_smc ; set the self-modify code - - ldy #16 ; skip first row, all zeros - ldx #16 ; c=16 -vol_outer: - clc ; add HL,DE - lda z80_l - adc z80_e - sta z80_e - lda #0 - adc z80_d - sta z80_d ; carry is important - - ; sbc hl,hl - lda #0 - adc #$ff - eor #$ff - -vol_write: - sta z80_h - pha - -vol_inner: - pla - pha - -vol_smc: - nop ; nop or ROL depending - - lda z80_h - - adc #$0 ; a=a+carry; - - sta VolumeTable,Y - iny - - pla ; add HL,DE - adc z80_e - pha - lda z80_h - adc z80_d - sta z80_h - - inx ; inc C - txa ; a=c - and #$f - bne vol_inner - - - pla - - lda z80_e ; a=e - cmp #$77 - bne vol_m3 - - inc z80_e - -vol_m3: - txa ; a=c - bne vol_outer - -vol_done: - rts + tay ; 2 + ; Set the loop value + ; a->ornament_loop=pt3->data[a->ornament_pointer]; + lda (ORNAMENT_L),Y ; 5+ + sta note_a+NOTE_ORNAMENT_LOOP,X ; 5 + ; Set the length value + ; a->ornament_length=pt3->data[a->ornament_pointer]; + iny ; 2 + lda (ORNAMENT_L),Y ; 5+ + sta note_a+NOTE_ORNAMENT_LENGTH,X ; 5 + ; Set the pointer to the value past the length + lda ORNAMENT_L ; 3 + adc #$2 ; 2 + sta note_a+NOTE_ORNAMENT_POINTER_L,X ; 5 + lda ORNAMENT_H ; 3 + adc #$0 ; 2 + sta note_a+NOTE_ORNAMENT_POINTER_H,X ; 5 + ldy PT3_TEMP ; restore Y value ; 3 + rts ; 6 + ;============ + ; 83 @@ -676,12 +418,12 @@ note_enabled: ; b0 = pt3->data[a->sample_pointer + a->sample_position * 4]; lda (SAMPLE_L),Y ; 5+ - sta sample_b0 ; 4 + sta sample_b0_smc+1 ; 4 ; b1 = pt3->data[a->sample_pointer + a->sample_position * 4 + 1]; iny ; 2 lda (SAMPLE_L),Y ; 5+ - sta sample_b1 ; 4 + sta sample_b1_smc+1 ; 4 ; a->tone = pt3->data[a->sample_pointer + a->sample_position*4+2]; ; a->tone+=(pt3->data[a->sample_pointer + a->sample_position*4+3])<<8; @@ -700,7 +442,7 @@ note_enabled: ; Accumulate tone if set ; (if sample_b1 & $40) - bit sample_b1 + bit sample_b1_smc+1 bvc no_accum ; (so, if b1&0x40 is zero, skip it) sta note_a+NOTE_TONE_ACCUMULATOR_H,X @@ -732,25 +474,27 @@ note_not_too_high: ; w = GetNoteFreq(j,pt3->frequency_table); - jsr GetNoteFreq + tay ; for GetNoteFreq later ; a->tone = (a->tone + a->tone_sliding + w) & 0xfff; clc - ldy note_a+NOTE_TONE_SLIDING_L,X - tya + lda note_a+NOTE_TONE_SLIDING_L,X adc note_a+NOTE_TONE_L,X - sta note_a+NOTE_TONE_L,X + sta temp_word_l1_smc+1 + lda note_a+NOTE_TONE_H,X adc note_a+NOTE_TONE_SLIDING_H,X - sta note_a+NOTE_TONE_H,X + sta temp_word_h1_smc+1 clc ;;can be removed if ADC SLIDING_H cannot overflow - lda note_a+NOTE_TONE_L,X - adc freq_l +temp_word_l1_smc: + lda #$d1 + adc NoteTable_low,Y ; GetNoteFreq sta note_a+NOTE_TONE_L,X - lda note_a+NOTE_TONE_H,X - adc freq_h +temp_word_h1_smc: + lda #$d1 + adc NoteTable_high,Y ; GetNoteFreq and #$0f sta note_a+NOTE_TONE_H,X @@ -767,10 +511,10 @@ note_not_too_high: ; a->tone_sliding+=a->tone_slide_step clc ;;can be removed if ADC freq_h cannot overflow - tya + lda note_a+NOTE_TONE_SLIDING_L,X adc note_a+NOTE_TONE_SLIDE_STEP_L,X sta note_a+NOTE_TONE_SLIDING_L,X - tay + tay ; save NOTE_TONE_SLIDING_L in y lda note_a+NOTE_TONE_SLIDING_H,X adc note_a+NOTE_TONE_SLIDE_STEP_H,X sta note_a+NOTE_TONE_SLIDING_H,X @@ -791,8 +535,8 @@ check1: ; (a->tone_sliding <= a->tone_delta) || ; 16 bit signed compare - tya ; NUM1-NUM2 - cmp note_a+NOTE_TONE_DELTA_L,X ; + tya ; y has NOTE_TONE_SLIDING_L + cmp note_a+NOTE_TONE_DELTA_L,X ; NUM1-NUM2 lda note_a+NOTE_TONE_SLIDING_H,X sbc note_a+NOTE_TONE_DELTA_H,X bvc sc_loser1 ; N eor V @@ -801,7 +545,7 @@ sc_loser1: bmi slide_to_note ; then A (signed) < NUM (signed) and BMI will branch ; equals case - tya + tya ; y has NOTE_TONE_SLIDING_L cmp note_a+NOTE_TONE_DELTA_L,X bne check2 lda note_a+NOTE_TONE_SLIDING_H,X @@ -815,8 +559,8 @@ check2: ; (a->tone_sliding >= a->tone_delta) ; 16 bit signed compare - tya ; NUM1-NUM2 - cmp note_a+NOTE_TONE_DELTA_L,X ; + tya ; y has NOTE_TONE_SLIDING_L + cmp note_a+NOTE_TONE_DELTA_L,X ; num1-num2 lda note_a+NOTE_TONE_SLIDING_H,X sbc note_a+NOTE_TONE_DELTA_H,X bvc sc_loser2 ; N eor V @@ -842,7 +586,8 @@ no_tone_sliding: calc_amplitude: ; get base value from the sample (bottom 4 bits of sample_b1) - lda sample_b1 ; a->amplitude= (b1 & 0xf); +sample_b1_smc: + lda #$d1 ; a->amplitude= (b1 & 0xf); and #$f ;======================================== @@ -850,7 +595,7 @@ calc_amplitude: ; adjust amplitude sliding - bit sample_b0 ; if ((b0 & 0x80)!=0) { + bit sample_b0_smc+1 ; if ((b0 & 0x80)!=0) { bpl done_amp_sliding ; so if top bit not set, skip tay @@ -922,7 +667,7 @@ done_clamp_amplitude: asl ; 2 asl ; 2 note_amp_smc: - ora #0 ; 4+ + ora #$d1 ; 4+ tay ; 2 lda VolumeTable,Y ; 4+ @@ -937,7 +682,8 @@ check_envelope_enable: ; if (((b0 & 0x1) == 0) && ( a->envelope_enabled)) { - lda sample_b0 +sample_b0_smc: + lda #$d1 lsr tay bcs envelope_slide @@ -959,12 +705,12 @@ envelope_slide: ; Envelope slide ; If b1 top bits are 10 or 11 - lda sample_b0 + lda sample_b0_smc+1 asl asl asl ; b0 bit 5 to carry flag lda #$20 - bit sample_b1 ; b1 bit 7 to sign flag, bit 5 to zero flag + bit sample_b1_smc+1 ; b1 bit 7 to sign flag, bit 5 to zero flag php bpl else_noise_slide ; if ((b1 & 0x80) != 0) { tya @@ -980,7 +726,7 @@ envelope_slide_down: ; j = ((b0>>1)|0xF0) + a->envelope_sliding adc note_a+NOTE_ENVELOPE_SLIDING,X - sta e_slide_amount ; j + sta e_slide_amount_smc+1 ; j envelope_slide_done: @@ -995,9 +741,10 @@ last_envelope: ; pt3->envelope_add+=j; clc - lda e_slide_amount - adc pt3_envelope_add - sta pt3_envelope_add +e_slide_amount_smc: + lda #$d1 + adc pt3_envelope_add_smc+1 + sta pt3_envelope_add_smc+1 jmp noise_slide_done ; skip else @@ -1009,7 +756,7 @@ else_noise_slide: tya clc adc note_a+NOTE_NOISE_SLIDING,X - sta pt3_noise_add + sta pt3_noise_add_smc+1 plp beq noise_slide_done ; if ((b1 & 0x20) != 0) { @@ -1021,11 +768,12 @@ noise_slide_done: ;====================== ; set mixer - lda sample_b1 ; pt3->mixer_value = ((b1 >>1) & 0x48) | pt3->mixer_value; + lda sample_b1_smc+1 ; pt3->mixer_value = ((b1 >>1) & 0x48) | pt3->mixer_value; lsr and #$48 - ora pt3_mixer_value - sta pt3_mixer_value + + ora PT3_MIXER_VAL ; 3 + sta PT3_MIXER_VAL ; 3 ;======================== @@ -1061,7 +809,7 @@ done_note: ; set mixer value ; this is a bit complex (from original code) ; after 3 calls it is set up properly - lsr pt3_mixer_value + lsr PT3_MIXER_VAL handle_onoff: ldy note_a+NOTE_ONOFF,X ;if (a->onoff>0) { @@ -1071,7 +819,7 @@ handle_onoff: bne put_offon ; if (a->onoff==0) { lda note_a+NOTE_ENABLED,X - eor #$1 ; toggle + eor #$1 ; toggle note_enabled sta note_a+NOTE_ENABLED,X beq do_offon @@ -1081,8 +829,12 @@ do_onoff: do_offon: ldy note_a+NOTE_OFFON_DELAY,X ; else a->onoff=a->offon_delay; put_offon: - tya - sta note_a+NOTE_ONOFF,X +.ifdef PT3_USE_ZERO_PAGE + sty note_a+NOTE_ONOFF,X +.else + lda note_a+NOTE_ONOFF,X + tay +.endif done_onoff: @@ -1143,7 +895,7 @@ decode_note: ; Init vars ldy #0 ; 2 - sty spec_command ; 4 + sty spec_command_smc+1 ; 4 ; Skip decode if note still running lda note_a+NOTE_LEN_COUNT,X ; 4+ @@ -1153,12 +905,12 @@ decode_note: keep_decoding: lda note_a+NOTE_NOTE,X ; store prev note ; 4+ - sta prev_note ; 4 + sta prev_note_smc+1 ; 4 lda note_a+NOTE_TONE_SLIDING_H,X ; store prev sliding ; 4+ - sta prev_sliding_h ; 4 + sta prev_sliding_h_smc+1 ; 4 lda note_a+NOTE_TONE_SLIDING_L,X ; 4+ - sta prev_sliding_l ; 4 + sta prev_sliding_l_smc+1 ; 4 ;============ @@ -1175,10 +927,12 @@ note_decode_loop: ;===> ; get next value lda (PATTERN_L),Y ; 5+ - sta note_command ; save termporarily ; 4 + sta note_command_smc+1 ; save termporarily ; 4 and #$0f ; 2 - sta note_command_bottom ; 4 - lda note_command ; 4 + sta note_command_bottom_smc+1 ; 4 + +note_command_smc: + lda #$d1 ; 2 ; FIXME: use a jump table?? ; further reflection, that would require 32-bytes of addresses @@ -1196,7 +950,8 @@ decode_case_0X: ; $0X set special effect ;============================== ; -1 - lda note_command_bottom ; 4 +note_command_bottom_smc: + lda #$d1 ; 2 ; we can always store spec as 0 means no spec @@ -1204,25 +959,20 @@ decode_case_0X: ; Doesn't seem to happen in practice ; But AY_emul has code to handle it - sta spec_command ; 4 + sta spec_command_smc+1 ; 4 bne decode_case_0X_not_zero ; 2/3 ;============= - ; 12 + ; 8 ; 00 case ; means end of pattern ; -1 sta note_a+NOTE_LEN_COUNT,X ; len_count=0; ; 5 - dec pt3_pattern_done ; 6 + dec pt3_pattern_done_smc+1 ; 6 jmp note_done_decoding ; 3 -decode_case_0X_not_zero: - - jmp done_decode_loop ; 3 - - decode_case_1X: ;============================== ; $1X -- Set Envelope Type @@ -1234,7 +984,7 @@ decode_case_1X: ; 5 ; -1 - lda note_command_bottom ; 4 + lda note_command_bottom_smc+1 ; 4 bne decode_case_not_10 ; 3 decode_case_10: @@ -1256,6 +1006,8 @@ decode_case_1x_common: lda #0 ; 2 sta note_a+NOTE_ORNAMENT_POSITION,X ; ornament_position=0 ; 5 +decode_case_0X_not_zero: + jmp done_decode_loop ; 3 decode_case_2X: @@ -1267,13 +1019,13 @@ decode_case_3X: cmp #$40 ; 2 bcs decode_case_4X ; branch greater/equal ; 3 ; -1 - lda note_command ; 3 + lda note_command_smc+1 ; 4 adc #$e0 ; same as subtract $20 ; 2 - sta pt3_noise_period ; 3 + sta pt3_noise_period_smc+1 ; 3 jmp done_decode_loop ; 3 ;=========== - ; 15 + ; 16 decode_case_4X: ;============================== @@ -1282,7 +1034,7 @@ decode_case_4X: ; cmp #$40 ; already set ; bne decode_case_5X ; 3 ; -1 - lda note_command_bottom ; set ornament to bottom nibble ; 4 + lda note_command_bottom_smc+1; set ornament to bottom nibble; 4 jsr load_ornament ; 6+93 jmp done_decode_loop ; 3 @@ -1297,7 +1049,7 @@ decode_case_5X: bcs decode_case_bX ; branch greater/equal ; 3 ; -1 - lda note_command ; 4 + lda note_command_smc+1 ; 4 adc #$b0 ; 2 sta note_a+NOTE_NOTE,X ; note=(current_val-0x50); ; 5 @@ -1316,7 +1068,7 @@ decode_case_bX: ; cmp #$b0 ; already set from before bne decode_case_cX ; 3 ; -1 - lda note_command_bottom ; 4 + lda note_command_bottom_smc+1 ; 4 beq decode_case_b0 ; 3 ; -1 sbc #1 ; envelope_type=(current_val&0xf)-1; ; 2 @@ -1353,7 +1105,7 @@ decode_case_cX: cmp #$c0 ; check top nibble $C ; 2 bne decode_case_dX ; 3 ; -1 - lda note_command_bottom ; 4 + lda note_command_bottom_smc+1 ; 4 bne decode_case_cx_not_c0 ; 3 ; -1 decode_case_c0: @@ -1380,7 +1132,7 @@ decode_case_dX: beq decode_case_fX ; 3 ; -1 - lda note_command ; 4 + lda note_command_smc+1 ; 4 sec ; 2 sbc #$d0 ; 2 beq note_done_decoding ; 3 @@ -1407,7 +1159,7 @@ decode_case_fX: sta note_a+NOTE_ENVELOPE_ENABLED,X ; 5 ; Set ornament to low byte of command - lda note_command_bottom ; 4 + lda note_command_bottom_smc+1 ; 4 jsr load_ornament ; ornament to load in A ; 6+? ; Get next byte @@ -1437,7 +1189,8 @@ note_done_decoding: ; In the same order they appear. We don't bother? handle_effects: - lda spec_command ; 4 +spec_command_smc: + lda #$d1 ; 2 ;============================== ; Effect #1 -- Tone Down @@ -1523,30 +1276,34 @@ skip_step_inc1: ; a->tone_delta=GetNoteFreq(a->note,pt3)- ; GetNoteFreq(prev_note,pt3); - lda note_a+NOTE_NOTE,X - jsr GetNoteFreq - lda freq_l - sta temp_word_l - lda freq_h - sta temp_word_h + sty PT3_TEMP ; save Y +prev_note_smc: + ldy #$d1 + lda NoteTable_low,Y ; GetNoteFreq + sta temp_word_l2_smc+1 + lda NoteTable_high,Y ; GetNoteFreq + sta temp_word_h2_smc+1 - lda prev_note - jsr GetNoteFreq + ldy note_a+NOTE_NOTE,X + lda NoteTable_low,Y ; GetNoteFreq sec - lda temp_word_l - sbc freq_l +temp_word_l2_smc: + sbc #$d1 sta note_a+NOTE_TONE_DELTA_L,X - lda temp_word_h - sbc freq_h + lda NoteTable_high,Y ; GetNoteFreq +temp_word_h2_smc: + sbc #$d1 sta note_a+NOTE_TONE_DELTA_H,X ; a->slide_to_note=a->note; lda note_a+NOTE_NOTE,X sta note_a+NOTE_SLIDE_TO_NOTE,X + ldy PT3_TEMP ; restore Y + ; a->note=prev_note; - lda prev_note + lda prev_note_smc+1 sta note_a+NOTE_NOTE,X ; implement file version 6 and above slide behavior @@ -1554,9 +1311,11 @@ skip_step_inc1: version_smc: jmp weird_version ; (JMP to BIT via smc) ; 3 - lda prev_sliding_l +prev_sliding_l_smc: + lda #$d1 sta note_a+NOTE_TONE_SLIDING_L,X - lda prev_sliding_h +prev_sliding_h_smc: + lda #$d1 sta note_a+NOTE_TONE_SLIDING_H,X weird_version: @@ -1568,7 +1327,7 @@ weird_version: sbc note_a+NOTE_TONE_SLIDING_L,X lda note_a+NOTE_TONE_DELTA_H,X sbc note_a+NOTE_TONE_SLIDING_H,X - bpl no_need + bpl no_effect ; a->tone_slide_step = -a->tone_slide_step; @@ -1582,8 +1341,6 @@ weird_version: adc #$0 sta note_a+NOTE_TONE_SLIDE_STEP_H,X -no_need: - jmp no_effect ;============================== @@ -1645,18 +1402,18 @@ effect_8: ; delay lda (PATTERN_L),Y ; load byte, set as speed iny - sta pt3_envelope_delay - sta pt3_envelope_delay_orig + sta pt3_envelope_delay_smc+1 + sta pt3_envelope_delay_orig_smc+1 ; low value lda (PATTERN_L),Y ; load byte, set as low iny - sta pt3_envelope_slide_add_l + sta pt3_envelope_slide_add_l_smc+1 ; high value lda (PATTERN_L),Y ; load byte, set as high iny - sta pt3_envelope_slide_add_h + sta pt3_envelope_slide_add_h_smc+1 bne no_effect ; branch always @@ -1698,30 +1455,30 @@ no_effect: set_envelope: - sta pt3_envelope_type ; 4 + sta pt3_envelope_type_smc+1 ; 4 ; give fake old to force update? maybe only needed if printing? ; pt3->envelope_type_old=0x78; lda #$78 ; 2 - sta pt3_envelope_type_old ; 4 + sta pt3_envelope_type_old_smc+1 ; 4 ; get next byte iny ; 2 lda (PATTERN_L),Y ; 5+ - sta pt3_envelope_period_h ; 4 + sta pt3_envelope_period_h_smc+1 ; 4 iny ; 2 lda (PATTERN_L),Y ; 5+ - sta pt3_envelope_period_l ; 4 + sta pt3_envelope_period_l_smc+1 ; 4 lda #1 ; 2 sta note_a+NOTE_ENVELOPE_ENABLED,X ; envelope_enabled=1 ; 5 lsr ; 2 sta note_a+NOTE_ORNAMENT_POSITION,X ; ornament_position=0 ; 5 - sta pt3_envelope_delay ; envelope_delay=0 ; 4 - sta pt3_envelope_slide_l ; envelope_slide=0 ; 4 - sta pt3_envelope_slide_h ; 4 + sta pt3_envelope_delay_smc+1 ; envelope_delay=0 ; 4 + sta pt3_envelope_slide_l_smc+1 ; envelope_slide=0 ; 4 + sta pt3_envelope_slide_h_smc+1 ; 4 rts ; 6 ;=========== @@ -1769,7 +1526,8 @@ is_done: pt3_set_pattern: ; Lookup current pattern in pattern table - ldy current_pattern ; 4 +current_pattern_smc: + ldy #$d1 ; 2 lda PT3_LOC+PT3_PATTERN_TABLE,Y ; 4+ ; if value is $FF we are at the end of the song @@ -1777,7 +1535,7 @@ pt3_set_pattern: beq is_done ; 2/3 ;============ - ; 22 if end + ; 20 if end not_done: @@ -1823,12 +1581,12 @@ not_done: ; clear out the noise channel lda #0 ; 2 - sta pt3_noise_period ; 4 + sta pt3_noise_period_smc+1 ; 4 ; Set all three channels as active ; FIXME: num_channels, may need to be 6 if doing 6-channel pt3? lda #3 ; 2 - sta pt3_pattern_done ; 4 + sta pt3_pattern_done_smc+1 ; 4 rts ; 6 @@ -1844,12 +1602,12 @@ not_done: ; pattern done early! early_end: - inc current_pattern ; increment pattern ; 6 - sta current_line ; 4 - sta current_subframe ; 4 + inc current_pattern_smc+1 ; increment pattern ; 6 + sta current_line_smc+1 ; 4 + sta current_subframe_smc+1 ; 4 check_subframe: - lda current_subframe ; 4 + lda current_subframe_smc+1 ; 4 bne pattern_good ; 2/3 ; load a new pattern in @@ -1864,48 +1622,51 @@ pt3_make_frame: ; see if we need a new pattern ; we do if line==0 and subframe==0 ; allow fallthrough where possible - lda current_line ; 4 +current_line_smc: + lda #$d1 ; 2 beq check_subframe ; 2/3 pattern_good: ; see if we need a new line - lda current_subframe ; 4 +current_subframe_smc: + lda #$d1 ; 2 bne line_good ; 2/3 ; decode a new line jsr pt3_decode_line ; 6+? ; check if pattern done early - lda pt3_pattern_done ; 4 +pt3_pattern_done_smc: + lda #$d1 ; 2 beq early_end ; 2/3 line_good: ; Increment everything - inc current_subframe ; subframe++ ; 6 - lda current_subframe ; 4 + inc current_subframe_smc+1 ; subframe++ ; 6 + lda current_subframe_smc+1 ; 4 ; if we hit pt3_speed, move to next pt3_speed_smc: - eor #0 ; 2 + eor #$d1 ; 2 bne do_frame ; 2/3 next_line: - sta current_subframe ; reset subframe to 0 ; 4 + sta current_subframe_smc+1 ; reset subframe to 0 ; 4 - inc current_line ; and increment line ; 6 - lda current_line ; 4 + inc current_line_smc+1 ; and increment line ; 6 + lda current_line_smc+1 ; 4 eor #64 ; always end at 64. ; 2 bne do_frame ; is this always needed? ; 2/3 next_pattern: - sta current_line ; reset line to 0 ; 4 + sta current_line_smc+1 ; reset line to 0 ; 4 - inc current_pattern ; increment pattern ; 6 + inc current_pattern_smc+1 ; increment pattern ; 6 do_frame: ; AY-3-8910 register summary @@ -1920,11 +1681,11 @@ do_frame: ; R13 = Envelope Shape, 0xff means don't write ; R14/R15 = I/O (ignored) - lda #0 ; needed ; 2 - sta pt3_mixer_value ; 4 - sta pt3_envelope_add ; 4 + ldx #0 ; needed ; 2 + stx PT3_MIXER_VAL ; 3 + stx pt3_envelope_add_smc+1 ; 4 - ldx #(NOTE_STRUCT_SIZE*0) ; Note A ; 2 + ;;ldx #(NOTE_STRUCT_SIZE*0) ; Note A ; 2 jsr calculate_note ; 6+? ldx #(NOTE_STRUCT_SIZE*1) ; Note B ; 2 jsr calculate_note ; 6+? @@ -2064,8 +1825,10 @@ no_scale_c: ; Noise ; frame[6]= (pt3->noise_period+pt3->noise_add)&0x1f; clc ; 2 - lda pt3_noise_period ; 4 - adc pt3_noise_add ; 4 +pt3_noise_period_smc: + lda #$d1 ; 2 +pt3_noise_add_smc: + adc #$d1 ; 2 and #$1f ; 2 sta AY_REGISTERS+6 ; 3 @@ -2096,36 +1859,40 @@ no_scale_n: ;======================= ; Mixer - lda pt3_mixer_value ; 4 - sta AY_REGISTERS+7 ; 3 + ; PT3_MIXER_VAL is already in AY_REGISTERS+7 ;======================= ; Amplitudes - lda note_a+NOTE_AMPLITUDE ; 4 + lda note_a+NOTE_AMPLITUDE ; 3 sta AY_REGISTERS+8 ; 3 - lda note_b+NOTE_AMPLITUDE ; 4 + lda note_b+NOTE_AMPLITUDE ; 3 sta AY_REGISTERS+9 ; 3 - lda note_c+NOTE_AMPLITUDE ; 4 + lda note_c+NOTE_AMPLITUDE ; 3 sta AY_REGISTERS+10 ; 3 ;====================================== ; Envelope period ; result=period+add+slide (16-bits) clc ; 2 - lda pt3_envelope_period_l ; 4 - adc pt3_envelope_add ; 4 +pt3_envelope_period_l_smc: + lda #$d1 ; 2 +pt3_envelope_add_smc: + adc #$d1 ; 2 tay ; 2 - lda pt3_envelope_period_h ; 4 +pt3_envelope_period_h_smc: + lda #$d1 ; 2 adc #0 ; 2 - sta temp_word_h ; 4 + tax ; 2 clc ; 2 tya ; 2 - adc pt3_envelope_slide_l ; 4 +pt3_envelope_slide_l_smc: + adc #$d1 ; 2 sta AY_REGISTERS+11 ; 3 - lda temp_word_h ; 4 - adc pt3_envelope_slide_h ; 4 + txa ; 2 +pt3_envelope_slide_h_smc: + adc #$d1 ; 2 sta AY_REGISTERS+12 ; 3 convert_177_smc5: @@ -2168,9 +1935,11 @@ no_scale_e: ;======================== ; Envelope shape - lda pt3_envelope_type ; 4 - cmp pt3_envelope_type_old ; 4 - sta pt3_envelope_type_old ; copy old to new ; 4 +pt3_envelope_type_smc: + lda #$d1 ; 2 +pt3_envelope_type_old_smc: + cmp #$d1 ; 2 + sta pt3_envelope_type_old_smc+1; copy old to new ; 4 bne envelope_diff ; 2/3 envelope_same: lda #$ff ; if same, store $ff ; 2 @@ -2183,166 +1952,39 @@ envelope_diff: ; end-of-frame envelope update ;============================== - lda pt3_envelope_delay ; 4 +pt3_envelope_delay_smc: + lda #$d1 ; 2 beq done_do_frame ; assume can't be negative? ; 2/3 ; do this if envelope_delay>0 - dec pt3_envelope_delay ; 6 + dec pt3_envelope_delay_smc+1 ; 6 bne done_do_frame ; 2/3 ; only do if we hit 0 - lda pt3_envelope_delay_orig ; reset envelope delay ; 4 - sta pt3_envelope_delay ; 4 +pt3_envelope_delay_orig_smc: + lda #$d1 ; reset envelope delay ; 2 + sta pt3_envelope_delay_smc+1 ; 4 clc ; 16-bit add ; 2 - lda pt3_envelope_slide_l ; 4 - adc pt3_envelope_slide_add_l ; 4 - sta pt3_envelope_slide_l ; 4 - lda pt3_envelope_slide_h ; 4 - adc pt3_envelope_slide_add_h ; 4 - sta pt3_envelope_slide_h ; 4 + lda pt3_envelope_slide_l_smc+1 ; 4 +pt3_envelope_slide_add_l_smc: + adc #$d1 ; 2 + sta pt3_envelope_slide_l_smc+1 ; 4 + lda pt3_envelope_slide_h_smc+1 ; 4 +pt3_envelope_slide_add_h_smc: + adc #$d1 ; 2 + sta pt3_envelope_slide_h_smc+1 ; 4 done_do_frame: rts ; 6 - ;====================================== - ; GetNoteFreq - ;====================================== - ; Return frequency from lookup table - ; Which note is in A - ; return in freq_l/freq_h - - ; FIXME: self modify code -GetNoteFreq: - - sty PT3_TEMP ; 3 - - tay ; 2 - lda PT3_LOC+PT3_HEADER_FREQUENCY ; 4 - cmp #1 ; 2 - bne freq_table_2 ; 2/3 - - lda PT3NoteTable_ST_high,Y ; 4+ - sta freq_h ; 4 - lda PT3NoteTable_ST_low,Y ; 4+ - sta freq_l ; 4 - - ldy PT3_TEMP ; 3 - rts ; 6 - ;=========== - ; 40 - - -freq_table_2: - lda PT3NoteTable_ASM_34_35_high,Y ; 4+ - sta freq_h ; 4 - lda PT3NoteTable_ASM_34_35_low,Y ; 4+ - sta freq_l ; 4 - - ldy PT3_TEMP ; 3 - rts ; 6 - ;=========== - ; 41 - - -; Table #1 of Pro Tracker 3.3x - 3.5x -PT3NoteTable_ST_high: -.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09 -.byte $09,$08,$08,$07,$07,$07,$06,$06 -.byte $05,$05,$05,$04,$04,$04,$04,$03 -.byte $03,$03,$03,$03,$02,$02,$02,$02 -.byte $02,$02,$02,$01,$01,$01,$01,$01 -.byte $01,$01,$01,$01,$01,$01,$01,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 - -PT3NoteTable_ST_low: -.byte $F8,$10,$60,$80,$D8,$28,$88,$F0 -.byte $60,$E0,$58,$E0,$7C,$08,$B0,$40 -.byte $EC,$94,$44,$F8,$B0,$70,$2C,$FD -.byte $BE,$84,$58,$20,$F6,$CA,$A2,$7C -.byte $58,$38,$16,$F8,$DF,$C2,$AC,$90 -.byte $7B,$65,$51,$3E,$2C,$1C,$0A,$FC -.byte $EF,$E1,$D6,$C8,$BD,$B2,$A8,$9F -.byte $96,$8E,$85,$7E,$77,$70,$6B,$64 -.byte $5E,$59,$54,$4F,$4B,$47,$42,$3F -.byte $3B,$38,$35,$32,$2F,$2C,$2A,$27 -.byte $25,$23,$21,$1F,$1D,$1C,$1A,$19 -.byte $17,$16,$15,$13,$12,$11,$10,$0F - - -; Table #2 of Pro Tracker 3.4x - 3.5x -PT3NoteTable_ASM_34_35_high: -.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08 -.byte $08,$07,$07,$06,$06,$06,$05,$05 -.byte $05,$04,$04,$04,$04,$03,$03,$03 -.byte $03,$03,$02,$02,$02,$02,$02,$02 -.byte $02,$01,$01,$01,$01,$01,$01,$01 -.byte $01,$01,$01,$01,$01,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 -.byte $00,$00,$00,$00,$00,$00,$00,$00 - -PT3NoteTable_ASM_34_35_low: -.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8 -.byte $3B,$C5,$55,$EC,$88,$2A,$D2,$7E -.byte $2F,$E5,$9E,$5C,$1D,$E2,$AB,$76 -.byte $44,$15,$E9,$BF,$98,$72,$4F,$2E -.byte $0F,$F1,$D5,$BB,$A2,$8B,$74,$60 -.byte $4C,$39,$28,$17,$07,$F9,$EB,$DD -.byte $D1,$C5,$BA,$B0,$A6,$9D,$94,$8C -.byte $84,$7C,$75,$6F,$69,$63,$5D,$58 -.byte $53,$4E,$4A,$46,$42,$3E,$3B,$37 -.byte $34,$31,$2F,$2C,$29,$27,$25,$23 -.byte $21,$1F,$1D,$1C,$1A,$19,$17,$16 -.byte $15,$14,$12,$11,$10,$0F,$0E,$0D - - -;PT3VolumeTable_33_34: -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 -;.byte $0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2 -;.byte $0,$0,$0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3 -;.byte $0,$0,$0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4 -;.byte $0,$0,$0,$1,$1,$1,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 -;.byte $0,$0,$0,$1,$1,$2,$2,$3,$3,$3,$4,$4,$5,$5,$6,$6 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$5,$5,$6,$6,$7,$7,$8 -;.byte $0,$0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$6,$7,$8,$8,$9 -;.byte $0,$0,$1,$2,$2,$3,$4,$4,$5,$6,$6,$7,$8,$8,$9,$A -;.byte $0,$0,$1,$2,$3,$3,$4,$5,$6,$6,$7,$8,$9,$9,$A,$B -;.byte $0,$0,$1,$2,$3,$4,$4,$5,$6,$7,$8,$8,$9,$A,$B,$C -;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D -;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F - -;PT3VolumeTable_35: -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 -;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 -;.byte $0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1,$2,$2,$2,$2 -;.byte $0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2,$3,$3,$3 -;.byte $0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3,$4,$4 -;.byte $0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 -;.byte $0,$0,$1,$1,$2,$2,$2,$3,$3,$4,$4,$4,$5,$5,$6,$6 -;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 -;.byte $0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7,$8 -;.byte $0,$1,$1,$2,$2,$3,$4,$4,$5,$5,$6,$7,$7,$8,$8,$9 -;.byte $0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$7,$7,$8,$9,$9,$A -;.byte $0,$1,$1,$2,$3,$4,$4,$5,$6,$7,$7,$8,$9,$A,$A,$B -;.byte $0,$1,$2,$2,$3,$4,$5,$6,$6,$7,$8,$9,$A,$A,$B,$C -;.byte $0,$1,$2,$3,$3,$4,$5,$6,$7,$8,$9,$A,$A,$B,$C,$D -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D,$E -;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F - - +; note, you might have slightly better performance if these are aligned +; so that loads don't have to cross page boundaries +NoteTable_high: + .res 96,0 +NoteTable_low: + .res 96,0 VolumeTable: .res 256,0 diff --git a/pt3_player/pt3_lib_init.s b/pt3_player/pt3_lib_init.s new file mode 100644 index 00000000..e2f7e448 --- /dev/null +++ b/pt3_player/pt3_lib_init.s @@ -0,0 +1,575 @@ +; pt3_lib_init.s + +; Initialize a song + +; this is done before song starts playing so it is not +; as performance / timing critical + + ;==================================== + ; pt3_init_song + ;==================================== + ; +pt3_init_song: + + lda #$0 + sta DONE_SONG ; 3 + ldx #(end_vars-begin_vars) +zero_song_structs_loop: + dex + sta note_a,X + bne zero_song_structs_loop + + sta pt3_noise_period_smc+1 ; 4 + sta pt3_noise_add_smc+1 ; 4 + + sta pt3_envelope_period_l_smc+1 ; 4 + sta pt3_envelope_period_h_smc+1 ; 4 + sta pt3_envelope_slide_l_smc+1 ; 4 + sta pt3_envelope_slide_h_smc+1 ; 4 + sta pt3_envelope_slide_add_l_smc+1 ; 4 + sta pt3_envelope_slide_add_h_smc+1 ; 4 + sta pt3_envelope_add_smc+1 ; 4 + sta pt3_envelope_type_smc+1 ; 4 + sta pt3_envelope_type_old_smc+1 ; 4 + sta pt3_envelope_delay_smc+1 ; 4 + sta pt3_envelope_delay_orig_smc+1 ; 4 + + sta PT3_MIXER_VAL ; 3 + + sta current_pattern_smc+1 ; 4 + sta current_line_smc+1 ; 4 + sta current_subframe_smc+1 ; 4 + + lda #$f ; 2 + sta note_a+NOTE_VOLUME ; 4 + sta note_b+NOTE_VOLUME ; 4 + sta note_c+NOTE_VOLUME ; 4 + + ; default ornament/sample in A + ; X is zero coming in here + ;ldx #(NOTE_STRUCT_SIZE*0) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ; default ornament/sample in B + ldx #(NOTE_STRUCT_SIZE*1) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ; default ornament/sample in C + ldx #(NOTE_STRUCT_SIZE*2) ; 2 + jsr load_ornament0_sample1 ; 6+93 + + ;======================= + ; load default speed + + lda PT3_LOC+PT3_SPEED ; 4 + sta pt3_speed_smc+1 ; 4 + + ;======================= + ; load loop + + lda PT3_LOC+PT3_LOOP ; 4 + sta pt3_loop_smc+1 ; 4 + + + ;======================== + ;======================== + ; set up note/freq table + ; this saves some space and makes things marginally faster longrun + ;======================== + ;======================== + ; note (heh) that there are separate tables if version 3.3 + ; but we are going to assume we are only going to be playing + ; newer 3.4+ version files so only need the newer tables + + ldx PT3_LOC+PT3_HEADER_FREQUENCY ; 4 + beq use_freq_table_0 + dex + beq use_freq_table_1 + dex + beq use_freq_table_2 + ; fallthrough (freq table 3) + +use_freq_table_3: + ;================================================= + ; Create Table #3, v4+, "PT3NoteTable_REAL_34_35" + ;================================================= + + ldy #11 ; !2 +freq_table_3_copy_loop: + ; note, high lookup almost same as 2v4, just need to adjust one value + + lda base2_v4_high,Y ; !3 + sta NoteTable_high,Y ; !3 + lda base3_low,Y ; !3 + sta NoteTable_low,Y ; !3 + dey ; !1 + bpl freq_table_3_copy_loop ; !2 + + dec NoteTable_high ; adjust to right value + + jsr NoteTablePropogate ; !3 + + lda #table3_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + jmp done_set_freq_table + + + +use_freq_table_2: + ;================================================= + ; Create Table #2, v4+, "PT3NoteTable_ASM_34_35" + ;================================================= + + ldy #11 +freq_table_2_copy_loop: + lda base2_v4_high,Y + sta NoteTable_high,Y + lda base2_v4_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_2_copy_loop + + jsr NoteTablePropogate ; !3 + + lda #table2_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + jmp done_set_freq_table + +use_freq_table_1: + ;================================================= + ; Create Table #1, "PT3NoteTable_ST" + ;================================================= + + ldy #11 +freq_table_1_copy_loop: + lda base1_high,Y + sta NoteTable_high,Y + lda base1_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_1_copy_loop + + jsr NoteTablePropogate ; !3 + + ; last adjustments + lda #$FD ; Tone[23]=$3FD + sta NoteTable_low+23 + dec NoteTable_low+46 ; Tone[46]-=1; + + + jmp done_set_freq_table + + +use_freq_table_0: + ;================================================= + ; Create Table #0, "PT3NoteTable_PT_34_35" + ;================================================= + + ldy #11 +freq_table_0_copy_loop: + lda base0_v4_high,Y + sta NoteTable_high,Y + lda base0_v4_low,Y + sta NoteTable_low,Y + dey + bpl freq_table_0_copy_loop + + jsr NoteTablePropogate ; !3 + + lda #table0_v4_adjust + sta note_table_adjust_smc+2 + + jsr NoteTableAdjust + + +done_set_freq_table: + + + ;====================== + ; calculate version + ldx #6 ; 2 + lda PT3_LOC+PT3_VERSION ; 4 + sec ; 2 + sbc #'0' ; 2 + cmp #9 ; 2 + bcs not_ascii_number ; bge ; 2/3 + tax ; 2 + +not_ascii_number: + + ; adjust version<6 SMC code in the slide code + + ; FIXME: I am sure there's a more clever way to do this + + lda #$2C ; BIT ; 2 + cpx #$6 ; 2 + bcs version_greater_than_or_equal_6 ; bgt ; 3 + ; less than 6, jump + ; also carry is known to be clear + adc #$20 ; BIT->JMP 2C->4C ; 2 +version_greater_than_or_equal_6: + sta version_smc ; 4 + +pick_volume_table: + + ;======================= + ; Pick which volume number, based on version + + ; if (PlParams.PT3.PT3_Version <= 4) + + cpx #5 ; 2 + + ; carry clear = 3.3/3.4 table + ; carry set = 3.5 table + + ;========================== + ; VolTableCreator + ;========================== + ; Creates the appropriate volume table + ; based on z80 code by Ivan Roshin ZXAYHOBETA/VTII10bG.asm + ; + + ; Called with carry==0 for 3.3/3.4 table + ; Called with carry==1 for 3.5 table + + ; 177f-1932 = 435 bytes, not that much better than 512 of lookup + + +VolTableCreator: + + ; Init initial variables + lda #$0 + sta z80_d_smc+1 + ldy #$11 + + ; Set up self modify + + ldx #$2A ; ROL for self-modify + bcs vol_type_35 + +vol_type_33: + + ; For older table, we set initial conditions a bit + ; different + + dey + tya + + ldx #$ea ; NOP for self modify + +vol_type_35: + sty z80_l_smc+1 ; l=16 or 17 + sta z80_e_smc+1 ; e=16 or 0 + stx vol_smc ; set the self-modify code + + ldy #16 ; skip first row, all zeros + ldx #16 ; c=16 +vol_outer: + clc ; add HL,DE +z80_l_smc: + lda #$d1 +z80_e_smc: + adc #$d1 + sta z80_e_smc+1 + lda #0 +z80_d_smc: + adc #$d1 + sta z80_d_smc+1 ; carry is important + + ; sbc hl,hl + lda #0 + adc #$ff + eor #$ff + +vol_write: + sta z80_h_smc+1 + pha + +vol_inner: + pla + pha + +vol_smc: + nop ; nop or ROL depending + +z80_h_smc: + lda #$d1 + + adc #$0 ; a=a+carry; + + sta VolumeTable,Y + iny + + pla ; add HL,DE + adc z80_e_smc+1 + pha + lda z80_h_smc+1 + adc z80_d_smc+1 + sta z80_h_smc+1 + + inx ; inc C + txa ; a=c + and #$f + bne vol_inner + + + pla + + lda z80_e_smc+1 ; a=e + cmp #$77 + bne vol_m3 + + inc z80_e_smc+1 + +vol_m3: + txa ; a=c + bne vol_outer + +vol_done: + rts + + + ;========================================= + ; copy note table seed to proper location + ;========================================= + +; faster inlined + +;NoteTableCopy: + +; ldy #11 ; !2 +;note_table_copy_loop: +;ntc_smc1: +; lda base1_high,Y ; !3 +; sta NoteTable_high,Y ; !3 +;ntc_smc2: +; lda base1_low,Y ; !3 +; sta NoteTable_low,Y ; !3 +; dey ; !1 +; bpl note_table_copy_loop ; !2 +; rts ; !1 + + + ;========================================== + ; propogate the freq down, dividing by two + ;========================================== +NoteTablePropogate: + + ldy #0 +note_table_propogate_loop: + clc + lda NoteTable_high,Y + ror + sta NoteTable_high+12,Y + + lda NoteTable_low,Y + ror + sta NoteTable_low+12,Y + + iny + cpy #84 + bne note_table_propogate_loop + + rts + + + ;================================================ + ; propogation isn't enough, various values + ; are ofte off by one, so adjust using a bitmask + ;================================================ +NoteTableAdjust: + + ldx #0 +note_table_adjust_outer: + +note_table_adjust_smc: + lda table0_v4_adjust,X + sta PT3_TEMP + + ; reset smc + lda #NoteTable_low + sta ntl_smc+2 + + + ldy #7 +note_table_adjust_inner: + ror PT3_TEMP + bcc note_table_skip_adjust + +ntl_smc: + inc NoteTable_low,X + +note_table_skip_adjust: + clc + lda #12 + adc ntl_smc+1 + sta ntl_smc+1 + lda #0 + adc ntl_smc+2 ; unnecessary if aligned + sta ntl_smc+2 + +skip_adjust_done: + dey + bpl note_table_adjust_inner + + inx + cpx #12 + bne note_table_adjust_outer + + rts + + +;base0_v3_high: +;.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 +;base0_v3_low: +;.byte $21,$73,$CE,$33,$A0,$16,$93,$18,$A4,$36,$CE,$6D + +; note: same as base0_v3_high +base0_v4_high: +.byte $0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06,$06 +base0_v4_low: +.byte $22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF,$6D + +base1_high: +.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07 +base1_low: +.byte $F8,$10,$60,$80,$D8,$28,$88,$F0,$60,$E0,$58,$E0 + +;base2_v3_high: +;.byte $0D,$0C,$0B,$0B,$0A,$09,$09,$08,$08,$07,$07,$07 +;base2_v3_low: +;.byte $3E,$80,$CC,$22,$82,$EC,$5C,$D6,$58,$E0,$6E,$04 + +; note almost same as above +base2_v4_high: +.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 +base2_v4_low: +.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8,$3B,$C5,$55,$EC + +; note almost same as above +;base3_high: +;.byte $0C,$0C,$0B,$0A,$0A,$09,$09,$08,$08,$07,$07,$06 +base3_low: +.byte $DA,$22,$73,$CF,$33,$A1,$17,$94,$19,$A4,$37,$CF + + +; Adjustment factors +table0_v4_adjust: +.byte $40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c,$5a + +table2_v4_adjust: +.byte $20,$a8,$40,$f8,$bc,$90,$78,$70,$74,$08,$2a,$50 + +table3_v4_adjust: +.byte $B4,$40,$e6,$9c,$66,$40,$2c,$20,$30,$48,$6c,$1c + + +; Table #1 of Pro Tracker 3.3x - 3.5x +;PT3NoteTable_ST_high: +;.byte $0E,$0E,$0D,$0C,$0B,$0B,$0A,$09 +;.byte $09,$08,$08,$07,$07,$07,$06,$06 +;.byte $05,$05,$05,$04,$04,$04,$04,$03 +;.byte $03,$03,$03,$03,$02,$02,$02,$02 +;.byte $02,$02,$02,$01,$01,$01,$01,$01 +;.byte $01,$01,$01,$01,$01,$01,$01,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 + +;PT3NoteTable_ST_low: +;.byte $F8,$10,$60,$80,$D8,$28,$88,$F0 +;.byte $60,$E0,$58,$E0,$7C,$08,$B0,$40 +;.byte $EC,$94,$44,$F8,$B0,$70,$2C,$FD +;.byte $BE,$84,$58,$20,$F6,$CA,$A2,$7C +;.byte $58,$38,$16,$F8,$DF,$C2,$AC,$90 +;.byte $7B,$65,$51,$3E,$2C,$1C,$0A,$FC +;.byte $EF,$E1,$D6,$C8,$BD,$B2,$A8,$9F +;.byte $96,$8E,$85,$7E,$77,$70,$6B,$64 +;.byte $5E,$59,$54,$4F,$4B,$47,$42,$3F +;.byte $3B,$38,$35,$32,$2F,$2C,$2A,$27 +;.byte $25,$23,$21,$1F,$1D,$1C,$1A,$19 +;.byte $17,$16,$15,$13,$12,$11,$10,$0F + + +; Table #2 of Pro Tracker 3.4x - 3.5x +;PT3NoteTable_ASM_34_35_high: +;.byte $0D,$0C,$0B,$0A,$0A,$09,$09,$08 +;.byte $08,$07,$07,$06,$06,$06,$05,$05 +;.byte $05,$04,$04,$04,$04,$03,$03,$03 +;.byte $03,$03,$02,$02,$02,$02,$02,$02 +;.byte $02,$01,$01,$01,$01,$01,$01,$01 +;.byte $01,$01,$01,$01,$01,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 +;.byte $00,$00,$00,$00,$00,$00,$00,$00 + +;PT3NoteTable_ASM_34_35_low: +;.byte $10,$55,$A4,$FC,$5F,$CA,$3D,$B8 +;.byte $3B,$C5,$55,$EC,$88,$2A,$D2,$7E +;.byte $2F,$E5,$9E,$5C,$1D,$E2,$AB,$76 +;.byte $44,$15,$E9,$BF,$98,$72,$4F,$2E +;.byte $0F,$F1,$D5,$BB,$A2,$8B,$74,$60 +;.byte $4C,$39,$28,$17,$07,$F9,$EB,$DD +;.byte $D1,$C5,$BA,$B0,$A6,$9D,$94,$8C +;.byte $84,$7C,$75,$6F,$69,$63,$5D,$58 +;.byte $53,$4E,$4A,$46,$42,$3E,$3B,$37 +;.byte $34,$31,$2F,$2C,$29,$27,$25,$23 +;.byte $21,$1F,$1D,$1C,$1A,$19,$17,$16 +;.byte $15,$14,$12,$11,$10,$0F,$0E,$0D + + +;PT3VolumeTable_33_34: +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 +;.byte $0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2 +;.byte $0,$0,$0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3 +;.byte $0,$0,$0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4 +;.byte $0,$0,$0,$1,$1,$1,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 +;.byte $0,$0,$0,$1,$1,$2,$2,$3,$3,$3,$4,$4,$5,$5,$6,$6 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$5,$5,$6,$6,$7,$7,$8 +;.byte $0,$0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$6,$7,$8,$8,$9 +;.byte $0,$0,$1,$2,$2,$3,$4,$4,$5,$6,$6,$7,$8,$8,$9,$A +;.byte $0,$0,$1,$2,$3,$3,$4,$5,$6,$6,$7,$8,$9,$9,$A,$B +;.byte $0,$0,$1,$2,$3,$4,$4,$5,$6,$7,$8,$8,$9,$A,$B,$C +;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D +;.byte $0,$0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F + +;PT3VolumeTable_35: +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0,$0 +;.byte $0,$0,$0,$0,$0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1 +;.byte $0,$0,$0,$0,$1,$1,$1,$1,$1,$1,$1,$1,$2,$2,$2,$2 +;.byte $0,$0,$0,$1,$1,$1,$1,$1,$2,$2,$2,$2,$2,$3,$3,$3 +;.byte $0,$0,$1,$1,$1,$1,$2,$2,$2,$2,$3,$3,$3,$3,$4,$4 +;.byte $0,$0,$1,$1,$1,$2,$2,$2,$3,$3,$3,$4,$4,$4,$5,$5 +;.byte $0,$0,$1,$1,$2,$2,$2,$3,$3,$4,$4,$4,$5,$5,$6,$6 +;.byte $0,$0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7 +;.byte $0,$1,$1,$2,$2,$3,$3,$4,$4,$5,$5,$6,$6,$7,$7,$8 +;.byte $0,$1,$1,$2,$2,$3,$4,$4,$5,$5,$6,$7,$7,$8,$8,$9 +;.byte $0,$1,$1,$2,$3,$3,$4,$5,$5,$6,$7,$7,$8,$9,$9,$A +;.byte $0,$1,$1,$2,$3,$4,$4,$5,$6,$7,$7,$8,$9,$A,$A,$B +;.byte $0,$1,$2,$2,$3,$4,$5,$6,$6,$7,$8,$9,$A,$A,$B,$C +;.byte $0,$1,$2,$3,$3,$4,$5,$6,$7,$8,$9,$A,$A,$B,$C,$D +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$7,$8,$9,$A,$B,$C,$D,$E +;.byte $0,$1,$2,$3,$4,$5,$6,$7,$8,$9,$A,$B,$C,$D,$E,$F diff --git a/pt3_player/pt3_lib_irq_handler.s b/pt3_player/pt3_lib_irq_handler.s new file mode 100644 index 00000000..10899c88 --- /dev/null +++ b/pt3_player/pt3_lib_irq_handler.s @@ -0,0 +1,109 @@ + + +pt3_irq_handler: + + bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 + + lda DONE_PLAYING ; 3 + beq pt3_play_music ; if song done, don't play music ; 3/2nt + jmp done_pt3_irq_handler ; 3 + ;============ + ; 13 + +pt3_play_music: + + ; decode a frame of music + + jsr pt3_make_frame + + ; handle song over condition + lda DONE_SONG + beq mb_write_frame ; if not done, continue + + lda LOOP ; see if looping + beq move_to_next + +pt3_loop_smc: + lda #$d1 ; looping, move to loop location + ; non-zero to avoid the temptation + ; to merge with following lda #$0 + sta current_pattern_smc+1 + lda #$0 + sta current_line_smc+1 + sta current_subframe_smc+1 + sta DONE_SONG ; undo the next song + + beq done_pt3_irq_handler ; branch always + +move_to_next: + ; same as "press right" + ldx #$20 + jmp quiet_exit + + ;====================================== + ; Write frames to Mockingboard + ;====================================== + ; for speed could merge this into + ; the decode code + +mb_write_frame: + + + tax ; set up reg count ; 2 + ;============ + ; 2 + + ;================================== + ; loop through the 14 registers + ; reading the value, then write out + ;================================== + +mb_write_loop: + lda AY_REGISTERS,X ; load register value ; 4 + + ; special case R13. If it is 0xff, then don't update + ; otherwise might spuriously reset the envelope settings + + cpx #13 ; 2 + bne mb_not_13 ; 3/2nt + cmp #$ff ; 2 + beq mb_skip_13 ; 3/2nt + ;============ + ; typ 5 +mb_not_13: + + + ; address + stx MOCK_6522_ORA1 ; put address on PA1 ; 4 + stx MOCK_6522_ORA2 ; put address on PA2 ; 4 + ldy #MOCK_AY_LATCH_ADDR ; latch_address for PB1 ; 2 + sty MOCK_6522_ORB1 ; latch_address on PB1 ; 4 + sty MOCK_6522_ORB2 ; latch_address on PB2 ; 4 + ldy #MOCK_AY_INACTIVE ; go inactive ; 2 + sty MOCK_6522_ORB1 ; 4 + sty MOCK_6522_ORB2 ; 4 + + ; value + sta MOCK_6522_ORA1 ; put value on PA1 ; 4 + sta MOCK_6522_ORA2 ; put value on PA2 ; 4 + lda #MOCK_AY_WRITE ; ; 2 + sta MOCK_6522_ORB1 ; write on PB1 ; 4 + sta MOCK_6522_ORB2 ; write on PB2 ; 4 + sty MOCK_6522_ORB1 ; 4 + sty MOCK_6522_ORB2 ; 4 + ;=========== + ; 56 +mb_no_write: + inx ; point to next register ; 2 + cpx #14 ; if 14 we're done ; 2 + bmi mb_write_loop ; otherwise, loop ; 3/2nt + ;============ + ; 7 +mb_skip_13: + + + ;================================= + ; Finally done with this interrupt + ;================================= + +done_pt3_irq_handler: diff --git a/pt3_player/pt3_player.s b/pt3_player/pt3_player.s index 6aae003e..f797e769 100644 --- a/pt3_player/pt3_player.s +++ b/pt3_player/pt3_player.s @@ -10,6 +10,8 @@ ; If you change this, you need to update the Makefile PT3_LOC = $4000 +PT3_USE_ZERO_PAGE = 1 + ; Number of files. Should probably detect this automatically NUM_FILES = 19 @@ -724,8 +726,14 @@ song_list: .include "gr_setpage.s" .include "qkumba_rts.s" .include "keypress_minimal.s" + + +; pt3_lib stuff +.include "pt3_lib_core.s" +.include "pt3_lib_init.s" .include "interrupt_handler.s" -.include "pt3_lib.s" + +; visualization .include "fire.s" .include "random16.s" .include "gr_putsprite.s" diff --git a/pt3_player/pt3_table_test.s b/pt3_player/pt3_table_test.s index 84769554..b58322c7 100644 --- a/pt3_player/pt3_table_test.s +++ b/pt3_player/pt3_table_test.s @@ -136,7 +136,8 @@ error: ;routines ;========= -.include "pt3_lib.s" +.include "pt3_lib_core.s" +.include "pt3_lib_init.s" diff --git a/pt3_player/pt3_timer.s b/pt3_player/pt3_timer.s index af313ce7..7adaa7d0 100644 --- a/pt3_player/pt3_timer.s +++ b/pt3_player/pt3_timer.s @@ -5,7 +5,7 @@ PT3_LOC = $4000 -NUM_FILES = 15 +PT3_USE_ZERO_PAGE = 1 ;============================= ; Setup @@ -240,31 +240,6 @@ filename_found: rts - ;=============================== - ; Increment file we want to load - ;=============================== -increment_file: - inc WHICH_FILE - lda WHICH_FILE - cmp #NUM_FILES - bne done_increment - lda #0 - sta WHICH_FILE -done_increment: - rts - - ;=============================== - ; Decrement file we want to load - ;=============================== -decrement_file: - dec WHICH_FILE - bpl done_decrement - lda #(NUM_FILES-1) - sta WHICH_FILE -done_decrement: - rts - - ;========== ; filenames ;========== @@ -278,7 +253,9 @@ song_list: ;========= .include "mockingboard_a.s" .include "qkumba_rts.s" -.include "pt3_lib.s" + +.include "pt3_lib_core.s" +.include "pt3_lib_init.s"