From da2d2dd650d7968b55e8192522a488288a664d4d Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Mon, 27 Jan 2020 12:13:08 -0500 Subject: [PATCH] ootw: ending: update to use newew version of pt3_lib should now detect mockingboard (though still hardcodes slot #4) also at end of ending does cold-reset back to menu --- ootw/Makefile | 4 +- ootw/ending.s | 73 +++++- ootw/pt3_lib_core.s | 6 +- ootw/pt3_lib_init.s | 2 +- ootw/pt3_lib_irq_handler.s | 11 +- ootw/pt3_lib_mockingboard.s | 382 ----------------------------- ootw/pt3_lib_mockingboard_detect.s | 314 ++++++++++++++++++++++++ ootw/pt3_setup.s | 47 ---- ootw/zp.inc | 4 +- 9 files changed, 393 insertions(+), 450 deletions(-) delete mode 100644 ootw/pt3_lib_mockingboard.s create mode 100644 ootw/pt3_lib_mockingboard_detect.s delete mode 100644 ootw/pt3_setup.s diff --git a/ootw/Makefile b/ootw/Makefile index 2eb3ac713..41be4ce13 100644 --- a/ootw/Makefile +++ b/ootw/Makefile @@ -300,8 +300,8 @@ ENDING: ending.o ld65 -o ENDING ending.o -C ../linker_scripts/apple2_1700.inc ending.o: ending.s \ - pt3_lib_core.s pt3_lib_init.s pt3_lib_mockingboard.s \ - pt3_setup.s pt3_lib_irq_handler.s interrupt_handler.s \ + pt3_lib_core.s pt3_lib_init.s pt3_lib_mockingboard_detect.s \ + pt3_lib_mockingboard_setup.s pt3_lib_irq_handler.s interrupt_handler.s \ ootw_graphics/l15final/ootw_c15_final.inc \ ootw_graphics/l16end/ootw_c16_end.inc \ ootw_audio/ootw_outro.pt3 diff --git a/ootw/ending.s b/ootw/ending.s index 899912c21..ae45a8826 100644 --- a/ootw/ending.s +++ b/ootw/ending.s @@ -1,5 +1,6 @@ -; ootw -; quick demo of what the ending might be like +; ootw -- It's the End of the Game as We Know It + +; TODO: missing a bunch of frames ; by Vince "Deater" Weaver @@ -12,16 +13,54 @@ ending: ;========================= ; set up sound ;========================= - - jsr pt3_setup + lda #0 + sta DONE_PLAYING lda #1 sta LOOP + ; detect mockingboard -; jmp quit_level + jsr mockingboard_detect -; jsr wait_until_keypressed + bcc mockingboard_notfound + +mockingboard_found: + +; jsr mockingboard_patch ; patch to work in slots other than 4? + + ;======================= + ; Set up 50Hz interrupt + ;======================== + + jsr mockingboard_init + jsr mockingboard_setup_interrupt + + ;============================ + ; Init the Mockingboard + ;============================ + + jsr reset_ay_both + jsr clear_ay_both + + ;================== + ; init song + ;================== + + jsr pt3_init_song + + + jmp done_setup_sound + +mockingboard_notfound: + ; patch out cli/sei calls + + lda #$EA + sta cli_smc + sta sei_smc + + +done_setup_sound: repeat_ending: @@ -132,11 +171,12 @@ repeat_ending: jsr gr_overlay jsr page_flip - jsr wait_until_keypressed +; jsr wait_until_keypressed ; start music +cli_smc: cli ; enable interrupts ldx #240 @@ -691,7 +731,19 @@ print_loop: jsr wait_until_keypressed - jmp repeat_ending + ; disable music + + jsr clear_ay_both +sei_smc: + sei + + ; reboot to title + + lda #$ff ; force cold reboot + sta $03F4 + jmp ($FFFC) + +; jmp repeat_ending ; 0123456789012345678901234567890123456789 @@ -798,9 +850,8 @@ long_wait: .include "pt3_lib_core.s" .include "pt3_lib_init.s" .include "interrupt_handler.s" -.include "pt3_lib_mockingboard.s" - -.include "pt3_setup.s" +.include "pt3_lib_mockingboard_detect.s" +.include "pt3_lib_mockingboard_setup.s" diff --git a/ootw/pt3_lib_core.s b/ootw/pt3_lib_core.s index fed1de166..1118b5ae5 100644 --- a/ootw/pt3_lib_core.s +++ b/ootw/pt3_lib_core.s @@ -91,7 +91,7 @@ NOTE_TONE_SLIDE_TO_STEP =39 NOTE_STRUCT_SIZE=40 -.ifdef USE_ZERO_PAGE +.ifdef PT3_USE_ZERO_PAGE note_a = $80 note_b = $80+(NOTE_STRUCT_SIZE*1) note_c = $80+(NOTE_STRUCT_SIZE*2) @@ -100,7 +100,7 @@ begin_vars=$80 end_vars=$80+(NOTE_STRUCT_SIZE*3) -.else ; !USE_ZERO_PAGE +.else ; !PT3_USE_ZERO_PAGE begin_vars: note_a: ; reset? @@ -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/ootw/pt3_lib_init.s b/ootw/pt3_lib_init.s index e2f7e448e..037b1ade3 100644 --- a/ootw/pt3_lib_init.s +++ b/ootw/pt3_lib_init.s @@ -387,7 +387,7 @@ note_table_propogate_loop: ;================================================ ; propogation isn't enough, various values - ; are ofte off by one, so adjust using a bitmask + ; are often off by one, so adjust using a bitmask ;================================================ NoteTableAdjust: diff --git a/ootw/pt3_lib_irq_handler.s b/ootw/pt3_lib_irq_handler.s index 10899c88b..851a22bf2 100644 --- a/ootw/pt3_lib_irq_handler.s +++ b/ootw/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,22 +75,28 @@ 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 - sta MOCK_6522_ORB2 ; write on PB2 ; 4 sty MOCK_6522_ORB1 ; 4 +pt3_irq_smc7: + sta MOCK_6522_ORB2 ; write on PB2 ; 4 sty MOCK_6522_ORB2 ; 4 ;=========== ; 56 diff --git a/ootw/pt3_lib_mockingboard.s b/ootw/pt3_lib_mockingboard.s deleted file mode 100644 index 42c07b9e8..000000000 --- a/ootw/pt3_lib_mockingboard.s +++ /dev/null @@ -1,382 +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 - - -; 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 - lda MB_VALUE ; 3 - 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 - - 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 - - ;======================================= - ; 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 PT3_TEMP ; 3 cycles - lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles - ; between the two accesses to the timer - sec - sbc PT3_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 PT3_TEMP ; 3 cycles - lda (MB_ADDRL),Y ; + 5 cycles = 8 cycles - ; between the two accesses to the timer - sec - sbc PT3_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 - - - ;============================= - ; Setup - ;============================= -pt3_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 - sta $C403 - sta $C404 - - ; 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 - ;============================ - - 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 - - rts - - - - ;================================== - ; Print mockingboard detect message - ;================================== - ; note: on IIc must do this before enabling interrupt - ; as we disable ROM (COUT won't work?) - -print_mockingboard_detect: - - ; print detection message - ldy #0 -print_mocking_message: - lda mocking_message,Y ; load loading message - beq done_mocking_message - ora #$80 - jsr COUT - iny - jmp print_mocking_message -done_mocking_message: - jsr CROUT1 - - rts - -print_mocking_notfound: - - ldy #0 -print_not_message: - lda not_message,Y ; load loading message - beq print_not_message_done - ora #$80 - jsr COUT - iny - jmp print_not_message -print_not_message_done: - rts - -print_mocking_found: - ldy #0 -print_found_message: - lda found_message,Y ; load loading message - beq done_found_message - ora #$80 - jsr COUT - iny - jmp print_found_message -done_found_message: - - rts - -;========= -; strings -;========= -mocking_message: .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" -not_message: .byte "NOT " -found_message: .asciiz "FOUND" - - diff --git a/ootw/pt3_lib_mockingboard_detect.s b/ootw/pt3_lib_mockingboard_detect.s new file mode 100644 index 000000000..706d9407b --- /dev/null +++ b/ootw/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 #