;ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ ; ; 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): ; ; 5/28/93 IH Add comment about Display Mgr usage of CrsrNew. ; 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). ; 8/26/92 kc Roll in Horror changes. ; 7/24/92 GMR Fixed comaptibility problem with Hypercard/MacPaint Grid drawing ; mode (Atkinsons MouseMask secret). ; 7/17/92 GMR Changed the double-click translation table to match the Mouse ; CDEVs double-click times. ; 7/14/92 GMR Reset MBState to button up in CrsrDevReInit code. ; 7/13/92 djw 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. ; 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!). ; 7/6/92 GMR Update doubleTime lowmem when creating a new device. ; 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). ; 6/26/92 GMR 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. ; 6/10/92 GMR Fixed bug with buttonCount not being reset after waking up from ; sleep. ; 6/5/92 GMR Changed the movem's in the trap selector dispatcher to be ; movem.l. ; 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). ; 5/12/92 JC Fixed problem with CrsrDevHandleVBL trashing registers. ;
4/3/92 SWC Added overpatch padding at the end of the file. ;
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. ;

3/9/92 SWC Fixed bug in CrsrDevSetAccel where the acceleration to set ; 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!. ; 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. ; 5/29/92 KW (JC,H7) Fixed problem with CrsrDevHandleVBL trashing registers. ; 5/2/92 kc Roll in Horror. Comments follow: ;
4/3/92 SWC Added overpatch padding at the end of the file. ;
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. ;

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. ;

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. ;

