; ; 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: © 1981-1993 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; 9/12/93 SAM Changed all instances of _Translate24to32 to _rTranslate24to32 ; so they can conditionalized out of the build. ; 2/4/93 CSS Update from Horror: ;

7/13/92 djw Overpatched DrawCursor, EraseCursor and SetCrsrData, ; vectorizing them to allow access later. ; 6/11/92 stb stb Add comments from QDciPatchROM.a to ShowCursor, ; SetCCursor ; 5/16/92 kc Add forRom conditionals around last change. ; 5/16/92 kc Roll in Horror. Comments follow: ;

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. ; <¥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É ; <¥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. ; 11/7/87 BAL Rolled in patches to SetCCursor to preserve A2. ; 5/27/87 EHB Added fix to SetCCursor for trashed A2 ; 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. ; 7/2/86 EHB CLEAR D0 BEFORE CALLING EXTBL ROUTINES. Multiply offset amount ; by depth for left pinning Check 8 longs of cursor ; 7/2/86 EHB Include colorequ in great equate purge ; 6/30/86 EHB New ShowCursor/HideCursor for depth support Fixed branch bug in ; ShieldCursor ; 5/30/86 CSL Added changes for Aladdin, and Aladdin Front desk bus support. ; 5/6/86 RDC Added fixes in ShowCursor routine ; 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 ; 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 EXPORT DRAWCURSOR,ERASECURSOR ; Cursor Displaying 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 ;

TST.B CrsrNew ; Mouse changed? BEQ TrackDone ; No É return TST.B CrsrBusy ; Cursor locked? BNE TrackDone ; Yes É return TST.B CrsrCouple ; Cursor coupled to mouse? BEQ NoComp ; No É skip computation MOVE.W MTemp+H,D0 ; Find ÆMx SUB.W RawMouse+H,D0 MOVE.W MTemp+V,D1 ; Find ÆMy SUB.W RawMouse+V,D1 MOVE.W D0,D2 ; x := |ÆMx| BGE.S AbslXl NEG.W D2 AbslXl MOVE.W D1,D3 ; y := |ÆMy| BGE.S AbslYl NEG.W D3 AbslYl move.l MickeyBytes,a0 ; <10/7/86 SMH> get globals 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 É donÕt compute MOVE.W #1,adbCount(A0) ; No hits CLR.W Error(A0) ; No errors BRA DoPin ; Update the cursor 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 É 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 ² Table[i] MULS D2,D3 ; D4 := i*(Mag(ÆM)+Error) MULS D3,D0 ; ÆCx := (ÆMx*i*(Mag(ÆM)+Error))/Mag(Æ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 ; ÆCy := (ÆMy*i*(Mag(ÆM)+Error))/Mag(Æ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 ; LEA CrsrPin,A0 ; Bounding rect for cursor MOVE.L RawMouse,D0 ; Pin mouse inside rect Endif ; Not forRom

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 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 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 ;_______________________________________________________________________ ; ; ; ; PROCEDURE CursorSect -- called by shieldcursor, showcursor ; ; ; ; Does a sectrect of CrsrRect and ShieldRect, all global-cošrd like. ; ; CLEAR the z-flag if they DO intersect: BNE YesTheyIntersect. ; This code is was moved out of ShieldCursor. ; ; ; Since CrsrRect is in local screen cošrds, and ShieldRect is in globals, ; the CrsrDevice's GDRect is used as an offset. ;_______________________________________________________________________ ; CursorSect MOVEM.L A0/A1/D0,-(SP) ;save the approprate regs TST ShieldDepth ;Any shielding? BEQ.s @NoSect LEA CrsrRect,A0 ;point to crsr rect ; MOVE.L CrsrDevice,A1 ;GET CURSOR DEVICE ; MOVE.L (A1),A1 ;POINT TO CURSOR DEVICE ; ADD #GDRECT,A1 ;POINT TO DEVICE'S RECT ; MOVE ShieldRect+Bottom,D0 ;GET SHIELD BOTTOM ; SUB TOP(A1),D0 ;CONVERT TO SCREEN LOCAL; CMP (A0)+,D0 ;IS SHIELDBOTTOM < SAVETOP ? ; BLT.S @NOSECT ;YES, NO INTERSECTION ; MOVE ShieldRect+Right,D0 ;GET SHIELD RIGHT SUB LEFT(A1),D0 ;CONVERT TO SCREEN LOCAL CMP (A0)+,D0 ;IS SHIELDRIGHT <= SAVELEFT ? BLE.S @NOSECT ;YES, NO INTERSECTION MOVE ShieldRect+Top,D0 ;GET SHIELD TOP SUB TOP(A1),D0 ;CONVERT TO SCREEN LOCAL CMP (A0)+,D0 ;IS SHIELDTOP >= SAVEBOTTOM ? BGE.S @NOSECT ;YES, NO INTERSECTION MOVE ShieldRect+Left,D0 ;GET SHIELD LEFT SUB LEFT(A1),D0 ;CONVERT TO SCREEN LOCAL CMP (A0),D0 ;IS SHIELDLEFT >= SAVERIGHT ? BGE.S @NOSECT ;YES, NO INTERSECTION @SECT MOVEQ #1,D0 ;Clear the Z-flag BRA.S @out ; @NOSECT CLR D0 ;Set the Z-flag @out MOVEM.L (SP)+,A0/A1/D0 ;Restore regs 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" MOVE.B #1,CrsrObscure ;Mark it as obscure 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 ;________________________________________________________________________ ; 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 EraseCursor move.l EraseCrsrVector,-(sp) ; CSS rts ;jump to the vectored routine 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. ; ;Êthis reflects the fix from QDciPatchROM.a where obscure/show/hide left stb ; the cursor hidden only, and obscure/hide/show left the cursor obscured only. 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 ; clr.b CrsrObscure ;unobscure cursor if level went past zero ;fall into DrawCursor ;________________________________________________________________________ ; 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 DrawCursor move.l DrawCrsrVector,-(sp) ; CSS rts ;jump to the vectored routine 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 ; ShieldLeft DS.W 1 ; ShieldTop DS.W 1 ; ShieldRight DS.W 1 ; ShieldBot DS.W 1 ; return DS.L 1 ; ENDR WITH ShieldVars ShieldCursor TST ShieldDepth ;Any shielding already? ; 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 ; MOVE.L ShieldTop(SP),ShieldRect+topLeft ; @3 ADDQ #1,ShieldDepth ;Shielding officially on MOVE.B #1,CrsrBusy BSR CursorSect ; BEQ.s @1 ; 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 stb ; when setting CCursor on multiple device systems stb SetCCursor MOVEM.L D3-D4/A2-A4,-(SP) ;save work registers move.l 24(sp),a2 ;get ccrsrHandle 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 ; CSS bsr.l SetCrsrDelay ; 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 ; ; 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 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? 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 LSL D7,D5 ;MULTIPLY BY DEPTH 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 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 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 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 ; ; 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