mac-rom/QuickDraw/CCrsrCore.a

2028 lines
69 KiB
Plaintext
Raw Normal View History

;
; File: CCrsrCore.a
;
; Contains: system cursor/mouse routines. Contains the mouse interrupt receivers
; and cursor drawing and hiding routines.
;
; Written by: Bud Tribble 2-Oct-81
;
; Copyright: <09> 1981-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM6> 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32
; so they can conditionalized out of the build.
; <SM5> 2/4/93 CSS Update from Horror:
; <H3> 7/13/92 djw <GED> Overpatched DrawCursor, EraseCursor and SetCrsrData,
; vectorizing them to allow access later.
; <SM4> 6/11/92 stb <sm 6/9/92>stb Add comments from QDciPatchROM.a to ShowCursor,
; SetCCursor
; <SM3> 5/16/92 kc Add forRom conditionals around last change.
; <SM2> 5/16/92 kc Roll in Horror. Comments follow:
; <H2> 2/12/92 SWC Patched out most of CrsrVBLTask since the new cursor
; acceleration code does things differently.
; <7> 7/10/91 dba end of the forPost70 conditional; we are past 7.0 for good
; <6> 5/31/91 KON Register A2 gets trashed when setting a color cursor and there
; is more than one GDevice.
; <5> 9/17/90 BG Removed <4>. 040s are now behaving more reliably.
; <4> 6/25/90 BG Added EclipseNOPs for flakey 040s.
; <3> 6/25/90 KON Obscure-show-hide leaves crsr hidden only, Obscure-hide-show
; leaves crsr obscured only.
; <2> 1/3/90 BAL Updated to latest local source version.
; <<3C>1.7> 7/14/89 BAL For Aurora: Final CQD
; <1.6> 6/10/89 CEL Moved Private.a QuickDraw Equates into proper QuickDraw private
; file (colorequ.a), got rid of QuickDraw nFiles dependencies and
; fixed up necessary files<65>
; <<3C>1.5> 5/29/89 BAL Blasting in 32-Bit QuickDraw version 1.0 Final
; 4/7/89 BAL Moved crsrVBLTask to head of file and scrnAddress to end of file
; for VM.
; 9/7/88 BAL Altered showCursor to clear crsrObscure if showing cursor.
; 6/28/88 BAL Use special 1 to 24 bit pixel expansion routine.
; 6/21/88 BAL Finally fixed SetCCursor; Needed to Lock input handle across
; routine.
; 3/25/88 BAL Altered Show/Hide Cursor to use 32 bit clean addresses.
; 3/23/88 BAL Fixed bug in CrsrRect.right for pixel depth > 1.
; <C944> 11/7/87 BAL Rolled in patches to SetCCursor to preserve A2.
; 5/27/87 EHB Added fix to SetCCursor for trashed A2
; <C856> 5/26/87 CSL Fixed absolute cursor positioning problem.
; 10/13/86 EHB Rolled in new version of CrsrVBLTask
; 10/13/86 EHB Added AllocCrsr; called by AllocCursor.
; 10/6/86 EHB Added SetCCursor; redid other routines to support color.
; 10/2/86 EHB Redid inner loop of ShowCursor for color support
; 7/14/86 EHB Don't draw cursor if CRSRPTR not set up.
; <C63> 7/2/86 EHB CLEAR D0 BEFORE CALLING EXTBL ROUTINES. Multiply offset amount
; by depth for left pinning Check 8 longs of cursor
; <C63> 7/2/86 EHB Include colorequ in great equate purge
; <C60> 6/30/86 EHB New ShowCursor/HideCursor for depth support Fixed branch bug in
; ShieldCursor
; <C28> 5/30/86 CSL Added changes for Aladdin, and Aladdin Front desk bus support.
; <C1> 5/6/86 RDC Added fixes in ShowCursor routine
; <C1> 4/15/86 RDC Added changes for new 68020 Reno project (NuMac) - Added include
; for newequ.text to get at low mem equates for screen vars -
; Added changes in Cursor routines to use low mem for screen
; values
; 2/19/86 BBM Made some modifications to work under MPW
;_______________________________________________________________________
;
; Before Lonely Hearts
;_______________________________________________________________________
; 11/5/85 JTC for ELR (on telephone) Fix loop termination condition in
; HideCursor that killed MacPaint, e.g.
; 7/25/85 RDC Added include for HWequ file
; 7/23/85 RDC Moved mouse interrupt routines to IntHnd.Text
; 4/23/85 JTC Change to PIN hotSpot between 0 and 16, not 15. <23Apr85>
; 4/5/85 JTC Fix discontinuity in PinGuts; mask hotSpot with $000F000F in
; SetCursor; add ScreenAddress and ScreenSize to SysDef traplist;
; fix 'changed' test in SetCursor. Punted on desired call to get
; Cursor ID ... see Change note for details.
; 8/20/83 LAK Just uses CrsrThresh for scaling params.
; 8/18/83 LAK Changed name of CrsrTask to CrsrVBLTask (but why?).
; 7/20/83 SC Cleaned up after code review
; 4/28/83 AJH moved PinRect into crsrCore
; 1/28/83 AJH made SetCursor display it if its different
; 1/23/83 LAK Adapted for new equate files.
; 1/13/83 SC Decouple and scaled Cursor stuff
; 11/7/82 AJH Made ObscureCursor unbusy cursor if already obscured
; 10/16/82 LAK Modified for new LisaGraf cursor interface
; 9/5/82 LAK IntHnd now handles ext/sts interrupt resetting
; 8/26/82 LAK updated for 512-dots
; 8/5/82 LAK modified for INTHND change (no need to modify A0-1 for SCC port
; A) or read status reg.
; 5/4/82 LAK Updated MV1INT, MH1INT for SCC hardware
; 4/9/82 AJH Changed SHOWCURSOR to clip ala Rick Meyer's Lisa routines
; 10/31/81 AJH Hardwired the CRSR task into the VBL manager
; 10/19/81 bmw fixed a bug andy found in getscreen
; 7/3/81 AJH Installed "ObscureCursror" entry point and support
;
BLANKS ON
STRING ASIS
MACHINE MC68020 ;<C60/30JUN86>
cursorShadow EQU 0
CRSRCORE PROC EXPORT
EXPORT CrsrVBLTask
EXPORT InitCrTable
EXPORT PinRect
IMPORT ScrnAddress
IMPORT ScrnSize
IMPORT ScrnBitMap
IMPORT PATCONVERT ; expand routine for color cursors/patterns
IMPORT AllocCrsr ; proc at end of file
IMPORT SETCRSRDATA ; PROC AT END OF FILE
IMPORT SHFTTBL ; TO CONVERT DEPTH TO SHIFT
IMPORT RGetHSize
IMPORT BLITCURSOR,UNBLITCURSOR ; Cursor Pixelling <dvb 19sep88>
EXPORT DRAWCURSOR,ERASECURSOR ; Cursor Displaying <dvb 19sep88>
EXPORT CursorSect
EXPORT GETMAINCRSR ;JUST USED INTERNALLY
;
; offset table for jump table initialization
;
InitCrTable
DC.W HideCursor-InitCrTable
DC.W ShowCursor-InitCrTable
DC.W ShieldCursor-InitCrTable
DC.W ScrnAddress-InitCrTable
DC.W ScrnSize-InitCrTable
DC.W InitCursor-InitCrTable
DC.W SetCursor-InitCrTable
DC.W ObscureCursor-InitCrTable
DC.W AllocCrsr-InitCrTable
DC.W SetCCursor-InitCrTable
;_______________________________________________________________________
;
; CrsrVBLTask - executed once each vertical retrace
;
; ugly equs - stay here for now!
adbCount EQU 0 ; word: number of valid error deltas
MaxCnt EQU adbCount+2 ; word: limit on number of error deltas
Err7 EQU MaxCnt+2 ; word: time-7 error magnitude
Err6 EQU Err7+2 ; word: time-6 error magnitude
Err5 EQU Err6+2 ; word: time-5 error magnitude
Err4 EQU Err5+2 ; word: time-4 error magnitude
Err3 EQU Err4+2 ; word: time-3 error magnitude
Err2 EQU Err3+2 ; word: time-2 error magnitude
Err1 EQU Err2+2 ; word: time-1 error magnitude
Error EQU Err1+2 ; word: accumulated error
GSize EQU Error+2
CrsrVBLTask ;COME HERE ON VERTICAL RETRACE
If Not forRom Then ; <H2>
TST.B CrsrNew ; Mouse changed?
BEQ TrackDone ; No <20> return
TST.B CrsrBusy ; Cursor locked?
BNE TrackDone ; Yes <20> return
TST.B CrsrCouple ; Cursor coupled to mouse?
BEQ NoComp ; No <20> skip computation <DSV>
MOVE.W MTemp+H,D0 ; Find <20>Mx
SUB.W RawMouse+H,D0
MOVE.W MTemp+V,D1 ; Find <20>My
SUB.W RawMouse+V,D1
MOVE.W D0,D2 ; x := |<7C>Mx|
BGE.S AbslXl
NEG.W D2
AbslXl
MOVE.W D1,D3 ; y := |<7C>My|
BGE.S AbslYl
NEG.W D3
AbslYl
move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals <c856/26May87>
CMP.W D2,D3 ; D3 := magnitude(x,y)
BLS.S MagDone
EXG D2,D3
MagDone ASR.W #1,D3
ADD.W D2,D3
BNE.S DoComp ; Zero magnitude <20> don<6F>t compute <c856/26May87>
MOVE.W #1,adbCount(A0) ; No hits <c856/26May87>
CLR.W Error(A0) ; No errors <c856/26May87>
BRA DoPin ; Update the cursor <c856/26May87>
DoComp
;
MOVEM.L D4-D5,-(A7) ; Save off registers
MOVE.W adbCount(A0),D4 ; D4 is the number of samples
CMP.W MaxCnt(A0),D4 ; Is Count less than MaxCnt
BGE.S CountOK
ADD.W #1,adbCount(A0) ; Yes <20> we will have one more error
CountOK
MOVE.W D3,D5 ; Magnitude at current time
MOVE.W D4,D2 ; Get Count
SUB.W #1,D2 ; Index into JTab
ASL.W #1,D2 ; REQUIRES BRA.S<>s IN JUMP TABLES
JMP JTab(PC,D2.W) ; Jump to the right code per Count
JTab BRA.S E1 ; Count = 1
BRA.S E2 ; Count = 2
BRA.S E3 ; Count = 3
BRA.S E4 ; Count = 4
BRA.S E5 ; Count = 5
BRA.S E6 ; Count = 6
BRA.S E7 ; Count = 7
E8 ADD.W Err7(A0),D5 ; Accumulate time-7 magnitude
E7 ADD.W Err6(A0),D5 ; Accumulate time-6 magnitude
MOVE.W Err6(A0),Err7(A0) ; Shift out time-6 magnitude
E6 ADD.W Err5(A0),D5 ; Accumulate time-5 magnitude
MOVE.W Err5(A0),Err6(A0) ; Shift out time-5 magnitude
E5 ADD.W Err4(A0),D5 ; Accumulate time-4 magnitude
MOVE.W Err4(A0),Err5(A0) ; Shift out time-4 magnitude
E4 ADD.W Err3(A0),D5 ; Accumulate time-3 magnitude
MOVE.W Err3(A0),Err4(A0) ; Shift out time-3 magnitude
E3 ADD.W Err2(A0),D5 ; Accumulate time-2 magnitude
MOVE.W Err2(A0),Err3(A0) ; Shift out time-2 magnitude
E2 ADD.W Err1(A0),D5 ; Accumulate time-1 magnitude
MOVE.W Err1(A0),Err2(A0) ; Shift out time-1 magnitude
E1 MOVE.W D3,Err1(A0) ; Shift out current magnitude
MOVE.W D4,D2 ; Round up the divide
ASR.W #1,D2 ; by half the denominator
ADD.W D2,D5
EXT.L D5 ; Set up for the divide
DIVU D4,D5 ; Find the average magnitude
MOVE.W D3,D4 ; Get the original magnitude
SUB.W D5,D3 ; Find distance to average magnitude
ADD.W Error(A0),D3 ; Add on the accumulated error
CMP.W #-1,D3 ; Define -1 div 2 = 0
BNE.S DivOK
CLR.W D3
DivOK ASR.W #1,D3 ; Get half of it
MOVE.W D3,Error(A0) ; Update it
ADD.W D5,D3 ; Desired mag is average+Error
CMP.W #255,D5 ; mag := MAX(mag,255)
BLS.S MaxDone
MOVE.B #255,D5
MaxDone
move.l MickeyBytes,a0 ; <10/7/86 SMH> get at globals
add #GSize,a0 ; <10/24/86 SMH> point to table
CLR.W D2 ; i := 0
Search ADD.B #1,D2 ; repeat
CMP.B (A0)+,D5 ; i := i+1
BHI.S Search ; until mag <20> Table[i]
MULS D2,D3 ; D4 := i*(Mag(<28>M)+Error)
MULS D3,D0 ; <20>Cx := (<28>Mx*i*(Mag(<28>M)+Error))/Mag(<28>M)
DIVS D4,D0 ; <<<<<< D3 >>>>>>>
BMI.S @1 ; branch if minus
ANDI.W #$007F,D0 ; control max displacement (fix mouse jump)
BRA.S @3
@1
ORI.W #$FF80,D0 ; control max displacement (fix mouse jump)
@3
MULS D3,D1 ; <20>Cy := (<28>My*i*(Mag(<28>M)+Error))/Mag(<28>M)
DIVS D4,D1 ; <<<<<< D3 >>>>>>>
BMI.S @5 ; branch if minus
ANDI.W #$007F,D1 ; control max displacement (fix mouse jump)
BRA.S @7
@5
ORI.W #$FF80,D1 ; control max displacement (fix mouse jump)
@7
MOVEM.L (A7)+,D4-D5 ; Restore registers
ADD.W D0,RawMouse+H ; Update raw mouse location
ADD.W D1,RawMouse+V
;
DoPin ; <c456/26May87>
LEA CrsrPin,A0 ; Bounding rect for cursor
MOVE.L RawMouse,D0 ; Pin mouse inside rect
Endif ; Not forRom <H2>
BSR.S ScrnPin ; return to SHOWIT if screen changes
MOVE.L D0,RawMOUSE ; update cursor loc with clipped pt
MOVE.L D0,MTEMP ; Update real mouse location with ""
AND.L MOUSEMASK,D0 ; do jerky masking to drop low order bits
MOVE.L MOUSEOffset,D1 ; Get the offset
BEQ.S skipPin ; and skip 2nd pin if not
ADD.L D1,D0 ; do jerky offset
BSR.S ScrnPin ; return to SHOWIT if screen changes
skipPin MOVE.L D0,MOUSE
NotCup BSR ERASECURSOR ; HIDE THE CURSOR <dvb 19sep88>
SHOWIT CLR.B CRSRNEW ; RESET THE CURSOR CHANGED FLAG
CLR.B CRSROBSCURE ; it's no longer obscured
BSR DRAWCURSOR ; AND SHOW CURSOR IN NEW POSITION <dvb 19sep88>
CRSRDONE ;AND RETURN
RTS
TrackDone
move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals
MOVE.W #1,adbCount(A0) ; No hits
CLR.W Error(A0) ; No errors
RTS ; Goodbye
NoComp move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals
MOVE.W #1,adbCount(A0) ; No hits
CLR.W Error(A0) ; No errors
BRA.S NotCup ; Update the cursor
; --------end of ugly jcrsrcoreTask
ScrnPin CMP LEFT(A0),D0 ;less than left?
BGE.S LEFTOK ;if not, no problem
BSR.S FindScreen ;=>look for new screen
MOVE LEFT(A0),D0 ;pin to the left
LEFTOK CMP RIGHT(A0),D0 ;greater than right?
BLT.S RIGHTOK ;if not, no problem WAS BLE!! <05Apr85>
BSR.S FindScreen ;=>look for new screen
MOVE RIGHT(A0),D0 ;pin to the right
SUBQ #1,D0 ;really want one less
RIGHTOK SWAP D0 ;consider y
CMP TOP(A0),D0 ;less than top?
BGE.S TOPOK ;if not, no problem
SWAP D0
BSR.S FindScreen ;=>look for new screen
SWAP D0
MOVE TOP(A0),D0 ;pin to the top
TOPOK CMP BOTTOM(A0),D0 ;greater than bottom?
BLT.S BOTOK ;if not, no problem WAS BLE!! <05Apr85>
SWAP D0
BSR.S FindScreen ;=>look for new screen
SWAP D0
MOVE BOTTOM(A0),D0 ;pin to the bottom
SUBQ #1,D0 ;really want one less
BOTOK SWAP D0
RTS ;and return
; Check to see if cursor has moved to another screen.
; If not, returns with D0 unchanged.
; If so, hides the cursor, updates cursor globals and does messy return.
;
; Clobbers D1-D3/A0-A3 which are preserved by interrupt handler
FindScreen MOVE D0,D3 ;pt.h in D3
MOVE.L D0,D1 ;pt.v in D1
SWAP D1 ;pt.v in D1
MOVE.L DeviceList,D2 ;get the first GDevice
BMI.S NoDev ;=>just in case no GDevice
DoDev MOVE.L D2,A3 ;get device handle
MOVE.L (A3),A3 ;get device pointer
TST GDFlags(A3) ;is screen active?
BPL.S NxtDev ;=>no, try next device
LEA GDRect(A3),A1 ;point to rect
CMP (A1)+,D1 ;above top?
BLT.S NxtDev ;=>yes, check next device
CMP (A1)+,D3 ;to left of screen?
BLT.S NxtDev ;=>yes, check next device
CMP (A1)+,D1 ;to bottom of screen?
BGE.S NxtDev ;=>yes, check next device
CMP (A1)+,D3 ;to right of screen?
BLT.S GotDev ;=>no, cursor is on this screen
NxtDev MOVE.L GDNextGD(A3),D2 ;get next device in chain
BNE.S DoDev ;=>there is one, check it
NoDev RTS ;else return and pin to current screen
; cursor has changed devices, update depth and rowbytes for current device
GotDev MOVE.L CRSRPTR,A0 ;get handle to cursor data
MOVE.L (A0),A0 ;get pointer to cursor data
MOVE.L CrsrDevice,A1 ;get handle to current device
MOVE.L (A1),A1 ;point to current device
MOVE CCDEPTH(A0),GDCCDEPTH(A1) ;copy depth
MOVE CCBYTES(A0),GDCCBYTES(A1) ;copy expanded rowbytes
; now get the data, depth and rowbytes for the new device
BSR ERASECURSOR ;else erase the cursor
@0 SWAP D3 ;get pt.h in high word
MOVE D1,D3 ;get pt.v in low word
SWAP D3 ;now get them in the right order
MOVE.L D3,MTEMP ;update real mouse location with ""
MOVE.L D3,RawMOUSE ;update cursor loc with clipped pt
MOVE.L D3,MOUSE ;update mouse position
MOVE.L D2,CrsrDevice ;set the current cursor device
MOVE.L A3,A1 ;get pointer to grafDevice
JSR SetCrsrData ;and set up low-memory stuff for cursor
MOVE GDREFNUM(A3),D0 ;get the refNum
NOT D0 ;refNum -> unitnum
ASL #2,D0 ;get offset in unitTable
MOVE.L UTableBase,A0 ;get the base of the unit table
MOVE.L (A0,D0),A3 ;A3 = handle to the DCE
MOVE.L (A3),A0 ;get pointer to the DCE
MOVEQ #0,D0 ;clear out D0
MOVE.B dCtlSlot(A0),D0 ;get the slot number
_ATTACHVBL ;attach vbl to this slot
ADDQ #8,SP ;strip 2 RTS's from stack
BRA SHOWIT ;=>and go display cursor on new screen
; This routine is used by the pinrect routine below and is also called directly
; by CrsrVBLTask above to save time
; A0 should be pinning rect and D0 is the point to be pinned
; Fixed to avoid discontinuity on right and bottom. <05Apr85>
PinGuts
CMP LEFT(A0),D0 ;less than left?
BGE.S @1 ;if not, no problem
MOVE LEFT(A0),D0 ;pin to the left
@1 CMP RIGHT(A0),D0 ;greater than right?
BLT.S @2 ;if not, no problem WAS BLE!! <05Apr85>
MOVE RIGHT(A0),D0 ;pin to the right
SUBQ #1,D0 ;really want one less
@2 SWAP D0 ;consider y
CMP TOP(A0),D0 ;less than top?
BGE.S @3 ;if not, no problem
MOVE TOP(A0),D0 ;pin to the top
@3 CMP BOTTOM(A0),D0 ;greater than bottom?
BLT.S @4 ;if not, no problem WAS BLE!! <05Apr85>
MOVE BOTTOM(A0),D0 ;pin to the bottom
SUBQ #1,D0 ;really want one less
@4 SWAP D0
RTS
;
; Utility FUNCTION PinRect(theRect: Rect; thePt: Point): Point;
;
; given a rectangle and a point, pin the point inside the rectangle
;
PinRect
MOVE.L 4(SP),D0 ;get the point
MOVE.L 8(SP),A0 ;get the rect ptr
BSR.S PinGuts ; go pin it
MOVE.L (SP)+,A0 ;get return address
ADDQ #8,SP ;strip parameters
MOVE.L D0,(SP) ;return pinned pt as result
JMP (A0) ;return to caller
;_______________________________________________________________________ ;<dvb 19Sep88>
; ;<dvb 19Sep88>
; PROCEDURE CursorSect -- called by shieldcursor, showcursor ;<dvb 19Sep88>
; ;<dvb 19Sep88>
; Does a sectrect of CrsrRect and ShieldRect, all global-co<63>rd like. ;<dvb 19Sep88>
; CLEAR the z-flag if they DO intersect: BNE YesTheyIntersect.
; This code is was moved out of ShieldCursor. ;<dvb 19Sep88>
;
; Since CrsrRect is in local screen co<63>rds, and ShieldRect is in globals,
; the CrsrDevice's GDRect is used as an offset.
;_______________________________________________________________________ ;<dvb 19Sep88>
CursorSect MOVEM.L A0/A1/D0,-(SP) ;save the approprate regs <dvb 19Sep88>
TST ShieldDepth ;Any shielding?
BEQ.s @NoSect
LEA CrsrRect,A0 ;point to crsr rect ;<dvb 19Sep88>
MOVE.L CrsrDevice,A1 ;GET CURSOR DEVICE ;<dvb 19Sep88>
MOVE.L (A1),A1 ;POINT TO CURSOR DEVICE ;<dvb 19Sep88>
ADD #GDRECT,A1 ;POINT TO DEVICE'S RECT ;<dvb 19Sep88>
MOVE ShieldRect+Bottom,D0 ;GET SHIELD BOTTOM ;<dvb 19Sep88>
SUB TOP(A1),D0 ;CONVERT TO SCREEN LOCAL;<dvb 19Sep88>
CMP (A0)+,D0 ;IS SHIELDBOTTOM < SAVETOP ? ;<dvb 19Sep88>
BLT.S @NOSECT ;YES, NO INTERSECTION ;<dvb 19Sep88>
MOVE ShieldRect+Right,D0 ;GET SHIELD RIGHT <dvb 19Sep88>
SUB LEFT(A1),D0 ;CONVERT TO SCREEN LOCAL <dvb 19Sep88>
CMP (A0)+,D0 ;IS SHIELDRIGHT <= SAVELEFT ? <dvb 19Sep88>
BLE.S @NOSECT ;YES, NO INTERSECTION <dvb 19Sep88>
MOVE ShieldRect+Top,D0 ;GET SHIELD TOP <dvb 19Sep88>
SUB TOP(A1),D0 ;CONVERT TO SCREEN LOCAL <dvb 19Sep88>
CMP (A0)+,D0 ;IS SHIELDTOP >= SAVEBOTTOM ? <dvb 19Sep88>
BGE.S @NOSECT ;YES, NO INTERSECTION <dvb 19Sep88>
MOVE ShieldRect+Left,D0 ;GET SHIELD LEFT <dvb 19Sep88>
SUB LEFT(A1),D0 ;CONVERT TO SCREEN LOCAL <dvb 19Sep88>
CMP (A0),D0 ;IS SHIELDLEFT >= SAVERIGHT ? <dvb 19Sep88>
BGE.S @NOSECT ;YES, NO INTERSECTION <dvb 19Sep88>
@SECT MOVEQ #1,D0 ;Clear the Z-flag <dvb 19Sep88>
BRA.S @out ;<dvb 19Sep88>
@NOSECT CLR D0 ;Set the Z-flag <dvb 19Sep88>
@out MOVEM.L (SP)+,A0/A1/D0 ;Restore regs <dvb 19Sep88>
RTS ;bye.
;_______________________________________________________________________
;
; PROCEDURE ObscureCursor -- called via the jump table
;
; Removes the cursor from the screen without hiding it, so the next
; time the mouse moves, it will show up again.
;
;_______________________________________________________________________
ObscureCursor
MOVE.B #1,CrsrBusy ;"Occupado" <dvb 19sep88>
MOVE.B #1,CrsrObscure ;Mark it as obscure <dvb 19sep88>
BRA.S EraseCursor ;and erase it
;_______________________________________________________________________
;
; HIDECURSOR - is called from CrsrVBLTask, and via jump table.
;
; Subtracts 1 from crsrstate and hides the cursor if visible.
;
;
HideCursor
MOVE.B #1,CrsrBusy ;MARK CHANGE IN PROGRESS
SUB #1,CRSRSTATE ;CURSOR HIDDEN ONE DEEPER
;Fall into EraseCursor
;________________________________________________________________________
; <SM5> CSS Horror vectorized this vector. We are supporting this to be
; compatible with Horror.
; EraseCursor calls a vectorized version of the routine via lomem.
; EraseCursor is vectorized to gain access to low level cursor blit routines.
; (NOTE: Vector is initialized in StartInit.a to routine named VEraseCursor.)
; EraseCursor is much like HideCursor, but doesn't decrement the CrsrState <dvb 19sep88>
EraseCursor
move.l EraseCrsrVector,-(sp) ;<SM5> CSS
rts ;jump to the vectored routine <SM5> CSS
DoneHid CLR.B CRSRBUSY ;CHANGE COMPLETE
RTS
;_______________________________________________________________________
;
; PROCEDURE InitCursor;
;
; Definitely redisplay the cursor, independent of previous calls to
; HideCursor, ShieldCursor and ObscureCursor. It falls into showCursor.
;
InitCursor
MOVE.B #1,CrsrBusy ;mark it busy
CLR.B CrsrObscure ;we wont be obscure no more
CLR CrsrState ;reset state to 0
CLR ShieldDepth
;
; fall into ShowCursor
;
;_______________________________________________________________________
;
; SHOWCURSOR - Called from CrsrVBLTask and via Jump Table.
;
; Adds 1 to CRSRSTATE and paints cursor if zero and cursor is
; not already visible.
;
;<3B>this reflects the fix from QDciPatchROM.a where obscure/show/hide left <sm 6/9/92>stb
; the cursor hidden only, and obscure/hide/show left the cursor obscured only. <sm 6/9/92>stb
ShowCursor
MOVE.B #1,CRSRBUSY ;MARK CHANGE IN PROGRESS
TST ShieldDepth ;Any shielding?
BEQ.s @2
@1 SUBQ #1,ShieldDepth ;If so, this ShowCursor unshields,
BRA.s DrawCursor ;but doesn't up the cursor level.
@2 ADDQ #1,CRSRSTATE ;CURSOR HIDDEN ONE LESS DEEP
bmi.s DoneSho
beq.s DrawCursor ;<KON 25JUN90>
clr.b CrsrObscure ;unobscure cursor if level went past zero <KON 25JUN90>
;fall into DrawCursor
;________________________________________________________________________
; <SM5> CSS Horror vectorized this vector. We are supporting this to be
; compatible with Horror.
; DrawCursor calls a vectorized version of the routine via lomem.
; DrawCursor is vectorized to gain access to low level cursor blit routines.
; (NOTE: Vector is initialized in StartInit.a to routine named VDrawCursor.)
; DrawCursor is much like ShowCursor, but doesn't increment the CrsrState <dvb 19sep88>
DrawCursor
move.l DrawCrsrVector,-(sp) ; <SM5> CSS
rts ;jump to the vectored routine <SM5> CSS
DoneSho CLR.B CRSRBUSY ;CHANGE COMPLETE
RTS
;_______________________________________________________________________
;
; CURSHIELD - Called via Jump Table
;
; PROCEDURE ShieldCursor(left,top,right,bottom: INTEGER);
;
; Subtracts 1 from CRSRSTATE, hides cursor only if it intersects SHIELDRECT.
; left,top,right bottom is the shieldRect in global coordinates
;
; ALL REGISTERS RESTORED.
;
ShieldVars RECORD {return},DECREMENT ;<dvb 19Sep99>
ShieldLeft DS.W 1 ;<dvb 19Sep99>
ShieldTop DS.W 1 ;<dvb 19Sep99>
ShieldRight DS.W 1 ;<dvb 19Sep99>
ShieldBot DS.W 1 ;<dvb 19Sep99>
return DS.L 1 ;<dvb 19Sep99>
ENDR
WITH ShieldVars
ShieldCursor
TST ShieldDepth ;Any shielding already? ;<dvb 19Sep88>
BEQ.s @2 ;No=>don't unionrect
MOVEM.L D0/A0,-(SP) ;Save some regs (and +8 our vars below*)
LEA ShieldRect+right,A0 ;A0->ShieldRect.right
MOVE.L ShieldBot+8(SP),D0 ;D0 = New shield bot,right (*)
CMP (A0),D0 ;Compare to ShieldRect.right
BLE.s @u1 ;Is the new right bigger?
MOVE D0,(A0)
@u1 SWAP D0 ;D0 = New shield bottom
CMP -(A0),D0 ;Compare to ShieldRect.bottom
BLE.s @u2 ;Is the new bottom bigger?
MOVE D0,(A0) ;If so, replace with it.
@u2 MOVE.L ShieldTop+8(SP),D0 ;D0 = New shield top,left (*)
CMP -(A0),D0 ;Compare to ShieldRect.left
BGE.s @u3 ;Is the new left smaller?
MOVE D0,(A0)
@u3 SWAP D0 ;D0 = New shield top
CMP -(A0),D0 ;Compare to ShieldRect.top
BGE.s @u4 ;Is the new top smaller?
MOVE D0,(A0)
@u4 MOVEM.L (SP)+,D0/A0
BRA.s @3
@2 MOVE.L ShieldBot(SP),ShieldRect+botRight ;save shieldrect ;<dvb 19Sep88>
MOVE.L ShieldTop(SP),ShieldRect+topLeft ;<dvb 19Sep88>
@3 ADDQ #1,ShieldDepth ;Shielding officially on
MOVE.B #1,CrsrBusy
BSR CursorSect ;<dvb 19Sep88>
BEQ.s @1 ;<dvb 19Sep88>
BSR EraseCursor ;IT DOES INTERSECT, REMOVE IT
@1 CLR.B CrsrBusy
MOVE.L (SP)+,(SP) ;STRIP 8 bytes of PARAMETERS, MOVING
MOVE.L (SP)+,(SP) ;RETURN ADDR UP ON STACK
RTS
ENDWITH
IMPORT CopyHandle,PatConvert
;_______________________________________________________________________
;
; PROCEDURE SetCCursor(cCrsr: CCrsrHandle);
;
; This procedure copies the data in the specified color cursor into the
; system's cursor save area. If the depth > 2, it expands it.
; this routine was taken from QDciPatchROM.a because A2 was getting trashed <sm 6/9/92>stb
; when setting CCursor on multiple device systems <sm 6/9/92>stb
SetCCursor MOVEM.L D3-D4/A2-A4,-(SP) ;save work registers
move.l 24(sp),a2 ;get ccrsrHandle <BAL 21Jun88>
move.l a2,a0 ;make a copy
_HGetState
move d0,-(sp) ;save state for later
move.l a2,a0 ;make a copy
_HLock
MOVE.L (a2),A2 ;GET POINTER TO NEW CURSOR
MOVE.L ([CRSRPTR]),A3 ;point to current cursor (LOCKED)
MOVE.L crsrID(A2),D0 ;and get ID of new cursor
CMP #CCrsrPat,ccType(A3) ;is current cursor a color cursor?
BNE.S NotCC ;=>no, it has definitely changed
CMP.L ccID(A3),D0 ;same as current one?
BEQ SCCDONE ;=>yes, just return
NotCC MOVE.B #1,CRSRBUSY ;flag the cursor as busy
MOVE.L D0,ccID(A3) ;set new ID
LEA crsr1Data(A2),A0 ;point to old-cursor data
LEA THECRSR,A1 ;put it here
MOVEQ #16,D0 ;data+mask+hotspot = 17 longs
@0 MOVE.L (A0)+,(A1)+ ;copy data
DBRA D0,@0 ;until done
LEA crsr1Data(A2),A0 ;point to old-cursor data
LEA CCLASTCRSR(A3),A1 ;save here to indicate cursor changed
MOVEQ #7,D0 ;move 8 longs
@1 MOVE.L (A0)+,(A1)+ ;copy data
DBRA D0,@1 ;=>loop until done
MOVE crsrType(A2),ccType(A3) ;copy the type
; NOTE: ALL THE DST HANDLES ARE LOCKED, BUT THEY HAVE BEEN SET TO THE PROPER SIZE
MOVE.L crsrMap(A2),-(SP) ;push src pixMap handle
MOVE.L ccMap(A3),-(SP) ;push dst pixMap handle
_CopyPixMap ;copy the pixMap
MOVE.L crsrData(A2),-(SP) ;push src data handle
MOVE.L ccData(A3),-(SP) ;push dst data handle
_CopyHandle ;copy the cursor data
; FOR EACH ACTIVE SCREEN DEVICE, EXPAND CURSOR, IF NECESSARY
MOVE.L DEVICELIST,D4 ;D4 = CURRENT DEVICE
MOVE.L D4,A4 ;GET HANDLE TO CURRENT DEVICE
NXTSCR MOVE.L (A4),A4 ;A4 = POINTER TO CURRENT DEVICE
TST.W GDFLAGS(A4) ;IS THE DEVICE ACTIVE?
BPL CHKNXT ;=>NO, CHECK NEXT DEVICE
;ACTIVE DEVICES ARE LOCKED DOWN
MOVE.L GDPMAP(A4),A0 ;GET HANDLE TO DEVICE'S PIXMAP
MOVE.L (A0),A0 ;POINT TO DEVICE'S PIXMAP
MOVE PIXELSIZE(A0),D3 ;GET DEVICE'S PIXELSIZE
; IF THE PATTERN IS PRE-EXPANDED TO THE RIGHT DEPTH, JUST COPY THAT DATA
CLR GDCCDEPTH(A4) ;flag to expand one-bit data
MOVE CRSRXVALID(A2),D0 ;is there pre-expanded data?
BEQ.S GOEXP ;=>no, do expansion
CMP D3,D0 ;is the expanded data the right depth?
BNE.S GOEXP ;=>no, expand from the source
MOVE D0,GDCCDEPTH(A4) ;else copy the expanded depth
MOVE.L crsrXData(A2),-(SP) ;push the src xdata handle
MOVE.L CCXDATA(A3),-(SP) ;push the dst xdata handle
_CopyHandle ;and copy it
BRA.S CHKNXT ;=>data already expanded, just exit
GOEXP CMP #CCRSRPAT,CCTYPE(A3) ;IS IT A COLOR CURSOR?
BNE.S DONEONE ;=>NO, EXIT WITH DEPTH = 0
CMP #2,D3 ;IS DEPTH GREATER THAN 2?
BLE.S DONEONE ;=>NO, EXIT WITH DEPTH = 0
MOVE D3,GDCCDEPTH(A4) ;RECORD THE EXPANDED DEPTH
MOVE.L GDCCXDATA(A4),CCXDATA(A3) ;GET DEVICE'S EXPANDED DATA FOR PATCONVERT
MOVE.L THEGDEVICE,-(SP) ;SAVE GRAFDEVICE (USED BY PATCONVERT)
MOVE.L D4,THEGDEVICE ;SET IT TO CURRENT DEVICE
MOVE.L CRSRPTR,-(SP) ;PUSH HANDLE TO CURSOR (LOCKED)
_PATCONVERT ;AND EXPAND TO CURRENT DEPTH
MOVE.L (SP)+,THEGDEVICE ;RESTORE GRAFDEVICE
; EXPAND THE MASK TO THE CURRENT DEPTH
MOVE D3,D0 ;GET DEPTH
MOVEQ #0,D1 ;DEFAULT SHIFT = 0
NXTSHFT1 LSR #1,D0 ;CHECK NEXT DEPTH BIT
BCS.S GOTSHFT1 ;=>GOT SHIFT
ADDQ #1,D1 ;ELSE ADD ONE TO SHIFT
BRA.S NXTSHFT1 ;LOOP UNTIL WE HIT A ONE
GOTSHFT1 LEA THECRSR+MASK,A0 ;SRC = CURSOR MASK
MOVE.L ([GDCCXMASK,A4]),A1 ;POINT TO EXPANDED MASK (LOCKED)
move.l a2,d4 ;save pointer to new cursor <25APR91 KON>
MOVE.L A1,A2 ;GET START OF DST BUFFER <27May87 EHB>
MOVE #32,D0 ;GET #BYTES OF SOURCE <27May87 EHB>
LSL D1,D0 ;MULTIPLY BY DEPTH <27May87 EHB>
ADD D0,A2 ;POINT TO END OF BUFFER <27May87 EHB>
move.l ExTblPtr,A3 ;POINT TO ROUTINE TABLE
add.l 0(A3,D1*4),A3 ;USE DEPTH TO SELECT ROUTINE
MOVEQ #0,D0 ;CLEAR HIGH PART OF D0
JSR (A3) ;EXPAND 32*DEPTH BYTES
MOVE.L ([CRSRPTR]),A3 ;GET BACK POINTER TO CURSOR (LOCKED)
move.l d4,a2 ;restore pointer to new cursor <25APR91 KON>
DONEONE MOVE GDCCDEPTH(A4),D0 ;GET EXPANDED DEPTH
ADD D0,D0 ;DOUBLE IT
MOVE D0,GDCCBYTES(A4) ;AND SAVE AS CURSOR'S ROWBYTES
CHKNXT MOVE.L GDNEXTGD(A4),D4 ;IS THERE A NEXT DEVICE?
MOVE.L D4,A4 ;GET HANDLE TO NEXT DEVICE
BNE NXTSCR ;=>THERE IS ONE, PREPARE ITS CURSOR
BSR.S GETMAINCRSR ;RESTORE EXPAND DATA FOR MAIN CURSOR
BSR ERASECURSOR ;HIDE THE OLD CURSOR
BSR DRAWCURSOR ;DISPLAY THE NEW CURSOR
SCCDONE CLR.B CRSRBUSY ;CURSOR NOT BUSY ANYMORE
move (sp)+,d0 ;get ccrsrhandle state
move.l 24(sp),a0 ;get ccrsrHandle
_HSetState
MOVEM.L (SP)+,D3-D4/A2-A4 ;restore work registers
MOVE.L (SP)+,(SP) ;strip parameter
RTS ;and return
;_______________________________________________________________________
GETMAINCRSR MOVE.L CRSRDEVICE,A0 ;GET HANDLE TO CURSOR DEVICE
MOVE.L (A0),A0 ;GET POINTER TO CURSOR DEVICE
MOVE.L CRSRPTR,A1 ;GET HANDLE TO CURSOR SAVE AREA
MOVE.L (A1),A1 ;GET POINTER TO CURSOR SAVE
MOVE.L GDCCXDATA(A0),CCXDATA(A1) ;GET CURRENT EXPANDED DATA
MOVE.L GDCCXMASK(A0),CCXMASK(A1) ;GET CURRENT EXPANDED MASK
MOVE GDCCDEPTH(A0),CCDEPTH(A1) ;GET EXPANDED DEPTH
MOVE GDCCBYTES(A0),CCBYTES(A1) ;GET EXPANDED ROWBYTES
RTS ;AND RETURN
;_______________________________________________________________________
;
; PROCEDURE SetCursor(hotSpot: Point; height: INTEGER; data: Ptr; mask:Ptr);
;
; This procedure sets THECRSR pointer in the system global area.
; A reasonable hotSpot is ENFORCED! Also fix bug to note changed when only hotspot does. <05Apr85>
;
; WARNING: to save code, this routine really doesn't use the above interface.
; It ignores the height and mask parameters. It assumes that the mask immediately
; follows the data (as it does when called from LisaGraf)
;
SetCursor MOVE.L ([CRSRPTR]),A0 ;point to crsr data structure (LOCKED)
move.b #1,crsrBusy ;don't allow vbl drawing until we're done <09Aug88>
MOVE #oldCrsrPat,ccType(A0) ;say that it's an old cursor
MOVE.L 8(SP),A0 ;get address of data mask
LEA THECRSR,A1 ;point to system cursor buffer
MOVEQ #15,D2 ;have 16 longs to move
MOVEQ #0,D1 ;flag that its not different
SetCurLoop MOVE.L (A0)+,D0 ;get next longWord of new cursor
CMP.L (A1),D0 ;is it the same as what's there
BEQ.S @1 ;if so, skip
ADDQ #1,D1 ;flag that its different
@1 MOVE.L D0,(A1)+ ;move it into the cursor buffer
DBRA D2,SetCurLoop ;move all 64 bytes
MOVE.L 14(SP),D0 ;get the alleged hotspot <23Apr85>
; Clean up the two coordinates to lie between 0 and 16. <23Apr85>
MOVEQ #16,D2 ; VERY handy temp, from loop above <23Apr85>
CMP.W D2,D0 ; <23Apr85>
BLS.S @31 ; D0 LowerorSame as 16 is ok <23Apr85>
MOVE.W D2,D0 ;pin it at 16 <23Apr85>
@31 SWAP D0 ;align the high-order coord <23Apr85>
CMP.W D2,D0 ; <23Apr85>
BLS.S @33 ; D0 LowerorSame as 16 is ok <23Apr85>
MOVE.W D2,D0 ; <23Apr85>
@33 SWAP D0 ;realign coords <23Apr85>
CMP.L TheCrsr+HotSpot,D0 ;is it new? <05Apr85>
BEQ.S @3 ; <05Apr85>
ADDQ #1,D1 ;flag it's different <05Apr85>
MOVE.L D0,TheCrsr+HotSpot ;move in the hotSpot <05Apr85>
@3
; DID THE CURSOR CHANGE?
clr.b crsrBusy ;re-allow vbl drawing <09Aug88>
TST D1 ;did it change?
BEQ.S @6 ;skip if it didn't
; IF SO, FORCE THE CURSOR TO BE REDISPLAYED BY HIDING AND THEN SHOWING IT
BSR EraseCursor ;hide it
BSR DrawCursor ;then show it again to redraw it
@6 MOVE.L (SP)+,A0 ;get return address
ADD #14,SP ;strip parameters
JMP (A0) ;return to caller
SetCrsrData PROC EXPORT
;------------------------------------------------
; UTILITY SetCrsrData
;
; This routine is called to initialize low-memory locations
; to the necessary values for the grafDevice pointer in A1.
;
IMPORT SetCrsrDelay ;<SM5> CSS
bsr.l SetCrsrDelay ;<SM5> CSS
MOVE.L CRSRPTR,A0 ;get handle to cursor data
MOVE.L (A0),A0 ;get pointer to cursor data
; initialize the grafDevice's cursor variables
MOVE.L GDCCXDATA(A1),CCXDATA(A0) ;copy handle to expanded data
MOVE.L GDCCXMASK(A1),CCXMASK(A0) ;copy handle to expanded mask
MOVE GDCCDEPTH(A1),CCDEPTH(A0) ;copy depth
MOVE GDCCBYTES(A1),CCBYTES(A0) ;copy expanded rowbytes
; set the pinning rectangle to the current screen
LEA GDRect(A1),A0 ;get rect for current device
MOVE.L (A0)+,crsrPin ;and set pinning rectangle
MOVE.L (A0),crsrPin+4 ;from device's rectangle
; set the depth, rowbytes, height, and width of the current screen
MOVE.L GDPMap(A1),A0 ;get pixMap of current device
MOVE.L (A0),A0 ;point at pixmap
MOVE PixelSize(A0),chunkyDepth ;set depth of cursor's screen
MOVE.L (A0)+,crsrBase ;update base address for cursor
MOVE (A0)+,D0 ;get rowbytes
AND #nuRBMask,D0 ;clear flag bits
MOVE D0,crsrRow ;set cursor rowbytes
MOVE bottom(A0),D0 ;get bottom of cursor's screen
SUB top(A0),D0 ;calc height of cursor's screen
MOVE D0,ColLines ;save height of cursor's screen
MOVE right(A0),D0 ;get right of cursor's screen
SUB left(A0),D0 ;calc width of cursor's screen
MOVE D0,RowBits ;save width of cursor's screen
RTS
ALLOCCRSR PROC EXPORT
IMPORT PatConvert,GETMAINCRSR,SetCrsrData
IMPORT RNEWHANDLE,ERASECURSOR,DRAWCURSOR
;--------------------------------------------------
;
; PROCEDURE AllocCrsr;
;
; Allocates all global cursor data structures. A maximum depth of 8 is assumed.
;
; CRSRPTR IS USED AS A HANDLE TO AN EXTENDED PATTERN WHICH CONTAINS THESE FIELDS:
;
; CCTYPE EQU 0 ;[WORD] CURSOR TYPE
; CCMAP EQU CCTYPE+2 ;[LONG] HANDLE TO CURSOR'S PIXMAP
; CCDATA EQU CCMAP+4 ;[LONG] HANDLE TO CURSOR'S COLOR DATA
; CCXDATA EQU CCDATA+4 ;[LONG] HANDLE TO EXPANDED DATA
; CCXMASK EQU CCXDATA+4 ;[LONG] HANDLE TO EXPANDED MASK
; CCSAVE EQU CCXMASK+4 ;[LONG] HANDLE TO SAVE BITS UNDER CURSOR
; CCLASTCRSR EQU CCSAVE+4 ;[32 BYTES] DATA FOR LAST B/W CURSOR DRAWN
; CCID EQU CCLASTCRSR ;[LONG] ID FOR LAST COLOR CURSOR DRAWN
; CCTABLE EQU CCID+4 ;[LONG] TABLE ID FOR LAST COLOR CURSOR
; CCDEPTH EQU CCLASTCRSR+32 ;[WORD] DEPTH FOR LAST CURSOR DRAWN
; CCSTATEREGS EQU CCDEPTH+2 ;[20 BYTES] STATE INFO OF SAVED DATA
; CCBYTES EQU CCSTATEREGS+16 ;[WORD] ROWBYTES OF EXPANDED DATA
; CCMAXDEPTH EQU CCBYTES+2 ;[WORD] MAXIMUM CURSOR DEPTH
MOVEM.L D0-D6/A0-A4/A6,-(SP) ;PRESERVE ALL REGS
MOVE.L THEZONE,-(SP) ;SAVE THE CURRENT HEAP ZONE
MOVE.L SYSZONE,THEZONE ;SET CURRENT ZONE TO SYS ZONE
; ALLOCATE MAIN CURSOR STRUCTURE AND DATA AREAS IF NECESSARY
BSR ERASECURSOR ;HIDE THE CURSOR
MOVE.B #1,CRSRBUSY ;MARK CHANGE IN PROGRESS
MOVE.L CRSRPTR,D0 ;GET CRSRPTR (REALLY HANDLE)
CMP.L MINUSONE,D0 ;IS IT ALLOCATED?
BNE.S MAINOK ;=>ALREADY ALLOCATED, CONTINUE
; RESERVE MEMORY FOR AND ALLOCATE CURSOR STRUCTURE.
; THE CURSOR SAVE RECORD CONTAINS A PIXMAP, A DATA HANDLE, AND A SAVE HANDLE.
clr.b CrsrObscure ;we wont be obscure no more
clr CrsrState ;reset state to 0
clr ShieldDepth ;no more shielding
MOVEQ #CCSAVEREC,D1 ;GET SIZE OF CURSOR SAVE RECORD
BSR GETLOWHANDLE ;ALLOCATE RECORD DOWN LOW AND LOCK
MOVE.L A0,CRSRPTR ;SAVE HANDLE TO CURSOR
MOVE.L (A0),A4 ;KEEP POINTER IN A4
MOVEQ #PMREC,D0 ;WE'RE GOING TO LOCK THIS
_RESRVMEM ;SO RESERVE SPACE DOWN LOW
CLR.L -(SP) ;MAKE ROOM FOR FUNCTION RESULT
_NEWPIXMAP ;ALLOCATE A PIXMAP
MOVE.L (SP)+,A0 ;GET HANDLE TO PIXMAP
MOVE.L A0,CCMAP(A4) ;SAVE PIXMAP IN CURSOR RECORD
_HLOCK ;LOCK IT DOWN
MOVEQ #2,D0 ;DEFAULT SIZE OF DATA HANDLE
JSR RNEWHANDLE ;ALLOCATE IT
MOVE.L A0,CCDATA(A4) ;AND SAVE FOR CURSOR DATA
; RESERVE AND ALLOCATE MEMORY IN WHICH TO SAVE THE BITS BEHIND THE CURSOR.
; MAGIC AMOUNT OF MEMORY RESERVED IS FOR 32 BIT DEEP, LONG ALIGNED CURSOR.
if cursorShadow then
MOVE.L #$400*4,D1 ;GET REQUIRED SIZE 32*32*4
else
MOVE.L #$400,D1 ;GET REQUIRED SIZE 16*16*4
endif
BSR GETLOWHANDLE ;GET LOW,LOCKED HANDLE
MOVE.L A0,CCSAVE(A4) ;SAVE INTO RECORD
; INITIALIZE THE CURSOR TO THE ARROW CURSOR.
MOVE #OLDCRSRPAT,CCTYPE(A4) ;SAY THAT IT'S AN OLD CURSOR
CLR CCDEPTH(A4) ;CLEAR DEPTH TO SAY NOT EXPANDED
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO GRAFGLOBALS
LEA ARROW(A0),A0 ;POINT TO ARROW CURSOR
LEA THECRSR,A1 ;PUT IT HERE
MOVEQ #16,D0 ;DATA+MASK+HOTSPOT = 17 LONGS
@2 MOVE.L (A0)+,(A1)+ ;COPY DATA
DBRA D0,@2 ;UNTIL DONE
; FOR EACH ACTIVE SCREEN DEVICE, ALLOCATE EXPANDED CURSOR MEMORY IF NECESSARY
; ALL DEVICES ARE GUARANTEED TO BE LOCKED.
MAINOK MOVE.L CRSRPTR,A4 ;GET HANDLE TO CURSOR STUFF
MOVE.L (A4),A4 ;GET POINTER (LOCKED)
MOVE.L DEVICELIST,D4 ;D4 = CURRENT DEVICE
MOVE.L D4,A6 ;GET HANDLE TO CURRENT DEVICE
NXTDEVICE MOVE.L (A6),A6 ;A6 = POINTER TO CURRENT DEVICE
TST.W GDFLAGS(A6) ;IS THE DEVICE ACTIVE?
BPL CHKNEXT ;=>NO, CHECK NEXT DEVICE
TST GDCCDEPTH(A6) ;HAS MEMORY BEEN ALLOCATED?
BNE.S DOEXPAND ;=>YES, EXPAND CURSOR IF NECESSARY
MOVE.L GDCCXDATA(A6),A0 ;GET HANDLE TO EXPANDED DATA
_DISPOSHANDLE ;DISPOSE THE CURRENT HANDLE
MOVE.L #$400,D1 ;GET SIZE OF EXPANDED HANDLE @@@@ used to be $100
BSR GETLOWHANDLE ;GET A LOW, LOCKED HANDLE
MOVE.L A0,GDCCXDATA(A6) ;AND SAVE IT
MOVE.L GDCCXMASK(A6),A0 ;GET HANDLE TO EXPANDED DATA
_DISPOSHANDLE ;DISPOSE THE CURRENT HANDLE
BSR GETLOWHANDLE ;GET A LOW, LOCKED HANDLE
MOVE.L A0,GDCCXMASK(A6) ;AND SAVE IT
DOEXPAND
; MAKE SURE ALL THE HANDLES ARE THE RIGHT SIZE FOR THE CURRENT DEPTH.
; IF COLOR CURSOR AND DEPTH IS > 2 BITS PER PIXEL, THEN EXPAND TO CURRENT DEPTH.
; BLACK AND WHITE (AND 2 BIT) CURSORS ARE EXPANDED BY SHOWCURSOR.
MOVE.L GDPMAP(A6),A0 ;GET HANDLE TO DEVICE'S PIXMAP
MOVE.L (A0),A0 ;POINT TO DEVICE'S PIXMAP
MOVE PIXELSIZE(A0),D3 ;GET DEVICE'S PIXELSIZE
CMP GDCCDEPTH(A6),D3 ;HAS DEPTH CHANGED?
BEQ.S CHKNEXT ;=>NO, THIS DEVICE IS OK
; CONVERT DEPTH TO SHIFT AMOUNT IN D6
MOVE D3,D0 ;GET DEPTH
MOVEQ #0,D6 ;DEFAULT SHIFT = 0
NXTSHFT LSR #1,D0 ;CHECK NEXT DEPTH BIT
BCS.S GOTSHFT ;=>GOT SHIFT
ADDQ #1,D6 ;ELSE ADD ONE TO SHIFT
BRA.S NXTSHFT ;LOOP UNTIL WE HIT A ONE
GOTSHFT CMP #CCRSRPAT,CCTYPE(A4) ;IS IT A COLOR CURSOR?
BNE.S CHKNEXT ;=>NO
CMP #2,D3 ;IS DEPTH GREATER THAN 2?
BLE.S CHKNEXT ;=>NO
MOVE.L GDCCXDATA(A6),CCXDATA(A4) ;GET EXPAND HANDLE FOR PATCONVERT
MOVE.L THEGDEVICE,-(SP) ;SAVE GRAFDEVICE
MOVE.L D4,THEGDEVICE ;SET IT TO CURRENT DEVICE
MOVE.L CRSRPTR,-(SP) ;PUSH HANDLE TO CURSOR
_PATCONVERT ;AND EXPAND TO CURRENT DEPTH
MOVE.L (SP)+,THEGDEVICE ;RESTORE GRAFDEVICE
; EXPAND THE MASK TO THE CURRENT DEPTH
LEA THECRSR+MASK,A0 ;SRC = CURSOR MASK
MOVE.L ([GDCCXMASK,A6]),A1 ;POINT TO EXPANDED MASK (LOCKED)
MOVE.L A1,A2 ;GET START OF DST BUFFER
MOVE #32,D0 ;GET #BYTES OF SOURCE
LSL D6,D0 ;MULTIPLY BY DEPTH
ADD D0,A2 ;POINT TO END OF BUFFER
move.l ExTblPtr,A3 ;POINT TO ROUTINE TABLE
add.l 0(A3,D6*4),A3 ;USE DEPTH TO SELECT ROUTINE
MOVEQ #0,D0 ;CLEAR HIGH PART OF D0
JSR (A3) ;EXPAND 32*DEPTH BYTES
MOVE D3,GDCCDEPTH(A6) ;SAVE DEPTH OF EXPANDED CURSOR
ADD D3,D3 ;GET 2*DEPTH
MOVE D3,GDCCBYTES(A6) ;SAVE ROWBYTES FOR EXPANDED CURSOR
CHKNEXT MOVE.L GDNEXTGD(A6),D4 ;IS THERE A NEXT DEVICE?
MOVE.L D4,A6 ;GET HANDLE TO NEXT DEVICE
BNE NXTDEVICE ;=>THERE IS ONE, PREPARE ITS CURSOR
BSR GETMAINCRSR ;SET UP FIELDS FOR MAIN CURSOR
MOVE.L CRSRDEVICE,A1 ;GET HANDLE TO CURSOR DEVICE
MOVE.L (A1),A1 ;GET POINTER TO CURSOR DEVICE
JSR SetCrsrData ;AND SET UP LOW-MEM FOR THIS DEVICE
MOVE.L (SP)+,THEZONE ;RESTORE THE ZONE
CLR.B CRSRBUSY ;CHANGE COMPLETE
BSR DRAWCURSOR
MOVEM.L (SP)+,D0-D6/A0-A4/A6 ;RESTORE ALL REGS
RTS
GETLOWHANDLE
;--------------------------------------------------
; UTILITY GETLOWHANDLE
;
; THIS ROUTINE RESERVES MEMORY FOR A HANDLE, ALLOCATES THE HANDLE
; AND THEN LOCKS IT DOWN. THE DESIRED SIZE IS IN D1. THE RETURNED HANDLE IS IN A0
; ONLY D0 IS TRASHED
MOVE.L D1,D0 ;GET THE DESIRED SIZE
_RESRVMEM ;RESERVE SPACE FOR THE HANDLE DOWN LOW
BNE.S MEMFULL ;=>ON ERROR, JUST BOMB
MOVE.L D1,D0 ;GET THE DESIRED SIZE
_NEWHANDLE ,CLEAR ;ALLOCATE THE HANDLE
_HLOCK ;LOCK IT
RTS ;AND RETURN
MEMFULL MOVEQ #25,D0 ;MEM FULL ERROR
_SYSERROR ;FLAG IT
DC.W $A9FF ;JUST IN CASE WE RETURN
;_______________________________________________________________________
;
; BLITCURSOR <dvb 19sep88>
;
; The only thing that will stop this routine from blitting the cursor
; to the screen is ShieldRect. Since the new CrsrRect isn't known
; until pretty far through the process, it's checked here, not
; DrawCursor. CrsrState and CrsrObscure are _not_ checked here.
; It seems likely that patching this routine will have use on accelerator
; cards etc.
BLITCURSOR PROC EXPORT
IMPORT CursorSect, SHFTTBL
TST.L CRSRPTR ;CURSOR ALLOCATED?
BMI NoBlit ;=>NO, JUST RETURN
MOVEM.L D0-D7/A0-A6,-(SP) ;SAVE REGISTERS
LEA THECRSR+DATA,A2 ;POINT TO THE CURSOR
;-----------------------------------------------
;
; CONVERT CHUNKY DEPTH TO SHIFT AMOUNT IN D7
;
LEA SHFTTBL,A0 ;TO CONVERT DEPTH TO SHIFT
MOVE CHUNKYDEPTH,D1 ;GET DEPTH
MOVEQ #0,D7 ;DEFAULT SHIFT = 0
MOVE.B 0(A0,D1),D7 ;GET SHIFT AMOUNT IN D7
;-----------------------------------------------
;
; CHECK THE CURSOR TO SEE IF IT HAS CHANGED
; OLD CURSORS: CHECK CURSOR DATA AND DEPTH
; NEW CURSORS: CHECK DEPTH
;
GOTSHFT MOVE.L ([CRSRPTR]),A4 ;GET POINTER TO CURSOR DATA (LOCKED)
CMP #CCRSRPAT,CCTYPE(A4) ;IS IT A COLOR CURSOR?
BNE.S OLDCUR ;=>NO, JUST AN OLD ONE
CMP CCDEPTH(A4),D1 ;HAS DEPTH CHANGED?
BEQ NOEXPAND ;=>NO, DON'T EXPAND
CMP #2,D1 ;IS DEPTH 2 or 1?
BGT EXPMASK ;=>NO, JUST EXPAND MASK
BRA.S CPYDATA ;=>ELSE JUST COPY DATA
OLDCUR LEA CCLASTCRSR(A4),A0 ;POINT TO SAVED DATA
MOVE.L A2,A1 ;GET POINTER TO CURSOR
MOVEQ #7,D0 ;CHECK 8 LONGS
@0 CMP.L (A0)+,(A1)+ ;ARE THEY THE SAME?
BNE.S GOEXPAND ;=>NO, EXPAND IT
DBRA D0,@0 ;=>LOOP UNTIL DONE
CMP CCDEPTH(A4),D1 ;HAS DEPTH CHANGED?
BEQ NOEXPAND ;=>NO, DON'T EXPAND
GOEXPAND
;-----------------------------------------------
;
; INVALIDATE EXPANDED DATA FOR EACH DEVICE BY CLEARING DEPTH
; THIS MUST BE DONE SO THAT ALL EXPANDED CURSOR IMAGES ARE RENDERED INVALID AFTER
; AN OLD CURSOR HAS BEEN SET. IF THE CURSOR IS NEW, SETCCURSOR ALREADY DID THIS.
MOVE.L DEVICELIST,A0 ;GET FIRST HANDLE IN DEVICE LIST
NXTGD MOVE.L (A0),A0 ;POINT TO FIRST DEVICE
TST GDFLAGS(A0) ;IS IT ACTIVE?
BPL.S NOTACT ;=>NO, SKIP TO NEXT
CLR GDCCDEPTH(A0) ;ELSE INVALIDATE EXPANDED DATA
NOTACT MOVE.L GDNEXTGD(A0),D0 ;GET NEXT GRAFDEVICE
MOVE.L D0,A0 ;GET INTO A0
BNE.S NXTGD ;=>REPEAT FOR ALL DEVICES
; COPY THE CURSOR DATA TO IDENTIFY THIS CURSOR
CPYDATA LEA CCLASTCRSR(A4),A0 ;POINT TO SAVED DATA
MOVE.L A2,A1 ;GET CURSOR
MOVEQ #7,D0 ;MOVE 8 LONGS
@0 MOVE.L (A1)+,(A0)+ ;MOVE A LONG
DBRA D0,@0 ;=>LOOP UNTIL DONE
; UPDATE THE ROWBYTES AND DEPTH FOR THE EXPANDED DATA
; MOVE D1,(A0)+ ;COPY THE DEPTH TOO <this is the top half of ccID! <BAL 01Apr89>
MOVE D1,CCDEPTH(A4) ;SET DEPTH TO SAY IT'S EXPANDED
ADD D1,D1 ;DOUBLE FOR CURSOR'S ROWBYTES
MOVE D1,CCBYTES(A4) ;AND UPDATE ROWBYTES
;-----------------------------------------------
;
; EXPAND THE CURSOR TO THE CURRENT DEPTH
;
MOVE.L A2,A0 ;SRC = CURSOR
MOVE.L ([CCXDATA,A4]),A1 ;POINT TO EXPANDED DATA (LOCKED)
MOVE.L A1,A2 ;GET START OF DST BUFFER
MOVE #32,D5 ;GET #BYTES OF SOURCE
LSL D7,D5 ;MULTIPLY BY DEPTH
ADD D5,A2 ;POINT TO END OF BUFFER
move d7,d0
cmp #4,d0 ;16/32 bits per pixel? <BAL 28Jun88>
blt.s @1 ;no, don't hack depth conversion
addq #2,d0 ;get address of spiffy 1 to 15/24 bit expand
@1 move.l ExTblPtr,A3 ;POINT TO ROUTINE TABLE
add.l 0(A3,D0*4),A3 ;USE DEPTH TO SELECT ROUTINE
MOVEQ #0,D0 ;CLEAR HIGH PART OF D0
JSR (A3) ;EXPAND 32*DEPTH BYTES
;-----------------------------------------------
;
; EXPAND THE MASK TO THE CURRENT DEPTH
;
EXPMASK LEA THECRSR+MASK,A0 ;SRC = CURSOR MASK
MOVE.L ([CCXMASK,A4]),A1 ;POINT TO EXPANDED MASK (LOCKED)
MOVE.L A1,A2 ;GET START OF DST BUFFER
MOVE #32,D5 ;GET #BYTES OF SOURCE <BAL 14Jun88>
LSL D7,D5 ;MULTIPLY BY DEPTH <BAL 14Jun88>
ADD D5,A2 ;POINT TO END OF BUFFER
move.l ExTblPtr,A3 ;POINT TO ROUTINE TABLE
add.l 0(A3,D7*4),A3 ;USE DEPTH TO SELECT ROUTINE
MOVEQ #0,D0 ;CLEAR HIGH PART OF D0
JSR (A3) ;EXPAND 32*DEPTH BYTES
;-----------------------------------------------
;
; PREPARE TO BLT THE CURSOR ON THE SCREEN IN ANY DEPTH
; (SUBTITLE: WALTZ OF THE REGISTERS)
;
NOEXPAND
MOVE.L ([CCXDATA,A4]),d0 ;A2 = EXPANDED DATA FOR BLT (LOCKED)
_rTranslate24To32 ;strip off high byte
move.l d0,a2
MOVE.L ([CCXMASK,A4]),d0 ;A3 = EXPANDED MASK FOR BLT (LOCKED)
_rTranslate24To32 ;strip off high byte
move.l d0,a3
MOVEQ #16,D5 ;D5 = 16
;-----------------------------------------------
;
; CLIP THE CURSOR VERTICALLY AND GET THE TOP AND BOTTOM INTO D2 AND D3.
; IF THE TOP IS CLIPPED, UPDATE THE DATA BASE ADDRESSES IN A2 AND A3.
;
MOVE MOUSE+V,D2 ;MOUSE POSITION Y
SUB CRSRPIN+TOP,D2 ;CONVERT TO SCREEN LOCAL COORDS
SUB THECRSR+HOTSPOT+V,D2 ; - HOTSPOT = TOP EDGE
MOVE D2,D3 ;GET CURSOR BOTTOM
ADD D5,D3 ; = TOP + 16
CMP D5,D3 ;AT TOP?
BGE.S CHKBOT ;=>NOT AT TOP
NEG D2 ;GET NUMBER OF CLIPPED ROWS
CMP D5,D2 ;ARE ALL 16 CLIPPED?
BEQ SkipBlit ;=>IF SO, NOTHING TO SHOW
MULU CCBYTES(A4),D2 ; * ROWBYTES FOR OFFSET
ADD.L D2,A2 ;ADD VERTICAL OFFSET INTO CURSOR
ADD.L D2,A3 ;ADD VERTICAL OFFSET INTO MASK
MOVEQ #0,D2 ;AND PIN CURSOR TO TOP
CHKBOT MOVE COLLINES,D4 ;GET BOTTOM OF SCREEN
CMP D4,D3 ;PAST BOTTOM?
BLE.S CHKLFT ;=>NO, VERTICAL OK
MOVE D4,D3 ;ELSE PIN TO BOTTOM EDGE
;-----------------------------------------------
;
; CLIP THE CURSOR HORIZONTALLY AND GET THE LEFT AND RIGHT INTO D0 AND D1
; IF THE LEFT OF THE CURSOR IS CLIPPED, ADJUST THE OFFET IN D6.
CHKLFT MOVEQ #0,D6 ;INIT SRC/DST OFFSET TO 0
MOVE MOUSE+H,D0 ;MOUSE POSITION X
SUB CRSRPIN+LEFT,D0 ;CONVERT TO SCREEN LOCAL COORDS
SUB THECRSR+HOTSPOT+H,D0 ; - HOTSPOT = CURSOR LEFT
MOVE D0,D1 ;GET CURSOR RIGHT
ADD D5,D1 ; = LEFT + 16
CMP D5,D1 ;AT LEFT EDGE?
BGE.S CHKRT ;=>NOT AT LEFT EDGE
SUB D0,D6 ;OFFSET = AMOUNT CLIPPED
MOVEQ #0,D0 ;AND PIN TO LEFT EDGE
CHKRT MOVE ROWBITS,D4 ;GET RIGHT EDGE OF SCREEN
CMP D4,D1 ;PAST RIGHT EDGE?
BLE.S RTOK ;=>NO, HORIZONTAL OK
MOVE D4,D1 ;ELSE PIN TO RIGHT EDGE
RTOK
;-----------------------------------------------
;
; USE TOP AND LEFT TO CALCULATE THE LONG ALIGNED SCREEN BASE ADDRESS
MOVE.L CRSRBASE,A5 ;A5 = POINTER TO BASE OF SCREEN
MOVE CRSRROW,A0 ;A0 = SCREEN ROWBYTES
MOVE A0,D4 ;COPY FOR MULU
MULU D2,D4 ;TOP * ROWBYTES
ADD.L D4,A5 ;ADD VERT OFFSET INTO SCREEN
ext.l d0 ;make it a long <BAL 17Jan89>
LSL.l D7,D0 ;CONVERT LEFT PIXELS TO BITS
MOVE.l D0,D4 ;GET LEFT EDGE
AND.l #~$1F,D4 ;LONGWORD ALIGNED
MOVE.l D4,D5 ;MAKE A COPY
ASR.l #3,D5 ;CONVERT BITS TO BYTES
ADD.l D5,A5 ;GET BASE OFFSET IN SCREEN
;-----------------------------------------------
;
; SAVE THE CRSRRECT FOR CURSHIELD
LEA CrsrRect,A1 ;SET UP CRSRRECT
MOVE D2,(A1)+ ;TOP
MOVE.l D4,D5 ;GET LONG ALIGNED LEFT IN BITS
LSR.l D7,D5 ;CONVERT TO PIXELS
MOVE D5,(A1)+ ;LONG ALIGNED LEFT
MOVE D3,(A1)+ ;BOTTOM
MOVE D5,(A1) ;RIGHT = LEFT + longcount/pixs in long
if cursorShadow then
add.w #16,-2(a1) ;grow height for shadow
add.w #16,(a1) ;grow width for shadow
endif
SAMELONG
;-----------------------------------------------
;
; ADJUST DST/SRC OFFSET IN D6
; GET NUMBER OF ROWS TO DO IN D3
; GET LONGCNT IN D5 AND USE TO ADJUST DSTBUMP IN A0
AND #$1F,D0 ;GET LEFT EDGE MOD 32
LSL D7,D6 ;CONVERT OFFSET TO BITS
SUB D0,D6 ; = NEG OFFSET FROM SOURCE
ext.l d1 ;make it a long <BAL 17Jan89>
LSL.l D7,D1 ;CONVERT RIGHT EDGE TO BITS
MOVE.l D1,D5 ;MAKE COPY
SUB.l D4,D5 ;GET WIDTH OF CURSOR
ble SkipBlit ;crsr fits in 0 or fewer longs so don't draw
subq #1,d5 ;force multiples of 32 to round down
LSR.l #5,D5 ;GET LONGS-1
SUB D2,D3 ;D3 = # ROWS TO DO
SUBQ #1,D3 ;MAKE IT 0 BASED
MOVE.l D5,D2 ;GET LONGS
ADDQ.l #1,D2 ;MAKE ONE BASED
LSL.l #2,D2 ;CONVERT TO BYTES
SUB.l D2,A0 ;ADJUST DST BUMP
lsl.l #3,d2 ;get long aligned bit width
lsr.l d7,d2 ;get effective cursr pixel width
add d2,(a1) ;adjust crsrRect.right = left+width
BSR CursorSect ;Now then, do we intersect shield?
BNE SkipBlit ;If so, ththat's all.
;-----------------------------------------------
;
; CONVERT LEFT EDGE AND RIGHT EDGE TO LEFTMASK AND RIGHTMASK IN D4 AND D2
MOVEQ #-1,D4 ;FILL LONG WITH ONES
LSR.L D0,D4 ;AND SHIFT IN 0'S FOR LEFTMASK
MOVEQ #-1,D2 ;FILL LONG WITH ONES
AND #$1F,D1 ;GET RIGHT MOD 32
beq.s @1 ;does right have a real mask? no, flush it
LSR.L D1,D2 ;AND SHIFT 0'S IN FROM RIGHT
NOT.L D2 ;GET RIGHTMASK
;-----------------------------------------------
;
; SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT INTO CRSRPTR SO THAT
; HIDECURSOR KNOWS HOW MUCH SCREEN TO REPLACE.
@1 LEA CCBYTES(A4),A6 ;POINT TO END OF SAVE STATE AREA
MOVE (A6),A1 ;A1 = ROWBYTES FOR EXPANDED CURSOR
MOVE.L ([CCSAVE,A4]),d0 ;A4 = POINTER TO SAVE AREA (LOCKED)
_rTranslate24To32 ;strip off high byte
move.l d0,a4
MOVEM.L A5/A0/D5/D3,-(A6) ;SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT
moveq #true32b,d0 ;switch to 32 bit addressing
movem.l a0-a2,-(sp) ;save off registers
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a2, d0/d2)
movem.l (sp)+,a0-a2 ;restore registers
move.b d0,-(sp) ;save previous state for later
MOVE.L D5,A6 ;SAVE LONGCNT
EXT.L D6 ;BFEXTU LIKES LONG OFFSETS
MOVE.L D6,-(SP) ;SAVE OFFSET ON STACK
MOVE.L D4,-(SP) ;SAVE LEFTMASK ON STACK
;use alternate loop if on Direct Device <BAL 12 Mar89>
cmp #4,d7 ;are we 16 or 32 bits/pixel (direct device) ?
bge Direct ;no, don't hack
if cursorShadow then
cmp #3,d7
beq Shadow8
endif
TST D5 ;CHECK FOR JUST ONE LONG
BRA.S START ;AND JUMP INTO MIDDLE
;-----------------------------------------------
;
; DISPLAY THE CURSOR AND SAVE THE BITS BEHIND IT (DO THE CURSOR LIMBO!!)
;
; THE FUNNY TRANSFER MODE USED HERE WORKS THE SAME AS BEFORE FOR ONE BIT
; MODE, AND SIMILARLY FOR COLOR. IN COLOR, THE DATA PIXELS WITHIN THE MASK
; REPLACE THE DESTINATION; THE DATA PIXELS OUTSIDE THE MASK ARE XORED WITH
; THE DST. IF THE DATA PIXELS OUTSIDE OF THE MASK ARE BLACK (ALL F'S),
; THEN THE DST IS SIMPLY INVERTED. IF THEY ARE OTHER COLORS, INTERESTING
; EFFECTS WILL MANIFEST THEMSELVES.
;
; REGISTER USE: D0: SCRATCH A0: DSTBUMP
; D1: SCRATCH A1: SRCBUMP
; D2: RIGHTMASK A2: SRCPTR
; D3: ROWCNT A3: MASKPTR
; D4: LEFTMASK A4: SAVEPTR
; D5: LONGCNT A5: DSTPTR
; D6: OFFSET A6: COPY LONGCNT
; D7: SCRATCH (A7): LEFTMASK
; 4(A7): COPY OFFSET
END AND.L D2,D4 ;AND RIGHTMASK INTO LEFTMASK
MAIN BFEXTU (A2){D6:0},D0 ;EXTRACT A LONG OF SRC
BFEXTU (A3){D6:0},D1 ;EXTRACT A LONG OF MASK
ADD.L #32,D6 ;BUMP TO NEXT LONG
AND.L D4,D0 ;AND SRC WITH LEFTMASK
AND.L D4,D1 ;AND MASK WITH LEFTMASK
MOVE.L D0,D7 ;COPY SRC
AND.L D1,D7 ;GET MASK AND SRC (PIXELS TO REPLACE)
NOT.L D1 ;GET NOTMASK
MOVE.L (A5),d4 ;get a long of screen
move.l d4,(A4)+ ;SAVE A LONG OF SCREEN
AND.L D1,D0 ;GET NOTMASK AND SRC (PIXELS TO INVERT)
AND.L d4,D1 ;PUNCH HOLE FOR PIXELS TO REPLACE (used to be A5)
OR.L D7,D1 ;REPLACE PIXELS WITHIN MASK
EOR.L D0,D1 ;INVERT PIXELS OUTSIDE OF MASK
MOVE.L D1,(A5)+ ;AND PUT TO DST
MOVEQ #-1,D4 ;FLUSH LEFTMASK
SUB #1,D5 ;DECREMENT LONGCNT
START BGT.S MAIN ;=>MORE THAN ONE TO DO
BEQ.S END ;=>DO LAST LONG
MOVE.L 4(SP),D6 ;RESTORE OFFSET
MOVE.L (SP),D4 ;RESTORE LEFTMASK
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT (TEST D5)
DBRA D3,START ;=>DO NEXT ROW
bra DoneBlit
Direct
bgt.s Direct32
;-----------------------------------------------
;
; DISPLAY THE CURSOR AND SAVE THE BITS BEHIND IT (DO THE CURSOR LIMBO!!)
;
; THE FUNNY TRANSFER MODE USED HERE WORKS THE SAME AS BEFORE FOR ONE BIT
; MODE, AND SIMILARLY FOR COLOR. IN COLOR, THE DATA PIXELS WITHIN THE MASK
; REPLACE THE DESTINATION; THE DATA PIXELS OUTSIDE THE MASK ARE XORED WITH
; THE DST. IF THE DATA PIXELS OUTSIDE OF THE MASK ARE BLACK (ALL F'S),
; THEN THE DST IS SIMPLY INVERTED. IF THEY ARE OTHER COLORS, INTERESTING
; EFFECTS WILL MANIFEST THEMSELVES.
;
; REGISTER USE: D0: SCRATCH A0: DSTBUMP
; D1: SCRATCH A1: SRCBUMP
; D2: RIGHTMASK A2: SRCPTR
; D3: ROWCNT A3: MASKPTR
; D4: LEFTMASK A4: SAVEPTR
; D5: LONGCNT A5: DSTPTR
; D6: OFFSET A6: COPY LONGCNT
; D7: SCRATCH (A7): LEFTMASK
; 4(A7): COPY OFFSET
Direct16
swap d4
addq #1,d5 ;make one based
add d5,d5 ;convert longcnt to word cnt
move d5,d0 ;save pixel cnt
subq #2,d5 ;make zero based - 1
move d5,a6 ;save a copy for later scans
moveq #-1,d7
lsr.w #1,d7 ;make into low15bits mask
add d0,d0 ;make into byte cnt
sub d0,a1 ;make srcRow into srcBump
asr #3,d6 ;make offset into bytes
add d6,a2 ;adjust src ptr
add d6,a3 ;adjust mask ptr
@first tst d4 ;is left pixel masked?
bne.s @MAIN ;no, go to it
move.w (a5)+,(a4)+ ;save first pixel
addq #2,a2 ;bump past first src pixel
addq #2,a3 ;bump past first mask pixel
bra.s @next
@MAIN move.w (A2)+,D0 ;EXTRACT A LONG OF SRC
MOVE.w (A5),d1 ;get a long of screen
move.w d1,(A4)+ ;SAVE A LONG OF SCREEN
tst.w (A3)+ ;EXTRACT A LONG OF MASK
bne.s @inside
not.w d0 ;flip src so that black is all 1's
and.w d7,d0 ;mask off high bit
beq.s @skipit ;no use in xoring with zero
eor.w d1,d0 ;xor dst with src
@inside
move.w d0,(a5)
@skipit addq #2,a5
@next dbra D5,@MAIN ;DECREMENT LONGCNT
tst d2 ;is right pixel masked?
bne.s @last ;no, go to it
move.w (a5)+,(a4)+ ;save first pixel
addq #2,a2 ;bump past first src pixel
addq #2,a3 ;bump past first mask pixel
bra.s @nxtScn
@last move.w (A2)+,D0 ;EXTRACT A LONG OF SRC
MOVE.w (A5),d1 ;get a long of screen
move.w d1,(A4)+ ;SAVE A LONG OF SCREEN
tst.w (A3)+ ;EXTRACT A LONG OF MASK
bne.s @in
not.w d0 ;flip src so that black is all 1's
and.w d7,d0 ;mask off high bit
beq.s @skip ;no use in xoring with zero
eor.w d1,d0 ;xor dst with src
@in
move.w d0,(a5)
@skip addq #2,a5
@nxtScn ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@First ;=>DO NEXT ROW
bra DoneBlit
;-----------------------------------------------
;
; DISPLAY THE CURSOR AND SAVE THE BITS BEHIND IT (DO THE CURSOR LIMBO!!)
;
; THE FUNNY TRANSFER MODE USED HERE WORKS THE SAME AS BEFORE FOR ONE BIT
; MODE, AND SIMILARLY FOR COLOR. IN COLOR, THE DATA PIXELS WITHIN THE MASK
; REPLACE THE DESTINATION; THE DATA PIXELS OUTSIDE THE MASK ARE XORED WITH
; THE DST. IF THE DATA PIXELS OUTSIDE OF THE MASK ARE BLACK (ALL F'S),
; THEN THE DST IS SIMPLY INVERTED. IF THEY ARE OTHER COLORS, INTERESTING
; EFFECTS WILL MANIFEST THEMSELVES.
;
; REGISTER USE: D0: SCRATCH A0: DSTBUMP
; D1: SCRATCH A1: SRCBUMP
; D2: RIGHTMASK A2: SRCPTR
; D3: ROWCNT A3: MASKPTR
; D4: LEFTMASK A4: SAVEPTR
; D5: LONGCNT A5: DSTPTR
; D6: OFFSET A6: COPY LONGCNT
; D7: SCRATCH (A7): LEFTMASK
; 4(A7): COPY OFFSET
if cursorShadow then
Direct32
move d5,d0 ;get a copy of long cnt
addq #1,d0 ;make one based
lsl #2,d0 ;make into byte cnt
sub d0,a1 ;make srcRow into srcBump
asr #3,d6 ;make offset into bytes
add d6,a2 ;adjust src ptr
add d6,a3 ;adjust mask ptr
voff equ 4
hoff equ 4
;-----------------------------------------------
;
; SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT INTO CRSRPTR SO THAT
; HIDECURSOR KNOWS HOW MUCH SCREEN TO REPLACE.
movem.l d3/d5/a6/a5/a0,-(sp)
MOVE.L ([CRSRPTR]),D0 ;GET POINTER TO CURSOR DATA (LOCKED)
_rTranslate24To32
MOVE.L D0,A6
LEA CCBYTES(A6),A6 ;POINT TO END OF SAVE STATE AREA
move.w mouse,d0 ;get vert pos
lsr.w #6,d0
; add.w #voff,d3
add.w d0,d3
move.w mouse+2,d0 ;get horiz pos
lsr.w #6,d0
; add.w #hoff,d5
add.w d0,d5
lsl.w #2,d0
; sub.w #hoff*4,a0
sub.w d0,a0
MOVEM.L A5/A0/D5/D3,-(A6) ;SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT
MOVE.L D5,A6 ;SAVE LONGCNT
@MAIN2 MOVE.L (A5)+,d1 ;get a long of screen
move.l d1,(a4)+ ;save a long of screen
dbra D5,@MAIN2 ;DECREMENT LONGCNT
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN2 ;=>DO NEXT ROW
movem.l (sp)+,a5/d3/d5/a6/a0
movem.l d3/a2-a5,-(sp)
; moveq #voff,d0
move.w mouse,d0 ;get vert pos
lsr.w #6,d0
bra.s @1
@0 ADD.w CRSRROW,A5 ;offset SCREEN POINTER vertically
@1 dbra d0,@0
move.w mouse+2,d0 ;get horiz pos
lsr.w #6,d0
lsl.w #2,d0
; add.w #hoff*4,a5
add.w d0,a5
@MAIN1 MOVE.L (A5),d1 ;get a long of screen
move.l (A2)+,d0 ;combine A LONG OF src
not.l d0 ;interested in nothing , dammit!!@!
and.l $31a,d0 ; shit line
or.l (A3)+,d0 ;EXTRACT A LONG OF MASK
beq.s @skipit1
;d0 = 0
moveq #0,d0 ;assume result is black
moveq #$3f,d4 ;amount to remove from screen
swap d4 ;d4 = $3f0000
sub.l d4,d1 ;darken the red channel
bcs.s @pinred
move.l d1,d0 ;take the red channel
@pinred
lsr.l #8,d4
sub.w d4,d1 ;darken the grn channel
bcs.s @pingrn
move.w d1,d0 ;take the grn channel
@pingrn
lsr.w #8,d4
sub.b d4,d1 ;darken the blu channel
bcs.s @pinblu
move.b d1,d0 ;take the blu channel
@pinblu
move.l d0,(a5)
@skipit1
addq #4,a5
dbra D5,@MAIN1 ;DECREMENT LONGCNT
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN1 ;=>DO NEXT ROW
movem.l (sp)+,d3/a2-a5
@MAIN move.l (A2)+,D0 ;EXTRACT A LONG OF SRC
MOVE.L (A5),d1 ;get a long of screen
tst.l (A3)+ ;EXTRACT A LONG OF MASK
bne.s @inside
not.l d0 ;flip src so that black is all 1's
beq.s @skipit ;no use in xoring with zero
eor.l d1,d0 ;xor dst with src
@inside
move.l d0,(a5)
@skipit addq #4,a5
dbra D5,@MAIN ;DECREMENT LONGCNT
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN ;=>DO NEXT ROW
bra DoneBlit
; REGISTER USE: D0: SCRATCH A0: DSTBUMP
; D1: SCRATCH A1: SRCBUMP
; D2: RIGHTMASK A2: SRCPTR
; D3: ROWCNT A3: MASKPTR
; D4: LEFTMASK A4: SAVEPTR
; D5: LONGCNT A5: DSTPTR
; D6: OFFSET A6: COPY LONGCNT
; D7: SCRATCH (A7): LEFTMASK
; 4(A7): COPY OFFSET
Shadow8
move d5,d0 ;get a copy of long cnt
addq #1,d0 ;make one based
lsl #2,d0 ;make into byte cnt
sub d0,a1 ;make srcRow into srcBump
asr #3,d6 ;make offset into bytes
add d6,a2 ;adjust src ptr
add d6,a3 ;adjust mask ptr
;-----------------------------------------------
;
; SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT INTO CRSRPTR SO THAT
; HIDECURSOR KNOWS HOW MUCH SCREEN TO REPLACE.
movem.l d3/d5/a6/a5/a0,-(sp)
MOVE.L ([CRSRPTR]),D0 ;GET POINTER TO CURSOR DATA (LOCKED)
_rTranslate24To32
MOVE.L D0,A6
LEA CCBYTES(A6),A6 ;POINT TO END OF SAVE STATE AREA
move.w mouse,d0 ;get vert pos
lsr.w #6,d0 ;d0=voff
; add.w #voff,d3
add.w d0,d3
move.w mouse+2,d0 ;get horiz pos
lsr.w #6,d0 ;d0=hoff
; add.w #hoff,d5
addq #3,d0
lsr.w #2,d0 ;d0=shadow width longs
add.w d0,d5
lsl.w #2,d0
; sub.w #hoff*4,a0
sub.w d0,a0
MOVEM.L A5/A0/D5/D3,-(A6) ;SAVE DSTLEFT/DSTBUMP/LONGCNT/ROWCNT
MOVE.L D5,A6 ;SAVE LONGCNT
;-------------------------------------------
; Save bits under cursor/shadow
;-------------------------------------------
@MAIN2 MOVE.L (A5)+,d1 ;get a long of screen
move.l d1,(a4)+ ;save a long of screen
dbra D5,@MAIN2 ;DECREMENT LONGCNT
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN2 ;=>DO NEXT ROW
movem.l (sp)+,a5/d3/d5/a6/a0
;-------------------------------------------
; Draw Shadow
;-------------------------------------------
movem.l d3/a2-a5,-(sp)
; moveq #voff-1,d0
move.w mouse,d0 ;get vert pos
lsr.w #6,d0
bra.s @1
@0 ADD.w CRSRROW,A5 ;offset SCREEN POINTER vertically
@1 dbra d0,@0
move.w mouse+2,d0 ;get horiz pos
lsr.w #6,d0
add.w d0,a5
; add.w #hoff,a5
@MAIN1 MOVE.l (A5),d1 ;get a long of screen
move.l (A2)+,d0 ;combine A LONG OF src
or.l (A3)+,d0 ;EXTRACT A LONG OF MASK
beq.s @skipit1
;d0 = 0
moveq #0,d0 ;assume result is black
moveq #$3f,d4 ;amount to remove from screen
swap d4 ;d4 = $3f0000
sub.l d4,d1 ;darken the red channel
bcs.s @pinred
move.l d1,d0 ;take the red channel
@pinred
lsr.l #8,d4
sub.w d4,d1 ;darken the grn channel
bcs.s @pingrn
move.w d1,d0 ;take the grn channel
@pingrn
lsr.w #8,d4
sub.b d4,d1 ;darken the blu channel
bcs.s @pinblu
move.b d1,d0 ;take the blu channel
@pinblu
; move.l d0,(a5)
@skipit1
addq #4,a5
dbra D5,@MAIN1 ;DECREMENT LONGCNT
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN1 ;=>DO NEXT ROW
movem.l (sp)+,d3/a2-a5
;-------------------------------------------
; Draw cursor atop shadow
;-------------------------------------------
@MAIN move.l (A2)+,D0 ;EXTRACT A LONG OF SRC
tst.l (A3)+ ;EXTRACT A LONG OF MASK
bne.s @inside
tst.l d0 ;flip src so that black is all 1's
beq.s @skipit ;no use in xoring with zero
MOVE.L (A5),d1 ;get a long of screen
eor.l d1,d0 ;xor dst with src
@inside
move.l d0,(a5)
@skipit addq #4,a5
dbra D5,@MAIN ;DECREMENT LONGCNT
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN ;=>DO NEXT ROW
else
Direct32
moveq #-1,d4
lsr.l #8,d4 ;get low3bytes in d4
move d5,d0 ;get a copy of long cnt
addq #1,d0 ;make one based
lsl #2,d0 ;make into byte cnt
sub d0,a1 ;make srcRow into srcBump
asr #3,d6 ;make offset into bytes
add d6,a2 ;adjust src ptr
add d6,a3 ;adjust mask ptr
@MAIN move.l (A2)+,D0 ;EXTRACT A LONG OF SRC
MOVE.L (A5),d1 ;get a long of screen
move.l d1,(A4)+ ;SAVE A LONG OF SCREEN
tst.l (A3)+ ;EXTRACT A LONG OF MASK
bne.s @inside
not.l d0 ;flip src so that black is all 1's
and.l d4,d0 ;mask off high byte
beq.s @skipit ;no use in xoring with zero
eor.l d1,d0 ;xor dst with src
@inside
move.l d0,(a5)
@skipit addq #4,a5
dbra D5,@MAIN ;DECREMENT LONGCNT
ADD.L A1,A3 ;BUMP CURSOR DATA
ADD.L A1,A2 ;BUMP CURSOR MASK
ADD.L A0,A5 ;BUMP SCREEN POINTER
MOVE.L A6,D5 ;RESTORE LONGCNT
DBRA D3,@MAIN ;=>DO NEXT ROW
endif
DoneBlit
ADDQ #8,SP ;STRIP LEFTMASK AND OFFSET
MOVE.B #1,CrsrVis ;CURSOR VISIBLE
moveq #0,d0
move.b (sp)+,d0 ;get previous MMU state in d0
_rSwapMMUMode ;restore MMU mode from d0.b
SkipBlit
MOVEM.L (SP)+,D0-D7/A0-A6 ;THE WALTZ IS OVER...(TANGO VERY MUCH)
NoBlit
RTS
;_______________________________________________________________________
;
; UNBLITCURSOR <dvb 19sep88>
;
; This routine unconditionally removes cursor according to the data in
; CCSTATEREGS.
; Such things as crsrstate, crsrvis, and other nonsense have already been
; checked. Vectoring this routine may prove useful for later cursor
; enhancements.
UNBLITCURSOR PROC EXPORT
TST.L CRSRPTR ;CURSOR ALLOCATED?
BMI.S DONEHIDE ;=>NO, JUST RETURN
MOVEM.L D1-D4/A0-A2,-(SP) ;SAVE REGS USED
MOVE.L ([CRSRPTR]),A0 ;GET POINTER TO CURSOR SAVE DATA (LOCKED)
MOVE.L CCSAVE(A0),A1 ;GET HANDLE TO SAVED BITS
MOVE.L (A1),d0 ;POINT TO SAVED BITS
_rTranslate24To32 ;mask off high byte
move.l d0,a1
LEA CCSTATEREGS(A0),A0 ;POINT TO SAVE STATE AREA
MOVEM.L (A0)+,D2/D3/D4/A2 ;GET /ROWCNT/LONGCNT/DSTBUMP/DSTLEFT
moveq #true32b,d0 ;switch to 32 bit mode
movem.l d2/a1/a2,-(sp) ;save off registers
_rSwapMMUMode ;get previous mode in d0.b (can trash a0/a2, d0/d2)
movem.l (sp)+,d2/a1/a2 ;restore registers
MOVE.L D3,A0 ;SAVE LONGCNT
@1 MOVE.L (A1)+,(A2)+ ;RESTORE A LONG OF SOURCE
DBRA D3,@1 ;=>DO ENTIRE ROW
MOVE.L A0,D3 ;RESTORE LONGCNT
ADD D4,A2 ;BUMP DST
DBRA D2,@1 ;=>DO FOR ALL LINES
_rSwapMMUMode ;restore original mode from d0.b
CLR.B CRSRVIS ;MARK IT AS INVISIBLE
MOVEM.L (SP)+,D1-D4/A0-A2 ;RESTORE REGS USED
DONEHIDE RTS
;
;_______________________________________________________________________
;
; FUNCTION ScrnAddress:Ptr;
;
; return a pointer to the start of the bit-map display
;
ScrnAddress PROC EXPORT
MOVE.L ScrnBase,4(SP) ;get screenBase set up by OS
RTS ;that was easy!
;
;_______________________________________________________________________
;
; PROCEDURE ScrnSize(VAR hDots,vDots: INTEGER);
;
; return the size of the screen in pixels
;
ScrnSize PROC EXPORT
MOVE.L (SP)+,D0 ;get the return address
MOVE.L MainDevice,A0 ;get handle to main screen device
MOVE.L (A0),A0 ;point to main screen device
MOVE.L (SP)+,A1 ;get pointer to vDots
MOVE GDRect+bottom(A0),D1 ;get bottom
SUB GDRect+top(A0),D1 ;calc height
MOVE D1,(A1) ;return the number of vertical pixels
MOVE.L (SP)+,A1 ;get pointer to hdots
MOVE GDRect+right(A0),D1 ;get right
SUB GDRect+left(A0),D1 ;calc width
MOVE D1,(A1) ;return the number of horizontal pixels
MOVE.L D0,A0 ;get return address
JMP (A0) ;and return
;_______________________________________________________________________
;
; PROCEDURE ScrnBitMap(VAR x: BitMap);
;
; return the screen bitmap
;
ScrnBitMap PROC EXPORT
MOVE.L (SP)+,D0 ;get the return address
MOVE.L MainDevice,A0 ;get handle to main screen device
MOVE.L (A0),A0 ;point to main screen device
MOVE.L GDPMap(A0),A0 ;get handle to screen's pixMap
MOVE.L (A0),A0 ;point to screen's pixMap
MOVE.L (SP)+,A1 ;get pointer to BitMap
MOVE.L (A0)+,(A1)+ ;copy base addr
MOVE (A0)+,D1 ;get rowbytes
AND #nuRBMask,D1 ;mask flag bits
MOVE D1,(A1)+ ;copy rowbytes
MOVE.L (A0)+,(A1)+ ;copy bounds.topleft
MOVE.L (A0)+,(A1)+ ;copy bounds.botright
MOVE.L D0,A0 ;get return address
JMP (A0) ;and return