; Oliver Schmidt, 03.09.2005
;
- .include "zeropage.inc"
- .include "mouse-kernel.inc"
- .include "apple2.inc"
+ .include "zeropage.inc"
+ .include "mouse-kernel.inc"
+ .include "apple2.inc"
; ------------------------------------------------------------------------
-SETMOUSE = $12 ; Sets mouse mode
-SERVEMOUSE = $13 ; Services mouse interrupt
-READMOUSE = $14 ; Reads mouse position
-CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode)
-POSMOUSE = $16 ; Sets mouse position to a user-defined pos
-CLAMPMOUSE = $17 ; Sets mouse bounds in a window
-HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win
-INITMOUSE = $19 ; Resets mouse clamps to default values and
- ; sets mouse position to 0,0
-
-pos1_lo := $0478
-pos1_hi := $0578
-pos2_lo := $04F8
-pos2_hi := $05F8
-status := $0778
+SETMOUSE = $12 ; Sets mouse mode
+SERVEMOUSE = $13 ; Services mouse interrupt
+READMOUSE = $14 ; Reads mouse position
+CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode)
+POSMOUSE = $16 ; Sets mouse position to a user-defined pos
+CLAMPMOUSE = $17 ; Sets mouse bounds in a window
+HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win
+INITMOUSE = $19 ; Resets mouse clamps to default values and
+ ; sets mouse position to 0,0
+
+pos1_lo := $0478
+pos1_hi := $0578
+pos2_lo := $04F8
+pos2_hi := $05F8
+status := $0778
; ------------------------------------------------------------------------
- .segment "JUMPTABLE"
-
- ; Driver signature
- .byte $6D, $6F, $75 ; "mou"
- .byte MOUSE_API_VERSION ; Mouse driver API version number
-
- ; Jump table.
- .addr INSTALL
- .addr UNINSTALL
- .addr HIDE
- .addr SHOW
- .addr SETBOX
- .addr GETBOX
- .addr MOVE
- .addr BUTTONS
- .addr POS
- .addr INFO
- .addr IOCTL
- .addr IRQ
+ .segment "JUMPTABLE"
+
+ ; Driver signature
+ .byte $6D, $6F, $75 ; "mou"
+ .byte MOUSE_API_VERSION ; Mouse driver API version number
+
+ ; Jump table.
+ .addr INSTALL
+ .addr UNINSTALL
+ .addr HIDE
+ .addr SHOW
+ .addr SETBOX
+ .addr GETBOX
+ .addr MOVE
+ .addr BUTTONS
+ .addr POS
+ .addr INFO
+ .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
-CMOVEX: jmp $0000 ; Move the cursor to X coord
-CMOVEY: jmp $0000 ; Move the cursor to Y coord
+ ; Callback table, set by the kernel before INSTALL is called
+CHIDE: jmp $0000 ; Hide the cursor
+CSHOW: jmp $0000 ; Show the cursor
+CMOVEX: jmp $0000 ; Move the cursor to X coord
+CMOVEY: jmp $0000 ; Move the cursor to Y coord
; ------------------------------------------------------------------------
- .bss
+ .bss
-box: .tag MOUSE_BOX
-info: .tag MOUSE_INFO
-slot: .res 1
-visible:.res 1
+box: .tag MOUSE_BOX
+info: .tag MOUSE_INFO
+slot: .res 1
+visible:.res 1
; ------------------------------------------------------------------------
- .rodata
+ .rodata
-offsets:.byte $05 ; Pascal 1.0 ID byte
- .byte $07 ; Pascal 1.0 ID byte
- .byte $0B ; Pascal 1.1 generic signature byte
- .byte $0C ; Device signature byte
+offsets:.byte $05 ; Pascal 1.0 ID byte
+ .byte $07 ; Pascal 1.0 ID byte
+ .byte $0B ; Pascal 1.1 generic signature byte
+ .byte $0C ; Device signature byte
-values: .byte $38 ; Fixed
- .byte $18 ; Fixed
- .byte $01 ; Fixed
- .byte $20 ; X-Y pointing device type 0
+values: .byte $38 ; Fixed
+ .byte $18 ; Fixed
+ .byte $01 ; Fixed
+ .byte $20 ; X-Y pointing device type 0
-size = * - values
+size = * - values
-inibox: .word 0 ; MinX
- .word 0 ; MinY
- .word 279 ; MaxX
- .word 191 ; MaxY
+inibox: .word 0 ; MinX
+ .word 0 ; MinY
+ .word 279 ; MaxX
+ .word 191 ; MaxY
; ------------------------------------------------------------------------
- .data
+ .data
firmware:
- ; Lookup and patch firmware address lobyte
-lookup: ldy $FF00,x ; Patched at runtime
- sty jump+1 ; Modify code below
+ ; Lookup and patch firmware address lobyte
+lookup: ldy $FF00,x ; Patched at runtime
+ sty jump+1 ; Modify code below
- ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
- ; "Enter all mouse routines (...) with the X register set to $Cn
- ; and Y register set to $n0, where n = the slot number."
-xparam: ldx #$FF ; Patched at runtime
-yparam: ldy #$FF ; Patched at runtime
+ ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
+ ; "Enter all mouse routines (...) with the X register set to $Cn
+ ; and Y register set to $n0, where n = the slot number."
+xparam: ldx #$FF ; Patched at runtime
+yparam: ldy #$FF ; Patched at runtime
-jump: jmp $FFFF ; Patched at runtime
+jump: jmp $FFFF ; Patched at runtime
; ------------------------------------------------------------------------
- .code
+ .code
; INSTALL: Is called after the driver is loaded into memory. If possible,
; check if the hardware is present. Must return an MOUSE_ERR_xx code in A/X.
INSTALL:
- lda #<$C000
- sta ptr1
- lda #>$C000
- sta ptr1+1
-
- ; Search for AppleMouse II firmware in slots 1 - 7
-next: inc ptr1+1
- lda ptr1+1
- cmp #>$C800
- bcc :+
-
- ; Mouse firmware not found
- lda #<MOUSE_ERR_NO_DEVICE
- ldx #>MOUSE_ERR_NO_DEVICE
- rts
-
- ; Check Pascal 1.1 Firmware Protocol ID bytes
-: ldx #size - 1
-: ldy offsets,x
- lda values,x
- cmp (ptr1),y
- 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
-
- ; Convert to and patch I/O register index
- asl
- asl
- asl
- asl
- sta yparam+1
-
- ; 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 #<inibox
- ldx #>inibox
- jsr SETBOX
-
- ; Set initial mouse position
- ldx slot
- lda #<(279 / 2)
- sta pos1_lo,x
- lda #>(279 / 2)
- sta pos1_hi,x
- lda #<(191 / 2)
- sta pos2_lo,x
- lda #>(191 / 2)
- sta pos2_hi,x
- ldx #POSMOUSE
- jsr firmware
-
- ; Update cursor
- jsr update
-
- ; Turn VBL interrupt on
- lda #%00001001
- ldx #SETMOUSE
-common: jsr firmware
-
- ; Enable interrupts and return success
- cli
- lda #<MOUSE_ERR_OK
- ldx #>MOUSE_ERR_OK
- rts
+ lda #<$C000
+ sta ptr1
+ lda #>$C000
+ sta ptr1+1
+
+ ; Search for AppleMouse II firmware in slots 1 - 7
+next: inc ptr1+1
+ lda ptr1+1
+ cmp #>$C800
+ bcc :+
+
+ ; Mouse firmware not found
+ lda #<MOUSE_ERR_NO_DEVICE
+ ldx #>MOUSE_ERR_NO_DEVICE
+ rts
+
+ ; Check Pascal 1.1 Firmware Protocol ID bytes
+: ldx #size - 1
+: ldy offsets,x
+ lda values,x
+ cmp (ptr1),y
+ 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
+
+ ; Convert to and patch I/O register index
+ asl
+ asl
+ asl
+ asl
+ sta yparam+1
+
+ ; 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 #<inibox
+ ldx #>inibox
+ jsr SETBOX
+
+ ; Set initial mouse position
+ ldx slot
+ lda #<(279 / 2)
+ sta pos1_lo,x
+ lda #>(279 / 2)
+ sta pos1_hi,x
+ lda #<(191 / 2)
+ sta pos2_lo,x
+ lda #>(191 / 2)
+ sta pos2_hi,x
+ ldx #POSMOUSE
+ jsr firmware
+
+ ; Update cursor
+ jsr update
+
+ ; Turn VBL interrupt on
+ lda #%00001001
+ ldx #SETMOUSE
+common: jsr firmware
+
+ ; Enable interrupts and return success
+ cli
+ lda #<MOUSE_ERR_OK
+ ldx #>MOUSE_ERR_OK
+ rts
; UNINSTALL: Is called before the driver is removed from memory.
; No return code required (the driver is removed from memory on return).
UNINSTALL:
- ; Hide cursor
- sei
- jsr CHIDE
+ ; Hide cursor
+ sei
+ jsr CHIDE
- ; Turn mouse off
- lda #%00000000
- ldx #SETMOUSE
- bne common ; Branch always
+ ; Turn mouse off
+ lda #%00000000
+ ldx #SETMOUSE
+ bne common ; Branch always
; 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.
; of the caller. It is not necessary to validate the parameters, trust the
; caller and save some code here. No return code required.
SETBOX:
- sta ptr1
- stx ptr1+1
+ sta ptr1
+ stx ptr1+1
+
+ ; Set x clamps
+ ldx #$00
+ ldy #MOUSE_BOX::MINX
+ jsr :+
- ; Set x clamps
- ldx #$00
- ldy #MOUSE_BOX::MINX
- jsr :+
-
- ; Set y clamps
- ldx #$01
- ldy #MOUSE_BOX::MINY
-
- ; 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
- lda (ptr1),y
- sta box,y
- sta pos1_hi
-
- ; Skip one word
- iny
- iny
-
- ; Set high clamp
- iny
- 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
+ ; Set y clamps
+ ldx #$01
+ ldy #MOUSE_BOX::MINY
+
+ ; 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
+ lda (ptr1),y
+ sta box,y
+ sta pos1_hi
+
+ ; Skip one word
+ iny
+ iny
+
+ ; Set high clamp
+ iny
+ 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
+ sta ptr1
+ stx ptr1+1
- ldy #.sizeof(MOUSE_BOX)-1
-: lda box,y
- sta (ptr1),y
- dey
- bpl :-
- rts
+ 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
; No checks are done if the new position is valid (within the bounding box or
; the screen). No return code required.
MOVE:
- ldy slot
- sei
+ ldy slot
+ sei
- ; Set y
- sta pos2_lo,y
- txa
- sta pos2_hi,y
+ ; Set y
+ sta pos2_lo,y
+ txa
+ sta pos2_hi,y
- tya
- tax
- ldy #$00 ; Start at top of stack
+ tya
+ tax
+ ldy #$00 ; Start at top of stack
- ; Set x
- lda (sp),y
- iny
- sta pos1_lo,x
- lda (sp),y
- sta pos1_hi,x
+ ; Set x
+ lda (sp),y
+ iny
+ sta pos1_lo,x
+ lda (sp),y
+ sta pos1_hi,x
- ; Update cursor
- jsr update
+ ; Update cursor
+ jsr update
- ldx #POSMOUSE
- bne common ; Branch always
+ 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 special action is required besides hiding the mouse cursor.
; No return code required.
HIDE:
- dec visible
- sei
- jsr CHIDE
- cli
- rts
+ dec visible
+ sei
+ jsr CHIDE
+ cli
+ rts
-; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
+; 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 special action is required besides enabling the mouse cursor.
; No return code required.
SHOW:
- inc visible
- rts
+ inc visible
+ rts
; BUTTONS: Return the button mask in A/X.
BUTTONS:
- lda info + MOUSE_INFO::BUTTONS
- ldx #$00
- rts
+ lda info + MOUSE_INFO::BUTTONS
+ ldx #$00
+ rts
; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
; No return code required.
POS:
- ldy #.sizeof(MOUSE_POS)-1
- bne copy ; Branch always
+ 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:
- ldy #.sizeof(MOUSE_INFO)-1
-copy: sei
-: lda info,y
- sta (ptr1),y
- dey
- bpl :-
- cli
- rts
+ ldy #.sizeof(MOUSE_INFO)-1
+copy: sei
+: lda info,y
+ sta (ptr1),y
+ dey
+ bpl :-
+ cli
+ rts
; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
; specific data in ptr1, and the ioctl code in A.
; Must return an MOUSE_ERR_xx code in A/X.
IOCTL:
- lda #<MOUSE_ERR_INV_IOCTL
- ldx #>MOUSE_ERR_INV_IOCTL
- rts
+ 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
-done: rts
-
-: ldx #READMOUSE
- jsr firmware
-
- ; Get status
- 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
-
- ; Set button mask
- beq :+
- lda #MOUSE_BTN_RIGHT
-: 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
- beq :+
-
- ; Remove the cursor at the old position
-update: jsr CHIDE
-
- ; Get and set the new X position
- ldy slot
- lda pos1_lo,y
- ldx pos1_hi,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
- ldx pos2_hi,y
- sta info + MOUSE_POS::YCOORD
- stx info + MOUSE_POS::YCOORD+1
- jsr CMOVEY
-
- ; Check for visibility
-: lda visible
- beq :+
-
- ; Draw the cursor at the new position
- jsr CSHOW
-: sec ; Interrupt handled
- rts
+ ; Check for installed mouse
+ lda slot
+ beq done
+
+ ; Check for mouse interrupt
+ ldx #SERVEMOUSE
+ jsr firmware
+ bcc :+
+ clc ; Interrupt not handled
+done: rts
+
+: ldx #READMOUSE
+ jsr firmware
+
+ ; Get status
+ 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
+
+ ; Set button mask
+ beq :+
+ lda #MOUSE_BTN_RIGHT
+: 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
+ beq :+
+
+ ; Remove the cursor at the old position
+update: jsr CHIDE
+
+ ; Get and set the new X position
+ ldy slot
+ lda pos1_lo,y
+ ldx pos1_hi,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
+ ldx pos2_hi,y
+ sta info + MOUSE_POS::YCOORD
+ stx info + MOUSE_POS::YCOORD+1
+ jsr CMOVEY
+
+ ; Check for visibility
+: lda visible
+ beq :+
+
+ ; Draw the cursor at the new position
+ jsr CSHOW
+: sec ; Interrupt handled
+ rts