mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-04 01:29:22 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
2346 lines
76 KiB
Plaintext
2346 lines
76 KiB
Plaintext
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; File: CrsrDev.a
|
|
;
|
|
; Contains: This file holds the new cursor device implementation, including new mouse
|
|
; /trackball handler and the new acceleration routines for jCrsrTask.
|
|
;
|
|
; Written by: Gary Rensberger (based on Dan Venolia's Cursory API) [11/20/91]
|
|
;
|
|
; Copyright: © 1991-1993 by Apple Computer, Inc. All rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM7> 5/28/93 IH Add comment about Display Mgr usage of CrsrNew.
|
|
; <SM6> 12/01/92 HY Fix a bug with uncoupled cursors(fixes MS Flight Simulator v4.0).
|
|
; Fixed a cursor flicker problem on slower machines like LC930. The
|
|
; cursor is drawn prior to calculating new positions of devices. The
|
|
; calculations were using up all the available VBL time, causing the
|
|
; flicker (cursor is drawn every other VBL, and calculations performed
|
|
; every other VBL).
|
|
; <SM5> 8/26/92 kc Roll in Horror changes.
|
|
; <H18> 7/24/92 GMR Fixed comaptibility problem with Hypercard/MacPaint Grid drawing
|
|
; mode (Atkinsons MouseMask secret).
|
|
; <H17> 7/17/92 GMR Changed the double-click translation table to match the Mouse
|
|
; CDEVs double-click times.
|
|
; <H16> 7/14/92 GMR Reset MBState to button up in CrsrDevReInit code.
|
|
; <H15> 7/13/92 djw <GED> Added code in InitCrsrDev to initialize vectors for:
|
|
; DrawCursor, EraseCursor, the @drawCursor section of the new VBL,
|
|
; and a hook for SetCrsrData. Also added default vector code for
|
|
; the above.
|
|
; <H14> 7/13/92 GMR Re-arranged the initialization routine so that our expandmem
|
|
; globals are created before InitADB, then InitADB is called.
|
|
; Update MBTicks when a button goes down, since Andy looks at it
|
|
; (shame on you!).
|
|
; <H13> 7/6/92 GMR Update doubleTime lowmem when creating a new device.
|
|
; <H12> 6/29/92 BG Changed AERROR message in the overpatching check at the bottom
|
|
; of the file to refer to the correct file being too big (you're
|
|
; welcome, Steve).
|
|
; <H11> 6/26/92 GMR <SKH> Modified CrsrDevHandleADB to handle extended device data,
|
|
; ie: more than 2 buttons and up to 16bit resolution. Changed
|
|
; CrsrNewDevice to properly init cntButtons (it was moving a word
|
|
; into cntButtons). Changed CrsrDevSetAccel to enter the debugger
|
|
; if no 'accl' resources do not exist.
|
|
; <H10> 6/10/92 GMR Fixed bug with buttonCount not being reset after waking up from
|
|
; sleep.
|
|
; <H9> 6/5/92 GMR Changed the movem's in the trap selector dispatcher to be
|
|
; movem.l.
|
|
; <H8> 6/1/92 GMR Removed the extra 'default' device created for address 3, since
|
|
; testers complained. Now, if a second mouse (or 1st mouse on
|
|
; portables) is added while the machine is running, it's
|
|
; acceleration won't be correct. Tough shit).
|
|
; <H7> 5/12/92 JC Fixed problem with CrsrDevHandleVBL trashing registers.
|
|
; <H6> 4/3/92 SWC Added overpatch padding at the end of the file.
|
|
; <H5> 3/11/92 SWC <GMR> Setup so second trackball button will behave just like the first
|
|
; one. Exported CrsrDevDispatch now that we have a trap for it.
|
|
; <H4> 3/9/92 SWC <GMR> Fixed bug in CrsrDevSetAccel where the acceleration to set
|
|
; <SM4> 7/30/92 fau Made the MOVEM instructions in CrsrDevDispatch and StdExit be a
|
|
; MOVEM.L. This fixes a bug in the Mouse cdev in Cyclone where
|
|
; the MOVEM was assembled to a MOVEM.W which sign-extends to 32
|
|
; bits when writing back to a register!.
|
|
; <SM3> 7/7/92 CSS Change name of include from ApplDeskBusPriv.a to
|
|
; AppleDeskBusPriv.a to bring in line with Reality.
|
|
; The file "ApplDeskBusPriv.a" was inadvertently
|
|
; brought in from Horror.
|
|
; <SM2> 5/29/92 KW (JC,H7) Fixed problem with CrsrDevHandleVBL trashing registers.
|
|
; <SM1> 5/2/92 kc Roll in Horror. Comments follow:
|
|
; <H6> 4/3/92 SWC Added overpatch padding at the end of the file.
|
|
; <H5> 3/11/92 SWC Setup so second trackball button will behave just like the first
|
|
; one. Exported CrsrDevDispatch now that we have a trap for it.
|
|
; <H4> 3/9/92 SWC GMR/Fixed bug in CrsrDevSetAccel where the acceleration to set
|
|
; is 0. Added more compatiblity code to jCrsrTask so the VU test
|
|
; tool will work. Setup address 3 to be a default device with 100
|
|
; dpi resolution, so if a user unplugs then plugs in a mouse, it
|
|
; will work.
|
|
; <H3> 2/17/92 SWC Used different registers in FindResource since the _GetResource
|
|
; call can trash D0-D2. Changed references to CrsrDevRec.resolution
|
|
; to a long since it's a fixed point number.
|
|
; <H2> 2/14/92 SWC Added a RomMapInsert before all resource calls so we make sure
|
|
; we at least find our resources in the ROM.
|
|
; <H1> 2/12/92 GMR First checked in.
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
INCLUDE 'EgretEqu.a'
|
|
INCLUDE 'IOPEqu.a'
|
|
INCLUDE 'AppleDeskBusPriv.a'
|
|
INCLUDE 'CrsrDevEqu.a'
|
|
PRINT ON
|
|
|
|
MACHINE MC68020
|
|
|
|
|
|
_FixDiv OPWORD $A84D
|
|
|
|
|
|
|
|
|
|
CrsrDev PROC
|
|
|
|
EXPORT InitCrsrDev,CrsrDevDispatch
|
|
IMPORT CrsrVBLTask
|
|
|
|
WITH CrsrDevGlobals, CrsrDevRec, CrsrDevSegment, CrsrDataRec
|
|
WITH ADBDeviceEntry, ADBVars, ExpandMemRec
|
|
|
|
|
|
_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevDispatch (trap # $AADB)
|
|
;
|
|
; Inputs: d0.w - selector
|
|
; 4(sp) - last parameter
|
|
; 8(sp) - 2nd to last parameter
|
|
;
|
|
; Outputs: d0 - result code
|
|
;
|
|
; Destroys: a0
|
|
;
|
|
; Function: This routine is our selector based dispatcher for the exported
|
|
; CrsrDev routines. It follows toolbox conventions (e.g. parameters
|
|
; are passed in on the stack, with the function selector in D0).
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevDispatch
|
|
link a6,#0 ; parameters referenced off a6
|
|
movem.l a1-a3/d1-d3,-(sp) ; save a bunch of registers
|
|
add.w d0,d0 ; (shift so we work on 68000's)
|
|
lea @jmpTable,a0 ; point to our jump table
|
|
adda.w (a0,d0.w),a0 ; add offset to routine
|
|
jmp (a0) ; jump to selected routine
|
|
|
|
;-------------------------------
|
|
|
|
|
|
@jmpTable dc.w CrsrDevMoveTrap- @jmpTable ; Selector 0
|
|
dc.w CrsrDevMoveToTrap- @jmpTable ; 1
|
|
dc.w CrsrDevFlushTrap- @jmpTable ; 2
|
|
|
|
dc.w CrsrDevButtonsTrap- @jmpTable ; 3
|
|
dc.w CrsrDevButtonDownTrap- @jmpTable ; 4
|
|
dc.w CrsrDevButtonUpTrap- @jmpTable ; 5
|
|
dc.w CrsrDevButtonOpTrap- @jmpTable ; 6
|
|
dc.w CrsrDevSetButtonsTrap- @jmpTable ; 7
|
|
|
|
dc.w CrsrDevSetAccelTrap- @jmpTable ; 8
|
|
dc.w CrsrDevDoubleTimeTrap- @jmpTable ; 9
|
|
dc.w CrsrDevSetUnitsPerInchTrap- @jmpTable ; 10
|
|
|
|
dc.w CrsrDevNextDeviceTrap- @jmpTable ; 11
|
|
dc.w CrsrDevNewDeviceTrap- @jmpTable ; 12
|
|
dc.w CrsrDevDisposeDevTrap- @jmpTable ; 13
|
|
|
|
|
|
|
|
;-------------------------------
|
|
stdExit movem.l (sp)+,a1-a3/d1-d3 ; restore registers
|
|
unlk a6
|
|
move.l (sp)+,a0
|
|
add.w d0,sp ; dump parameters
|
|
jmp (a0)
|
|
|
|
|
|
|
|
|
|
|
|
userFrame RECORD 0,increment
|
|
saveA6 ds.l 1
|
|
returnAddr ds.l 1
|
|
paramBase equ * ; ptr to base of parameters
|
|
ENDR
|
|
|
|
|
|
WITH userFrame
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevMoveTrap
|
|
;
|
|
; Inputs: 8(a6).l - delta Y
|
|
; 12(a6).l - delta X
|
|
; 16(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: d1-d2,a1-a2
|
|
;
|
|
; Function: This routine accumulates given deltas for crsrDev, and
|
|
; flags that is has new data. The next time the cursor position
|
|
; is computed, dh and dv will be run through the acceleration
|
|
; algorithm and will contribute to the cursor movement.
|
|
;====================================================================
|
|
|
|
CrsrDevMoveTrap
|
|
|
|
move.l paramBase(a6),d1 ; Æy in d1
|
|
move.l paramBase+4(a6),d0 ; Æx in d0
|
|
move.l paramBase+8(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevMove ; accumulate the deltas
|
|
move.w d0,paramBase+12(a6) ; result code
|
|
moveq #12,d0 ; dump three parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevMoveToTrap
|
|
;
|
|
; Inputs: 8(a6).l - V
|
|
; 12(a6).l - H
|
|
; 16(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: d1,a1-a2
|
|
;
|
|
; Function: This routine transforms the coordinates (h,v) to screen
|
|
; space so that the next time the cursor position is computed
|
|
; it jumps to that point and any relative movement will be ignored.
|
|
;====================================================================
|
|
|
|
CrsrDevMoveToTrap
|
|
|
|
move.l paramBase+8(a6),a2 ; crsrDevRec in a2
|
|
move.l whichCursor(a2),a1 ; a1 pts to cursor globals
|
|
|
|
moveq #0,d0
|
|
move.l paramBase(a6),d0 ; get V coord
|
|
swap d0 ; convert to fixed
|
|
move.l d0,whereY(a1) ; = whereY
|
|
|
|
moveq #0,d0
|
|
move.l paramBase+4(a6),d0 ; get H coord
|
|
swap d0 ; convert to fixed
|
|
move.l d0,whereX(a1) ; = whereX
|
|
|
|
st.b isAbs(a1) ; absolute mode
|
|
|
|
clr.w paramBase+12(a6) ; result code
|
|
moveq #12,d0 ; dump three parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevFlushTrap
|
|
;
|
|
; Inputs: 8(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2
|
|
;
|
|
; Function: This routine explicitly ends the relative device move,
|
|
; flushing out the error accumulators.
|
|
;====================================================================
|
|
|
|
CrsrDevFlushTrap
|
|
|
|
move.l paramBase(a6),a2 ; crsrDevRec in a2
|
|
|
|
move.l errorX(a2),d0 ; accumulate previous errors into
|
|
add.l d0,deltaX(a2) ; our deltas
|
|
move.l errorY(a2),d0
|
|
add.l d0,deltaY(a2)
|
|
|
|
clr.l errorX(a2) ; then flush the errors
|
|
clr.l errorY(a2)
|
|
move.w #-108,denom(a2) ; ???
|
|
|
|
clr.w paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevButtonsTrap
|
|
;
|
|
; Inputs: 8(a6).w - new button states (1 = down, 0 = up)
|
|
; 10(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a2,d1-d3
|
|
;
|
|
; Function: This routine handles button debounce and event posting. If the
|
|
; mouse button bounces, we don't want it to look like a double click,
|
|
; so if we see a mouse down less than 2 VBLs after a mouse up, we will
|
|
; ignore it, and consider the mouse to still be up. We will never
|
|
; ignore a mouse up event, which could lead to menus hanging and
|
|
; continuous scrolling.
|
|
;====================================================================
|
|
|
|
CrsrDevButtonsTrap
|
|
|
|
move.w paramBase(a6),d0 ; button states in d0
|
|
move.l paramBase+2(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevButtons ; handle button debounce/actions
|
|
move.w d0,paramBase+6(a6) ; result code
|
|
moveq #6,d0 ; dump two parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevButtonDownTrap
|
|
;
|
|
; Inputs: 8(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a2,d1
|
|
;
|
|
; Function: Posts a button down event if this is the 1st button to go down
|
|
;====================================================================
|
|
|
|
CrsrDevButtonDownTrap
|
|
|
|
move.l paramBase(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevButtonDown ; handle button down actions
|
|
move.w d0,paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevButtonUpTrap
|
|
;
|
|
; Inputs: 8(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a2,d1
|
|
;
|
|
; Function: Posts a button up event if this is the last button to go up.
|
|
;====================================================================
|
|
|
|
CrsrDevButtonUpTrap
|
|
|
|
move.l paramBase(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevButtonUp ; handle button up actions
|
|
move.w d0,paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevButtonOpTrap
|
|
;
|
|
; Inputs: 8(a6).l - Operation specific data
|
|
; 12(a6).w - Operation code
|
|
; 14(a6).w - Button #
|
|
; 16(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2,d1-d2
|
|
;
|
|
; Function: This routine sets a new operation to be associated with the
|
|
; given button. The optional data field is set as well.
|
|
;====================================================================
|
|
|
|
CrsrDevButtonOpTrap
|
|
|
|
move.w paramBase+6(a6),d0 ; button # in d0
|
|
move.l paramBase+8(a6),a2 ; crsrDevRec in a2
|
|
move.b paramBase+5(a6),buttonOp(a2,d0.w) ; stuff the new operation code
|
|
lsl.w #2,d0
|
|
move.l paramBase(a6),buttonData(a2,d0.w) ; and the new data (if any)
|
|
clr.w paramBase+12(a6) ; result code
|
|
moveq #12,d0 ; dump four parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevSetButtonsTrap
|
|
;
|
|
; Inputs: 8(a6).w - # buttons for this device
|
|
; 10(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2
|
|
;
|
|
; Function: This routine sets the total # of buttons for the given
|
|
; device.
|
|
;====================================================================
|
|
|
|
CrsrDevSetButtonsTrap
|
|
|
|
move.l paramBase+2(a6),a2 ; crsrDevRec in a2
|
|
move.b paramBase+1(a6),cntButtons(a2) ; only use a byte of the word
|
|
clr.w paramBase+6(a6) ; result code
|
|
moveq #6,d0 ; dump two parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevSetAccelTrap
|
|
;
|
|
; Inputs: 8(a6).l - acceleration (Fixed)
|
|
; 12(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2,d1-d2
|
|
;
|
|
; Function: This routine installs the proper acceleration table for
|
|
; the specified device, based on the passed in acceleration
|
|
; value.
|
|
;====================================================================
|
|
|
|
CrsrDevSetAccelTrap
|
|
|
|
move.l paramBase(a6),d0 ; acceleration
|
|
move.l paramBase+4(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevSetAccel ; generate acceleration table
|
|
move.w d0,paramBase+8(a6) ; result code
|
|
moveq #8,d0 ; dump two parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevDoubleTimeTrap
|
|
;
|
|
; Inputs: 8(a6).l - duration (ticks)
|
|
; 12(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2
|
|
;
|
|
; Function: This routine changes the double-click time for crsrDev to
|
|
; the indicated value. When crsrDev is clicked, it's double-
|
|
; click time is stuffed into the low-memory global DoubleTime.
|
|
; An application responding to the mouse-down event can check
|
|
; DoubleTime to determine whether to interpret a double-click.
|
|
;====================================================================
|
|
|
|
CrsrDevDoubleTimeTrap
|
|
|
|
move.l paramBase+4(a6),a2 ; crsrDevRec in a2
|
|
move.l paramBase(a6),doubleClickTime(a2) ; stuff the new value
|
|
move.w #0,paramBase+8(a6) ; result code
|
|
moveq #8,d0 ; dump two parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevSetUnitsPerInchTrap
|
|
;
|
|
; Inputs: 8(a6).l - resolution (fixed)
|
|
; 12(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a2
|
|
;
|
|
; Function: May be called if the software knows more about the resolution
|
|
; of the device than can be found from the ADB bus, e.g. for a
|
|
; serial device. Calls CrsrDevSetAcceleration (with the current
|
|
; accel value) to recompute the acceleration tables for the device,
|
|
; so the resource file that contains the 'accl' resource should be
|
|
; open.
|
|
;====================================================================
|
|
|
|
CrsrDevSetUnitsPerInchTrap
|
|
|
|
move.l paramBase+4(a6),a2 ; crsrDevRec in a2
|
|
move.l paramBase(a6),resolution(a2) ; set new resolution for this device
|
|
|
|
move.l acceleration(a2),d0 ; get current acceleration
|
|
bsr CrsrDevSetAccel ; generate acceleration table, based on new resolution
|
|
|
|
move.w #0,paramBase+8(a6) ; result code
|
|
moveq #8,d0 ; dump two parameters on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevNextDeviceTrap
|
|
;
|
|
; Inputs: 8(a6).l - VAR ptr to CrsrDevRec
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: none
|
|
;
|
|
; Function: When given NIL, returns the head of the global device list.
|
|
; When given a pointer to a cursor device reocrd, returns a
|
|
; pointer to the next one in the global device list.
|
|
;====================================================================
|
|
|
|
CrsrDevNextDeviceTrap
|
|
|
|
move.l paramBase(a6),a2 ; address of crsrDevRec ptr in a2
|
|
move.l (a2),a2 ; crsrDevRec ptr in a2
|
|
move.l a2,d0
|
|
beq.s @nil ; if NIL, special case
|
|
|
|
move.l nextCrsrDev(a2),a2 ; else, get next link
|
|
bra.s @exit
|
|
|
|
@nil movea.l ExpandMem,a2 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a2),a2 ; get cursory global ptr
|
|
move.l firstCrsrDev(a2),a2 ; get ptr to 1st CrsrDevRec
|
|
|
|
@exit move.l paramBase(a6),a0 ; get address of where to store crsrDevRec
|
|
move.l a2,(a0) ; return next crsrDevRec
|
|
|
|
move.w #0,paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevNewDeviceTrap
|
|
;
|
|
; Inputs: 8(a6).l - VAR pointer to CrsrDevRec
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: none
|
|
;
|
|
; Function: This routine creates a new CrsrDevRec, adds it to the
|
|
; linked list of device records, and initializes it's fields.
|
|
; Note: the caller must call CrsrDevSetAcceleration after
|
|
; calling this routine.
|
|
;====================================================================
|
|
|
|
CrsrDevNewDeviceTrap
|
|
|
|
bsr CrsrDevNewDevice ; create a new cursor device
|
|
move.l paramBase(a6),a0 ; address of crsrDevRec ptr in a2
|
|
move.l a2,(a0) ; return crsrDevRec pointer
|
|
move.w d0,paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
|
|
|
|
;====================================================================
|
|
;
|
|
; Routine: CrsrDevDisposeDevTrap
|
|
;
|
|
; Inputs: 8(a6).l - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: d1-d2,a0-a1
|
|
;
|
|
; Function: This routine eliminates CrsrDevRec from the linked list
|
|
; of device records, and disposes of all storage related to
|
|
; it.
|
|
;====================================================================
|
|
|
|
CrsrDevDisposeDevTrap
|
|
|
|
move.l paramBase(a6),a2 ; crsrDevRec in a2
|
|
bsr CrsrDevDisposeDev ; create a new cursor device
|
|
move.w d0,paramBase+4(a6) ; result code
|
|
moveq #4,d0 ; dump one parameter on exit
|
|
jmp stdExit ;
|
|
|
|
ENDWITH
|
|
|
|
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevHandleADB
|
|
;
|
|
; Inputs: a0 - pointer to mouse data
|
|
; a2 - pointer to CrsrDevRec for this device
|
|
; d0 - command byte
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: a0-a3/d0-d3
|
|
;
|
|
; Function: This routine is installed as the ADB service routine for all
|
|
; ADDR=03 relative devices. It decodes the ADB packet and
|
|
; passes the information to CrsrDevMove and CrsrDevButtons.
|
|
; This routine now handles old or new style packets.
|
|
;
|
|
; The packet has the following format:
|
|
; Byte# bits: 7 6 5 4 3 2 1 0
|
|
; 0 b0 y6 y5 y4 y3 y2 y1 y0
|
|
; 1 b1 x6 x5 x4 x3 x2 x1 x0
|
|
; 2 b2 y9 y8 y7 b3 x9 x8 x7 (optional) <H11>
|
|
; 3 b4 y12 y11 y10 b5 x12 x11 x10 (optional) <H11>
|
|
; 4 b6 y15 y14 y13 b7 x15 x14 x13 (optional) <H11>
|
|
;
|
|
; Where bn is button n (1 = not pressed, 0 = pressed)
|
|
; xn is bit n of the x delta information
|
|
; yn is bit n of the y delta information
|
|
;
|
|
; NOTE: The current approach for extracting the extended
|
|
; resolution information is kinda ugly. However, it is
|
|
; fast and I have been unable to construct an efficent, general,
|
|
; function for extracting the awkward 3bit fields in bytes 2 through
|
|
; n (currently n is 4). - SKH
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevHandleADB
|
|
move.b d0,d2 ; save command in D2.
|
|
move.l a2,d0 ; do we have globals?
|
|
beq @exit ; no, exit
|
|
|
|
lea 1(a0),a3 ; skip over length byte, free up A0
|
|
|
|
@x0to6 moveq.l #$7F,d0 ; prepare to mask button off
|
|
and.b 1(a3),d0 ; get 2nd data byte (Æ horiz)
|
|
|
|
@y0to6 moveq.l #$7F,d1 ; prepare to mask off button
|
|
and.b (a3),d1 ; get 1st data byte (Æ vert)
|
|
|
|
@byte3 cmp.b #3,(a0) ; check to see if we have 3rd byte <H11>
|
|
bge.s @x7to9 ; if so, process it. else, extend sign <H11>
|
|
@byte3extx btst #6,d0 ; check sign bit (bit 6) <H11>
|
|
beq.s @byte3exty ; <H11>
|
|
or.w #$ff80,d0 ; fake a negative, faster than ext <H11>
|
|
@byte3exty btst #6,d1 ; check sign bit (bit 6) <H11>
|
|
beq @domove ; <H11>
|
|
or.w #$ff80,d1 ; fake a negative for y <H11>
|
|
bra.s @domove ; <H11>
|
|
|
|
@x7to9 moveq.l #$7,d2 ; move mask into workspace <H11>
|
|
and.b 2(a3),d2 ; get x bits 7-9 <H11>
|
|
lsl.w #7,d2 ; move them to add to running tally <H11>
|
|
or.w d2,d0 ; <H11>
|
|
@y7to9 moveq.l #$70,d2 ; mask the bits <H11>
|
|
and.b 2(a3),d2 ; get y bits 7-9 <H11>
|
|
lsl.w #3,d2 ; move and add to tally <H11>
|
|
or.w d2,d1 ; <H11>
|
|
|
|
@byte4 cmp.b #4,(a0) ; check to see if we have a 4th byte <H11>
|
|
bge.s @x10to12 ; <H11>
|
|
@byte4extx btst #9,d0 ; check sign bit (bit 9) <H11>
|
|
beq.s @byte4exty ; <H11>
|
|
or.w #$fc00,d0 ; fake a negative for x <H11>
|
|
@byte4exty btst #9,d1 ; check sign bit (bit 9) <H11>
|
|
beq.s @domove ; <H11>
|
|
or.w #$fc00,d1 ; fake a negative for y <H11>
|
|
bra.s @domove ; <H11>
|
|
|
|
@x10to12 moveq.l #$7,d2 ; move mask into workspace <H11>
|
|
and.b 3(a3),d2 ; get x bits 10-12 <H11>
|
|
lsl.w #8,d2 ; move them to add to running tally <H11>
|
|
lsl.w #2,d2 ; do a 10 bit shift <H11>
|
|
or.w d2,d0 ; <H11>
|
|
@y10to12 moveq.l #$70,d2 ; mask the bits <H11>
|
|
and.b 3(a3),d2 ; get y bits 10-12 <H11>
|
|
lsl.w #6,d2 ; move and add to tally <H11>
|
|
or.w d2,d1 ; <H11>
|
|
|
|
@byte5 cmp.b #5,(a0) ; check to see if we have a 5th byte <H11>
|
|
bge.s @x13to15 ; <H11>
|
|
@byte5extx btst #12,d0 ; check sign bit (bit 12) <H11>
|
|
beq.s @byte5exty ; <H11>
|
|
or.w #$e000,d0 ; fake a negative for x <H11>
|
|
@byte5exty btst #12,d1 ; check sign bit (bit 12) <H11>
|
|
beq.s @domove ; <H11>
|
|
or.w #$e000,d1 ; fake a negative for y <H11>
|
|
bra.s @domove ;
|
|
|
|
@x13to15 moveq.l #$7,d2 ; move mask into workspace <H11>
|
|
and.b 4(a3),d2 ; get x bits 13-15 <H11>
|
|
lsl.w #8,d2 ; move them to add to running tally <H11>
|
|
lsl.w #5,d2 ; do a 13 bit shift <H11>
|
|
or.w d2,d0 ; <H11>
|
|
@y13to15 moveq.l #$70,d2 ; mask the bits <H11>
|
|
and.b 4(a3),d2 ; get y bits 13-15 <H11>
|
|
lsl.w #8,d2 ; move and add to tally <H11>
|
|
lsl.w #1,d2 ; do a 9 bit shift <H11>
|
|
or.w d2,d1 ; <H11>
|
|
|
|
@domove ext.l d0 ; convert our words into longs
|
|
ext.l d1 ;
|
|
bsr.s CrsrDevMove ; accumulate movement
|
|
|
|
clr.l d0 ; assume all buttons up <H11>
|
|
@btn0 clr.l d1 ; start looking at button 0 <H11>
|
|
btst.b #7,(a3)+ ; is 1st button up? <H11>
|
|
bne.s @btn1 ; yes, check 2nd button <H11>
|
|
bset d1,d0 ; no, indicate button down <H11>
|
|
|
|
@btn1 addq.b #1,d1 ; go to the next button (button 1) <H11>
|
|
btst.b #7,(a3)+ ; is 2nd button up? <H11>
|
|
bne.s @btnn ; yes, handle all button states <H11>
|
|
bset d1,d0 ; no, indicate button down <H11>
|
|
|
|
@btnn
|
|
addq.b #1,d1 ; go to the next button <H11>
|
|
cmp.b cntButtons(a2),d1 ; compare current button number to num buttons <H11>
|
|
bge.s @setBtns ; set the buttons if we are done <H11>
|
|
|
|
btst.b #7,(a3) ; check the button for the high nibble <H11>
|
|
bne.s @btnn_high ; not pressed, check high nibble <H11>
|
|
bset d1,d0 ; record the press <H11>
|
|
|
|
@btnn_high addq.b #1,d1 ; other button in low nibble <H11>
|
|
btst.b #3,(a3)+ ; the button for this nibble <H11>
|
|
bne.s @btnn ; loop again <H11>
|
|
bset d1,d0 ; record the press <H11>
|
|
bra.s @btnn ; <H11>
|
|
|
|
@setBtns bsr CrsrDevButtons ; handle our buttons
|
|
|
|
@exit
|
|
rts
|
|
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevMove
|
|
;
|
|
; Inputs: d0.l - delta X
|
|
; d1.l - delta Y
|
|
; a2 - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a1,d0-d2
|
|
;
|
|
; Function: This routine accumulates given deltas for crsrDev, and
|
|
; flags that is has new data. The next time the cursor position
|
|
; is computed, dh and dv will be run through the acceleration
|
|
; algorithm and will contribute to the cursor movement.
|
|
;_______________________________________________________________________
|
|
|
|
tempParams RECORD 0,decrement
|
|
tempY ds.l 1 ; delta Y
|
|
tempX ds.l 1 ; delta X
|
|
tempSize EQU * ; size of our param block
|
|
ENDR
|
|
|
|
CrsrDevMove
|
|
WITH tempParams
|
|
|
|
link a6,#tempSize ; create temp area
|
|
|
|
tst.l d0 ; and X movement?
|
|
bne.s @cont ; yes, continue
|
|
tst.l d1 ; and Y movement?
|
|
beq @exit ; no, just exit
|
|
|
|
@cont move.l d0,tempX(a6) ; save delta X
|
|
move.l d1,tempY(a6) ; save delta Y
|
|
|
|
swap d0 ; word2Fix
|
|
clr.w d0
|
|
move.l d0,-(sp) ; convert delta X to Fixed (push on stack)
|
|
|
|
swap d1 ; word2Fix
|
|
clr.w d1
|
|
move.l d1,-(sp) ; convert delta Y to Fixed (push on stack)
|
|
|
|
tst.b newData(a2) ; was the previous poll after last VBL?
|
|
bne.s @accum ; yes, handle separately
|
|
|
|
move.l (sp)+,deltaY(a2) ; else, save it away
|
|
move.l (sp)+,deltaX(a2) ;
|
|
|
|
st.b newData(a2) ; indicate we have new data
|
|
bra.s @checkDir ; and see if direction changed
|
|
|
|
|
|
@accum move.l (sp)+,d0
|
|
add.l d0,errorY(a2) ; accumulate error y
|
|
|
|
move.l (sp)+,d0
|
|
add.l d0,errorX(a2) ; accumulate error x
|
|
|
|
move.w spread(a2),d0 ; adjust the length of the double-sample time
|
|
sub.w denom(a2),d0 ; this spread = old spread - denom
|
|
cmpi.w #30,d0
|
|
bge.s @spread ; skip if new spread >= 30
|
|
|
|
add.w d0,spread(a2) ; if new spread < 30 then
|
|
addq.w #1,spread(a2)
|
|
lsr.w spread(a2) ; spread := (spread + old spread + 1) / 2
|
|
|
|
@spread moveq #8,d0 ; else, spread out error over next several VBL's
|
|
move.w spread(a2),denom(a2)
|
|
cmp.w denom(a2),d0 ; clip demon to 0-8
|
|
bge.s @checkDir ;
|
|
move.w d0,denom(a2)
|
|
|
|
|
|
@checkDir move.l tempY(a6),d0 ; any dy?
|
|
beq.s @chkXchg ; no, check X
|
|
move.l errorY(a2),d1
|
|
eor.l d1,d0 ; yes, did it's direction change?
|
|
bpl.s @chkXchg ; no, check X
|
|
|
|
add.l d1,deltaY(a2) ; direction changed, adjust delta
|
|
clr.l errorY(a2) ; and stomp the error
|
|
|
|
@chkXchg move.l tempX(a6),d0 ; any dx?
|
|
beq.s @exit ; no, exit
|
|
move.l errorX(a2),d1
|
|
eor.l d1,d0 ; yes, did it's direction change?
|
|
bpl.s @exit ; no, exit
|
|
|
|
add.l d1,deltaX(a2) ; direction changed, adjust delta
|
|
clr.l errorX(a2) ; and stomp the error
|
|
|
|
@exit unlk a6
|
|
moveq #0,d0 ; result code
|
|
rts
|
|
|
|
ENDWITH
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevButtons
|
|
;
|
|
; Inputs: d0.b - new button states (1 = down, 0 = up)
|
|
; a2 - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a1,d1-d3
|
|
;
|
|
; Function: This routine handles button debounce and event posting. If the
|
|
; mouse button bounces, we don't want it to look like a double click, so if we
|
|
; see a mouse down less than 2 VBLs after a mouse up, we will ignore it, and
|
|
; consider the mouse to still be up. We will never ignore a mouse up event,
|
|
; which could lead to menus hanging and continuous scrolling.
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevButtons
|
|
move.b d0,d1 ; get current button(s) state in d1
|
|
moveq #8-1,d3 ; init our button counter...
|
|
|
|
@loop btst.l d3,d1 ; check next current button state
|
|
beq.s @nowUp ; branch if up
|
|
|
|
@nowDwn btst.b d3,buttons(a2) ; down now, was it down before?
|
|
bne.s @nextButton ; yes, do nothing, handle next button
|
|
|
|
move.l Ticks,d0
|
|
move.w d3,d2 ;
|
|
lsl.w #2,d2 ;
|
|
sub.l buttonTicks(a2,d2.w),d0 ;
|
|
add.l d0,RndSeed ; randomize our seed
|
|
subq.l #2,d0
|
|
bmi.s @nextButton ; exit if went down too quickly (bounce)
|
|
bset.b d3,buttons(a2) ; mark that we're really down...
|
|
bra.s @dispatch ; and handle the down event
|
|
|
|
@nowUp btst.b d3,buttons(a2) ; was it up before?
|
|
beq.s @nextButton ; yes, do nothing, handle next button
|
|
|
|
move.w d3,d2 ;
|
|
lsl.w #2,d2 ;
|
|
move.l Ticks,buttonTicks(a2,d2.w) ; time-stamp the button-up event
|
|
bclr.b d3,buttons(a2) ; mark that we're up
|
|
* bra.s @dispatch ; and handle the down event
|
|
|
|
@dispatch move.b buttonOp(a2,d3.w),d0 ; get the button operation in d0
|
|
ext.w d0
|
|
add.w d0,d0 ; button op * 2 (need to run on 68000)
|
|
lea @jmpTable,a0
|
|
adda.w (a0,d0.w),a0 ; base + offset = rtn address
|
|
jsr (a0) ; handle button (d3 = button#, a2 = CrsrDevRec)
|
|
; ¥ routine must preserve d1 ¥
|
|
@nextButton dbra d3,@loop
|
|
|
|
moveq #0,d0 ; result code
|
|
rts ; we're done
|
|
|
|
|
|
;---------------------------------------------------------
|
|
@jmpTable dc.w doNop - @jmpTable ;
|
|
dc.w doSingle - @jmpTable ;
|
|
dc.w doDouble - @jmpTable ;
|
|
dc.w doClickLock - @jmpTable ;
|
|
dc.w d0CharStroke - @jmpTable ;
|
|
dc.w doAppleScript - @jmpTable ;
|
|
dc.w doCustom - @jmpTable ;
|
|
|
|
doNop rts
|
|
|
|
;---------------------------------------------------------
|
|
doSingle
|
|
btst.b d3,buttons(a2) ; are we down?
|
|
beq.s @up ; no, skip
|
|
bsr.s CrsrDevButtonDown ; yes, handle button down
|
|
bra.s @done
|
|
@up bsr CrsrDevButtonUp ; yes, handle button up
|
|
@done rts
|
|
|
|
;---------------------------------------------------------
|
|
doDouble
|
|
btst.b d3,buttons(a2) ; are we down?
|
|
beq.s @up ; no, skip
|
|
bsr.s CrsrDevButtonDown ; yes, generate 2 clicks
|
|
bsr.s CrsrDevButtonUp ;
|
|
bsr.s CrsrDevButtonDown ;
|
|
bra.s @done
|
|
@up bsr.s CrsrDevButtonUp ; and finally button up
|
|
@done rts
|
|
|
|
;---------------------------------------------------------
|
|
doClickLock
|
|
tst.b buttonData(a2,d3.w) ; is this the 1st time?
|
|
bne.s @secondHit ; no, skip
|
|
btst.b d3,buttons(a2) ; are we down?
|
|
beq.s @firstUp ; no, skip
|
|
bsr.s CrsrDevButtonDown ; yes, generate button down event
|
|
bra.s @done
|
|
|
|
@firstUp st.b buttonData(a2,d3.w) ; first up, mark it
|
|
bra.s @done
|
|
|
|
@secondHit btst.b d3,buttons(a2) ; are we up (2nd time)?
|
|
bne.s @done ; no, do nothing...
|
|
bsr.s CrsrDevButtonUp ; yes, post up event
|
|
clr.b buttonData(a2,d3.w) ; mark that we're really up
|
|
@done rts
|
|
|
|
|
|
;---------------------------------------------------------
|
|
d0CharStroke
|
|
|
|
rts
|
|
|
|
;---------------------------------------------------------
|
|
doAppleScript
|
|
|
|
rts
|
|
|
|
;---------------------------------------------------------
|
|
doCustom
|
|
pea buttonData(a2) ; push our custom routine address
|
|
rts ; and call it.
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevButtonDown
|
|
;
|
|
; Inputs: a2 - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a1,d0
|
|
;
|
|
; Function: Posts a button down event if this is the 1st button to go down
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevButtonDown
|
|
move.l whichCursor(a2),a1 ; get ptr to target cursor data
|
|
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr
|
|
move.l firstCrsrData(a0),a0 ; a0 points to main cursor data record
|
|
cmpa.l a0,a1 ; is this the main cursor?
|
|
bne.s @count ; no, just count other cursor's button
|
|
|
|
move.l doubleClickTime(a2),doubleTime ; set our double-click time
|
|
|
|
tst.b buttonCount(a1) ; is this the first button to go down?
|
|
bne.s @count ; no, no need to post another eventÉ
|
|
tst.b MBState ; yes, was mouse up before (should be)?
|
|
bpl.s @count ; no, just count the down event
|
|
|
|
clr.b MBState ; now say the button is down...
|
|
moveq #0,d0 ; no message for PostEvent
|
|
move.w #mButDwnEvt,a0 ; Get event number
|
|
_PostEvent ; post the mouse down event
|
|
|
|
@count move.l Ticks,MBTicks ; update MBTicks for compatibility <H14>
|
|
addq.b #1,buttonCount(a1) ; count the button down
|
|
moveq #0,d0 ; result code
|
|
rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevButtonUp
|
|
;
|
|
; Inputs: a2 - pointer to CrsrDevRec for this device
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: a0-a1,d0
|
|
;
|
|
; Function: Posts a button up event if this is the last button to go up.
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevButtonUp
|
|
move.l whichCursor(a2),a1 ; get ptr to target cursor data
|
|
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr
|
|
move.l firstCrsrData(a0),a0 ; a0 points to main cursor data record
|
|
|
|
subq.b #1,buttonCount(a1) ; count the button up
|
|
bpl.s @chkMain ;
|
|
clr.b buttonCount(a1) ; clip at 0 (no negatives allowed)
|
|
|
|
@chkMain cmpa.l a0,a1 ; is this the main cursor?
|
|
bne.s @exit ; no, just exit
|
|
|
|
tst.b buttonCount(a1) ; is this the last button to go up?
|
|
bne.s @exit ; no, no need to post another eventÉ
|
|
tst.b MBState ; yes, was mouse down before (should be)?
|
|
bmi.s @exit ; no, exit
|
|
|
|
bset.b #7,MBState ; now say the button is up...
|
|
moveq #0,d0 ; no message for PostEvent
|
|
move.w #mButUpEvt,a0 ; Get event number
|
|
_PostEvent ; post the mouse up event
|
|
|
|
@exit moveq #0,d0 ; result code
|
|
rts
|
|
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevSetAccel
|
|
;
|
|
; Inputs: a2 - pointer to CrsrDevRec for device we want to set
|
|
; d0 - acceleration to set (0-1, fixed point)
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: d0-d1,a0-a1
|
|
;
|
|
; Function: This routine installs the proper acceleration table for
|
|
; the specified device, based on the passed in acceleration
|
|
; value.
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevSetAccel
|
|
move.l d0,acceleration(a2) ; save new acceleration
|
|
movem.l d2-d7/a3-a4,-(sp) ; save a bunch of registers
|
|
|
|
move.l accelPoints(a2),d0 ; get ptr to old table
|
|
beq.s @cont
|
|
move.l d0,a0 ; if one existed,
|
|
_DisposPtr ; get rid of it
|
|
|
|
@cont move.w #mapTrue,RomMapInsert ; map ROM into resource chain <H2>
|
|
clr.w -(sp) ; room for function result
|
|
move.l #'accl',-(sp) ; we're looking for acceleration resources
|
|
_CountResources ; how many are there in the current resource file?
|
|
move.w (sp)+,d3 ; keep count in d3
|
|
beq.s @noaccl ; can't find any accl resources! <H11>
|
|
|
|
move.l devID(a2),d4 ; first try finding an 'accl' that matches our device ID<H3>
|
|
beq.s @tryClass ; if field NULL, use devClass
|
|
bsr FindResource ; did we find one?
|
|
beq.s @foundIt ; yes, skip below
|
|
|
|
@tryClass move.b devClass(a2),d4 ; try finding an 'accl' that matches our device class <H3>
|
|
ext.w d4 ; <H3>
|
|
ext.l d4 ; <H3>
|
|
bsr FindResource ; did we find one?
|
|
beq.s @foundIt ; yes, skip below
|
|
|
|
moveq #0,d4 ; otherwise, just load the flat ramp <H3>
|
|
bsr FindResource ; did we find one?
|
|
beq.s @foundIt
|
|
|
|
@noaccl _debugger ; ¥¥ break if we didn't find one (we should never get here!)
|
|
|
|
;----------------------------------------------
|
|
; first find the two tables which enclose the desired acceleration
|
|
;----------------------------------------------
|
|
|
|
@foundIt move.l acceleration(a2),d3 ; get new acceleration in d3
|
|
move.w (a0)+,d2 ; get # of acceleration tables in resource
|
|
move.l a0,a1 ; keep ptr to 'low' accel table in a1
|
|
|
|
@searchHi cmp.l (a0),d3 ; compare this acceleration to desired acceleration
|
|
ble.s @foundHi ; we found a table that is higher than us, done...
|
|
|
|
@nextEntry move.l a0,a1 ; update ptr to 'low' accel table in a1
|
|
addq.l #4,a0 ; skip past the acceleration
|
|
move.w (a0)+,d0 ; get # of points for this table
|
|
asl.w #3,d0 ; * 8 bytes for each entry
|
|
adda.w d0,a0 ; point to next table
|
|
bra.s @searchHi ; and try next acceleration
|
|
|
|
@foundHi move.l a0,a3 ; a3 = ptr to 'high' entry
|
|
cmpa.l a1,a3 ; are both tables same (matched 1st table) <H4>
|
|
bne.s @calcScale ; no, compute scale factor
|
|
addq.w #4,a1 ; bump past acceleration
|
|
addq.w #4,a3 ; in both tables
|
|
moveq #1,d7 ; yes, scale factor = 1
|
|
swap d7 ;
|
|
bra.s @scaleTable
|
|
|
|
@calcScale clr.l -(sp) ; room for function result
|
|
sub.l (a1),d3
|
|
move.l d3,-(sp) ; push (desired accel - low accel)
|
|
move.l (a3)+,d0
|
|
sub.l (a1)+,d0
|
|
move.l d0,-(sp) ; push (high accel - low accel)
|
|
_FixDiv ; divide to get our interpolation factor
|
|
move.l (sp)+,d7 ; d7 = scale factor
|
|
|
|
;----------------------------------------------
|
|
; now scale the lower resource table to the desired acceleration.
|
|
; The resulting table is pushed on the stack as it is created.
|
|
; d7 = scale factor
|
|
;
|
|
; uses d3,d4 to hold last dumped x1,y1
|
|
;----------------------------------------------
|
|
@scaleTable move.l sp,a4 ; keep ptr to stack buffer top
|
|
|
|
moveq #0,d3 ; init our 'prev' point 1
|
|
moveq #0,d4
|
|
|
|
clr.l -(sp) ; init x1
|
|
clr.l -(sp) ; init y1
|
|
|
|
move.w (a1)+,d5 ; d5 = # of points in lower table
|
|
move.w (a3)+,d6 ; d6 = # of points in upper table
|
|
|
|
cmpa.l a1,a3 ; did we find an exact match? <H4>
|
|
bne.s @scaleLoop ; yes, say no points left in one of the tables <H4>
|
|
moveq #0,d5 ; <H4>
|
|
|
|
@scaleLoop tst.w d5 ; any points left on lower line?
|
|
beq.s @lowLine ; no, then interpolate onto lower line
|
|
tst.w d6 ; any points left on upper line?
|
|
beq.s @highLine ; no, then interpolate onto upper line
|
|
|
|
move.l (a1),d0 ; see if next x point on lower accel table is
|
|
cmp.l (a3),d0 ; greater then next x point on higher accel table
|
|
bgt.s @lowLine ; yes, then use 2 points from lower table
|
|
|
|
;-----------
|
|
@highLine move.l (a3),-(sp) ; push x2 from upper curve
|
|
move.l 4(a3),-(sp) ; push y2 " "
|
|
move.l (a1),-(sp) ; push x3 from lower curve
|
|
move.l 4(a1),-(sp) ; push y3 " "
|
|
subq.w #1,d5 ; count the point
|
|
ble.s @doneLow ; if no more, we need to keep re-using last point
|
|
addq.w #8,a1 ; else, more points, point to next one
|
|
bra.s @int1
|
|
@doneLow moveq #0,d5 ; indicate no more points on lower line
|
|
|
|
@int1 bset #31,d7 ; indicate y3 is on lower curve
|
|
bsr Interpolate ; find new x' y'
|
|
bra.s @setPoint1 ; and set next point 1
|
|
|
|
|
|
;-----------
|
|
@lowLine move.l (a1),-(sp) ; push x2 from lower curve
|
|
move.l 4(a1),-(sp) ; push y2 " "
|
|
move.l (a3),-(sp) ; push x3 from upper curve
|
|
move.l 4(a3),-(sp) ; push y3 " "
|
|
subq.w #1,d6 ; count the point
|
|
ble.s @doneHigh ; if no more, we need to keep re-using last point
|
|
addq.w #8,a3 ; else, more points, point to next one
|
|
bra.s @int2
|
|
@doneHigh moveq #0,d6 ; indicate no more points on upper line
|
|
|
|
@int2 bsr Interpolate ; find new x' y'
|
|
|
|
;-----------
|
|
@setPoint1 tst.w d5 ; are we at end?
|
|
beq.s @restorePrevPt1 ; yes, restore previous pt1
|
|
|
|
tst.w d6 ; are we at end of upper line?
|
|
beq.s @restorePrevPt1 ; yes, restore previous pt1
|
|
|
|
move.l (a1),d0
|
|
cmp.l (a3),d0 ; is next point on upper curve before next point on low curve?
|
|
ble.s @swapLines ; no, skip below
|
|
|
|
@sameLine addq.w #8,sp ; dump last x3,y3 point
|
|
move.l 12(sp),4(sp) ; yes, old x1 becomes new x1
|
|
move.l 8(sp),(sp) ; old y1 becomes new y1
|
|
bra.s @nextPoint
|
|
|
|
@restorePrevPt1
|
|
addq.w #8,sp ; dump last x3,y3 point
|
|
move.l d3,4(sp) ; yes, previous x1 becomes new x1
|
|
move.l d4,(sp) ; previous y1 becomes new y1
|
|
bra.s @nextPoint
|
|
|
|
;-----------
|
|
|
|
|
|
@swapLines move.l (sp)+,4(sp) ; old y3 becomes new y1 data point
|
|
move.l (sp)+,4(sp) ; old x3 becomes new x1 data point
|
|
|
|
@nextPoint move.l 12(sp),d3 ; save last x1,y1 in case needed later
|
|
move.l 8(sp),d4
|
|
move.l d1,12(sp) ; set new x',y' data point on top of old x1,y1 point
|
|
move.l d2,8(sp) ;
|
|
|
|
move.w d5,d0 ; any more points in lower
|
|
or.w d6,d0 ; or upper table?
|
|
bne @scaleLoop ; yes, ok to continue
|
|
|
|
;------------------
|
|
|
|
addq.w #8,sp ; dump last x1,y1 point
|
|
|
|
move.l a4,d0 ; find out how big our computed buffer
|
|
sub.l sp,d0 ; is
|
|
lsr.l #3,d0 ; / 8 to find how many points
|
|
|
|
mulu #CrsrDevSegSize,d0 ; * size of each point
|
|
_NewPtr ,Sys,Clear ; allocate space for new table
|
|
move.l a0,accelPoints(a2) ; save ptr to table
|
|
|
|
;----------------------------------------------
|
|
; finally compute the table of accelPoints, based on the scaled accel resource
|
|
;----------------------------------------------
|
|
|
|
move.l a0,a3 ; keep working ptr to new table in a3
|
|
move.l a4,a1 ; ptr to top of table in a4 (grows toward low mem)
|
|
|
|
moveq #0,d1 ; init x1
|
|
moveq #0,d2 ; init y1
|
|
|
|
clr.l -(sp) ; first, calculate a couple of scaling constants
|
|
move.l resolution(a2),-(sp) ; device res
|
|
move.l #(frameRate<<16),-(sp) ; / frame rate
|
|
_FixDiv
|
|
move.l (sp)+,d6 ; = scale factor for device speed
|
|
|
|
clr.l -(sp)
|
|
move.l whichCursor(a2),a0
|
|
move.l CrsrDataRec.screenRes(a0),-(sp) ; screen res
|
|
move.l #(frameRate<<16),-(sp) ; / frame rate
|
|
_FixDiv
|
|
move.l (sp)+,d7 ; = scale factor for cursor speed
|
|
|
|
@loop clr.l -(sp) ; room for fixMul result
|
|
move.l -(a1),-(sp) ; get device speed for next point
|
|
move.l d6,-(sp) ;
|
|
_FixMul ; dev speed * [devRes / frameRate]
|
|
move.l (sp)+,d3 ; = x2
|
|
move.l d3,devUnits(a3) ; ¥¥ set max device speed for this segment
|
|
|
|
clr.l -(sp) ; room for fixMul result
|
|
move.l -(a1),-(sp) ; get cursor speed for next point
|
|
move.l d7,-(sp) ;
|
|
_FixMul ; y2 = cursor speed * [crsrRes / frameRate]
|
|
move.l (sp)+,d4 ;
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l d4,d0
|
|
sub.l d2,d0 ; y2-y1
|
|
move.l d0,-(sp)
|
|
move.l d3,d0
|
|
sub.l d1,d0 ; x2-x1
|
|
move.l d0,-(sp)
|
|
_FixDiv ; calculate the slope
|
|
move.l (sp)+,slope(a3) ; ¥¥ set slope in table
|
|
|
|
clr.l -(sp)
|
|
move.l slope(a3),-(sp)
|
|
move.l d3,-(sp)
|
|
_FixMul ; slope * X
|
|
move.l d4,d0
|
|
sub.l (sp)+,d0 ; Y - slope * X = intercept
|
|
move.l d0,intercept(a3) ; ¥¥ set intercept
|
|
adda.w #CrsrDevSegSize,a3 ; bump to next segment
|
|
|
|
move.l d3,d1 ; old x2,y2 becomes new x1,y1
|
|
move.l d4,d2
|
|
|
|
cmpa.l a1,sp ; are we done?
|
|
blt.s @loop ; no, continue
|
|
|
|
move.l a4,sp ; dump buffer from stack
|
|
|
|
move.l #$7FFFFFFF,-12(a3) ; set last 'highest device speed' to max
|
|
|
|
movem.l (sp)+,d2-d7/a3-a4 ; restore registers
|
|
|
|
moveq #0,d0 ; result code
|
|
rts
|
|
|
|
|
|
;------------------------------------------------
|
|
;
|
|
; Routine: FindResource
|
|
;
|
|
; Inputs: d3 - # of 'accl' resources to search
|
|
; d4 - 'accl' resource tag we're looking for
|
|
;
|
|
; Outputs: a0 - ptr to 'accl' resource (past tag) if we found it
|
|
; ccr.Z - set if we matched
|
|
;
|
|
; Destroys: a0,d0,d1,d2,d5
|
|
;
|
|
; Function: This routine scans 'accl' resources, searching
|
|
; for one with a tag matching d1.
|
|
;------------------------------------------------
|
|
|
|
FindResource
|
|
move.w d3,d5 ; init our index <H3>
|
|
@loop move.w #mapTrue,RomMapInsert ; map ROM into resource chain <H2>
|
|
clr.l -(sp) ; room for function result
|
|
move.l #'accl',-(sp) ; we're looking for acceleration resources
|
|
move.w d5,-(sp) ; push current index <H3>
|
|
_GetIndResource ; get next 'accl' resource
|
|
move.l (sp)+,d0 ; did we get this one? <H3>
|
|
beq.s @NotFound ; -> no, try the next one <H3>
|
|
move.l d0,a0 ; handle in a0 <H3>
|
|
move.l (a0),a0 ; ptr in a0
|
|
cmp.l (a0)+,d4 ; does tag match our selector?
|
|
beq.s @exit ; yes, exit (with res ptr in a0)
|
|
@NotFound subq.w #1,d5 ; no, bump to next resource <H3>
|
|
bne.s @loop ; keep searching... <H3>
|
|
moveq #1,d0 ; set BNE if not found <H3>
|
|
|
|
@exit rts ; exit with Z-Flag set on match
|
|
|
|
|
|
|
|
;------------------------------------------------
|
|
;
|
|
; Routine: Interpolate
|
|
;
|
|
; Inputs: 18(sp) - x1
|
|
; 14(sp) - y1
|
|
; 10(sp) - x2
|
|
; 0C(sp) - y2
|
|
; 08(sp) - x3
|
|
; 04(sp) - y3
|
|
; d7 - scale, bit 31 set if 3rd point on lower accel curve.
|
|
;
|
|
; Outputs: d1 - x'
|
|
; d2 - y'
|
|
; d7.31 - reset
|
|
;
|
|
; Destroys: a0,d0-d1
|
|
;
|
|
; Function: This routine interpolates to find a point on the line [x1,y1] [x2,y2] which
|
|
; is intersected by the line [x3,y3] [x3,y"]. The resulting y' is calculated
|
|
; by interpolating between y3 and y", towards the higher acceleration curve.
|
|
;------------------------------------------------
|
|
|
|
stackFrame RECORD 0,increment
|
|
saveA6 ds.l 1
|
|
retAddr ds.l 1
|
|
y3 ds.l 1
|
|
x3 ds.l 1
|
|
y2 ds.l 1
|
|
x2 ds.l 1
|
|
y1 ds.l 1
|
|
x1 ds.l 1
|
|
ENDR
|
|
|
|
|
|
Interpolate
|
|
WITH stackFrame
|
|
link a6,#0 ; set our frame ptr
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l y2(a6),d0 ; get y2
|
|
sub.l y1(a6),d0 ; y2 - y1
|
|
move.l d0,-(sp)
|
|
move.l x2(a6),d0 ; x2 - x1
|
|
sub.l x1(a6),d0
|
|
move.l d0,-(sp)
|
|
_FixDiv ; calculate slope, leave on stack
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l 4(sp),-(sp) ; push copy of slope
|
|
move.l x1(a6),-(sp) ; push x1
|
|
_FixMul ; slope * x1
|
|
move.l y1(a6),d1
|
|
sub.l (sp)+,d1 ; d1 = intercept = y1 - (slope * x1)
|
|
|
|
move.l (sp),-(sp) ; push slope, leave room for function result
|
|
move.l x3(a6),-(sp) ; push x3
|
|
_FixMul
|
|
add.l (sp)+,d1 ; y" = slope * x3 + intercept
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l y3(a6),d0
|
|
sub.l d1,d0
|
|
move.l d0,-(sp) ; push (y3 - y")
|
|
move.l d7,-(sp) ; push scale
|
|
bclr.b #7,(sp) ; make sure flag is off
|
|
_FixMul
|
|
bclr #31,d7 ; check if y3 is on lower curve
|
|
bne.s @lower ; yes, branch
|
|
|
|
@upper move.l (sp)+,d2 ; yes, interpolate upward
|
|
add.l d1,d2 ; y' = scale(y3-y") + y"
|
|
bra.s @exit
|
|
|
|
@lower move.l y3(a6),d2 ; interpolate downward,
|
|
sub.l (sp)+,d2 ; y' = y3 - scale(y3-y")
|
|
|
|
@exit move.l x3(a6),d1 ; return x'
|
|
unlk a6
|
|
rts
|
|
|
|
ENDWITH
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevHandleVBL
|
|
;
|
|
; Inputs: -
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: d0 <H7>
|
|
;
|
|
; Function: This routine moves the cursor on the screen. It handles error
|
|
; distribution and delta acceleration for all the devices, then
|
|
; redraws the cursor.
|
|
;_______________________________________________________________________
|
|
|
|
EXPORT CrsrDevHandleVBL
|
|
CrsrDevHandleVBL
|
|
movem.l a0-a4/d1-d5,-(sp) ; save a bunch of registers <H7>
|
|
|
|
movea.l ExpandMem,a3 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a3),a3 ; get cursory global ptr
|
|
move.l firstCrsrDev(a3),d0 ; get ptr to 1st CrsrDevRec
|
|
beq @exit ; if not even 1 device, just exit
|
|
move.l d0,a2 ; ptr in a2
|
|
|
|
tst.b CrsrNew ; has anyone touched the old cursor
|
|
beq.s @drawCheck ; globals (compatibility - Display Mgr sets this <IH> ) ? <SM6>
|
|
|
|
clr.b CrsrNew ; yes, ok, we're handling it now
|
|
move.l firstCrsrData(a3),a4 ; get ptr to only CrsrDataRec in a4
|
|
|
|
tst.b isAbs(a4) ; are we in relative mode?
|
|
bne.s @drawCheck ; no, skip <SM6>
|
|
|
|
move.l MTemp,d0 ; does RawMouse <H4>
|
|
cmp.l RawMouse,d0 ; = MTemp? <H4>
|
|
bne.s @delta ; no, then they're doing deltas <H4>
|
|
|
|
@abs move.w d0,whereX(a4) ; yes, then just set our whereXY global to theirs
|
|
clr.w whereX+2(a4)
|
|
swap d0
|
|
move.w d0,whereY(a4)
|
|
clr.w whereY+2(a4)
|
|
bra.s @drawCheck ; <SM6>
|
|
|
|
@delta move.w Mouse+h,d0 ; add in their movement to ours
|
|
sub.w where+h(a4),d0 ; Mouse.h - crsrData->where.h
|
|
add.w MTemp+h,d0 ;
|
|
sub.w RawMouse+h,d0 ; + MTemp.h - RawMouse.h
|
|
swap d0 ; Word2fix
|
|
clr.w d0 ;
|
|
add.l d0,whereX(a4) ; update our global x position
|
|
|
|
move.w Mouse+v,d0 ; yes, add in their movement to ours
|
|
sub.w where+v(a4),d0 ; Mouse.v - crsrData->where.v
|
|
add.w MTemp+v,d0 ;
|
|
sub.w RawMouse+v,d0 ; + MTemp.v - RawMouse.v
|
|
swap d0 ; Word2fix
|
|
clr.w d0 ;
|
|
add.l d0,whereY(a4) ; update our global y position
|
|
; <SM6>begin
|
|
; See if it is time to draw the cursor.
|
|
;
|
|
@drawCheck ;
|
|
IF LC930 THEN
|
|
bclr.b #SkipDraw,CrsrDevFlags(a3) ; if this is the first CRSR VBL don't draw, do the calculations only
|
|
bne.s @accumLoop ; will draw on the next VBL
|
|
|
|
;==================================
|
|
@flushCrsrs
|
|
movem.l d0/a0-a4,-(sp) ; save registers used by CursorDraw Routines
|
|
move.l firstCrsrData(a3),a4 ; get ptr to first CrsrDataRec
|
|
@flushLoop clr.b isAbs(a4)
|
|
|
|
move.w whereX(a4),where+h(a4) ; update our h coordinate
|
|
move.w whereY(a4),where+v(a4) ; update our h coordinate
|
|
|
|
move.l nextCrsrData(a4),a4
|
|
move.l a4,d0
|
|
bne.s @flushLoop ; and clear flush next cursor (if any)
|
|
|
|
;-----------------
|
|
@drawCursor movea.l DrawCrsrVBLVector(a3),a0 ; call the DrawCursor vector <H15>
|
|
jsr (a0) ; <H15>
|
|
movem.l (sp)+,d0/a0-a4 ; restore registers trashed by CursorDraw routine
|
|
ENDIF ; <SM6>end
|
|
|
|
;------------------------------------------------------
|
|
; Now add and accelerate deltas for all cursor devices
|
|
; and combine into our only cursor data record.
|
|
;------------------------------------------------------
|
|
|
|
@accumLoop move.l whichCursor(a2),a4 ; get ptr to this devices CrsrDataRec in a4
|
|
|
|
tst.b isAbs(a4) ; are we in absolute mode?
|
|
beq.s @relative ; no, skip
|
|
|
|
clr.l deltaX(a2) ; yes, absolute cursor,
|
|
clr.l deltaY(a2) ; flush relative info for this device
|
|
clr.l errorX(a2) ;
|
|
clr.l errorY(a2) ;
|
|
move.w #-104,denom(a2)
|
|
clr.b newData(a2)
|
|
bra @nextDev ; and continue
|
|
|
|
;----------------
|
|
@relative tst.b newData(a2) ; relative cursor, do we have new data?
|
|
beq.s @noNewData ; no, skip
|
|
|
|
clr.b newData(a2) ; we're handling the new stuff nowÉ
|
|
tst.w denom(a2) ; any errors?
|
|
ble.s @noError ; no, skip
|
|
|
|
clr.l -(sp) ; make room for fixDiv result
|
|
move.l errorX(a2),-(sp) ; 1st param for fixDiv
|
|
moveq #0,d0
|
|
move.w denom(a2),d0
|
|
swap d0 ; Word2Fix
|
|
move.l d0,-(sp) ; 2nd param for fixDiv
|
|
_FixDiv
|
|
move.l (sp)+,d3 ; dx = FixDiv(errorX,denom)
|
|
|
|
clr.l -(sp) ; make room for fixDiv result
|
|
move.l errorY(a2),-(sp) ; 1st param for fixDiv
|
|
moveq #0,d0
|
|
move.w denom(a2),d0
|
|
swap d0 ; Word2Fix
|
|
move.l d0,-(sp) ; 2nd param for fixDiv
|
|
_FixDiv
|
|
move.l (sp)+,d4 ; dy = FixDiv(errorY,denom)
|
|
|
|
sub.l d3,errorX(a2)
|
|
sub.l d4,errorY(a2)
|
|
bra.s @addDeltas
|
|
|
|
@noError clr.l d3
|
|
clr.l d4
|
|
|
|
@addDeltas add.l deltaX(a2),d3 ; add in the deltas
|
|
add.l deltaY(a2),d4
|
|
cmpi.w #-100,denom(a2) ; setup for next time
|
|
ble.s @findMag
|
|
subq.w #1,denom(a2)
|
|
bra.s @findMag
|
|
|
|
@noNewData move.l errorX(a2),d3 ; no new samples since last VBL,
|
|
move.l errorY(a2),d4 ; take all the error
|
|
clr.l errorX(a2)
|
|
clr.l errorY(a2)
|
|
move.w #-102,denom(a2)
|
|
|
|
;-----------------
|
|
@findMag move.l d3,d0 ; get dx
|
|
bpl.s @absDy ; ok if positive
|
|
neg.l d0 ; else, make positive
|
|
@absDy move.l d4,d1 ; get dy
|
|
bpl.s @chkMag ; ok if positive
|
|
neg.l d1 ; else, make positive
|
|
@chkMag cmp.l d1,d0
|
|
bgt.s @doY
|
|
lsr.l #1,d0
|
|
bra.s @setMag
|
|
@doY lsr.l #1,d1
|
|
@setMag add.l d0,d1 ; d1 = magnitude
|
|
beq.s @nextDev ; no magnitude, check next device
|
|
|
|
move.l accelPoints(a2),a1 ; a1 points to acceleration table
|
|
clr.w d0
|
|
@search cmp.l devUnits(a1,d0.w),d1 ; find entry in the table
|
|
ble.s @foundIt ; that matches our magnitude
|
|
add.w #CrsrDevSegSize,d0 ; not close yet, bump to next one
|
|
bra.s @search
|
|
|
|
;-----------------
|
|
@foundIt move.l intercept(a1,d0.w),-(sp) ; push intercept for later add
|
|
clr.l -(sp) ; room for function result
|
|
move.l slope(a1,d0.w),-(sp) ; push slope
|
|
move.l d1,-(sp) ; push mag
|
|
_FixMul
|
|
move.l (sp)+,d0
|
|
add.l (sp)+,d0 ; scale = intercept + slope*mag
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l d0,-(sp) ; push scale
|
|
move.l d1,-(sp) ; magnitude
|
|
_FixDiv ; scale = scale / mag
|
|
|
|
clr.l -(sp) ; room for function result
|
|
move.l 4(sp),-(sp) ; push a copy of scale
|
|
move.l d3,-(sp) ; push dx
|
|
_FixMul
|
|
move.l (sp)+,d0
|
|
add.l d0,whereX(a4) ; accumulate the accelerated move
|
|
|
|
move.l (sp),-(sp) ; push scale, leave room for function result
|
|
move.l d4,-(sp) ; push dy
|
|
_FixMul
|
|
move.l (sp)+,d0
|
|
add.l d0,whereY(a4) ; accumulate the accelerated move
|
|
|
|
|
|
@nextDev move.l nextCrsrDev(a2),a2 ; get next device ptr
|
|
move.l a2,d0 ; done all devices?
|
|
bne @accumLoop ; no, continue looping
|
|
|
|
IF NOT LC930 THEN ; <SM6>
|
|
|
|
;==================================
|
|
@flushCrsrs move.l firstCrsrData(a3),a4 ; get ptr to first CrsrDataRec
|
|
@flushLoop clr.b isAbs(a4)
|
|
|
|
move.w whereX(a4),where+h(a4) ; update our h coordinate
|
|
move.w whereY(a4),where+v(a4) ; update our h coordinate
|
|
|
|
move.l nextCrsrData(a4),a4
|
|
move.l a4,d0
|
|
bne.s @flushLoop ; and clear flush next cursor (if any)
|
|
|
|
;-----------------
|
|
@drawCursor movea.l DrawCrsrVBLVector(a3),a0 ; call the DrawCursor vector <H15>
|
|
jsr (a0) ; <H15>
|
|
|
|
ENDIF ; <SM6>
|
|
|
|
@exit movem.l (sp)+,a0-a4/d1-d5 ; restore a bunch of registers <H7>
|
|
rts
|
|
|
|
;_______________________________________________________________________ <H15>
|
|
;
|
|
; Routine: DrawCursor
|
|
;
|
|
; Inputs: a3 - ptr to CrsrDevGlobals
|
|
;
|
|
; Outputs:
|
|
;
|
|
; Destroys: d0,a0,a4
|
|
;
|
|
; Function: This routine is the default ROM routine called through
|
|
; the DrawCrsrVBLVector. The vector is initialized by
|
|
; InitCrsrDev. (Pulled from the in-line VBL code).
|
|
;_______________________________________________________________________
|
|
|
|
DrawCursor movea.l firstCrsrData(a3),a4 ; get ptr to main CrsrDataRec <H15>
|
|
move.l where(a4),d0 ; get new mouse coords
|
|
cmp.l Mouse,d0 ; has cursor moved?
|
|
beq.s @exit ; noÉ exit
|
|
tst.b CrsrCouple ; is cursor coupled to mouse?
|
|
bne.s @coupled ; yes, continue <SM6>
|
|
|
|
move.l d0,MTemp ; no, just update lowmem MTemp <SM6>
|
|
bra.s @exit ; and exit without drawing cursor <SM6>
|
|
|
|
@coupled tst.b CrsrBusy ; is it locked? <SM6>
|
|
bne.s @exit ; yesÉ exit
|
|
|
|
lea CrsrPin,a0 ; it's ok to update cursor, get bounding rect
|
|
BSR.L CrsrVBLTask ; pin and draw the cursor
|
|
|
|
move.l Mouse,d0 ; has cursor been pinned?
|
|
cmp.l where(a4),d0 ;
|
|
beq.s @exit ; noÉ exit
|
|
move.l d0,where(a4) ; reflect pinned location
|
|
|
|
move.l MouseMask,d1 ; <H18>
|
|
not.l d1
|
|
tst.w d1 ; are we gridding in x direction?
|
|
beq.s @updateX ; no, force update
|
|
|
|
move.w whereX(a4),d0 ; yes, see if we clipped at screen bounds <H18>
|
|
sub.w Mouse+h,d0
|
|
bpl.s @xok
|
|
neg.w d0
|
|
@xok cmp.w d1,d0 ; compare our error to grid delta
|
|
ble.s @chkGridv ; <, so don't update our running x position
|
|
@updateX move.w RawMouse+h,whereX(a4) ; stamp our new running x position
|
|
clr.w whereX+2(a4)
|
|
|
|
@chkGridv swap d1 ; <H18>
|
|
tst.w d1 ; are we gridding in y direction?
|
|
beq.s @updateY ; no, force update
|
|
|
|
move.w whereY(a4),d0 ; yes, see if we clipped at screen bounds <H18>
|
|
sub.w Mouse+v,d0
|
|
bpl.s @yok
|
|
neg.w d0
|
|
@yok cmp.w d1,d0 ; compare our error to grid delta
|
|
ble.s @exit ; <, so don't update our running y position
|
|
@updateY move.w RawMouse+v,whereY(a4) ; stamp our new running x position
|
|
clr.w whereY+2(a4) ; loose the fraction
|
|
|
|
@exit rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevNewDevice
|
|
;
|
|
; Inputs: ...
|
|
;
|
|
; Outputs: a2 - pointer to CrsrDevRec for device we initialized
|
|
; d0 - OSErr
|
|
;
|
|
; Destroys: d1-d2,a0-a1
|
|
;
|
|
; Function: This routine creates a new CrsrDevRec, adds it to the
|
|
; linked list of device records, and initializes it's fields.
|
|
; Note: the caller must call CrsrDevSetAcceleration after
|
|
; calling this routine.
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevNewDevice
|
|
move.l #CrsrDevSize,d0
|
|
_NewPtr ,Sys,Clear ; non-explicitly set fields will default to zeros
|
|
bne.s @error ; no memory, error exit
|
|
|
|
move.l a0,a2 ; keep ptr in a0
|
|
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr
|
|
move.l firstCrsrDev(a0),nextCrsrDev(a2) ; link into our chain
|
|
move.l a2,firstCrsrDev(a0) ; " "
|
|
|
|
move.l firstCrsrData(a0),whichCursor(a2) ; init the cursor data ptr
|
|
move.b #classMouse,devClass(a2) ; we're a mouse type device
|
|
move.b #1,cntButtons(a2) ; and have 1 button <H11>
|
|
move.b #btnSingleClick,buttonOp+0(a2) ; standard single-click operation
|
|
move.l #(72<<16),resolution(a2) ; standard screen resolution
|
|
|
|
subq #4,sp
|
|
move.l sp,a0
|
|
move.l #$00020008,d0
|
|
_ReadXPram ; read mouse PRAM
|
|
move.l (sp)+,d1 ; get PRAM setting for double-click time
|
|
move.l d1,d0
|
|
rol.l #5+2,d0
|
|
andi.w #$1C,d0
|
|
lea @accelToFixed,a0
|
|
move.l (a0,d0.w),acceleration(a2) ; convert to fixed, and set our acceleration
|
|
|
|
moveq #8+4,d0
|
|
rol.l d0,d1 ; get PRAM setting for double-click time
|
|
andi.w #$0F,d1
|
|
lea @clickToFixed,a0
|
|
moveq #0,d0
|
|
move.b (a0,d1.w),d0
|
|
move.l d0,doubleClickTime(a2) ; set our double-click time
|
|
move.l d0,doubleTime ; update lowmem as well... <H13>
|
|
|
|
move.w #-101,denom(a2)
|
|
move.w #4,spread(a2)
|
|
|
|
moveq #0,d0 ; result code
|
|
rts
|
|
|
|
@error moveq #-1,d0 ; error exit
|
|
rts
|
|
|
|
|
|
|
|
@accelToFixed
|
|
dc.l $00000000 ; 0
|
|
dc.l $00002000 ; 1
|
|
dc.l $00005000 ; 2
|
|
dc.l $00008000 ; 3
|
|
dc.l $0000B000 ; 4
|
|
dc.l $0000E000 ; 5
|
|
dc.l $00010000 ; 6
|
|
dc.l $00010000 ; 7
|
|
|
|
@clickToFixed
|
|
dc.b $0C ; 0
|
|
dc.b $0C ; 1
|
|
dc.b $0C ; 2
|
|
dc.b $0C ; 3
|
|
dc.b $10 ; 4
|
|
dc.b $14 ; 5 fast
|
|
dc.b $17 ; 6
|
|
dc.b $1B ; 7
|
|
dc.b $20 ; 8 medium
|
|
dc.b $23 ; 9
|
|
dc.b $26 ; a
|
|
dc.b $2C ; b
|
|
dc.b $30 ; c slow
|
|
dc.b $34 ; d
|
|
dc.b $38 ; e
|
|
dc.b $3C ; f
|
|
|
|
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevDisposeDev
|
|
;
|
|
; Inputs: a2 - pointer to CrsrDevRec for device we want to remove
|
|
;
|
|
; Outputs: d0 - OSErr
|
|
;
|
|
; Destroys: d0-d2,a0-a1
|
|
;
|
|
; Function: This routine eliminates CrsrDevRec from the linked list
|
|
; of device records, and disposes of all storage related to
|
|
; it.
|
|
;_______________________________________________________________________
|
|
|
|
CrsrDevDisposeDev
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr
|
|
move.l firstCrsrDev(a0),a1 ; d1 points to main cursor data record
|
|
|
|
moveq #0,d1 ; prev := NIL
|
|
|
|
@loop cmpa.l a1,a2 ; is this the linked list element we want?
|
|
beq.s @gotIt ; yes, handle it
|
|
move.l a1,d1 ; no, prev := next
|
|
move.l nextCrsrDev(a1),d0 ; get next->nextCrsrDev
|
|
beq.s @exit ; exit if NIL (we never found it)
|
|
move.l d0,a1 ; next := next->nextCrsrDev
|
|
bra.s @loop
|
|
|
|
@gotIt move.l nextCrsrDev(a1),a1 ; next := next->nextCrsrDev
|
|
tst.l d1 ; was it the first one?
|
|
beq.s @firstOne ; yes, handle special case
|
|
|
|
move.l d1,a2
|
|
move.l a1,nextCrsrDev(a2) ; else, delete our element from middle of list
|
|
bra.s @dispose
|
|
|
|
@firstOne move.l a1,firstCrsrDev(a0)
|
|
|
|
@dispose move.l accelPoints(a2),d0
|
|
beq.s @ridRecord ; get rid of storage within CrsrDevRec
|
|
move.l d0,a0
|
|
_DisposPtr
|
|
|
|
@ridRecord move.l a2,a0
|
|
_DisposPtr ; get rid of CrsrDevRec itself
|
|
|
|
@exit moveq #0,d0 ; result code
|
|
rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CrsrDevReInit
|
|
;
|
|
; Inputs: d0 - 0 = pre-init, 1=post-init
|
|
;
|
|
; Outputs: d0 - 0 = pre-init, 1=post-init
|
|
;
|
|
; Destroys: a0-a3/d1-d3
|
|
;
|
|
; Function: This routine handles pre and post ADB ReInit processing.
|
|
; Before reinit, it trashes all the crsrDevRecs that are
|
|
; hanging off the ADB chain. After the re-init, it restores
|
|
; all the devices. Devices that can enter Handler XX, like PGE,
|
|
; are polled for information from register 01, which is used
|
|
; to fill in the CrsrDevRec. Other devices are used in the
|
|
; appropriate defaults.
|
|
;_______________________________________________________________________
|
|
|
|
ADBParamBlk RECORD 0,decrement
|
|
iDataAddr ds.l 1 ; ADB device data ptr
|
|
iCRAddr ds.l 1 ; ADB device completion rtn
|
|
iOrigAddr ds.b 1 ; ADB original address
|
|
iDeviceTy ds.b 1 ; ADB device type
|
|
iPBlock EQU iDeviceTy ; the start of our GetInfo param block
|
|
iSPBlock EQU iCRAddr ; the start of our SetInfo param block
|
|
adbPBSize EQU * ; size of our param block
|
|
ENDR
|
|
|
|
EXPORT CrsrDevReInit
|
|
CrsrDevReInit ; <H14>
|
|
WITH ADBParamBlk
|
|
|
|
movem.l d0-d3/a0-a3,-(sp)
|
|
link a6,#adbPBSize ; Make a stack frame for our param block
|
|
bne.s @PostInit ; Skip if post-processing
|
|
|
|
;---------------------
|
|
; pre-init processing
|
|
;---------------------
|
|
_CountADBs ; Get the number of ADB devices
|
|
move.w d0,d2 ; Save in D2
|
|
beq @exit ; Skip if none
|
|
|
|
|
|
@killLoop lea iPBlock(a6),a0 ; a0 is parameter block
|
|
move.w d2,d0
|
|
_GetIndADB ; Get a device entry
|
|
bmi.s @nextRec1 ; Skip if not valid
|
|
cmpi.b #mouseAddr,iOrigAddr(a6); mouse?
|
|
bne.s @nextRec1 ; Skip if not
|
|
|
|
move.l iDataAddr(a6),a2 ; Save the data address pointer
|
|
clr.l iDataAddr(a6) ; Clear it out, so the keyboard won't trash memory
|
|
lea iSPBlock(a6),a0 ; a0 ptr to our short param block
|
|
_SetADBInfo ; d0 already contains the ADB Address
|
|
|
|
bsr.s CrsrDevDisposeDev ; eliminate it from our globals also
|
|
|
|
@nextRec1 subq.w #1,d2
|
|
bgt.s @killLoop
|
|
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr
|
|
clr.l firstCrsrDev(a0) ; clear out initial dev ptr
|
|
bra @exit
|
|
|
|
|
|
;---------------------
|
|
; post-init processing
|
|
;---------------------
|
|
@PostInit bset.b #7,MBState ; set current mouse button state to UP <H16>
|
|
clr.l MBTicks ; reset timestamp for mouse button <H16>
|
|
|
|
_CountADBs ; Get the number of ADB devices
|
|
move.w d0,d2 ; Save in D2
|
|
sub.w #10,sp ; allocate ADBOp reply buffer on stack for later
|
|
beq @postCheck ; Skip if no devices
|
|
|
|
|
|
@instLoop
|
|
lea iPBlock(a6),a0 ; a0 is parameter block
|
|
move.w d2,d0
|
|
_GetIndADB ; Get a device entry
|
|
move.w d0,d3 ; save ADB address
|
|
bmi @nextRec2 ; Skip if not valid
|
|
cmpi.b #mouseAddr,iOrigAddr(a6); mouse?
|
|
bne @nextRec2 ; Skip if not
|
|
|
|
bsr CrsrDevNewDevice ; create and chain in a new cursor record
|
|
; a2 points to crsrDevRec
|
|
move.b d3,d0 ; address in d0
|
|
lsl.b #4,d0 ; upper 4 bits
|
|
ori.b #%1111,d0 ; talk R3 command
|
|
move.l sp,a0 ; reply buffer ptr in a0
|
|
bsr syncADBTalk ; send command synchronously, reply in a0.
|
|
tst.b (a0) ; any data?
|
|
beq @nextRec2 ; no, skip (should not happen)
|
|
|
|
move.b #extDevHand,2(a0) ; yes, try to set to allow mouse extension
|
|
move.b d3,d0 ; address in d0
|
|
lsl.b #4,d0 ; upper 4 bits
|
|
ori.b #%1011,d0 ; Listen R3 command
|
|
bsr syncADBListen ; send command synchronously.
|
|
|
|
move.b d3,d0 ; now see if we switched be doing a talk R3 again
|
|
lsl.b #4,d0 ; addr in upper 4 bits
|
|
ori.b #%1111,d0 ; talk R3 command
|
|
move.l sp,a0 ; reply buffer ptr in a0
|
|
bsr syncADBTalk ; send command synchronously, reply in a0.
|
|
tst.b (a0) ; any data?
|
|
beq @nextRec2 ; no, skip (should not happen)
|
|
|
|
cmpi.b #extDevHand,2(a0) ; did we switch?
|
|
bne.s @preExisting ; no, doesn't
|
|
|
|
;--------------------------------
|
|
; We got an extended type device...
|
|
;--------------------------------
|
|
move.b d3,d0 ; now get the extended data from R1
|
|
lsl.b #4,d0 ; addr in upper 4 bits
|
|
ori.b #%1101,d0 ; talk R1 command
|
|
bsr syncADBTalk ; send command synchronously, reply in a0.
|
|
cmpi.b #8,(a0) ; did we get 8 bytes back?
|
|
bne.s @preExisting ; no, try handler 2 (maybe 1)
|
|
|
|
move.b 1(a0),devID+0(a2) ; copy the device ID (optimize later)
|
|
move.b 2(a0),devID+1(a2) ; "
|
|
move.b 3(a0),devID+2(a2) ; "
|
|
move.b 4(a0),devID+3(a2) ; "
|
|
|
|
move.b 5(a0),resolution+0(a2) ; Copy the resolution
|
|
move.b 6(a0),resolution+1(a2) ; "
|
|
clr.w resolution+2(a2) ; clear out the fraction part
|
|
|
|
move.b 7(a0),devClass(a2) ; Copy the device class
|
|
move.b 8(a0),cntButtons(a2) ; Copy the number of buttons
|
|
move.b #btnSingleClick,buttonOp+1(a2) ; single-click operation for 2nd button <H5>
|
|
bra.s @setInfo ; and setup globals/completion rtn for this device
|
|
|
|
;--------------------------------
|
|
; We got a pre-existing type device...
|
|
;--------------------------------
|
|
@preExisting
|
|
move.b #2,2(a0) ; yes, try to set to handler 2
|
|
move.b d3,d0 ; address in d0
|
|
lsl.b #4,d0 ; upper 4 bits
|
|
ori.b #%1011,d0 ; Listen R3 command
|
|
bsr syncADBListen ; send command synchronously.
|
|
|
|
move.b d3,d0 ; now see if we switched be doing a talk R3 again
|
|
lsl.b #4,d0 ; addr in upper 4 bits
|
|
ori.b #%1111,d0 ; talk R3 command
|
|
move.l sp,a0 ; reply buffer ptr in a0
|
|
bsr syncADBTalk ; send command synchronously, reply in a0.
|
|
tst.b (a0) ; any data?
|
|
beq.s @nextRec2 ; no, skip (should not happen)
|
|
|
|
cmpi.b #2,2(a0) ; did we switch to 2?
|
|
bne.s @brainDead ; no, must be stupid 4th party device
|
|
|
|
;-----------------------------------------
|
|
; We switched to 2, so adjust some paramters
|
|
;-----------------------------------------
|
|
move.l #'@200',devID(a2) ; set the device ID
|
|
move.w #200,resolution(a2) ; set the resolution
|
|
bra.s @setInfo
|
|
|
|
;-----------------------------------------
|
|
; We didn't switch to 2, so set back to 1 (is this necessary Dan?)
|
|
;-----------------------------------------
|
|
@brainDead move.b #1,2(a0) ; yes, try to set to handler 1
|
|
move.b d3,d0 ; address in d0
|
|
lsl.b #4,d0 ; upper 4 bits
|
|
ori.b #%1011,d0 ; Listen R3 command
|
|
bsr syncADBListen ; send command synchronously.
|
|
|
|
;--------------------------------
|
|
@setInfo move.l acceleration(a2),d0 ; d0 = acceleration for this device
|
|
bsr CrsrDevSetAccel ; set up the acceleration tables
|
|
|
|
lea CrsrDevHandleADB,a0
|
|
move.l a0,iCRAddr(a6) ; set our handler
|
|
move.l a2,iDataAddr(a6) ; set up the data area
|
|
lea iSPBlock(a6),a0 ; a0 ptr to our short param block
|
|
move.w d3,d0 ; d0 = ADB address
|
|
_SetADBInfo ; install the new info
|
|
|
|
@nextRec2 subq.w #1,d2
|
|
bgt @instLoop ; continue looping though all devices
|
|
bmi.s @postExit ; done when we've been through here twice (once to set default)
|
|
|
|
;---------------------
|
|
@postCheck move.b #mouseAddr,d3
|
|
moveq #numFDBAdr,d0 ; Number of table entries
|
|
move.l ADBBase,a3 ; get ADB globals in a3
|
|
move.l a3,a1 ; copy in a1
|
|
bra.s @chkMatch ;
|
|
|
|
@searchLoop adda.w #FRecSize,a1 ; Get to next record
|
|
@chkMatch cmp.b FDBAddr(a1),d3 ; Is this the right one?
|
|
beq.s @postExit ; If so, we're done
|
|
tst.b FDBAddr(a1) ; Is it 0?
|
|
dbeq d0,@searchLoop ; Loop until it is found or no more.
|
|
|
|
move.b #1,FDBDevTy(a1) ; assume handler 1
|
|
move.b d3,FDBOAddr(a1) ; set original address as 3
|
|
move.b d3,FDBAddr(a1) ; set FDB address as 3
|
|
bset.b d3,DevMap+1(a3) ; remember to poll it
|
|
|
|
bsr CrsrDevNewDevice ; else, create and chain in a default cursor record
|
|
bra.s @setInfo ; and set it it ADB unit table
|
|
|
|
@postExit add.w #10,sp ; ¥ dump our ADBOp buffer
|
|
movea.l ExpandMem,a0 ; get ptr to expandmem rec <H10>
|
|
movea.l emCursorGlobals(a0),a0 ; get cursory global ptr <H10>
|
|
move.l firstCrsrData(a0),a0 ; get the cursor data ptr <H10>
|
|
clr.b buttonCount(a0) ; init button down count <H10>
|
|
|
|
;---------------------
|
|
@exit unlk a6 ; dump the adbInfo param block
|
|
movem.l (sp)+,d0-d3/a0-a3
|
|
rts
|
|
|
|
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: syncADBTalk
|
|
;
|
|
; Inputs: d0 - address/command byte
|
|
; a0 - ptr to receive buffer
|
|
;
|
|
; Outputs: a0 - pts to pascal talk string
|
|
;
|
|
; Destroys: a1,d0
|
|
;
|
|
; Function: This routine makes a synchronous ADBOp call, and returns
|
|
; any data in the buffer pointed to by a0.
|
|
;_______________________________________________________________________
|
|
|
|
syncADBTalk
|
|
move.l a0,-(sp) ; save ptr to our buffer
|
|
clr.w -(sp) ; our 'sync' flag
|
|
|
|
move.l sp,a1 ; keep pointer to globals for later
|
|
move.l sp,-(sp) ; push pointer to globals
|
|
pea syncComp ; push pointer to our completion routine
|
|
move.l a0,-(sp) ; push pointer to our reply buffer
|
|
move.l sp,a0
|
|
_ADBOp
|
|
|
|
@spin tst.b (a1) ; have we completed?
|
|
beq.s @spin ; no, keep waiting
|
|
|
|
lea 14(sp),sp ; dump locals
|
|
move.l (sp)+,a0 ; restore a0
|
|
rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: syncADBListen
|
|
;
|
|
; Inputs: d0 - address/command byte
|
|
; a0 - ptr to transmit buffer
|
|
;
|
|
; Outputs: a0 - pts to pascal talk string
|
|
;
|
|
; Destroys: a0-a1,d0
|
|
;
|
|
; Function: This routine makes a synchronous ADBOp call, and returns
|
|
; any data in the buffer pointed to by a0.
|
|
;_______________________________________________________________________
|
|
|
|
syncADBListen
|
|
clr.w -(sp) ; our 'sync' flag
|
|
move.l sp,a1 ; keep pointer to data area for later
|
|
move.l sp,-(sp) ; push pointer to data area
|
|
pea syncComp ; push our completion address
|
|
move.l a0,-(sp) ; push ptr to data to send
|
|
move.l sp,a0
|
|
_ADBOp
|
|
|
|
@spin tst.b (a1) ; have we completed?
|
|
beq.s @spin ; no, keep waiting
|
|
|
|
lea 14(sp),sp ; dump locals
|
|
rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: syncComp
|
|
;
|
|
; Inputs: d0 - ADB command byte
|
|
; a0 - ptr to data (pascal string)
|
|
; a2 - ptr to data area
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: a0-a3,d0-d3
|
|
;
|
|
; Function: This is our ADB completion routine. It simply copies any
|
|
; data to our receive buffer in our data area, then sets our
|
|
; complete flag.
|
|
;_______________________________________________________________________
|
|
|
|
syncComp st.b (a2) ; set our complete flag
|
|
rts
|
|
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: InitCrsrDev
|
|
;
|
|
; Inputs: -
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: a0-a1/d0
|
|
;
|
|
; Function: This routine allocates and initializes globals for the
|
|
; CursorDevice routines, keeping a pointer to them in ExpandMem.
|
|
;_______________________________________________________________________
|
|
|
|
InitCrsrDev
|
|
|
|
moveq #CrsrGlobSize,d0
|
|
_NewPtr ,Sys,Clear ; allocate storage for our globals
|
|
|
|
movea.l ExpandMem,a1 ; get ptr to expandmem rec
|
|
exg a0,a1
|
|
move.l a1,emCursorGlobals(a0) ; set cursory global ptr
|
|
|
|
lea SetCrsrDelCore,a0 ; addr of default ROM handler <H15>
|
|
move.l a0,SetCrsrDelayVector(a1) ; install into vector <H15>
|
|
lea DrawCursor,a0 ; addr of default ROM handler <H15>
|
|
move.l a0,DrawCrsrVBLVector(a1) ; install into vector <H15>
|
|
|
|
moveq #CrsrDataSize,d0 ; size of our (only) cursor data record
|
|
_NewPtr ,Sys,Clear ; allocate it's globals
|
|
move.l a0,firstCrsrData(a1) ; set ptr to main cursor data in our globals
|
|
|
|
moveq #$10,d0
|
|
swap d0
|
|
move.l d0,whereX(a0) ; init cursor position
|
|
move.l d0,whereY(a0)
|
|
|
|
moveq #72,d0 ; init default screen resolution to 72 dpi
|
|
swap d0 ; word2Fix
|
|
move.l d0,screenRes(a0)
|
|
|
|
lea vDrawCursor,a0 ; vector low level drawing routines
|
|
move.l a0,DrawCrsrVector
|
|
lea vEraseCursor,a0
|
|
move.l a0,EraseCrsrVector
|
|
|
|
IF LC930 THEN
|
|
|
|
bset.b #SkipDraw,CrsrDevFlags(a1) ; Do not draw the fisrt VBL just do the position calculations <SM6>
|
|
|
|
ENDIF
|
|
|
|
rts ; <H14>
|
|
|
|
;______________________________________________________________________________ <H15>
|
|
;
|
|
; Routine: SetCrsrDelay
|
|
;
|
|
; Inputs: a1 contains the ptr to the cursor gDevice being setup
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: a0,d0
|
|
;
|
|
; Function: This routine sets the screenDelay value in the CrsrDataRec
|
|
; to an appropriate delay value based on the screen type.
|
|
; This delay value is used by the cursor VBL as a minimum
|
|
; delay between subsequent cursor blits.
|
|
;______________________________________________________________________________
|
|
EXPORT SetCrsrDelay ; <H15>
|
|
SetCrsrDelay
|
|
movea.l ExpandMem,a0
|
|
cmpa.l #-1,a0 ;has ExpandMem been initialized?
|
|
beq.s @skipIt ; if not, then don't call b/c vector is not there
|
|
movea.l emCursorGlobals(a0),a0
|
|
move.l SetCrsrDelayVector(a0),d0 ;vector to the code that does the real work
|
|
beq.s @skipIt ;make sure the value has been initialized
|
|
movea.l d0,a0
|
|
jsr (a0) ; must preserve a1
|
|
@skipIt
|
|
IF padForOverpatch THEN
|
|
move.l CRSRPTR,A0 ;get handle to cursor data [padding]
|
|
MOVE.L (A0),A0 ;get pointer to cursor data
|
|
ENDIF
|
|
rts
|
|
|
|
;______________________________________________________________________________ <H15>
|
|
;
|
|
; Routine: SetCrsrDelCore
|
|
;
|
|
; Inputs: a1 contains the ptr to the cursor gDevice being setup
|
|
;
|
|
; Outputs: -
|
|
;
|
|
; Destroys: a0,d0
|
|
;
|
|
; Function: This routine sets the screenDelay value in the CrsrDataRec
|
|
; to an appropriate delay value based on the screen type.
|
|
; This delay value is used by the cursor VBL as a minimum
|
|
; delay between subsequent cursor blits.
|
|
;______________________________________________________________________________
|
|
|
|
SetCrsrDelCore
|
|
rts ; just a hook for now
|
|
|
|
|
|
;_____________________________________________________________________________________________ <H15>
|
|
; VDrawCursor - default DrawCursor routine
|
|
;
|
|
; The low level cursor routine DrawCursor, is now called through the expandmem vector
|
|
; emDrawCursorVector. This is the default routine which is set into the vector by
|
|
; the routine InitCrsrVects.
|
|
;
|
|
|
|
EXPORT VDrawCursor
|
|
IMPORT BLITCURSOR ;from ccrsrcore.a
|
|
VDrawCursor
|
|
MOVE.B #1,CRSRBUSY ;MARK CHANGE IN PROGRESS
|
|
|
|
TST CRSRSTATE
|
|
BMI.S DoneSho ;QUIT IF STILL HIDDEN
|
|
CLR CRSRSTATE ;DON'T LET CRSRSTATE GET > 0
|
|
TST.B CRSRVIS ;IS CURSOR ALREADY VISIBLE?
|
|
BNE.S DoneSho ;YES, DON'T TRY TO REDRAW
|
|
TST.B CrsrObscure ;Skip if obscured
|
|
BNE.S DoneSho
|
|
|
|
BSR.L BLITCURSOR ;Do the real work: put pixels up
|
|
|
|
DoneSho CLR.B CRSRBUSY ;CHANGE COMPLETE
|
|
RTS
|
|
|
|
|
|
;______________________________________________________________________________________________ <H15>
|
|
; VEraseCursor - default EraseCursor routine
|
|
;
|
|
; The low level cursor routine EraseCursor, is now called through the expandmem vector
|
|
; emEraseCursorVector. This is the default routine which is set into the vector by
|
|
; the routine InitCrsrVects.
|
|
;
|
|
|
|
EXPORT VEraseCursor
|
|
IMPORT UNBLITCURSOR ;from ccrsrcore.a
|
|
VEraseCursor
|
|
MOVE.B #1,CRSRBUSY ;MARK CHANGE IN PROGRESS
|
|
TST.B CRSRVIS ;IS CURSOR VISIBLE?
|
|
BEQ.S DoneHid ;NO, DON'T TRY TO REMOVE IT
|
|
|
|
BSR.L UNBLITCURSOR ;Zap Pixels
|
|
|
|
DoneHid CLR.B CRSRBUSY ;CHANGE COMPLETE
|
|
RTS
|
|
|
|
END |