2/14/92 SWC Added a RomMapInsert before all resource calls so we make sure ; we at least find our resources in the ROM. ;

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,vDrawCursor,vEraseCursor WITH CrsrDevGlobals, CrsrDevRec, CrsrDevSegment, CrsrDataRec WITH ADBDeviceEntry, ADBVars, ExpandMemRec _______________________________________________________________________ ; ; Routine: CrsrDevDispatch 82b0 (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 82ec ; ; 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 8306 ; ; 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 8334 ; ; 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 8360 ; ; 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 8376 ; ; 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 8388 ; ; 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 839a ; ; 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 83ba ; ; 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 83ce ; ; 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 83e4 ; ; 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 83f8 ; ; 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 8414 ; ; 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 843c ; ; 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 8450 ; ; 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 8462 ; ; 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) ; 3 b4 y12 y11 y10 b5 x12 x11 x10 (optional) ; 4 b6 y15 y14 y13 b7 x15 x14 x13 (optional) ; ; 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 bge.s @x7to9 ; if so, process it. else, extend sign @byte3extx btst #6,d0 ; check sign bit (bit 6) beq.s @byte3exty ; or.w #$ff80,d0 ; fake a negative, faster than ext @byte3exty btst #6,d1 ; check sign bit (bit 6) beq @domove ; or.w #$ff80,d1 ; fake a negative for y bra.s @domove ; @x7to9 moveq.l #$7,d2 ; move mask into workspace and.b 2(a3),d2 ; get x bits 7-9 lsl.w #7,d2 ; move them to add to running tally or.w d2,d0 ; @y7to9 moveq.l #$70,d2 ; mask the bits and.b 2(a3),d2 ; get y bits 7-9 lsl.w #3,d2 ; move and add to tally or.w d2,d1 ; @byte4 cmp.b #4,(a0) ; check to see if we have a 4th byte bge.s @x10to12 ; @byte4extx btst #9,d0 ; check sign bit (bit 9) beq.s @byte4exty ; or.w #$fc00,d0 ; fake a negative for x @byte4exty btst #9,d1 ; check sign bit (bit 9) beq.s @domove ; or.w #$fc00,d1 ; fake a negative for y bra.s @domove ; @x10to12 moveq.l #$7,d2 ; move mask into workspace and.b 3(a3),d2 ; get x bits 10-12 lsl.w #8,d2 ; move them to add to running tally lsl.w #2,d2 ; do a 10 bit shift or.w d2,d0 ; @y10to12 moveq.l #$70,d2 ; mask the bits and.b 3(a3),d2 ; get y bits 10-12 lsl.w #6,d2 ; move and add to tally or.w d2,d1 ; @byte5 cmp.b #5,(a0) ; check to see if we have a 5th byte bge.s @x13to15 ; @byte5extx btst #12,d0 ; check sign bit (bit 12) beq.s @byte5exty ; or.w #$e000,d0 ; fake a negative for x @byte5exty btst #12,d1 ; check sign bit (bit 12) beq.s @domove ; or.w #$e000,d1 ; fake a negative for y bra.s @domove ; @x13to15 moveq.l #$7,d2 ; move mask into workspace and.b 4(a3),d2 ; get x bits 13-15 lsl.w #8,d2 ; move them to add to running tally lsl.w #5,d2 ; do a 13 bit shift or.w d2,d0 ; @y13to15 moveq.l #$70,d2 ; mask the bits and.b 4(a3),d2 ; get y bits 13-15 lsl.w #8,d2 ; move and add to tally lsl.w #1,d2 ; do a 9 bit shift or.w d2,d1 ; @domove ext.l d0 ; convert our words into longs ext.l d1 ; bsr.s CrsrDevMove ; accumulate movement clr.l d0 ; assume all buttons up @btn0 clr.l d1 ; start looking at button 0 btst.b #7,(a3)+ ; is 1st button up? bne.s @btn1 ; yes, check 2nd button bset d1,d0 ; no, indicate button down @btn1 addq.b #1,d1 ; go to the next button (button 1) btst.b #7,(a3)+ ; is 2nd button up? bne.s @btnn ; yes, handle all button states bset d1,d0 ; no, indicate button down @btnn addq.b #1,d1 ; go to the next button cmp.b cntButtons(a2),d1 ; compare current button number to num buttons bge.s @setBtns ; set the buttons if we are done btst.b #7,(a3) ; check the button for the high nibble bne.s @btnn_high ; not pressed, check high nibble bset d1,d0 ; record the press @btnn_high addq.b #1,d1 ; other button in low nibble btst.b #3,(a3)+ ; the button for this nibble bne.s @btnn ; loop again bset d1,d0 ; record the press bra.s @btnn ; @setBtns bsr CrsrDevButtons ; handle our buttons @exit rts ;_______________________________________________________________________ ; ; Routine: CrsrDevMove 854e ; ; 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 85ee ; ; 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,d2.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,d2.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,d2.w) ; mark that we're really up @done rts ;--------------------------------------------------------- d0CharStroke rts ;--------------------------------------------------------- doAppleScript rts ;--------------------------------------------------------- doCustom move.l buttonData(a2,d2.w),-(sp) ; push our custom routine address rts ; and call it. ;_______________________________________________________________________ ; ; Routine: CrsrDevButtonDown 86a4 ; ; 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 addq.b #1,buttonCount(a1) ; count the button down moveq #0,d0 ; result code rts ;_______________________________________________________________________ ; ; Routine: CrsrDevButtonUp 86e4 ; ; 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 8720 ; ; 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

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! move.l devID(a2),d4 ; first try finding an 'accl' that matches our device ID

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

ext.w d4 ;

ext.l d4 ;

bsr FindResource ; did we find one? beq.s @foundIt ; yes, skip below moveq #0,d4 ; otherwise, just load the flat ramp

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.B $85(A2), D3 BEQ.B @endofthing Clr -(SP) Move.L #'accl', -(A7) Move #$FFFF, (ROMMapInsert) _CountResources Move (SP)+, D3 Move.L #'USB*', D4 Bsr FindResource BEQ.B @endofthing MoveQ.L #$0, D4 Bsr FindResource @endofthing 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)

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?

bne.s @scaleLoop ; yes, say no points left in one of the tables

moveq #0,d5 ;

@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 8906 ; ; 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

@loop move.w #mapTrue,RomMapInsert ; map ROM into resource chain

clr.l -(sp) ; room for function result move.l #'accl',-(sp) ; we're looking for acceleration resources move.w d5,-(sp) ; push current index

_GetIndResource ; get next 'accl' resource move.l (sp)+,d0 ; did we get this one?

beq.s @NotFound ; -> no, try the next one

move.l d0,a0 ; handle in a0

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

bne.s @loop ; keep searching...

moveq #1,d0 ; set BNE if not found

