.include "zeropage.inc"
.include "mouse-kernel.inc"
+ .include "apple2.inc"
; ------------------------------------------------------------------------
.addr UNINSTALL
.addr HIDE
.addr SHOW
- .addr BOX
+ .addr SETBOX
+ .addr GETBOX
.addr MOVE
.addr BUTTONS
.addr POS
.addr IOCTL
.addr IRQ
+ ; Mouse driver flags
+ .byte MOUSE_FLAG_EARLY_IRQ
+
; Callback table, set by the kernel before INSTALL is called
CHIDE: jmp $0000 ; Hide the cursor
CSHOW: jmp $0000 ; Show the cursor
; ------------------------------------------------------------------------
.bss
-
+
+box: .tag MOUSE_BOX
+info: .tag MOUSE_INFO
slot: .res 1
visible:.res 1
-
+
; ------------------------------------------------------------------------
.rodata
size = * - values
+inibox: .word 0 ; MinX
+ .word 0 ; MinY
+ .word 279 ; MaxX
+ .word 191 ; MaxY
+
; ------------------------------------------------------------------------
.data
-
-info: .word 279 / 2 ; MOUSE_INFO::MOUSE_POS::XCOORD
- .word 191 / 2 ; MOUSE_INFO::MOUSE_POS::YCOORD
- .byte %00000000 ; MOUSE_INFO::BUTTONS
firmware:
; Lookup and patch firmware address lobyte
yparam: ldy #$FF ; Patched at runtime
jump: jmp $FFFF ; Patched at runtime
-
+
; ------------------------------------------------------------------------
.code
bne next
dex
bpl :-
-
+
; Get and patch firmware address hibyte
lda ptr1+1
sta lookup+2
sta xparam+1
sta jump+2
-
+
+ ; Disable interrupts now because setting the slot number makes
+ ; the IRQ handler (maybe called due to some non-mouse IRQ) try
+ ; calling the firmware which isn't correctly set up yet
+ sei
+
; Convert to and save slot number
and #$0F
sta slot
asl
asl
sta yparam+1
-
- ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
- ; "Disable interrupts when calling any mouse routine."
- sei
+
+ ; The AppleMouse II Card needs the ROM switched in
+ ; to be able to detect an Apple //e and use RDVBL
+ bit $C082
; Reset mouse hardware
ldx #INITMOUSE
jsr firmware
+
+ ; Switch in LC bank 2 for R/O
+ bit $C080
; Turn mouse on
lda #%00000001
ldx #SETMOUSE
jsr firmware
- ; Set initial mouse clamps
- lda #<279
- ldx #>279
- sta pos2_lo
- stx pos2_hi
- lda #$00 ; Set x clamps
- sta pos1_lo
- sta pos1_hi
- ldx #CLAMPMOUSE
- jsr firmware
- lda #<191
- ldx #>191
- sta pos2_lo
- stx pos2_hi
- lda #$01 ; Set y clamps
- ldx #CLAMPMOUSE
- jsr firmware
+ ; Set initial mouse clamps
+ lda #<inibox
+ ldx #>inibox
+ jsr SETBOX
; Set initial mouse position
ldx slot
ldx #POSMOUSE
jsr firmware
+ ; Update cursor
+ jsr update
+
; Turn VBL interrupt on
lda #%00001001
ldx #SETMOUSE
; Hide cursor
sei
jsr CHIDE
-
+
; Turn mouse off
lda #%00000000
ldx #SETMOUSE
bne common ; Branch always
-; HIDE: Is called to hide the mouse cursor. The mouse kernel manages a
-; counter for calls to show/hide, and the driver entry point is only called
-; if the mouse is currently visible and should get hidden. For most drivers,
-; no special action is required besides hiding the mouse cursor.
-; No return code required.
-HIDE:
- dec visible
- sei
- jsr CHIDE
- cli
- rts
-
-; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
-; counter for calls to show/hide, and the driver entry point is only called
-; if the mouse is currently hidden and should become visible. For most drivers,
-; no special action is required besides enabling the mouse cursor.
-; No return code required.
-SHOW:
- inc visible
- rts
-
-; BOX: Set the mouse bounding box. The parameters are passed as they come from
-; the C program, that is, maxy in A/X and the other parameters on the stack.
-; The C wrapper will remove the parameters from the stack when the driver
-; routine returns.
+; SETBOX: Set the mouse bounding box. The parameters are passed as they come
+; from the C program, that is, a pointer to a mouse_box struct in A/X.
; No checks are done if the mouse is currently inside the box, this is the job
; of the caller. It is not necessary to validate the parameters, trust the
; caller and save some code here. No return code required.
-BOX:
- ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
- ; "Disable interrupts before placing position information in the screen holes."
- sei
-
- ; Set high clamp
- sta pos2_lo
- txa
-
- ldx #$01 ; Set y clamps
- ldy #$00 ; Start at top of stack
+SETBOX:
+ sta ptr1
+ stx ptr1+1
+
+ ; Set x clamps
+ ldx #$00
+ ldy #MOUSE_BOX::MINX
jsr :+
- ldx #$00 ; Set x clamps
- ldy #$00 ; Start at top of stack
+ ; Set y clamps
+ ldx #$01
+ ldy #MOUSE_BOX::MINY
- ; Set high clamp
- lda (sp),y
- iny
- sei
- sta pos2_lo
- lda (sp),y
+ ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
+ ; "Disable interrupts before placing position information in the
+ ; screen holes."
+: sei
+
+ ; Set low clamp
+ lda (ptr1),y
+ sta box,y
+ sta pos1_lo
iny
-: sta pos2_hi
+ lda (ptr1),y
+ sta box,y
+ sta pos1_hi
- ; Skip one parameter
+ ; Skip one word
iny
iny
- ; Set low clamp
- lda (sp),y
+ ; Set high clamp
iny
- sta pos1_lo
- lda (sp),y
- sta pos1_hi
+ lda (ptr1),y
+ sta box,y
+ sta pos2_lo
+ iny
+ lda (ptr1),y
+ sta box,y
+ sta pos2_hi
txa
ldx #CLAMPMOUSE
bne common ; Branch always
+; GETBOX: Return the mouse bounding box. The parameters are passed as they
+; come from the C program, that is, a pointer to a mouse_box struct in A/X.
+GETBOX:
+ sta ptr1
+ stx ptr1+1
+
+ ldy #.sizeof(MOUSE_BOX)-1
+: lda box,y
+ sta (ptr1),y
+ dey
+ bpl :-
+ rts
+
; MOVE: Move the mouse to a new position. The position is passed as it comes
; from the C program, that is: x on the stack and y in A/X. The C wrapper will
; remove the parameter from the stack on return.
; Update cursor
jsr update
-
+
ldx #POSMOUSE
bne common ; Branch always
+; HIDE: Is called to hide the mouse cursor. The mouse kernel manages a
+; counter for calls to show/hide, and the driver entry point is only called
+; if the mouse is currently visible and should get hidden. For most drivers,
+; no special action is required besides hiding the mouse cursor.
+; No return code required.
+HIDE:
+ dec visible
+ sei
+ jsr CHIDE
+ cli
+ rts
+
+; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
+; counter for calls to show/hide, and the driver entry point is only called
+; if the mouse is currently hidden and should become visible. For most drivers,
+; no special action is required besides enabling the mouse cursor.
+; No return code required.
+SHOW:
+ inc visible
+ rts
+
; BUTTONS: Return the button mask in A/X.
BUTTONS:
lda info + MOUSE_INFO::BUTTONS
; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
; No return code required.
POS:
- ldx #.sizeof(MOUSE_POS)-1
+ ldy #.sizeof(MOUSE_POS)-1
bne copy ; Branch always
; INFO: Returns mouse position and current button mask in the MOUSE_INFO
; struct pointed to by ptr1. No return code required.
INFO:
- ldx #.sizeof(MOUSE_INFO)-1
-copy: txa
- tay
- sei
-: lda info,x
+ ldy #.sizeof(MOUSE_INFO)-1
+copy: sei
+: lda info,y
sta (ptr1),y
- dex
dey
bpl :-
cli
lda #<MOUSE_ERR_INV_IOCTL
ldx #>MOUSE_ERR_INV_IOCTL
rts
-
+
; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
; registers are already saved, no parameters are passed, but the carry flag
; is clear on entry. The routine must return with carry set if the interrupt
; was handled, otherwise with carry clear.
IRQ:
+ ; Check for installed mouse
+ lda slot
+ beq done
+
; Check for mouse interrupt
ldx #SERVEMOUSE
jsr firmware
bcc :+
clc ; Interrupt not handled
- rts
+done: rts
: ldx #READMOUSE
jsr firmware
ldy slot
lda status,y
tax ; Save status
-
+
; Extract button down values
asl ; C = Button 0 is currently down
and #%00100000 ; !Z = Button 1 is currently down
: bcc :+
ora #MOUSE_BTN_LEFT
: sta info + MOUSE_INFO::BUTTONS
-
+
; Check for mouse movement
txa ; Restore status
and #%00100000 ; X or Y changed since last READMOUSE
; Remove the cursor at the old position
update: jsr CHIDE
-
+
; Get and set the new X position
ldy slot
lda pos1_lo,y
sta info + MOUSE_POS::XCOORD
stx info + MOUSE_POS::XCOORD+1
jsr CMOVEX
-
+
; Get and set the new Y position
ldy slot
lda pos2_lo,y