💾 Archived View for mirrors.apple2.org.za › archive › ground.icaen.uiowa.edu › Faqs › R034MOUSEPRG.T… captured on 2023-01-29 at 05:17:33.

View Raw

More Information

-=-=-=-=-=-=-

The comp.sys.apple2 Usenet newsgroup Apple II FAQs originate from
the Ground Apple II archive. Administrator: Steve Nelson

Csa2 FAQs-on-Ground resource file: R034MOUSEPRG.TXT

Writing Programs Which Use the Mouse


Note: To correctly view tables and diagrams on a super-res display,
 use a mono-spaced Font such as CoPilot or PCMononspaced.

____________________________





Writing Programs Which Use the Mouse

by David Empson



The assembly language interface to the mouse firmware is documented in three
places:

- the reference material that was supplied with the AppleMouse card for the
  IIe.

- the IIc Technical Reference Manual.

- the IIgs Firmware Reference Manual.

Interfacing to the mouse is somewhat complicated, especially if you want to
implement some kind of mouse cursor (usually requires writing an interrupt
handler).

The first problem is locating the mouse firmware.  It could be in any slot
for a IIe or IIgs, or either of two slots for the IIc.  The safest method is
just to do a slot search, looking for the mouse ID bytes:

$Cn05 = $38
$Cn07 = $18
$Cn0B = $01
$Cn0C = $20
$CnFB = $D6

where n= Slot number

On a ROM 3 IIgs, it is possible that the mouse firmware will not be
available, because this doesn't prevent the use of the mouse from GS/OS (the
Miscellaneous Toolset or Event Manager can still be used). An AppleMouse card,
if installed, is not used by the toolbox.

On a ROM 1 IIgs, the slot mouse firmware is used by the toolbox, so slot 4
must be set to "Mouse Port", or an AppleMouse card may be installed in any
slot.


Using the mouse firmware consists of calling the various parameters provided
by the firmware.  An entry point table is provided in the mouse slot.  The
routines common to all implementations are:

$Cn12    SETMOUSE      Sets mouse mode
$Cn13    SERVEMOUSE    Services mouse interrupt
$Cn14    READMOUSE     Reads mouse position
$Cn15    CLEARMOUSE    Clears mouse position to 0 (for delta mode)
$Cn16    POSMOUSE      Sets mouse position to a user-defined pos
$Cn17    CLAMPMOUSE    Sets mouse bounds in a window
$Cn18    HOMEMOUSE     Sets mouse to upper-left corner of clamp win
$Cn19    INITMOUSE     Resets mouse clamps to default values;
                       sets mouse position to 0,0

Each of the above locations contains the low byte of the entry point for the
routine.  The high byte is $Cn.  The usual method for calling these routines
is to set up a single subroutine which is patched with the location of the
appropriate routine as required.  You could also set up a series of
subroutines for calling each routine.

The general logic would be as follows:

Locate the mouse slot by searching for the ID bytes described earlier. Patch
the slot into the following routine:

TOMOUSE  LDX #$C1   ; Patch operand byte with slot in $Cn form
         LDY #$10   ; Patch operand byte with slot in $n0 form
         JMP $C100  ; Patch high byte of operand with slot in
                    ; $Cn form.  Low byte of operand must be
                    ; patched with entry point from table above

You should also set up a pair of locations on zero page containing $Cn00,
which will be used to look up the table.  You can then have code as follows to
call each of the routines:

MOUSEPTR EQU $00    ; (or some other pair of zero page locations)

SETMOUSE
         LDY #$12      ; Offset to entry point
         BNE GOMOUSE   ; Go to the mouse routine - always taken

SERVEMOUSE
         LDY #$13      ; Offset to entry point
         BNE GOMOUSE   ; Go to the mouse routine - always taken

[etc. - one routine for each mouse call you will be using]

GOMOUSE  TAX               ; Preserve the value in A
         LDA (MOUSEPTR),Y  ; Get the routine entry point
         STA TOMOUSE+5     ; Patch the JMP instruction
         TXA               ; Restore the value in A

; The following operand bytes must be patched by the
; initialization code which detects the mouse.

TOMOUSE  LDX #$C1          ; Set up slot in $Cn form in X
         LDY #$10          ; Set up slot in $n0 form in Y
         JMP $C100         ; Go to the mouse routine


With code like the above, your program can just use JSR INITMOUSE, etc. to
call the appropriate routine.

The mouse routines make use of screen holes for the slot containing the mouse
interface firmware/card.  The screen holes are as follows:

$0478 + slot        Low byte of absolute X position
$04F8 + slot        Low byte of absolute Y position
$0578 + slot        High byte of absolute X position
$05F8 + slot        High byte of absolute Y position
$0678 + slot        Reserved and used by the firmware
$06F8 + slot        Reserved and used by the firmware
$0778 + slot        Button 0/1 interrupt status byte
$07F8 + slot        Mode byte

You can access the screen holes by getting the mouse slot number in the $Cn
form (LDX TOMOUSE+1), then indexing off the above locations minus $C0 with X
(or just AND the value with $0F and use the base addresses directly).

