2 ; Driver for the AppleMouse II Card.
4 ; Oliver Schmidt, 03.09.2005
7 .include "zeropage.inc"
8 .include "mouse-kernel.inc"
10 ; ------------------------------------------------------------------------
12 SETMOUSE = $12 ; Sets mouse mode
13 SERVEMOUSE = $13 ; Services mouse interrupt
14 READMOUSE = $14 ; Reads mouse position
15 CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode)
16 POSMOUSE = $16 ; Sets mouse position to a user-defined pos
17 CLAMPMOUSE = $17 ; Sets mouse bounds in a window
18 HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win
19 INITMOUSE = $19 ; Resets mouse clamps to default values and
20 ; sets mouse position to 0,0
28 ; ------------------------------------------------------------------------
33 .byte $6D, $6F, $75 ; "mou"
34 .byte MOUSE_API_VERSION ; Mouse driver API version number
49 ; Callback table, set by the kernel before INSTALL is called
50 CHIDE: jmp $0000 ; Hide the cursor
51 CSHOW: jmp $0000 ; Show the cursor
52 CMOVEX: jmp $0000 ; Move the cursor to X coord
53 CMOVEY: jmp $0000 ; Move the cursor to Y coord
55 ; ------------------------------------------------------------------------
62 ; ------------------------------------------------------------------------
66 offsets:.byte $05 ; Pascal 1.0 ID byte
67 .byte $07 ; Pascal 1.0 ID byte
68 .byte $0B ; Pascal 1.1 generic signature byte
69 .byte $0C ; Device signature byte
71 values: .byte $38 ; Fixed
74 .byte $20 ; X-Y pointing device type 0
78 ; ------------------------------------------------------------------------
82 info: .word 279 / 2 ; MOUSE_INFO::MOUSE_POS::XCOORD
83 .word 191 / 2 ; MOUSE_INFO::MOUSE_POS::YCOORD
84 .byte %00000000 ; MOUSE_INFO::BUTTONS
87 ; Lookup and patch firmware address lobyte
88 lookup: ldy $FF00,x ; Patched at runtime
89 sty jump+1 ; Modify code below
91 ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
92 ; "Enter all mouse routines (...) with the X register set to $Cn
93 ; and Y register set to $n0, where n = the slot number."
94 xparam: ldx #$FF ; Patched at runtime
95 yparam: ldy #$FF ; Patched at runtime
97 jump: jmp $FFFF ; Patched at runtime
99 ; ------------------------------------------------------------------------
103 ; INSTALL: Is called after the driver is loaded into memory. If possible,
104 ; check if the hardware is present. Must return an MOUSE_ERR_xx code in A/X.
111 ; Search for AppleMouse II firmware in slots 1 - 7
117 ; Mouse firmware not found
118 lda #<MOUSE_ERR_NO_DEVICE
119 ldx #>MOUSE_ERR_NO_DEVICE
122 ; Check Pascal 1.1 Firmware Protocol ID bytes
131 ; Get and patch firmware address hibyte
137 ; Convert to and save slot number
141 ; Convert to and patch I/O register index
148 ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
149 ; "Disable interrupts when calling any mouse routine."
152 ; Reset mouse hardware
161 ; Set initial mouse clamps
166 lda #$00 ; Set x clamps
175 lda #$01 ; Set y clamps
179 ; Set initial mouse position
192 ; Turn VBL interrupt on
197 ; Enable interrupts and return success
203 ; UNINSTALL: Is called before the driver is removed from memory.
204 ; No return code required (the driver is removed from memory on return).
213 bne common ; Branch always
215 ; HIDE: Is called to hide the mouse cursor. The mouse kernel manages a
216 ; counter for calls to show/hide, and the driver entry point is only called
217 ; if the mouse is currently visible and should get hidden. For most drivers,
218 ; no special action is required besides hiding the mouse cursor.
219 ; No return code required.
227 ; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
228 ; counter for calls to show/hide, and the driver entry point is only called
229 ; if the mouse is currently hidden and should become visible. For most drivers,
230 ; no special action is required besides enabling the mouse cursor.
231 ; No return code required.
236 ; BOX: Set the mouse bounding box. The parameters are passed as they come from
237 ; the C program, that is, maxy in A/X and the other parameters on the stack.
238 ; The C wrapper will remove the parameters from the stack when the driver
240 ; No checks are done if the mouse is currently inside the box, this is the job
241 ; of the caller. It is not necessary to validate the parameters, trust the
242 ; caller and save some code here. No return code required.
244 ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
245 ; "Disable interrupts before placing position information in the screen holes."
252 ldx #$01 ; Set y clamps
253 ldy #$00 ; Start at top of stack
256 ldx #$00 ; Set x clamps
257 ldy #$00 ; Start at top of stack
281 bne common ; Branch always
283 ; MOVE: Move the mouse to a new position. The position is passed as it comes
284 ; from the C program, that is: x on the stack and y in A/X. The C wrapper will
285 ; remove the parameter from the stack on return.
286 ; No checks are done if the new position is valid (within the bounding box or
287 ; the screen). No return code required.
299 ldy #$00 ; Start at top of stack
312 bne common ; Branch always
314 ; BUTTONS: Return the button mask in A/X.
316 lda info + MOUSE_INFO::BUTTONS
320 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
321 ; No return code required.
323 ldx #.sizeof(MOUSE_POS)-1
324 bne copy ; Branch always
326 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
327 ; struct pointed to by ptr1. No return code required.
329 ldx #.sizeof(MOUSE_INFO)-1
341 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
342 ; specific data in ptr1, and the ioctl code in A.
343 ; Must return an MOUSE_ERR_xx code in A/X.
345 lda #<MOUSE_ERR_INV_IOCTL
346 ldx #>MOUSE_ERR_INV_IOCTL
349 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
350 ; registers are already saved, no parameters are passed, but the carry flag
351 ; is clear on entry. The routine must return with carry set if the interrupt
352 ; was handled, otherwise with carry clear.
354 ; Check for mouse interrupt
358 clc ; Interrupt not handled
369 ; Extract button down values
370 asl ; C = Button 0 is currently down
371 and #%00100000 ; !Z = Button 1 is currently down
378 : sta info + MOUSE_INFO::BUTTONS
380 ; Check for mouse movement
382 and #%00100000 ; X or Y changed since last READMOUSE
385 ; Remove the cursor at the old position
388 ; Get and set the new X position
392 sta info + MOUSE_POS::XCOORD
393 stx info + MOUSE_POS::XCOORD+1
396 ; Get and set the new Y position
400 sta info + MOUSE_POS::YCOORD
401 stx info + MOUSE_POS::YCOORD+1
404 ; Check for visibility
408 ; Draw the cursor at the new position
410 : sec ; Interrupt handled