;=================================================================== ; 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: ; activate Mockingboard IIc ; + the Mockingboard has to take over Slot#4 (IIc has no slots) ; in theory any write to the firmware area in $C400 will ; activate it, but that might not be fast enough when detecting ; so writing $FF to $C403/$C404 is official way to enable ; + Note this disables permanently the mouse firmware in $C400 ; so "normal" interrupts are broken :( The hack to fix things ; is to switch in RAM for $F000 and just replace the IRQ ; vectors at $FFFE/$FFFF instead of $3FE/$3FF but that makes ; it difficult if you actually wanted to use any ; Applesoft/Monitor ROM routines .ifdef PT3_ENABLE_APPLE_IIC lda APPLEII_MODEL cmp #'C' bne not_iic lda #$ff ; don't bother patching these, IIc mockingboard always slot 4 sta MOCK_6522_DDRA1 ; $C403 sta MOCK_6522_T1CL ; $C404 .endif not_iic: 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 #