The screen holes should be used only as specified by the mouse routines
below. You should never write to them, except as specified by POSMOUSE.

The interrupt status byte is defined as follows:

Bit 7 6 5 4 3 2 1 0
    | | | | | | | |
    | | | | | | | \---  Previously, button 1 was up (0) or down (1)
    | | | | | | \-----  Movement interrupt
    | | | | | \-------  Button 0/1 interrupt
    | | | | \---------  VBL interrupt
    | | | \-----------  Currently, button 1 is up (0) or down (1)
    | | \-------------  X/Y moved since last READMOUSE
    | \---------------  Previously, button 0 was up (0) or down (1)
    \-----------------  Currently, button 0 is up (0) or down (1)

(Button 1 is not physically present on the mouse, and is probably
only supported for an ADB mouse on the IIgs.)


The mode byte is defined as follows.

Bit 7 6 5 4 3 2 1 0
    | | | | | | | |
    | | | | | | | \---  Mouse off (0) or on (1)
    | | | | | | \-----  Interrupt if mouse is moved
    | | | | | \-------  Interrupt if button is pressed
    | | | | \---------  Interrupt on VBL
    | | | \-----------  Reserved
    | | \-------------  Reserved
    | \---------------  Reserved
    \-----------------  Reserved


The button and movement status are only valid after calling READMOUSE.
Interrupt status bits are only valid after SERVEMOUSE and are cleared by
READMOUSE.  The appropriate screen hole information must be copied elsewhere
before enabling interrupts with CLI or PLP.


The routines are used as follows.  X and Y must be set up with $Cn and $n0 in
all cases.  Interrupts must be disabled before calling any of these routines.
Assume all registers are scrambled on exit unless otherwise noted.

SETMOUSE

          Sets mouse operation mode.

   Entry: A = mouse operation mode ($00 to $0F) - see mode byte.

   Exit:  C = 1 if illegal mode entered.
          Screen hole mode byte is updated.


SERVEMOUSE

          Tests for interrupt from mouse and resets mouse's
          interrupt line.

   Exit:  C = 0 if mouse interrupt occurred.
          Screen hole interrupt status bits are updated to show
          current status.


READMOUSE

          Reads delta (X/Y) positions, updates absolute X/Y pos,
          and reads button statuses from the mouse.

   Exit:  C = 0 (always).
          Screen hole positions and button/movement status bits are
          updated, interrupt status bits are cleared.


CLEARMOUSE

          Resets buttons, movement and interrupt status 0.
         (This routine is intended to be used for delta mouse
          positioning instead of absolute positioning.)

   Exit:  C = 0 (always).
          Screen hole positions and button/movement status bits are
          updated, interrupt status bits are cleared.


POSMOUSE

          Allows caller to change current mouse position.

   Entry: Caller places new absolute X/Y positions directly in
          appropriate screen holes.

   Exit:  C = 0 (always).
          Screen hole positions may be updated if necessary (e.g.
          clamping).


CLAMPMOUSE

          Sets up clamping window for mouse user.  Power up default
          values are 0 to 1023 ($0000 to $03FF).

   Entry: A = 0 if entering X clamps, 1 if entering Y clamps.

          Clamps are entered in slot 0 screen holes as follows.
          NOTE: these are NOT indexed by the mouse slot number.

          $0478 = low byte of low clamp.
          $04F8 = low byte of high clamp.
          $0578 = high byte of low clamp.
          $05F8 = high byte of high clamp.

   Exit:  C = 0 (always).
          Screen hole position is set to top left corner of clamping
          window for the IIgs.

   Note:  The IIgs automatically homes the mouse when this call is
          made, but this doesn't happen for the IIc and AppleMouse
          card.


HOMEMOUSE

          Sets the absolute position to upper-left corner of
          clamping window.

   Exit:  C = 0 (always).
          Screen hole positions are updated.


INITMOUSE

          Sets screen holes to default values and sets clamping win
          to default value of 0 to 1023 in both X and Y directions,
          resets hardware.

   Exit:  C = 0 (always).
          Screen holes are updated.



The general method of using the mouse firmware is as follows:

- Call SETMOUSE specifying a mode of 1 (enabled, no interrupts).
- Call INITMOUSE.
- Call CLAMPMOUSE to set up the required clamps (once per ea axis).
- If necessary, call SETMOUSE again with the actual mode you want.
  You must set up a ProDOS interrupt handler if you want to use the
  interrupt modes.

If you are using polled mode, call READMOUSE as required to update the mouse
position and button status information.

If you are using interrupt mode, your interrupt handler should call
SERVEMOUSE to check for a mouse interrupt.  If none occurred, return to ProDOS
with C=1. If one did occur, note the type of interrupt (if necessary), then
call READMOUSE to the new position information, and copy the data elsewhere.
Finally, return to ProDOS with C=0.

When your program is finished, it should disable the mouse by using SETMOUSE
with A=0, and remove the interrupt handler (if necessary).


David Empson