2 ; Driver for the AppleMouse II Card.
4 ; Oliver Schmidt, 03.09.2005
7 .include "zeropage.inc"
8 .include "mouse-kernel.inc"
13 ; ------------------------------------------------------------------------
15 SETMOUSE = $12 ; Sets mouse mode
16 SERVEMOUSE = $13 ; Services mouse interrupt
17 READMOUSE = $14 ; Reads mouse position
18 CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode)
19 POSMOUSE = $16 ; Sets mouse position to a user-defined pos
20 CLAMPMOUSE = $17 ; Sets mouse bounds in a window
21 HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win
22 INITMOUSE = $19 ; Resets mouse clamps to default values and
23 ; sets mouse position to 0,0
31 ; ------------------------------------------------------------------------
34 module_header _a2e_stdmou_mou
36 module_header _a2_stdmou_mou
40 .byte $6D, $6F, $75 ; "mou"
41 .byte MOUSE_API_VERSION ; Mouse driver API version number
61 .byte MOUSE_FLAG_EARLY_IRQ
63 ; Callback table, set by the kernel before INSTALL is called
64 CHIDE: jmp $0000 ; Hide the cursor
65 CSHOW: jmp $0000 ; Show the cursor
66 CPREP: jmp $0000 ; Prepare to move the cursor
67 CDRAW: jmp $0000 ; Draw the cursor
68 CMOVEX: jmp $0000 ; Move the cursor to X coord
69 CMOVEY: jmp $0000 ; Move the cursor to Y coord
71 ; ------------------------------------------------------------------------
79 ; ------------------------------------------------------------------------
83 offsets:.byte $05 ; Pascal 1.0 ID byte
84 .byte $07 ; Pascal 1.0 ID byte
85 .byte $0B ; Pascal 1.1 generic signature byte
86 .byte $0C ; Device signature byte
88 values: .byte $38 ; Fixed
91 .byte $20 ; X-Y pointing device type 0
95 inibox: .word 0 ; MinX
100 ; ------------------------------------------------------------------------
105 ; Lookup and patch firmware address lobyte
106 lookup: ldy $FF00,x ; Patched at runtime
107 sty jump+1 ; Modify code below
109 ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
110 ; "Enter all mouse routines (...) with the X register set to $Cn
111 ; and Y register set to $n0, where n = the slot number."
112 xparam: ldx #$FF ; Patched at runtime
113 yparam: ldy #$FF ; Patched at runtime
115 jump: jmp $FFFF ; Patched at runtime
117 ; ------------------------------------------------------------------------
121 ; INSTALL: Is called after the driver is loaded into memory. If possible,
122 ; check if the hardware is present. Must return an MOUSE_ERR_xx code in A/X.
129 ; Search for AppleMouse II firmware in slots 1 - 7
135 ; Mouse firmware not found
136 lda #<MOUSE_ERR_NO_DEVICE
137 ldx #>MOUSE_ERR_NO_DEVICE
140 ; Check Pascal 1.1 Firmware Protocol ID bytes
149 ; Get and patch firmware address hibyte
155 ; Disable interrupts now because setting the slot number makes
156 ; the IRQ handler (maybe called due to some non-mouse IRQ) try
157 ; calling the firmware which isn't correctly set up yet
160 ; Convert to and save slot number
164 ; Convert to and patch I/O register index
171 ; The AppleMouse II Card needs the ROM switched in
172 ; to be able to detect an Apple //e and use RDVBL
175 ; Reset mouse hardware
179 ; Switch in LC bank 2 for R/O
187 ; Set initial mouse clamps
192 ; Set initial mouse position
208 ; Turn VBL interrupt on
213 ; Enable interrupts and return success
219 ; UNINSTALL: Is called before the driver is removed from memory.
220 ; No return code required (the driver is removed from memory on return).
229 bne common ; Branch always
231 ; SETBOX: Set the mouse bounding box. The parameters are passed as they come
232 ; from the C program, that is, a pointer to a mouse_box struct in A/X.
233 ; No checks are done if the mouse is currently inside the box, this is the job
234 ; of the caller. It is not necessary to validate the parameters, trust the
235 ; caller and save some code here. No return code required.
249 ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse:
250 ; "Disable interrupts before placing position information in the
279 bne common ; Branch always
281 ; GETBOX: Return the mouse bounding box. The parameters are passed as they
282 ; come from the C program, that is, a pointer to a mouse_box struct in A/X.
287 ldy #.sizeof(MOUSE_BOX)-1
294 ; MOVE: Move the mouse to a new position. The position is passed as it comes
295 ; from the C program, that is: x on the stack and y in A/X. The C wrapper will
296 ; remove the parameter from the stack on return.
297 ; No checks are done if the new position is valid (within the bounding box or
298 ; the screen). No return code required.
310 ldy #$00 ; Start at top of stack
323 bne common ; Branch always
325 ; HIDE: Is called to hide the mouse cursor. The mouse kernel manages a
326 ; counter for calls to show/hide, and the driver entry point is only called
327 ; if the mouse is currently visible and should get hidden. For most drivers,
328 ; no special action is required besides hiding the mouse cursor.
329 ; No return code required.
336 ; SHOW: Is called to show the mouse cursor. The mouse kernel manages a
337 ; counter for calls to show/hide, and the driver entry point is only called
338 ; if the mouse is currently hidden and should become visible. For most drivers,
339 ; no special action is required besides enabling the mouse cursor.
340 ; No return code required.
347 ; BUTTONS: Return the button mask in A/X.
349 lda info + MOUSE_INFO::BUTTONS
353 ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1.
354 ; No return code required.
356 ldy #.sizeof(MOUSE_POS)-1
357 bne copy ; Branch always
359 ; INFO: Returns mouse position and current button mask in the MOUSE_INFO
360 ; struct pointed to by ptr1. No return code required.
362 ldy #.sizeof(MOUSE_INFO)-1
371 ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
372 ; specific data in ptr1, and the ioctl code in A.
373 ; Must return an MOUSE_ERR_xx code in A/X.
375 lda #<MOUSE_ERR_INV_IOCTL
376 ldx #>MOUSE_ERR_INV_IOCTL
379 ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
380 ; registers are already saved, no parameters are passed, but the carry flag
381 ; is clear on entry. The routine must return with carry set if the interrupt
382 ; was handled, otherwise with carry clear.
384 ; Check for installed mouse
388 ; Check for mouse interrupt
392 clc ; Interrupt not handled
403 ; Extract button down values
404 asl ; C = Button 0 is currently down
405 and #%00100000 ; !Z = Button 1 is currently down
412 : sta info + MOUSE_INFO::BUTTONS
414 ; Check for mouse movement
416 and #%00100000 ; X or Y changed since last READMOUSE
419 ; Remove the cursor at the old position
422 ; Get and set the new X position
426 sta info + MOUSE_POS::XCOORD
427 stx info + MOUSE_POS::XCOORD+1
430 ; Get and set the new Y position
434 sta info + MOUSE_POS::YCOORD
435 stx info + MOUSE_POS::YCOORD+1
438 ; Draw the cursor at the new position
440 sec ; Interrupt handled