.INCLUDE GRAFTYPES.TEXT ;----------------------------------------------------------- ; ; ; **** *** ***** * * * **** *** ; * * * * ** ** * * * * * * ; * * * * * * * * * * * * * ; **** * * * * * * * **** *** ; * * * * * * ***** * * ; * * * * * * * * * * * ; **** *** * * * * * * *** ; ; ; ; QuickDraw Routines to operate on BitMaps. ; .PROC StdBits,5 .REF CheckPic,PutPicByte,PutPicWord,PutPicRgn,PutPicData .REF StretchBits,PackBits ;--------------------------------------------------------------- ; ; PROCEDURE StdBits(VAR srcBits: BitMap; ; VAR srcRect: Rect; ; VAR dstRect: Rect; ; mode: INTEGER; ; maskRgn: RgnHandle); ; ; A6 OFFSETS OF PARAMS AFTER LINK: ; PARAMSIZE .EQU 18 SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP SRCRECT .EQU SRCBITS-4 ;LONG, ADDR OF RECT DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT MODE .EQU DSTRECT-2 ;WORD MASKRGN .EQU MODE-4 ;LONG, RGNHANDLE MYBITS .EQU -14 ;BITMAP PACKBUF .EQU MYBITS-256 ;SCANLINE PACKING BUFFER SRCPTR .EQU PACKBUF-4 ;LONG DSTPTR .EQU SRCPTR-4 ;LONG VARSIZE .EQU DSTPTR ;TOTAL BYTES OF LOCALS LINK A6,#VARSIZE ;ALLOCATE STACK FRAME MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE REGS JSR CHECKPIC ;SET UP A4,A3 AND CHECK PICSAVE BLE NOTPIC ;BRANCH IF NOT PICSAVE MOVEQ #8,D6 ; ; TRIM SRCBITS ; MOVE.L SRCBITS(A6),A0 ;GET ADDR OF SRCBITS LEA MYBITS(A6),A1 ;POINT TO MY COPY MOVE.L BASEADDR(A0),A3 ;GET BASEADDR (CLOBBERS A3) MOVE ROWBYTES(A0),D4 ;GET OLD ROWBYTES MOVE.L BOUNDS+TOPLEFT(A0),BOUNDS+TOPLEFT(A1) ;COPY BOUNDS TOPLEFT MOVE.L BOUNDS+BOTRIGHT(A0),BOUNDS+BOTRIGHT(A1) ;COPY BOUNDS BOTRIGHT MOVE.L SRCRECT(A6),A0 ;POINT TO SRCRECT MOVE TOP(A0),D0 ;GET SRCRECT.TOP SUB BOUNDS+TOP(A1),D0 ;SKIPTOP:=SRCRECT.TOP-BOUNDS.TOP BLE.S TOPOK ;CONTINUE IF SKIPTOP NEG ADD D0,BOUNDS+TOP(A1) ;NEWTOP := SRCRECT TOP MULU D4,D0 ;CALC VERT OFFSET ADD.L D0,A3 ;ADJUST BASEADDR TOPOK MOVE BOTTOM(A0),D0 ;GET SRCRECT.BOTTOM CMP BOUNDS+BOTTOM(A1),D0 ;IS SRCRECT BOT < BOUNDS BOT ? BGE.S BOTOK ;NO, CONTINUE MOVE D0,BOUNDS+BOTTOM(A1) ;YES, TRIM BOUNDS BOTTOM BOTOK MOVE LEFT(A0),D0 ;GET SRCRECT.LEFT SUB BOUNDS+LEFT(A1),D0 ;CALC SKIPLEFT BLE.S LEFTOK ;CONTINUE IF SKIPLEFT NEG LSR #3,D0 ;DIV BY 8 FOR SKIP BYTES ADD D0,A3 ;OFFSET BASEADDR HORIZ LSL #3,D0 ;BYTES TIMES 8 FOR DOTS ADD D0,BOUNDS+LEFT(A1) ;ADD DOTS TO BOUNDS.LEFT LEFTOK MOVE RIGHT(A0),D0 ;GET SRCRECT.RIGHT SUB BOUNDS+LEFT(A1),D0 ;CONVERT TO GLOBAL ADD #7,D0 ;ROUND UP LSR #3,D0 ;TO NEXT MULT OF 8 LSL #3,D0 ADD BOUNDS+LEFT(A1),D0 ;RETURN TO LOCAL CMP BOUNDS+RIGHT(A1),D0 ;IS RESULT < BOUNDS.RIGHT ? BGE.S RIGHTOK ;NO, CONTINUE MOVE D0,BOUNDS+RIGHT(A1) ;YES, TRIM RIGHT RIGHTOK ; ; CALC NEW ROWBYTES AFTER TRIMMING ; MOVE BOUNDS+RIGHT(A1),D5 ;GET TRIMMED RIGHT SUB BOUNDS+LEFT(A1),D5 ;CALC WIDTH ADD #15,D5 ;ROUND UP LSR #4,D5 ;DIV BY 16 BLE BITSOK ;IGNORE IF NEWROW <= 0 ADD D5,D5 ;DOUBLE FOR NEW ROWBYTES MOVE D5,ROWBYTES(A1) ;COPY ROWBYTES MOVE.B #$90,-(SP) ;PUSH OPCODE=BITSRECT TST.L MASKRGN(A6) ;IS MASKRGN NIL ? BEQ.S NOTRGN ;YES, CONTINUE ADD.B #1,(SP) ;REPLACE OPCODE=BITSRGN (IE. $91) ;FIXED BUG 12/3/83, RP NOTRGN CMP D6,D5 ;IS NEWROW < 8 ? BLT.S NOPACK ;YES, DONT BITPACK ADD.B #8,(SP) ;SET BIT 3 FOR BITPACK NOPACK JSR PutPicByte ;PUT OPCODE TO THEPIC PEA MYBITS+ROWBYTES(A6) ;PUSH ADDR OF ROWBYTYES,BOUNDS MOVE #10,-(SP) ;PUSH BYTECOUNT = 10 JSR PutPicData ;PUT ROWBYTES,BOUNDS TO THEPIC MOVE.L SRCRECT(A6),-(SP) MOVE D6,-(SP) JSR PutPicData ;PUT SRCRECT MOVE.L DSTRECT(A6),-(SP) MOVE D6,-(SP) JSR PutPicData ;PUT DSTRECT MOVE MODE(A6),-(SP) JSR PutPicWord ;PUT MODE TST.L MASKRGN(A6) ;IS MASKRGN NIL ? BEQ.S NOMASK ;YES, SKIP IT MOVE.L MASKRGN(A6),-(SP) ;NO, PUSH MASKRGN JSR PutPicRgn ;PUT MASKRGN TO THEPIC NOMASK ; ; NOW PUT THE BITMAP DATA: IF NEWROW >= 8 THEN USE PACKBITS ; LEA MYBITS(A6),A2 ;POINT TO (TRIMMED) BITMAP MOVE BOUNDS+BOTTOM(A2),D7 SUB BOUNDS+TOP(A2),D7 ;HEIGHT := BOUNDS BOT - TOP CMP D6,D5 ;IS NEWROW < 8 ? BLT.S START2 ;YES, DONT TRY TO PACK BRA.S START1 ;GO TO LOOP START MORE1 MOVE.L A3,SRCPTR(A6) ;SRCPTR := ^SCANLINE DATA LEA PACKBUF(A6),A0 MOVE.L A0,DSTPTR(A6) ;DSTPTR := @PACKBUF PEA SRCPTR(A6) ;PUSH VAR SRCPTR PEA DSTPTR(A6) ;PUSH VAR DSTPTR MOVE D5,-(SP) ;PUSH SRCBYTES = NEWROW JSR PackBits ;PACK ROW INTO PACKBUF MOVE.L DSTPTR(A6),D6 ;GET UPDATED DSTPTR LEA PACKBUF(A6),A0 ;POINT TO PACKBUF SUB.L A0,D6 ;CALC PACKED BYTECOUNT MOVE.B D6,-(SP) JSR PutPicByte ;PUT PACKED BYTECOUNT TO THEPIC PEA PACKBUF(A6) MOVE D6,-(SP) JSR PutPicData ;PUT PACKED DATA TO THEPIC ADD D4,A3 ;ADD OLDROW TO BITS PTR START1 DBRA D7,MORE1 ;LOOP FOR HEIGHT ROWS BRA.S BITSOK ; ; ROWBYTES < 8, DONT USE PACKBITS ; MORE2 MOVE.L A3,-(SP) ;PUSH ADDR OF BITS MOVE D5,-(SP) ;PUSH BYTECOUNT = NEWROW JSR PutPicData ;PUT ONE ROW OF BITMAP DATA ADD D4,A3 ;ADD OLDROW TO BITS PTR START2 DBRA D7,MORE2 ;LOOP FOR HEIGHT ROWS BITSOK MOVE.L THEPORT(A4),A3 ;RESTORE THEPORT PTR NOTPIC TST PNVIS(A3) ;IS PNVIS >= 0 ? BLT.S GOHOME ;NO, QUIT MOVE.L SRCBITS(A6),-(SP) ;PUSH SRCBITS PEA PORTBITS(A3) ;PUSH DSTBITS = PORTBITS MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT MOVE MODE(A6),-(SP) ;PUSH MODE MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN BNE.S MASKOK ;WAS IT NIL ? MOVE.L WIDEOPEN(A4),(SP) ;YES, REPLACE WITH WIDEOPEN MASKOK JSR STRETCHBITS ;CALL STRETCHBITS GOHOME MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE REGS UNLINK PARAMSIZE,'STDBITS ' .PROC CopyBits,6 .REF StdBits,ShieldCursor,ShowCursor,StretchBits ;--------------------------------------------------------------- ; ; PROCEDURE CopyBits(srcBits,dstBits: BitMap; ; srcRect,dstRect: Rect; ; mode: INTEGER; ; maskRgn: RgnHandle *); ; ; ; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK: ; PARAMSIZE .EQU 22 ;TOTAL BYTES OF PARAMS SRCBITS .EQU PARAMSIZE+8-4 ;LONG, ADDR OF BITMAP DSTBITS .EQU SRCBITS-4 ;LONG, ADDR OF BITMAP SRCRECT .EQU DSTBITS-4 ;LONG, ADDR OF RECT DSTRECT .EQU SRCRECT-4 ;LONG, ADDR OF RECT MODE .EQU DSTRECT-2 ;WORD MASKRGN .EQU MODE-4 ;LONG, RGNHANDLE LINK A6,#0 ;NO LOCAL VARS MOVEM.L D6-D7/A2-A4,-(SP) ;SAVE REGS MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT MOVE.L SRCBITS(A6),A2 ;POINT TO SRCBITS MOVE.L BASEADDR(A2),D7 ;GET SRCBITS.BASEADDR MOVE.L SCREENBITS+BASEADDR(A4),D6 ;GET SCREENBITS.BASEADDR CMP.L D6,D7 ;IS SRC FROM THE SCREEN ? BNE.S SRCOK ;NO, CONTINUE MOVE.L SRCRECT(A6),-(SP) ;YES, PUSH SRCRECT MOVE.L BOUNDS+TOPLEFT(A2),-(SP) ;PUSH OFFSET POINT JSR SHIELDCURSOR ;HIDE THE CURSOR IF IN SRCRECT ;----------------------------------------------------- ; ; TEST IF DST IS TO THEPORT, (IF SO WE CLIP) ; SRCOK MOVE.L DSTBITS(A6),A1 ;POINT TO DSTBITS MOVE.L A3,D0 ;IS THEPORT NIL ? BEQ.S NOTPORT ;YES, NOT TO THEPORT BTST #0,D0 ;IS THEPORT ODD ? BNE.S NOTPORT ;YES, NOT TO THEPORT MOVE.L PORTBITS+BASEADDR(A3),D0 ;GET PORTBITS.BASEADDR CMP.L BASEADDR(A1),D0 ;IS DST BASEADDR SAME ? BNE.S NOTPORT ;NO, NOT TO THEPORT MOVE.L PORTBOUNDS(A3),D0 ;GET PORT BOUNDS TOPLEFT CMP.L BOUNDS(A1),D0 ;IS BOUNDS TOPLEFT SAME ? BEQ.S TOPORT ;YES, ITS PROBABLY TO THEPORT ; ; DST IS DEFINITELY NOT TO THEPORT, SO WE CAN'T USE THE CAPTURE PROC. ; StretchBits(srcBits,dstBits,srcRect,dstRect,mode,wideOpen,wideOpen,maskRgn); ; NOTPORT MOVE.L A2,-(SP) ;PUSH SRCBITS MOVE.L A1,-(SP) ;PUSH DSTBITS MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT MOVE MODE(A6),-(SP) ;PUSH MODE MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN MOVE.L (SP),-(SP) ;PUSH WIDEOPEN MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN BNE.S MASKOK ;WAS IT NIL ? MOVE.L WIDEOPEN(A4),(SP) ;YES, REPLACE WITH WIDEOPEN MASKOK JSR STRETCHBITS ;CALL STRETCHBITS BRA.S CLEANUP ;AND CONTINUE ; ; DST IS PROBABLY TO THEPORT, SO WE USE THE CAPTURE PROC. ; CallBits(srcBits,srcRect,dstRect,mode,maskRgn) ; TOPORT MOVE.L A2,-(SP) ;PUSH SRCBITS MOVE.L SRCRECT(A6),-(SP) ;PUSH SRCRECT MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT MOVE MODE(A6),-(SP) ;PUSH MODE MOVE.L MASKRGN(A6),-(SP) ;PUSH MASKRGN (NIL OK) MOVE.L GRAFPROCS(A3),D0 ;IS GRAFPROCS NIL ? LEA STDBITS,A0 BEQ.S USESTD ;YES, USE STD PROC MOVE.L D0,A0 MOVE.L BITSPROC(A0),A0 ;NO, GET PROC PTR USESTD JSR (A0) ;CALL IT CLEANUP CMP.L D6,D7 ;WAS SRC FROM THE SCREEN ? BNE.S DONE ;NO, CONTINUE JSR SHOWCURSOR ;YES, REPLACE CURSOR DONE MOVEM.L (SP)+,D6-D7/A2-A4 ;RESTORE REGS UNLINK PARAMSIZE,'COPYBITS' .PROC CopyMask .REF RSect,HideCursor,ShowCursor,InitRgn,SeekRgn,XorSlab ;-------------------------------------------------------------- ; ; PROCEDURE CopyMask(srcBits,maskBits,dstBits: BitMap; ; srcRect,maskRect,dstRect: Rect); ; ; NEW ROUTINE ADDED TO QUICKDRAW April 28, 1985 ; ; Written by Bill Atkinson. CopyRight 1985 Apple Computer Inc. ; ; A6 OFFSETS OF PARAMETERS AFTER LINK: ; paramSize .EQU 24 ;total bytes of params srcBits .EQU paramSize+8-4 ;long, addr of BitMap maskBits .EQU srcBits-4 ;long, addr of BitMap dstBits .EQU maskBits-4 ;long, addr of BitMap srcRect .EQU dstBits-4 ;long, addr of Rect maskRect .EQU srcRect-4 ;long, addr of Rect dstRect .EQU maskRect-4 ;long, addr of Rect ;------------------------------------------------- ; ; A6 OFFSETS OF LOCALS AFTER LINK: ; MINRECT .EQU -8 ;RECT RGNA .EQU MINRECT-4 ;RgnHandle RGNB .EQU RGNA-4 ;RgnHandle STATEA .EQU RGNB-RGNREC ;REGION STATE RECORD STATEB .EQU STATEA-RGNREC ;REGION STATE RECORD BUFLEFT .EQU STATEB-2 ;WORD SRCADDR .EQU BUFLEFT-4 ;LONG MASKADDR .EQU SRCADDR-4 ;LONG DSTADDR .EQU MASKADDR-4 ;LONG SRCROW .EQU DSTADDR-4 ;LONG MASKROW .EQU SRCROW-4 ;LONG DSTROW .EQU MASKROW-4 ;LONG SAVESTK .EQU DSTROW-4 ;LONG VARSIZE .EQU SAVESTK ;SIZE OF LOCALS LINK A6,#VARSIZE ;ALLOCATE STACK FRAME MOVEM.L D0-D7/A1-A4,-(SP) ;SAVE REGS MOVE.L SP,SAVESTK(A6) ;REMEMBER STACK FOR LATER MOVE.L GRAFGLOBALS(A5),A2 ;point to QuickDraw globals MOVE.L WIDEOPEN(A2),RGNA(A6) ;init RGNA to wideOpen MOVE.L WIDEOPEN(A2),RGNB(A6) ;init RGNB to wideOpen MOVE.L THEPORT(A2),A2 ;point to thePort MOVE.L DSTBITS(A6),A4 ;A4 POINTS TO DSTBITS MOVE.L DSTRECT(A6),A3 ;A3 POINTS TO DSTRECT ; ; if dst is in thePort, then clip to visRgn and clipRgn ; MOVE.L portBits+baseAddr(A2),D0 ;get thePort^.portBits CMP.L baseAddr(A4),D0 ;is dst on screen ? BNE.S NOTPORT ;no, continue MOVE.L CLIPRGN(A2),RGNA(A6) ;yes, clip to clipRgn MOVE.L VISRGN(A2),RGNB(A6) ;and to visRgn NOTPORT ; ; CALC MINRECT, THE INTERSECTION OF DSTRECT, DSTBITS.BOUNDS, ; AND TWO REGION BOUNDING BOXES. QUIT IF RESULT IS EMPTY. ; MOVE.L A3,-(SP) ;PUSH DSTRECT PEA BOUNDS(A4) ;PUSH DSTBITS.BOUNDS MOVE.L RGNA(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT PEA RGNBBOX(A0) ;PUSH BOUNDING BOX MOVE.L RGNB(A6),A0 ;GET RGNHANDLE MOVE.L (A0),A0 ;DE-REFERENCE IT PEA RGNBBOX(A0) ;PUSH BOUNDING BOX MOVE #4,-(SP) ;PUSH NRECTS = 4 DOSECT PEA MINRECT(A6) ;PUSH WHERE TO PUT RESULT JSR RSECT ;INTERSECT 4 RECTS BEQ GOHOME ;QUIT IF EMPTY JSR HideCursor ;ELSE HIDE THE CURSOR ; ; CALC BUFLEFT SO THAT RGNBUF WILL ALIGN TO DSTBITS ; MOVE MINRECT+LEFT(A6),D1 ;GET MINRECT LEFT SUB BOUNDS+LEFT(A4),D1 ;CONVERT TO GLOBAL COORDS AND #$FFF0,D1 ;TRUNC TO MULT OF 16 ADD BOUNDS+LEFT(A4),D1 ;CONVERT BACK TO LOCAL MOVE D1,BUFLEFT(A6) ;SAVE AS BUFLEFT ; ; INIT BOTH REGION STATE RECORDS AND ALLOCATE BUFFERS ; MOVE.L RGNA(A6),A0 ;GET RGNHANDLE LEA STATEA(A6),A1 ;POINT TO STATE RECORD AGAIN MOVE.L (A0),A0 ;DE-REFERENCE RGNHANDLE CMP #10,RGNSIZE(A0) ;IS IT RECTANGULAR ? SEQ D7 ;REMEMBER FOR BELOW MOVE MINRECT+LEFT(A6),D0 ;GET MINH MOVE MINRECT+RIGHT(A6),D1 ;GET MAXH MOVE BUFLEFT(A6),D2 ;GET BUFLEFT JSR INITRGN ;INIT STATE, ALLOC BUFFER ; ; IF REGION WAS RECTANGULAR, DRAW TOP SCANLINE INTO ITS BUFFER ; AND SET UP THISV AND NEXTV SO SEEKRGN DOES NOTHING ; TST.B D7 ;was region rectangular ? BEQ.S NOTRECT ;no, continue MOVE #-32767,THISV(A1) ;yes, say we're at infinity MOVE #32767,NEXTV(A1) ;and next change is never MOVE.L SCANBUF(A1),A0 ;point to buffer MOVE MINRECT+LEFT(A6),D3 ;get minrect.left SUB BUFLEFT(A6),D3 ;make buffer relative MOVE MINRECT+RIGHT(A6),D4 ;get minrect.right SUB BUFLEFT(A6),D4 ;make buffer relative JSR XorSlab ;draw into buffer NOTRECT LEA STATEB(A6),A0 ;point to state record B CMP.L A0,A1 ;did we just do RGNB ? BEQ.S GETDST ;yes, continue MOVE.L A0,A1 ;no, point to STATEB MOVE.L RGNB(A6),A0 ;get RGNB handle BRA AGAIN ;and loop to init STATEB ; ; Set up dstRow and starting dstAddr ; GETDST MOVE ROWBYTES(A4),D1 ;get dst rowBytes EXT.L D1 ;make it long MOVE.L D1,DSTROW(A6) ;save dstRow for later MOVE MINRECT+TOP(A6),D0 ;get dst top SUB BOUNDS+TOP(A4),D0 ;convert to global MULU D1,D0 ;mult by rowbytes MOVE.L BASEADDR(A4),A0 ;get dst baseAddr ADD.L D0,A0 ;add vertical offset MOVE MINRECT+LEFT(A6),D0 ;get dst left SUB BOUNDS+LEFT(A4),D0 ;convert to global LSR #4,D0 ;convert dots to words ADD D0,D0 ;double for bytes ADD D0,A0 ;add horizontal offset MOVE.L A0,DSTADDR(A6) ;save result in dstAddr ; ; Set up srcRow, srcShift, and starting srcAddr ; MOVE.L SRCRECT(A6),A1 ;point to srcRect MOVE.L SRCBITS(A6),A2 ;point to srcBits MOVE ROWBYTES(A2),D1 ;get src rowBytes EXT.L D1 ;make it long MOVE.L D1,SRCROW(A6) ;save srcRow for later MOVE LEFT(A3),D6 ;get dst left SUB BOUNDS+LEFT(A4),D6 ;convert to global MOVE LEFT(A1),D1 ;get src left SUB BOUNDS+LEFT(A2),D1 ;convert to global SUB D1,D6 ;calc delta horiz AND #$F,D6 ;mod 16 for srcShift MOVE MINRECT+TOP(A6),D0 ;get clipped dst top SUB TOP(A3),D0 ;convert from dst coords ADD TOP(A1),D0 ;to src coords SUB BOUNDS+TOP(A2),D0 ;convert to global MULU ROWBYTES(A2),D0 ;mult by src rowbytes MOVE.L BASEADDR(A2),A0 ;get src baseAddr ADD.L D0,A0 ;add vertical offset MOVE MINRECT+LEFT(A6),D0 ;get clipped dstLeft SUB LEFT(A3),D0 ;convert from dst coords ADD LEFT(A1),D0 ;to src coords SUB BOUNDS+LEFT(A2),D0 ;convert to global ADD D6,D0 ;add srcShift LSR #4,D0 ;convert dots to words ADD D0,D0 ;double for bytes ADD D0,A0 ;add horiz offset MOVE.L A0,SRCADDR(A6) ;save srcAddr for later ; ; Set up maskRow, maskShift, and starting maskAddr ; MOVE.L MASKRECT(A6),A1 ;point to maskRect MOVE.L MASKBITS(A6),A2 ;point to maskBits MOVE ROWBYTES(A2),D1 ;get mask rowBytes EXT.L D1 ;make it long MOVE.L D1,MASKROW(A6) ;save maskRow for later MOVE LEFT(A3),D7 ;get dst left SUB BOUNDS+LEFT(A4),D7 ;convert to global MOVE LEFT(A1),D1 ;get mask left SUB BOUNDS+LEFT(A2),D1 ;convert to global SUB D1,D7 ;calc delta horiz AND #$F,D7 ;mod 16 for maskShift MOVE MINRECT+TOP(A6),D0 ;get clipped dst top SUB TOP(A3),D0 ;convert from dst coords ADD TOP(A1),D0 ;to mask coords SUB BOUNDS+TOP(A2),D0 ;convert to global MULU ROWBYTES(A2),D0 ;mult by mask rowbytes MOVE.L BASEADDR(A2),A0 ;get mask baseAddr ADD.L D0,A0 ;add vertical offset MOVE MINRECT+LEFT(A6),D0 ;get clipped dstLeft SUB LEFT(A3),D0 ;convert from dst coords ADD LEFT(A1),D0 ;to mask coords SUB BOUNDS+LEFT(A2),D0 ;convert to global ADD D7,D0 ;add maskShift LSR #4,D0 ;convert dots to words ADD D0,D0 ;double for bytes ADD D0,A0 ;add horiz offset MOVE.L A0,MASKADDR(A6) ;save maskAddr for later ; ; MAKE REGION BUFFERS CURRENT FOR THIS VERTICAL. ; THEN SET UP AND DRAW CURRENT SCANLINE. ; MOVE MINRECT+TOP(A6),D5 ;init CURRENT VERTICAL NEXTROW MOVE D5,D0 ;get current vert LEA STATEA(A6),A1 ;point to state record A JSR SEEKRGN ;seek region to current vert MOVE D5,D0 ;get current vert LEA STATEB(A6),A1 ;point to state record B JSR SEEKRGN ;seek region to current vert MOVE.L STATEA+SCANBUF(A6),A0 ;init REGION A PTR MOVE.L STATEB+SCANBUF(A6),A1 ;init REGION B PTR MOVE.L SRCADDR(A6),A2 ;init SRCPTR MOVE.L MASKADDR(A6),A3 ;init MASKPTR MOVE.L DSTADDR(A6),A4 ;init DSTPTR MOVE STATEA+SCANSIZE(A6),D3 ;init LONGCOUNT NEXTLONG MOVE.L -2(A2),D0 ;get a long of src LSR.L D6,D0 ;align to dst SWAP D0 ;put result in hi word MOVE.L (A2)+,D1 ;get second long of src LSR.L D6,D1 ;align to dst MOVE.W D1,D0 ;assemble one long of src MOVE.L -2(A3),D1 ;get a long of mask LSR.L D7,D1 ;align to dst SWAP D1 ;put result in hi word MOVE.L (A3)+,D2 ;get second long of mask LSR.L D7,D2 ;align to dst MOVE.W D2,D1 ;assemble one long of mask AND.L (A0)+,D1 ;and with RGNA buffer AND.L (A1)+,D1 ;and with RGNB buffer AND.L D1,D0 ;mask src data NOT.L D1 ;form notmask AND.L (A4),D1 ;get dst data OR.L D1,D0 ;merge with src data MOVE.L D0,(A4)+ ;store result into dst DBRA D3,NEXTLONG ;loop all longs this scanline ; ; bump vertically and loop for all scanlines ; MOVE.L SRCROW(A6),D0 ;GET SRC ROWBYTES ADD.L D0,SRCADDR(A6) ;BUMP SRC TO NEXT ROW MOVE.L MASKROW(A6),D0 ;GET MASK ROWBYTES ADD.L D0,MASKADDR(A6) ;BUMP MASK TO NEXT ROW MOVE.L DSTROW(A6),D0 ;GET DST ROWBYTES ADD.L D0,DSTADDR(A6) ;BUMP DST TO NEXT ROW ADD #1,D5 ;ADD ONE TO VERT CMP MINRECT+BOTTOM(A6),D5 ;ARE WE AT THE BOTTOM ? BNE NEXTROW ;NO, LOOP FOR ALL SCAN LINES JSR SHOWCURSOR ;RESTORE CURSOR GOHOME MOVE.L SAVESTK(A6),SP ;STRIP VARIABLE SIZED BUFFER MOVEM.L (SP)+,D0-D7/A1-A4 ;RESTORE REGISTERS UNLINK PARAMSIZE,'CopyMask' .PROC SeedFill .DEF CalcMask ;------------------------------------------------------------------------- ; ; PROCEDURE SeedFill(srcPtr,dstPtr: Ptr; ; srcRow,dstRow,height,words: INTEGER; ; seedH,seedV: INTEGER) ; MOVE.L (SP)+,A0 ;pop return addr MOVEQ #-1,D0 ;get a long of -1 MOVE.L D0,-(SP) ;push edge = all ones BRA.S SHARE ;share common code ;------------------------------------------------------------------------- ; ; PROCEDURE CalcMask(srcPtr,dstPtr: Ptr; ; srcRow,dstRow,height,words: INTEGER); ; CalcMask MOVE.L (SP)+,A0 ;pop return addr MOVEQ #-1,D0 ;get a long of -1 MOVE.L D0,-(SP) ;push seed = (-1,-1) CLR.L -(SP) ;push edge = zeros SHARE MOVE.L A0,-(SP) ;restore return addr ;------------------------------------------------------------------------- ; ; LOCAL PROCEDURE MakeMask(srcPtr,dstPtr: Ptr; ; srcRow,dstRow,height,words: INTEGER; ; seedH,seedV: INTEGER; ; edge: LongInt); ; ; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK: ; params .EQU 24 srcPtr .EQU params+8-4 ;long dstPtr .EQU srcPtr-4 ;long srcRow .EQU dstPtr-2 ;word dstRow .EQU srcRow-2 ;word height .EQU dstRow-2 ;word words .EQU height-2 ;word seedH .EQU words-2 ;word seedV .EQU seedH-2 ;word edge .EQU seedV-4 ;long dstBump .EQU -2 ;word saveStk .EQU dstBump-4 ;long varSize .EQU saveStk ;total locals LINK A6,#varSize ;allocate stack frame MOVEM.L D3-D7/A2-A4,-(SP) ;save regs MOVE.L SP,saveStk(A6) ;save stack pointer ; ; prepare height and words for DBRA count. Quit if either <= 0. ; MOVE words(A6),D5 ;get count of words BLE GOHOME ;quit if words <= 0 SUB #1,D5 ;subtract 1 for DBRA count SUB #1,height(A6) ;convert height to DBRA BLT GOHOME ;quit if height <= 0 ; ; init dst to all ones: ; MOVE words(A6),D0 ;get # of words ADD D0,D0 ;double for bytes MOVE dstRow(A6),D1 ;get dstRow SUB D0,D1 ;subtract bytes for dstBump MOVE D1,dstBump(A6) ;save dstBump for later MOVE.L dstPtr(A6),A2 ;point to dst MOVEQ #-1,D0 ;get some black MOVE height(A6),D3 ;init DBRA rowCount BLACK1 MOVE D5,D2 ;init DBRA wordCount BLACK2 MOVE D0,(A2)+ ;put a word of black DBRA D2,BLACK2 ;loop all words in row ADD D1,A2 ;bump to next row DBRA D3,BLACK1 ;loop height rows ; ; clear one dst pixel at seedH,seedV ; MOVE seedV(A6),D0 ;get seed vert coord BLT.S NOSEED ;skip if neg (no seed) MULU dstRow(A6),D0 ;mul times dst row MOVE.L dstPtr(A6),A0 ;point to dst ADD D0,A0 ;add vertical offset MOVE seedH(A6),D0 ;get seed horiz coord MOVE D0,D1 ;copy seedH LSR #3,D0 ;div by 8 for byte NOT D1 ;invert bit number BCLR D1,0(A0,D0) ;clear seed pixel NOSEED ; ; allocate a scanline buffer of ones or zeros on the stack: ; MOVE.L edge(A6),D6 ;get zero or all ones MOVE D5,D1 ;get longCount NEXTBUF MOVE D6,-(SP) ;write a word of ones or zeros DBRA D1,NEXTBUF ;loop all words MOVE.L srcPtr(A6),A0 ;point to top of src MOVE.L dstPtr(A6),A2 ;point to top of dst NXTPASS SF D7 ;clear dirty flag MOVE height(A6),D4 ;get DBRA rowCount MOVE.L SP,A1 ;point dst above to edgeBuf ; ; smear dst zeros down and to the right, smear limited by src. ; NEXTROW MOVE.L D6,D1 ;init prev dst to edge MOVE D5,D3 ;get DBRA wordCount RNEXT MOVE (A2),D1 ;get dst word BNE.S RDSTOK ;is it already zero ? ADD #2,A0 ;yes, bump srcPtr ADD #2,A1 ;bump dstAbove ptr ADD #2,A2 ;bump dst ptr SWAP D1 ;put prev dst in hi word DBRA D3,RNEXT ;loop all words in row BRA RDONE ;and continue below RDSTOK MOVE (A0)+,D2 ;get src word AND (A1)+,D1 ;smear zeros down OR D2,D1 ;limit vertical smear by src BRA.S RSTART ;go to loop start RMORE MOVE D0,D1 ;update dst RSTART MOVE.L D1,D0 ;copy dst and prev dst word LSR.L #1,D0 ;shift right with carry from prev AND D1,D0 ;smear zeros to the right OR D2,D0 ;limit smear by src CMP D1,D0 ;any changes ? BNE RMORE ;yes, keep smearing CMP (A2),D1 ;has dst changed ? BEQ.S RSAME ;no, leave it alone ST D7 ;yes, set dirty flag RSAME MOVE D1,(A2)+ ;write dst to memory SWAP D1 ;put prev dst in hi word DBRA D3,RNEXT ;loop all words in row RDONE ; ; smear dst zeros down and to the left, smear limited by src. ; LSMEAR MOVE.L D6,D1 ;init prev dst to edge MOVE D5,D3 ;get DBRA wordCount LNEXT MOVE -(A2),D1 ;get dst word BNE.S LDSTOK ;is dst already zero ? SUB #2,A0 ;yes, just bump srcPtr SUB #2,A1 ;bump dstAbove ptr SWAP D1 ;put prev dst in hi word DBRA D3,LNEXT ;loop all words in row BRA.S LDONE ;and continue LDSTOK MOVE -(A0),D2 ;get src word AND -(A1),D1 ;smear zeros down OR D2,D1 ;limit vertical smear by src BRA.S LSTART ;go to loop start LMORE MOVE D0,D1 ;update dst LSTART MOVE.L D1,D0 ;copy dst and prev dst word ROL.L #1,D0 ;shift left with carry from prev AND D1,D0 ;smear zeros to the left OR D2,D0 ;limit smear by src CMP D1,D0 ;any changes ? BNE LMORE ;yes, keep smearing CMP (A2),D1 ;has dst changed ? BEQ.S LSAME ;no, leave it alone ST D7 ;yes, set dirty flag MOVE D1,(A2) ;write dst to memory LSAME SWAP D1 ;put prev dst in hi word DBRA D3,LNEXT ;loop all words in row LDONE ; ; bump three pointers down and loop for height scanlines ; ADD srcRow(A6),A0 ;bump srcPtr down a row ADD dstRow(A6),A2 ;bump dstPtr down a row MOVE.L A2,A1 ;copy dstPtr SUB dstRow(A6),A1 ;point to dst above DBRA D4,NEXTROW ;loop all rows ; ; switch directions, adjust pointers, and loop till no change ; NEG srcRow(A6) ;reverse src bump NEG dstRow(A6) ;reverse dst bump ADD srcRow(A6),A0 ;offset first src scanline ADD dstRow(A6),A2 ;offset first dst scanline TST.B D7 ;did anything change this pass ? BNE NXTPASS ;yes go for another pass ; ; if seedFill, then invert dst ; TST D6 ;is edge = black ? BPL.S GOHOME ;no, we're done MOVE dstBump(A6),D1 ;get dstBump MOVE.L dstPtr(A6),A2 ;point to dst MOVE height(A6),D3 ;init DBRA rowCount INVERT1 MOVE D5,D2 ;init DBRA wordCount INVERT2 NOT (A2)+ ;invert a word of dst DBRA D2,INVERT2 ;loop all words in row ADD D1,A2 ;bump to next row DBRA D3,INVERT1 ;loop height rows GOHOME MOVE.L saveStk(A6),SP ;restore stack pointer MOVEM.L (SP)+,D3-D7/A2-A4 ;restore regs UNLK A6 ;release stack frame MOVE.L (SP)+,A0 ;pop return addr ADD #params,SP ;strip params JMP (A0) ;and return .PROC ScrollRect,4 .REF NewRgn,RectRgn,SectRgn,CopyRgn,OffsetRgn,SetEmptyRgn .REF DiffRgn,ShieldCursor,RgnBlt,ShowCursor ;--------------------------------------------------------------------- ; ; PROCEDURE ScrollRect(dstRect: Rect; dh,dv: INTEGER; updateRgn: RgnHandle); ; ; Scroll a rectangular block of bits, erase and return an update region ; ; A6 OFFSETS OF PARAMS AND LOCALS AFTER LINK: ; PARAMSIZE .EQU 12 ;TOTAL BYTES OF PARAMS DSTRECT .EQU PARAMSIZE+8-4 ;LONG, ADDR OF RECT DH .EQU DSTRECT-2 ;WORD DV .EQU DH-2 ;WORD UPDATERGN .EQU DV-4 ;LONG, RGNHANDLE SRCRECT .EQU -8 ;RECT VARSIZE .EQU SRCRECT ;TOTAL LOCALS LINK A6,#VARSIZE ;ALLOCATE STACK FRAME MOVEM.L D6-D7/A3-A4,-(SP) ;SAVE REGS MOVE.L GRAFGLOBALS(A5),A4 ;POINT TO QUICKDRAW GLOBALS MOVE.L THEPORT(A4),A3 ;POINT TO CURRENT GRAFPORT TST PNVIS(A3) ;IS PNVIS < 0 ? BLT ABORT ;YES, QUIT FAST TST.L DV(A6) ;ARE DH AND DV BOTH 0 ? BEQ ABORT ;YES, QUIT FAST CLR.L -(SP) ;ROOM FOR FCN RESULT JSR NEWRGN ;ALLOCATE SRCRGN MOVE.L (SP)+,D7 ;GET SRCRGN HANDLE IN D7 CLR.L -(SP) ;ROOM FOR FCN RESULT JSR NEWRGN ;ALLOCATE DSTRGN MOVE.L (SP)+,D6 ;GET DSTRGN HANDLE IN D6 ; ; srcRgn := dstRect SECT visRgn SECT clipRgn ; MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT JSR RECTRGN ;RectRgn(srcRgn,dstRect); MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L VISRGN(A3),-(SP) ;PUSH VISRGN MOVE.L D7,-(SP) ;PUSH SRCRGN JSR SECTRGN ;SectRgn(srcRgn,visRgn,srcRgn); MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L CLIPRGN(A3),-(SP) ;PUSH CLIPRGN MOVE.L D7,-(SP) ;PUSH SRCRGN JSR SECTRGN ;SectRgn(srcRgn,clipRgn,srcRgn); ; ; dstRgn := offset srcRgn ; MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L D6,-(SP) ;PUSH DSTRGN JSR COPYRGN ;CopyRgn(srcRgn,dstRgn); MOVE.L D6,-(SP) ;PUSH DSTRGN MOVE.L DV(A6),-(SP) ;PUSH DH,DV JSR OFFSETRGN ;OffsetRgn(dstRgn,dh,dv); MOVE.L DSTRECT(A6),A0 ;POINT TO DSTRECT MOVE.L (A0)+,SRCRECT(A6) ;COPY DSTRECT INTO SRCRECT MOVE.L (A0)+,SRCRECT+4(A6) MOVE.L DV(A6),D0 ;GET DH,DV SUB D0,SRCRECT+LEFT(A6) ;OFFSET SRCRECT (-DH,-DV) SUB D0,SRCRECT+RIGHT(A6) SWAP D0 ;GET DV IN LO WORD SUB D0,SRCRECT+TOP(A6) SUB D0,SRCRECT+BOTTOM(A6) ; ; Compute updateRgn := srcRgn - dstRgn ; MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L D6,-(SP) ;PUSH DSTRGN MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN JSR DIFFRGN ;DiffRgn(srcRgn,dstRgn,updateRgn); ; ; ShieldCursor(dstRect,portBits.bounds.topLeft); { protect source } ; MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT MOVE.L PORTBITS+BOUNDS+TOPLEFT(A3),-(SP) ;PUSH OFFSET POINT JSR SHIELDCURSOR ;REMOVE CRSR IF INTERSECTS ; ; Copy all bits which are in both srcRgn and dstRgn. ; RgnBlt(portBits,portBits,srcRect,dstRect,0,white,dstRgn,srcRgn,wideOpen); ; PEA PORTBITS(A3) ;PUSH SRCBITS MOVE.L (SP),-(SP) ;PUSH DSTBITS PEA SRCRECT(A6) ;PUSH SRCRECT MOVE.L DSTRECT(A6),-(SP) ;PUSH DSTRECT CLR -(SP) ;PUSH MODE = SRCCOPY CLR.L -(SP) ;PAT NOT USED MOVE.L D6,-(SP) ;PUSH DSTRGN MOVE.L D7,-(SP) ;PUSH SRCRGN MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN JSR RGNBLT ;COPY THE BITS ; ; Erase the update region ; RgnBlt(portBits,portBits,dstRect,dstRect,8,bkPat,updateRgn,wideOpen,wideOpen); ; PEA PORTBITS(A3) ;PUSH SRCBITS MOVE.L (SP),-(SP) ;PUSH DSTBITS MOVE.L DSTRECT(A6),-(SP) ;PUSH SRCRECT MOVE.L (SP),-(SP) ;PUSH DSTRECT MOVE #8,-(SP) ;PUSH MODE = PATCOPY PEA BKPAT(A3) ;PUSH PAT = BKPAT MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN MOVE.L WIDEOPEN(A4),-(SP) ;PUSH WIDEOPEN MOVE.L (SP),-(SP) ;PUSH WIDEOPEN JSR RGNBLT ;ERASE THE UPDATE RGN JSR SHOWCURSOR ;RESTORE THE CURSOR MOVE.L D7,A0 ;GET SRCRGN _DisposHandle ;DISCARD IT MOVE.L D6,A0 ;PUSH DSTRGN _DisposHandle ;DISCARD IT BRA.S DONE ABORT MOVE.L UPDATERGN(A6),-(SP) ;PUSH UPDATERGN HANDLE JSR SETEMPTYRGN ;SET IT TO EMPTY DONE MOVEM.L (SP)+,D6-D7/A3-A4 ;RESTORE REGS UNLINK PARAMSIZE,'SCROLLRE' .PROC PackBits .DEF UnpackBits ;--------------------------------------------------------------------- ; ; PROCEDURE PackBits(VAR srcPtr,dstPtr: Ptr; srcBytes: INTEGER); ; ; Packs one scanline of data, compressing equal bytes. ; Returns updated srcPtr and dstPtr. ; ; Equates for parameters are shared with UnpackBits ; PARAMSIZE .EQU 10 ;TOTAL BYTES OF PARAMS SRCPTR .EQU PARAMSIZE+4-4 ;LONG, VAR DSTPTR .EQU SRCPTR-4 ;LONG,VAR SRCBYTES .EQU DSTPTR-2 ;WORD DSTBYTES .EQU SRCBYTES ;ALIAS MOVE.L A2,-(SP) ;SAVE REGS MOVE.L SRCPTR+4(SP),A0 ;GET VAR ADDR MOVE.L (A0),A0 ;GET SRCPTR ITSELF MOVE.L DSTPTR+4(SP),A1 ;GET VAR ADDR MOVE.L (A1),A1 ;GET DSTPTR ITSELF MOVE SRCBYTES+4(SP),D1 ;GET SRCBYTES SUB #1,D1 ;INIT SRC DBRA COUNT BLT.S DONE ;QUIT IF SRCBYTES <= 0 MOVE.B (A0)+,D0 ;GET FIRST BYTE OF SRC BRA.S START ;AND GO TO LOOP START FILLOP MOVE.B -1(A0),D0 ;PUT SRCDATA IN DO SUB A0,D2 ;COMPUTE FILLOP ADD #1,D2 MOVE.B D2,(A2) ;STORE FILLOP START MOVE A0,D2 ;REMEMBER SRCSTART MOVE.L A1,A2 ;REMEMBER OPLOC CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE CMP.B (A0),D0 ;IS NEXT SRC THE SAME ? BNE.S DOCOPY ;NO, USE COPY LOOP CMP.B 1(A0),D0 ;THREE IN A ROW ? BNE.S DOCOPY ;NO, USE COPY LOOP BRA.S DOFILL ;YES, USE FILL LOOP NXTCOPY MOVE.B (A0)+,D0 ;GET BYTE OF SRC CMP.B (A0),D0 ;IS THE NEXT THE SAME ? BNE.S DOCOPY ;NO, CONTINUE CMP.B 1(A0),D0 ;THREE IN A ROW ? BEQ.S COPYOP ;YES, END OF COPY RUN DOCOPY MOVE.B D0,(A1)+ ;COPY DATA TO DST DBRA D1,NXTCOPY ;AND LOOP FOR MORE ENDCOPY SUB A0,D2 ;COMPUTE COPYOP NEG D2 ;NEGATE ONLY MOVE.B D2,(A2) ;INSTALL COPYOP BRA.S DONE ;AND QUIT COPYOP TST D1 ;IS THIS THE LAST SRC BYTE ? BEQ DOCOPY ;YES, FINISH OFF COPY RUN SUB A0,D2 ;COMPUTE COPYOP NOT D2 ;NEGATE AND SUBTRACT 1 MOVE.B D2,(A2) ;STORE COPYOP MOVE.L A0,D2 ;REMEMBER SRCSTART MOVE.L A1,A2 ;REMEMBER OPLOC CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE DOFILL MOVE.B D0,(A1)+ ;COPY THE DATA BYTE NXTFILL CMP.B (A0)+,D0 ;IS NEXT BYTE THE SAME ? DBNE D1,NXTFILL ;LOOP TILL NOT SAME OR END SRC BEQ.S ENDFILL ;BRANCH IF SRC EXHAUSTED SUB #1,D1 ;COMPENSATE FOR DBNE DIDNT SUB BGE FILLOP ;BR IF SRC NOT EXHAUSTED ENDFILL SUB A0,D2 ;COMPUTE FILLOP ADD #1,D2 MOVE.B D2,(A2) ;INSTALL FILLOP DONE CLR.L D0 ;GET READY FOR WORD MOVE SRCBYTES+4(SP),D0 ;GET SRCBYTES MOVE.L SRCPTR+4(SP),A0 ;GET VAR ADDR OF SRCPTR ADD.L D0,(A0) ;BUMP SRCPTR MOVE.L DSTPTR+4(SP),A2 ;GET VAR ADDR OF DSTPTR MOVE.L A1,(A2) ;UPDATE DSTPTR MOVE.L (SP)+,A2 ;RESTORE REGS SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR ADD #PARAMSIZE,SP ;STRIP PARAMS JMP (A0) ;AND RETURN ;-------------------------------------------------------- ; ; PROCEDURE UnpackBits(VAR srcPtr,dstPtr: Ptr; dstBytes: INTEGER); ; ; Unpacks one scanline of data, as compressed by PackBits. ; Returns updated srcPtr and dstPtr. ; ; Equates for parameters are the same as PackBits! ; UnpackBits MOVE.L SRCPTR(SP),A0 ;GET ADDR OF SRCPTR MOVE.L (A0),A0 ;GET SRCPTR ITSELF MOVE.L DSTPTR(SP),A1 ;GET ADDR OF DSTPTR MOVE.L (A1),A1 ;GET DSTPTR ITSELF MOVE DSTBYTES(SP),D2 ;GET DSTBYTES EXT.L D2 ;MAKE IT LONG ADD.L A1,D2 ;LIMIT := DSTPTR + BYTECOUNT BRA.S @3 ;GO TO LOOP START @1 EXT.W D1 ;CLEAR HI BYTE OF COUNT @2 MOVE.B (A0)+,(A1)+ ;COPY A BYTE OF DATA DBRA D1,@2 ;LOOP ALL COPY BYTES @3 CMP.L D2,A1 ;IS DSTPTR >= LIMIT ? BHS.S @5 ;YES, WE'RE DONE MOVE.B (A0)+,D1 ;NO, GET OPCODE BPL.S @1 ;0..127 --> COPY 1..128 BYTES NEG.B D1 ;-1..-127 --> FILL 2..128 BYTES BVS.S @3 ;IGNORE $80 FOR BACKWARD COMPAT EXT.W D1 ;CLEAR HI BYTE OF COUNT MOVE.B (A0)+,D0 ;GET FILL DATA BYTE @4 MOVE.B D0,(A1)+ ;COPY IT TO DST DBRA D1,@4 ;LOOP ALL FILL BYTES BRA.S @3 ;THEN GET NEXT OPCODE @5 MOVE.L A0,D0 ;STASH SRCPTR MOVE.L SRCPTR(SP),A0 ;GET VAR ADDR MOVE.L D0,(A0) ;UPDATE VAR SRCPTR MOVE.L DSTPTR(SP),A0 ;GET VAR ADDR MOVE.L A1,(A0) ;UPDATE VAR DSTPTR BRA.S SHARE .END