@exit rts ; exit with Z-Flag set on match ;------------------------------------------------ ; ; Routine: Interpolate 892e ; ; 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 8992 ; ; Inputs: - ; ; Outputs: - ; ; Destroys: d0 ; ; 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 movea.l ExpandMem,a3 ; get ptr to expandmem rec movea.l emCursorGlobals(a3),a3 ; get cursory global ptr tst.l a3 beq @exit 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 ) ? 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 move.l MTemp,d0 ; does RawMouse

cmp.l RawMouse,d0 ; = MTemp?

bne.s @delta ; no, then they're doing deltas

@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 ; @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 ; 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 jsr (a0) ; movem.l (sp)+,d0/a0-a4 ; restore registers trashed by CursorDraw routine ENDIF ; 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 ; ;================================== @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 jsr (a0) ; ENDIF ; @exit movem.l (sp)+,a0-a4/d1-d5 ; restore a bunch of registers rts ;_______________________________________________________________________ ; ; Routine: DrawCursor 8b38 ; ; 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 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 move.l d0,MTemp ; no, just update lowmem MTemp bra.s @exit ; and exit without drawing cursor @coupled tst.b CrsrBusy ; is it locked? bne.s @exit ; yesΙ exit lea CrsrPin,a0 ; it's ok to update cursor, get bounding rect move.l d0,-(sp) 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 ; 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 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 ; 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 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 8bb8 ; ; 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 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... 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 8c6e ; ; 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 beq.s @exit 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 a2,d0 move.l d1,a2 move.l a1,nextCrsrDev(a2) ; else, delete our element from middle of list move.l d0,a2 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 8cae ; ; 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 ; WITH ADBParamBlk movem.l d0-d3/a0-a3,-(sp) link a6,#adbPBSize ; Make a stack frame for our param block tst d0 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 clr.l MBTicks ; reset timestamp for mouse button _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
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 movea.l emCursorGlobals(a0),a0 ; get cursory global ptr move.l firstCrsrData(a0),a0 ; get the cursor data ptr clr.b buttonCount(a0) ; init button down count ;--------------------- @exit unlk a6 ; dump the adbInfo param block movem.l (sp)+,d0-d3/a0-a3 rts ;_______________________________________________________________________ ; ; Routine: syncADBTalk 8e7c ; ; 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 @restart move.l a0,-(sp) ; save ptr to our buffer move.l d0,-(sp) 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 bmi.s @weird @spin tst.b (a1) ; have we completed? beq.s @spin ; no, keep waiting lea 18(sp),sp ; dump locals move.l (sp)+,a0 ; restore a0 rts @weird lea.l $e(sp),sp move.l (sp)+,d0 move.l (sp)+,a0 bra.s @restart ;_______________________________________________________________________ ; ; Routine: syncADBListen 8ea8 ; ; 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 @restart movem.l d0/a0,-(sp) 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 bmi.s @weird @spin tst.b (a1) ; have we completed? beq.s @spin ; no, keep waiting lea 22(sp),sp ; dump locals rts @weird lea.l $e(sp),sp movem.l (sp)+,d0/a0 bra.s @restart ;_______________________________________________________________________ ; ; Routine: syncComp 8ed2 ; ; 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 8ed6 ; ; 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 move.l a0,SetCrsrDelayVector(a1) ; install into vector lea DrawCursor,a0 ; addr of default ROM handler move.l a0,DrawCrsrVBLVector(a1) ; install into vector 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 ENDIF rts ; ;______________________________________________________________________________ ; ; Routine: SetCrsrDelay 8f22 ; ; 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 ; 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 ;______________________________________________________________________________ ; ; Routine: SetCrsrDelCore 8f3c ; ; 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 NewCrsrFunction ; 8f3e Move.L (DeviceList), D0 @loop BEQ.B @done MoveA.L D0, A0 CmpA.L D1, A0 BNE.B @moredone MoveA.L (A0), A0 Move.L $1E(A0), D0 Bra.B @loop @done SubA.L A0, A0 @moredone Move.L A0, D1 Rts ;_____________________________________________________________________________________________ ; 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. ; VDrawCursor PROC EXPORT IMPORT QD_DRAWCURSOR BRA.L QD_DRAWCURSOR ;______________________________________________________________________________________________ ; 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. ; VEraseCursor PROC EXPORT IMPORT QD_ERASECURSOR BRA.L QD_ERASECURSOR END