;;;------------------------------------------------------------------- ;;; ;;; Mouse ;;; ;;;------------------------------------------------------------------- ;; .error "Mouse support not fully implemented" .proc Mouse ;;;-------------------------------------------------- ;;; Mouse Screen Holes ;;;-------------------------------------------------- ;;; For ReadMouse and PosMouse MOUSE_X_LSB := $0478 ; + slot Low byte of X coordinate MOUSE_Y_LSB := $04F8 ; + slot Low byte of Y coordinate MOUSE_X_MSB := $0578 ; + slot High byte of X coordinate MOUSE_Y_MSB := $05F8 ; + slot High byte of Y coordinate MOUSE_RSV1 := $0678 ; + slot Reserved MOUSE_RSV2 := $06F8 ; + slot Reserved MOUSE_STATUS := $0778 ; + slot Status byte ;; 7 Button down ;; 6 Button was down on last read and still down ;; 5 Movement since last read ;; 4 Reserved ;; 3 Interrupt from VBlInt ;; 2 Interrupt from button ;; 1 Interrupt from movement ;; 0 Reserved MOUSE_MODE := $07F8 ; + slot Mode byte ;; 7-4 Reserved ;; 3 VBlInt active ;; 2 VBL interrupt on button ;; 1 VBL interrupt on movement ;; 0 Mouse active ;;; Scratch area for ClampMouse: MOUSE_CMIN_LSB := $0478 ; Low byte of clamping minimum MOUSE_CMAX_LSB := $04F8 ; Low byte of clamping maximum MOUSE_CMIN_MSB := $0578 ; High byte of clamping minimum MOUSE_CMAX_MSB := $05F8 ; High byte of clamping maximum ;;;-------------------------------------------------- ;;; Mouse Constants ;;;-------------------------------------------------- MOUSE_CLAMP_X := 0 ; Value for A when setting X clamp with ClampMouse MOUSE_CLAMP_Y := 1 ; Value for A when setting X clamp with ClampMouse ;;; Mouse ID bytes MOUSEID_MAX := 4 MOUSEID_ADDR: .byte $05, $07, $0b, $0c, $fb MOUSEID_VAL: .byte $38, $18, $01, $20, $d6 SLOT_BASE := $C000 ;;;-------------------------------------------------- ;;; Mouse firmware routine ;;;-------------------------------------------------- SetMouse := $12 ; A=mode; C=0 on success ServeMouse := $13 ; C=0 mouse interrupt, C=1 other ReadMouse := $14 ClearMouse := $15 PosMouse := $16 ClampMouse := $17 HomeMouse := $18 InitMouse := $19 .macro MOUSE_CALL routine ldy routine jmp CallMouse .endmacro ;;;-------------------------------------------------- ;;; Data ;;;-------------------------------------------------- ;;; Mouse mouse_slot: .byte 0 ; mouse slot, or 0 if none mouse_fw_hi: .byte 0 ; mouse slot as $Cn mouse_op: .byte 0 ; mouse slot as $n0 mouse_ptr := $EB ; Zero page location ;;;-------------------------------------------------- ;;; Routines ;;;-------------------------------------------------- MOUSE_CLAMP_MIN := $10 MOUSE_CLAMP_MAX := $1F MOUSE_CENTER := $17 MOUSE_POS_MASK := $0F ;;;-------------------------------------------------- ;;; Macros for common mouse operations ;;;-------------------------------------------------- ;;;---------------------------------------- .macro DoClampMouse axis, min, max ;;;---------------------------------------- ;;; axis: MOUSE_CLAMP_X or MOUSE_CLAMP_Y ;;; min: minimum value (2 byte) ;;; max: maximum value (2 byte) ;;;---------------------------------------- lda #min sta MOUSE_CMIN_MSB lda #max sta MOUSE_CMAX_MSB lda #axis MOUSE_CALL ClampMouse .endmacro ;;;---------------------------------------- .macro DoPosMouse px, py ;;;---------------------------------------- ldx mouse_slot lda #px sta MOUSE_X_MSB,x lda #py sta MOUSE_Y_MSB,x MOUSE_CALL PosMouse .endmacro ;;;---------------------------------------- .macro DoSetMouse mode ;;;---------------------------------------- lda #mode MOUSE_CALL SetMouse .endmacro ;;;--------------------------------------------------------- ;;; Find and initialize the mouse port .proc FindMouse ;;; Reference: http://home.swbell.net/rubywand/R034MOUSEPRG.TXT sei ; No interrupts while we're getting set up ;; Find mouse card by scanning slots for ID bytes ldy #MAX_SLOT ; Start search in slot 7 slot_loop: sty mouse_slot ; Save for later tya clc adc #>SLOT_BASE ; Firmware is $Cn sta slot_addr + 1 ; Update msb of signature test ldx #MOUSEID_MAX ; This many signature bytes : lda MOUSEID_ADDR,x sta slot_addr ; Update lsb of signature test slot_addr := *+1 lda SLOT_BASE ; Self-modified cmp MOUSEID_VAL,x ; Does it match the signature? bne no_match ; Nope - try the next slot dex ; Yes! Keep testing bpl :- ; Fall through if all done jmp found no_match: dey ; Didn't match bne slot_loop ; Keep looking until slot 0 sty mouse_slot ; Oops, no mouse - make a note rts ; and bail ;; Store results needed for call ($Cn and $n0) found: tya ; Slot is in y ora #>SLOT_BASE ; Compute $Cn - needed for calls sta mouse_fw_hi tya asl ; Compute $n0 - needed for calls asl asl asl sta mouse_op ;; Initialize and configure mouse card MOUSE_CALL InitMouse ; reset, clamp to 0-1023 x/y DoSetMouse $01 ; mouse on, no interrupts ; TODO: test carry bit result (set = error) ;; Clamp for deltas DoClampMouse MOUSE_CLAMP_X, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX DoClampMouse MOUSE_CLAMP_Y, MOUSE_CLAMP_MIN, MOUSE_CLAMP_MAX DoPosMouse MOUSE_CENTER, MOUSE_CENTER cli ; Enable interrupts so mouse can function rts .endproc ;;;-------------------------------------------------- ;;; Call mouse firmware, param in A, routine in Y .proc CallMouse pha ; Save A (param) ldx mouse_fw_hi ; $Cn stx mouse_ptr+1 lda #0 sta mouse_ptr lda (mouse_ptr),y ; Look up routine offset sta mouse_ptr pla ; param in A ldy mouse_op ; $n0 in Y php sei jsr call plp rts call: jmp (mouse_ptr) .endproc ;;;-------------------------------------------------- ;;; Read mouse pos, send deltas, and recenter .proc SendMouse SaveRegisters lda mouse_slot beq done MOUSE_CALL ReadMouse lda Protocol::MouseX jsr SSC::Put lda #1 ; Data size jsr SSC::Put ldx mouse_slot lda MOUSE_X_LSB,x ora MOUSE_POS_MASK jsr SSC::Put lda Protocol::MouseY jsr SSC::Put lda #1 ; Data size jsr SSC::Put ldx mouse_slot lda MOUSE_Y_LSB,x ora MOUSE_POS_MASK jsr SSC::Put lda Protocol::MouseBtn jsr SSC::Put lda #1 ; Data size jsr SSC::Put ldx mouse_slot lda MOUSE_STATUS,x jsr SSC::Put DoPosMouse MOUSE_CENTER, MOUSE_CENTER done: RestoreRegisters rts .endproc .endproc