From 95aca92cb090310e034340f7717e7924f84956b0 Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Sat, 28 Dec 2019 23:20:17 -0500 Subject: [PATCH] pt3_player: update to auto-detect mockingboard slot --- pt3_lib/README.pt3_lib | 4 - pt3_lib/pt3_lib.dsk | Bin 143360 -> 143360 bytes pt3_lib/pt3_lib_core.s | 2 +- pt3_lib/pt3_test.s | 4 +- pt3_player/Makefile | 4 +- pt3_player/hello.bas | 2 +- pt3_player/mockingboard_a.s | 240 ----------------- pt3_player/pt3_lib_core.s | 8 +- pt3_player/pt3_lib_irq_handler.s | 9 +- pt3_player/pt3_lib_mockingboard_detect.s | 314 +++++++++++++++++++++++ pt3_player/pt3_lib_mockingboard_setup.s | 250 ++++++++++++++++++ pt3_player/pt3_player.dsk | Bin 143360 -> 143360 bytes pt3_player/pt3_player.s | 103 ++------ pt3_player/pt3_timer.s | 43 +--- pt3_player/zp.inc | 5 +- 15 files changed, 611 insertions(+), 377 deletions(-) delete mode 100644 pt3_player/mockingboard_a.s create mode 100644 pt3_player/pt3_lib_mockingboard_detect.s create mode 100644 pt3_player/pt3_lib_mockingboard_setup.s diff --git a/pt3_lib/README.pt3_lib b/pt3_lib/README.pt3_lib index f8027021..73d898f3 100644 --- a/pt3_lib/README.pt3_lib +++ b/pt3_lib/README.pt3_lib @@ -14,10 +14,6 @@ Background: This code is meant as a relatively simple, reasonably optimized version of the PT3 Vortex-Tracker player for use in other programs. -A much more optimized version can be found in ../pt3_player/ -That codebase has been *extremely* optimized to the point it's no longer -very straightforward to reuse the code. - For some more background on this you can watch the talk I gave at Demosplash 2019 on this topic. diff --git a/pt3_lib/pt3_lib.dsk b/pt3_lib/pt3_lib.dsk index 87a591972fad50ce3c978dce5aa32bc23cf0156b..f370adc9e592c62cc507883e5f6684e788652c26 100644 GIT binary patch delta 19 ZcmZp8z|jCiTNq_FGiq#?-OTv71^`gi2ju_& delta 19 ZcmZp8z|jCiTNq_FGpcTv-OTv71^`gN2jTz# diff --git a/pt3_lib/pt3_lib_core.s b/pt3_lib/pt3_lib_core.s index b3c95d9c..1118b5ae 100644 --- a/pt3_lib/pt3_lib_core.s +++ b/pt3_lib/pt3_lib_core.s @@ -829,7 +829,7 @@ do_onoff: do_offon: ldy note_a+NOTE_OFFON_DELAY,X ; else a->onoff=a->offon_delay; put_offon: -.ifdef USE_ZERO_PAGE +.ifdef PT3_USE_ZERO_PAGE sty note_a+NOTE_ONOFF,X .else lda note_a+NOTE_ONOFF,X diff --git a/pt3_lib/pt3_test.s b/pt3_lib/pt3_test.s index fcaf5dcb..63e644a0 100644 --- a/pt3_lib/pt3_test.s +++ b/pt3_lib/pt3_test.s @@ -66,14 +66,14 @@ mockingboard_found: jsr print_mocking_found -setup_interrupt: - ;================================================== ; patch the playing code with the proper slot value ;================================================== jsr mockingboard_patch +setup_interrupt: + ;======================= ; Set up 50Hz interrupt ;======================== diff --git a/pt3_player/Makefile b/pt3_player/Makefile index 5b332cd8..34902322 100644 --- a/pt3_player/Makefile +++ b/pt3_player/Makefile @@ -81,7 +81,9 @@ PT3_PLAYER: pt3_player.o pt3_player.o: pt3_player.s \ 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 + pt3_lib_init.s pt3_lib_core.s interrupt_handler.s \ + pt3_lib_irq_handler.s \ + pt3_lib_mockingboard_setup.s pt3_lib_mockingboard_detect.s ca65 -o pt3_player.o pt3_player.s -l pt3_player.lst # diff --git a/pt3_player/hello.bas b/pt3_player/hello.bas index d22be204..1ca680f2 100644 --- a/pt3_player/hello.bas +++ b/pt3_player/hello.bas @@ -1,2 +1,2 @@ - 10 PRINT "PT3 PLAYER V1.3" + 10 PRINT "PT3 PLAYER V1.4" 100 PRINT CHR$ (4)"BRUN PT3_PLAYER" diff --git a/pt3_player/mockingboard_a.s b/pt3_player/mockingboard_a.s deleted file mode 100644 index e8bac8f9..00000000 --- a/pt3_player/mockingboard_a.s +++ /dev/null @@ -1,240 +0,0 @@ -; Mockingboad programming: -; + Has two 6522 I/O chips connected to two AY-3-8910 chips -; + Optionally has some speech chips controlled via the outport on the AY -; + Often in slot 4 -; TODO: how to auto-detect? -; References used: -; http://macgui.com/usenet/?group=2&id=8366 -; 6522 Data Sheet -; AY-3-8910 Data Sheet - -;======================== -; Mockingboard card -; Essentially two 6522s hooked to the Apple II bus -; Connected to AY-3-8910 chips -; PA0-PA7 on 6522 connected to DA0-DA7 on AY -; PB0 on 6522 connected to BC1 -; PB1 on 6522 connected to BDIR -; PB2 on 6522 connected to RESET - - -; left speaker -MOCK_6522_ORB1 = $C400 ; 6522 #1 port b data -MOCK_6522_ORA1 = $C401 ; 6522 #1 port a data -MOCK_6522_DDRB1 = $C402 ; 6522 #1 data direction port B -MOCK_6522_DDRA1 = $C403 ; 6522 #1 data direction port A - -; right speaker -MOCK_6522_ORB2 = $C480 ; 6522 #2 port b data -MOCK_6522_ORA2 = $C481 ; 6522 #2 port a data -MOCK_6522_DDRB2 = $C482 ; 6522 #2 data direction port B -MOCK_6522_DDRA2 = $C483 ; 6522 #2 data direction port A - -; AY-3-8910 commands on port B -; RESET BDIR BC1 -MOCK_AY_RESET = $0 ; 0 0 0 -MOCK_AY_INACTIVE = $4 ; 1 0 0 -MOCK_AY_READ = $5 ; 1 0 1 -MOCK_AY_WRITE = $6 ; 1 1 0 -MOCK_AY_LATCH_ADDR = $7 ; 1 1 1 - - - ;======================== - ; Mockingboard Init - ;======================== - ; Initialize the 6522s - ; set the data direction for all pins of PortA/PortB to be output - -mockingboard_init: - lda #$ff ; all output (1) - sta MOCK_6522_DDRB1 - sta MOCK_6522_DDRA1 - sta MOCK_6522_DDRB2 - sta MOCK_6522_DDRA2 - rts - - ;====================== - ; Reset Left AY-3-8910 - ;====================== -reset_ay_both: - lda #MOCK_AY_RESET - sta MOCK_6522_ORB1 - lda #MOCK_AY_INACTIVE - sta MOCK_6522_ORB1 - - ;====================== - ; Reset Right AY-3-8910 - ;====================== -;reset_ay_right: -;could be merged with both - lda #MOCK_AY_RESET - sta MOCK_6522_ORB2 - lda #MOCK_AY_INACTIVE - sta MOCK_6522_ORB2 - rts - - - ;======================================= - ; clear ay -- clear all 14 AY registers - ; should silence the card - ;======================================= -clear_ay_both: - ldx #14 - lda #0 - sta MB_VALUE_smc+1 -clear_ay_left_loop: -; Write sequence -; Inactive -> Latch Address -> Inactive -> Write Data -> Inactive - - ;========================================= - ; Write Right/Left to save value AY-3-8910 - ;========================================= - ; register in X - ; value in MB_VALUE - -write_ay_both: - ; address - stx MOCK_6522_ORA1 ; put address on PA1 ; 3 - stx MOCK_6522_ORA2 ; put address on PA2 ; 3 - lda #MOCK_AY_LATCH_ADDR ; latch_address on PB1 ; 2 - sta MOCK_6522_ORB1 ; latch_address on PB1 ; 3 - sta MOCK_6522_ORB2 ; latch_address on PB2 ; 3 - ldy #MOCK_AY_INACTIVE ; go inactive ; 2 - sty MOCK_6522_ORB1 ; 3 - sty MOCK_6522_ORB2 ; 3 - - ; value -MB_VALUE_smc: - lda #$d1 ; 2 - sta MOCK_6522_ORA1 ; put value on PA1 ; 3 - sta MOCK_6522_ORA2 ; put value on PA2 ; 3 - lda #MOCK_AY_WRITE ; ; 2 - sta MOCK_6522_ORB1 ; write on PB1 ; 3 - sta MOCK_6522_ORB2 ; write on PB2 ; 3 - sty MOCK_6522_ORB1 ; 3 - sty MOCK_6522_ORB2 ; 3 - - ;=========== - ; 44 - dex - bpl clear_ay_left_loop - rts - - ;======================================= - ; Detect a Mockingboard card - ;======================================= - ; Based on code from the French Touch "Pure Noise" Demo - ; Attempts to time an instruction sequence with a 6522 - ; - ; If found, puts in bMB - ; MB_ADDRL:MB_ADDRH has address of Mockingboard - ; returns X=0 if not found, X=1 if found - -mockingboard_detect: - lda #0 - sta MB_ADDRL - -mb_detect_loop: ; self-modifying - lda #$07 ; we start in slot 7 ($C7) and go down to 0 ($C0) - ora #$C0 ; make it start with C - sta MB_ADDRH - ldy #04 ; $CX04 - ldx #02 ; 2 tries? -mb_check_cycle_loop: - lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter) - ; count down - sta TEMP ; 3 cycles - lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles - ; between the two accesses to the timer - sec - sbc TEMP ; subtract to see if we had 8 cycles - cmp #$f8 ; -8 - bne mb_not_in_this_slot - dex ; decrement, try one more time - bne mb_check_cycle_loop ; loop detection - inx ; Mockingboard found (X=1) -done_mb_detect: - ;stx bMB ; store result to bMB - rts ; return - -mb_not_in_this_slot: - dec mb_detect_loop+1 ; decrement the "slot" (self_modify) - bne mb_detect_loop ; loop down to one - ldx #00 - beq done_mb_detect - -;alternative MB detection from Nox Archaist -; lda #$04 -; sta MB_ADDRL -; ldx #$c7 -; -;find_mb: -; stx MB_ADDRH -; -; ;detect sound I -; -; sec -; ldy #$00 -; lda (MB_ADDRL), y -; sbc (MB_ADDRL), y -; cmp #$05 -; beq found_mb -; dex -; cpx #$c0 -; bne find_mb -; ldx #$00 ;no mockingboard found -; rts -; -;found_mb: -; ldx #$01 ;mockingboard found -; rts -; -; ;optionally detect sound II -; -; sec -; ldy #$80 -; lda (MB_ADDRL), y -; sbc (MB_ADDRL), y -; cmp #$05 -; beq found_mb - - - ;======================================= - ; Detect a Mockingboard card in Slot4 - ;======================================= - ; Based on code from the French Touch "Pure Noise" Demo - ; Attempts to time an instruction sequence with a 6522 - ; - ; MB_ADDRL:MB_ADDRH has address of Mockingboard - ; returns X=0 if not found, X=1 if found - -mockingboard_detect_slot4: - lda #0 - sta MB_ADDRL - -mb4_detect_loop: ; self-modifying - lda #$04 ; we're only looking in Slot 4 - ora #$C0 ; make it start with C - sta MB_ADDRH - ldy #04 ; $CX04 - ldx #02 ; 2 tries? -mb4_check_cycle_loop: - lda (MB_ADDRL),Y ; timer 6522 (Low Order Counter) - ; count down - sta TEMP ; 3 cycles - lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles - ; between the two accesses to the timer - sec - sbc TEMP ; subtract to see if we had 8 cycles - cmp #$f8 ; -8 - bne mb4_not_in_this_slot - dex ; decrement, try one more time - bne mb4_check_cycle_loop ; loop detection - inx ; Mockingboard found (X=1) -done_mb4_detect: - rts ; return - -mb4_not_in_this_slot: - ldx #00 - beq done_mb4_detect - diff --git a/pt3_player/pt3_lib_core.s b/pt3_player/pt3_lib_core.s index 6af8f98e..1118b5ae 100644 --- a/pt3_player/pt3_lib_core.s +++ b/pt3_player/pt3_lib_core.s @@ -232,20 +232,14 @@ note_c: end_vars: .endif - ; this is only called by lib_init load_ornament0_sample1: lda #0 ; 2 jsr load_ornament ; 6 ; fall through -load_sample1: - lda #1 ; 2 - - ;=========================== ;=========================== ; Load Sample ;=========================== - ;=========================== ; sample in A ; which note offset in X @@ -260,6 +254,8 @@ load_sample1: ; Optimization: ; see comments on ornament setting +load_sample1: + lda #1 ; 2 load_sample: diff --git a/pt3_player/pt3_lib_irq_handler.s b/pt3_player/pt3_lib_irq_handler.s index 475e9c2e..851a22bf 100644 --- a/pt3_player/pt3_lib_irq_handler.s +++ b/pt3_player/pt3_lib_irq_handler.s @@ -2,7 +2,8 @@ pt3_irq_handler: - bit $C404 ; clear 6522 interrupt by reading T1C-L ; 4 +pt3_irq_smc1: + bit MOCK_6522_T1CL ; 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 @@ -74,21 +75,27 @@ mb_not_13: ; address +pt3_irq_smc2: 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 +pt3_irq_smc3: 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 +pt3_irq_smc4: sty MOCK_6522_ORB1 ; 4 sty MOCK_6522_ORB2 ; 4 ; value +pt3_irq_smc5: sta MOCK_6522_ORA1 ; put value on PA1 ; 4 sta MOCK_6522_ORA2 ; put value on PA2 ; 4 lda #MOCK_AY_WRITE ; ; 2 +pt3_irq_smc6: sta MOCK_6522_ORB1 ; write on PB1 ; 4 sty MOCK_6522_ORB1 ; 4 +pt3_irq_smc7: sta MOCK_6522_ORB2 ; write on PB2 ; 4 sty MOCK_6522_ORB2 ; 4 ;=========== diff --git a/pt3_player/pt3_lib_mockingboard_detect.s b/pt3_player/pt3_lib_mockingboard_detect.s new file mode 100644 index 00000000..706d9407 --- /dev/null +++ b/pt3_player/pt3_lib_mockingboard_detect.s @@ -0,0 +1,314 @@ +;=================================================================== +; code to detect mockingboard +;=================================================================== +; this isn't always easy +; my inclination is to just assume slot #4 but that isn't always realistic + +; code below based on "hw.mockingboard.a" from "Total Replay" + +;license:MIT +; By Andrew Roughan +; in the style of 4am for Total Replay +; +; Mockingboard support functions +; + +;------------------------------------------------------------------------------ +; HasMockingboard +; detect Mockingboard card by searching for 6522 timers across all slots +; access 6522 timers with deterministic cycle counts +; +; based on prior art in Mockingboard Developers Toolkit +; with optimisation from deater/french touch +; also takes into account FastChip //e clock difference +; +; in: none +; accelerators should be off +; out: C set if Mockingboard found in any slot +; if card was found, X = #$Cn where n is the slot number of the card +; C clear if no Mockingboard found +; other flags clobbered +; zp $65-$67 clobbered +; A/Y clobbered +;------------------------------------------------------------------------------ + +mockingboard_detect: + lda #$00 + sta MB_ADDR_L + ldx #$C7 ; start at slot #7 +mb_slot_loop: + stx MB_ADDR_H + ldy #$04 ; 6522 #1 $Cx04 + jsr mb_timer_check + bne mb_next_slot + ldy #$84 ; 6522 #2 $Cx84 + jsr mb_timer_check + bne mb_next_slot +mb_found: + sec ; found + rts + +mb_next_slot: + dex + cpx #$C0 + bne mb_slot_loop + + clc ; not found + rts + +mb_timer_check: + lda (MB_ADDR_L),Y ; read 6522 timer low byte + sta MB_VALUE + lda (MB_ADDR_L),Y ; second time + sec + sbc MB_VALUE + cmp #$F8 ; looking for (-)8 cycles between reads + beq mb_timer_check_done + cmp #$F7 ; FastChip //e clock is different +mb_timer_check_done: + rts + + + +;=================================================================== +; code to patch mockingboard if not in slot#4 +;=================================================================== +; this is the brute force version, we have to patch 39 locations +; see further below if you want to try a smaller, more dangerous, patch + +.if 0 +mockingboard_patch: + + lda MB_ADDR_H + + sta pt3_irq_smc1+2 ; 1 + + sta pt3_irq_smc2+2 ; 2 + sta pt3_irq_smc2+5 ; 3 + + sta pt3_irq_smc3+2 ; 4 + sta pt3_irq_smc3+5 ; 5 + + sta pt3_irq_smc4+2 ; 6 + sta pt3_irq_smc4+5 ; 7 + + sta pt3_irq_smc5+2 ; 8 + sta pt3_irq_smc5+5 ; 9 + + sta pt3_irq_smc6+2 ; 10 + sta pt3_irq_smc6+5 ; 11 + + sta pt3_irq_smc7+2 ; 12 + sta pt3_irq_smc7+5 ; 13 + + sta mock_init_smc1+2 ; 14 + sta mock_init_smc1+5 ; 15 + + sta mock_init_smc2+2 ; 16 + sta mock_init_smc2+5 ; 17 + + sta reset_ay_smc1+2 ; 18 + sta reset_ay_smc2+2 ; 19 + sta reset_ay_smc3+2 ; 20 + sta reset_ay_smc4+2 ; 21 + + sta write_ay_smc1+2 ; 22 + sta write_ay_smc1+5 ; 23 + + sta write_ay_smc2+2 ; 24 + sta write_ay_smc2+5 ; 25 + + sta write_ay_smc3+2 ; 26 + sta write_ay_smc3+5 ; 27 + + sta write_ay_smc4+2 ; 28 + sta write_ay_smc4+5 ; 29 + + sta write_ay_smc5+2 ; 30 + sta write_ay_smc5+5 ; 31 + + sta write_ay_smc6+2 ; 32 + sta write_ay_smc6+5 ; 33 + + sta setup_irq_smc1+2 ; 34 + sta setup_irq_smc2+2 ; 35 + sta setup_irq_smc3+2 ; 36 + sta setup_irq_smc4+2 ; 37 + sta setup_irq_smc5+2 ; 38 + sta setup_irq_smc6+2 ; 39 + + rts +.endif + +;=================================================================== +; dangerous code to patch mockingboard if not in slot#4 +;=================================================================== +; this code patches any $C4 value to the proper slot# if not slot4 +; this can be dangerous, it might over-write other important values +; that should be $C4 + +; safer ways to do this: +; only do this if 2 bytes after a LDA/STA/LDX/STX +; count total and if not 39 then print error message + +mockingboard_patch: + ; from mockingboard_init $1BBF + ; to done_pt3_irq_handler $1D85 + + ldx MB_ADDR_H + ldy #0 + + lda #mockingboard_init + sta MB_ADDR_H + +mb_patch_loop: + lda (MB_ADDR_L),Y + cmp #$C4 + bne mb_patch_nomatch + + txa + sta (MB_ADDR_L),Y +mb_patch_nomatch: + + inc MB_ADDR_L + lda MB_ADDR_L + bne mb_patch_oflo + inc MB_ADDR_H + +mb_patch_oflo: + lda MB_ADDR_H + cmp #>done_pt3_irq_handler + bne mb_patch_loop + lda MB_ADDR_L + cmp # Latch Address -> Inactive -> Write Data -> Inactive + + ;========================================= + ; Write Right/Left to save value AY-3-8910 + ;========================================= + ; register in X + ; value in MB_VALUE + +write_ay_both: + ; address + +write_ay_smc1: + stx MOCK_6522_ORA1 ; put address on PA1 ; 3 + stx MOCK_6522_ORA2 ; put address on PA2 ; 3 + lda #MOCK_AY_LATCH_ADDR ; latch_address on PB1 ; 2 +write_ay_smc2: + sta MOCK_6522_ORB1 ; latch_address on PB1 ; 3 + sta MOCK_6522_ORB2 ; latch_address on PB2 ; 3 + ldy #MOCK_AY_INACTIVE ; go inactive ; 2 +write_ay_smc3: + sty MOCK_6522_ORB1 ; 3 + sty MOCK_6522_ORB2 ; 3 + + ; value + lda MB_VALUE ; 3 +write_ay_smc4: + sta MOCK_6522_ORA1 ; put value on PA1 ; 3 + sta MOCK_6522_ORA2 ; put value on PA2 ; 3 + lda #MOCK_AY_WRITE ; ; 2 +write_ay_smc5: + sta MOCK_6522_ORB1 ; write on PB1 ; 3 + sta MOCK_6522_ORB2 ; write on PB2 ; 3 +write_ay_smc6: + sty MOCK_6522_ORB1 ; 3 + sty MOCK_6522_ORB2 ; 3 + + rts ; 6 + ;=========== + ; 51 + ;======================================= + ; clear ay -- clear all 14 AY registers + ; should silence the card + ;======================================= +clear_ay_both: + ldx #14 + lda #0 + sta MB_VALUE +clear_ay_left_loop: + jsr write_ay_both + dex + bpl clear_ay_left_loop + rts + + + ;============================= + ; Setup + ;============================= +mockingboard_setup_interrupt: + + ;=========================== + ; Check for Apple IIc + ;=========================== + ; it does interrupts differently + + lda $FBB3 ; IIe and newer is $06 + cmp #6 + beq apple_iie_or_newer + + jmp done_apple_detect +apple_iie_or_newer: + lda $FBC0 ; 0 on a IIc + bne done_apple_detect +apple_iic: + ; activate IIc mockingboard? + ; this might only be necessary to allow detection + ; I get the impression the Mockingboard 4c activates + ; when you access any of the 6522 ports in Slot 4 + lda #$ff + + ; don't bother patching these, IIc mockingboard always slot 4? + + sta MOCK_6522_DDRA1 + sta MOCK_6522_T1CL + + ; bypass the firmware interrupt handler + ; should we do this on IIe too? probably faster + + sei ; disable interrupts + lda $c08b ; disable ROM (enable language card) + lda $c08b + lda #interrupt_handler + sta $ffff + + lda #$EA ; nop out the "lda $45" in the irq hand + sta interrupt_smc + sta interrupt_smc+1 + +done_apple_detect: + + + ;========================= + ; Setup Interrupt Handler + ;========================= + ; Vector address goes to 0x3fe/0x3ff + ; FIXME: should chain any existing handler + + lda #interrupt_handler + sta $03ff + + ;============================ + ; Enable 50Hz clock on 6522 + ;============================ + + ; 4fe7 / 1e6 = .020s, 50Hz + + ; 9c40 / 1e6 = .040s, 25Hz + ; 411a / 1e6 = .016s, 60Hz + + sei ; disable interrupts just in case + + lda #$40 ; Continuous interrupts, don't touch PB7 +setup_irq_smc1: + sta MOCK_6522_ACR ; ACR register + lda #$7F ; clear all interrupt flags +setup_irq_smc2: + sta MOCK_6522_IER ; IER register (interrupt enable) + + lda #$C0 +setup_irq_smc3: + sta MOCK_6522_IFR ; IFR: 1100, enable interrupt on timer one oflow +setup_irq_smc4: + sta MOCK_6522_IER ; IER: 1100, enable timer one interrupt + + lda #$E7 +setup_irq_smc5: + sta MOCK_6522_T1CL ; write into low-order latch + lda #$4f +setup_irq_smc6: + sta MOCK_6522_T1CH ; write into high-order latch, + ; load both values into counter + ; clear interrupt and start counting + + rts diff --git a/pt3_player/pt3_player.dsk b/pt3_player/pt3_player.dsk index 385487f212b58c601014b7d2e0ddba36cc1a43ab..901f2e868d3d026b07ef1893a1a376e388e46894 100644 GIT binary patch delta 3322 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 A<^TWy diff --git a/pt3_player/pt3_player.s b/pt3_player/pt3_player.s index c6ca651c..b77084e1 100644 --- a/pt3_player/pt3_player.s +++ b/pt3_player/pt3_player.s @@ -36,40 +36,13 @@ pt3_setup: lda $FBB3 ; IIe and newer is $06 cmp #6 - beq apple_iie_or_newer + beq done_lowecase_smc lda #$d0 ; set if older than a IIe sta apple_ii_smc - bne done_apple_detect ; branch always -apple_iie_or_newer: - lda $FBC0 ; 0 on a IIc - bne done_apple_detect -apple_iic: - ; activate IIc mockingboard? - ; this might only be necessary to allow detection - ; I get the impression the Mockingboard 4c activates - ; when you access any of the 6522 ports in Slot 4 - lda #$ff - sta $C403 - sta $C404 +done_lowecase_smc: - ; bypass the firmware interrupt handler - ; should we do this on IIe too? probably faster - - sei ; disable interrupts - lda $c08b ; disable ROM (enable language card) - lda $c08b - lda #interrupt_handler - sta $ffff - - lda #$EA ; nop out the "lda $45" in the irq hand - sta interrupt_smc - sta interrupt_smc+1 - -done_apple_detect: ;=============== ; Init disk code @@ -91,22 +64,9 @@ done_apple_detect: ; Detect mockingboard ;======================== - ; Note, we do this, but then ignore it, as sometimes - ; the test fails and then you don't get music. - ; In theory this could do bad things if you had something - ; easily confused in slot4, but that's probably not an issue. + jsr mockingboard_detect ; call detection routine - ; print detection message - -; lda #mocking_message -; sta OUTH -; jsr move_and_print ; print it - - jsr mockingboard_detect_slot4 ; call detection routine - cpx #$1 - beq mockingboard_found + bcs mockingboard_found lda #interrupt_handler - sta $03ff - - ;============================ - ; Enable 50Hz clock on 6522 - ;============================ - - sei ; disable interrupts just in case - - lda #$40 ; Continuous interrupts, don't touch PB7 - sta $C40B ; ACR register - lda #$7F ; clear all interrupt flags - sta $C40E ; IER register (interrupt enable) - - lda #$C0 - sta $C40D ; IFR: 1100, enable interrupt on timer one oflow - sta $C40E ; IER: 1100, enable timer one interrupt - - lda #$E7 - sta $C404 ; write into low-order latch - lda #$4f - sta $C405 ; write into high-order latch, - ; load both values into counter - ; clear interrupt and start counting - - ; 4fe7 / 1e6 = .020s, 50Hz - - ;================== ; load first song ;================== @@ -720,7 +660,6 @@ song_list: ;========= .include "gr_offsets.s" .include "text_print.s" -.include "mockingboard_a.s" .include "gr_fast_clear.s" .include "pageflip.s" .include "gr_setpage.s" @@ -731,7 +670,9 @@ song_list: ; pt3_lib stuff .include "pt3_lib_core.s" .include "pt3_lib_init.s" +.include "pt3_lib_mockingboard_setup.s" .include "interrupt_handler.s" +.include "pt3_lib_mockingboard_detect.s" ; visualization .include "fire.s" diff --git a/pt3_player/pt3_timer.s b/pt3_player/pt3_timer.s index 7adaa7d0..758c8c91 100644 --- a/pt3_player/pt3_timer.s +++ b/pt3_player/pt3_timer.s @@ -25,9 +25,8 @@ pt3_setup: sta DONE_PLAYING sta WHICH_FILE - jsr mockingboard_detect_slot4 ; call detection routine - cpx #$1 - beq mockingboard_found +; jsr mockingboard_detect ; call detection routine +; bcs mockingboard_found mockingboard_found: @@ -37,43 +36,10 @@ mockingboard_found: ;============================ jsr mockingboard_init + jsr mockingboard_setup_interrupt jsr reset_ay_both jsr clear_ay_both - ;========================= - ; Setup Interrupt Handler - ;========================= - ; Vector address goes to 0x3fe/0x3ff - ; FIXME: should chain any existing handler - - lda #interrupt_handler - sta $03ff - - ;============================ - ; Enable 50Hz clock on 6522 - ;============================ - - sei ; disable interrupts just in case - - lda #$40 ; Continuous interrupts, don't touch PB7 - sta $C40B ; ACR register - lda #$7F ; clear all interrupt flags - sta $C40E ; IER register (interrupt enable) - - lda #$C0 - sta $C40D ; IFR: 1100, enable interrupt on timer one oflow - sta $C40E ; IER: 1100, enable timer one interrupt - - lda #$E7 - sta $C404 ; write into low-order latch - lda #$4f - sta $C405 ; write into high-order latch, - ; load both values into counter - ; clear interrupt and start counting - - ; 4fe7 / 1e6 = .020s, 50Hz ;================== ; load first song @@ -251,7 +217,7 @@ song_list: ;========= ;routines ;========= -.include "mockingboard_a.s" +.include "pt3_lib_mockingboard_setup.s" .include "qkumba_rts.s" .include "pt3_lib_core.s" @@ -434,6 +400,7 @@ exit_interrupt: tay ; restore Y pla tax ; restore X +interrupt_smc: lda $45 ; restore A diff --git a/pt3_player/zp.inc b/pt3_player/zp.inc index f46b2b3d..e33253ea 100644 --- a/pt3_player/zp.inc +++ b/pt3_player/zp.inc @@ -68,11 +68,12 @@ ORNAMENT_H = $03 SAMPLE_L = $04 SAMPLE_H = $05 +MB_VALUE = $61 PT3_TEMP = $62 WHICH_FILE = $63 LOOP = $64 -MB_ADDRL = $65 -MB_ADDRH = $66 +MB_ADDR_L = $65 +MB_ADDR_H = $66 DONE_PLAYING = $67 DONE_SONG = $68 FIRE_FB_L = $69