mac-rom/QuickDraw/getPMData.a

632 lines
21 KiB
Plaintext

;
; File: getPMData.a
;
; Copyright: © 1989-1991 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <5> 10/2/91 DTY Conditionalise last change for TheFuture.
; <4> 10/1/91 KON Check for QDError = AbortPicPlaybackErr after calling
; GetPicData. If an error is detected, abort immediately.
; <3> 8/2/90 gbm Change some identifiers that conflict with existing ones
; <1+> 1/3/90 BAL Fix bug in call to stackspace.
; <1.0> 11/15/89 KON Broken out of pictures.a
;
; To Do:
;
;EASE$$$ READ ONLY COPY of file ÒGetPMData.aÓ
; 1.0 KON 11/15/1989 Broken out of pictures.a
; END EASE MODIFICATION HISTORY
GetDirectPMData PROC EXPORT
IMPORT GetBigPicData, UnPackWords, GetPicData, GetUByte, GetWord
;------------------------------------------------------
;
; PROCEDURE GetDirectPMData(myDst: Ptr; myData: Handle);
;
; HANDLE SIZE IS SET TO ROWBYTES*(BOUNDS.BOTTOM-BOUNDS.TOP) EXTERNALLY
; Handle is locked by caller.
;
;
PARAMSIZE EQU 8
MYDST EQU PARAMSIZE+8-4 ;DST PIXMAP POINTER
MYDATA EQU MYDST-4 ;DST DATA HANDLE
SRCPTR EQU -4 ;VAR POINTER TO SOURCE
DSTPTR EQU SRCPTR-4 ;VAR POINTER TO DST
DSTBUF EQU DSTPTR-4 ;POINTER TO WINDING BUFFER
PACKBUF EQU DSTBUF-4 ;POINTER TO PACKING BUFFER
SAVEDSP EQU PACKBUF-4 ;PRESERVE STACK POINTER
PackHandle equ SAVEDSP-4
VARSIZE EQU PackHandle
LINK A6,#VARSIZE ;MAKE A STACK FRAME
MOVEM.L D3-D7/A2-A4,-(SP) ;SAVE WORK REGISTERS
MOVE.L SP,SAVEDSP(A6) ;PRESERVE STACK POINTER
MOVE.L MYDST(A6),A2 ;POINT TO BITMAP
MOVE.L MYDATA(A6),A0 ;GET DATA HANDLE
;_HLOCK ;LOCK IT DOWN
MOVE.L (A0),A3 ;GET DATA POINTER IN A3
MOVEQ #8,D6 ;GET USEFUL VALUE
MOVE BOUNDS+BOTTOM(A2),D7
SUB BOUNDS+TOP(A2),D7 ;HEIGHT := BOUNDS BOT - TOP
MOVE ROWBYTES(A2),D5 ;GET ROWBYTES
AND #nuRBMask,D5 ;CLEAR OFF FLAG BITS
CMP D6,D5 ;IS NEWROW < 8 ?
BLT NOPACK ;=>YES, DON'T UNPACK
;----------------------------------------------------------------
;
; Determine desired packing scheme:
;
; Type Depth(s) Description
; ---- -------- -----------
; 1 16/32 No packing; Memory image (Handled by GetPMData)
; 2 16 Pixel packing; RunLength by pixel size (PackWords)
; 3 32 Drop pad byte; Save RGB triples
; 4 32 Run packing; RunLength by component by scanline
; >4 32 UNKNOWN; skip data for future compatibility
;
cmp.w #4,packType(a2) ;which packing format?
bgt SkipScans ;unknown, skip over data
beq.s RunPacking ;unpack by cmp by scan
cmp.w #3,packType(a2) ;which packing format?
beq PixelPacking ;run length (16 bit) pixels
MakePadByte
move.w d5,d0 ;get rowbytes
mulu.w d7,d0 ;get rowbytes * height
lsr.l #2,d0 ;get pixel count = byte count / 4
move.l d0,d7 ;make a copy in d7
add.l d0,d0 ;2 * pixel count
add.l d7,d0 ;3 * pixel count
MOVE.L A3,-(SP) ;PUSH DATA POINTER
add.l d7,(sp) ;advance 1/4 way into data buffer
MOVE.L d0,-(SP) ;PUSH BYTECOUNT
JSR GetBigPicData ;READ DATA RGB's
move.l a3,a0 ;point to output buffer
move.l a3,a1 ;
add.l d7,a1 ;advance to RGB triples
@1 clr.b (a0)+ ;clear out alpha channel
move.b (a1)+,(a0)+ ;copy red
move.b (a1)+,(a0)+ ;copy green
move.b (a1)+,(a0)+ ;copy blue
subq.l #1,d7 ;for all output pixels
bhi.s @1
bra done ;clean up and return
RunPacking
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
clr.l packHandle(a6) ;assume there'll be space on stack
_StackSpace ;make sure we have enough...
ext.l d5 ;make rowbytes a long
cmp.l d0,d5 ;...room to allocate one buffer
bge SkipScans ;just consume data and return
;
;Stack space exists for at least one buffer.
;
SUB D5,SP ;GET SIZE OF DSTBUF
MOVE.L SP,DSTBUF(A6) ;POINT TO DSTBUF
moveq #0, d1 ;clear high bytes
MOVE D5,D1 ;GET ROWBYTES
LSR #7,D1 ;GET # OF 128 BYTE RUNS
ADDQ #2,D1 ;ROUND UP
bclr #0,d1 ;guarantee A7 word alignment <BAL 28Apr89>
add.l d5,d1 ;get buffer+padding
_StackSpace ;room for second buffer?
cmp.l d0, d1
blt.s @UseStack
move.l d1,d0
_NewHandle
bne SkipScans
move.l (a0), packbuf(a6)
move.l a0, packHandle(a6)
_HLock
bra.s BufferAllocated
@UseStack
sub d1, sp
move.l sp, packbuf(a6)
BufferAllocated
CMP #4,CMPCOUNT(A2) ;MUST WE CLEAR DEST PAD BYTE?
BEQ.S NOPAD ;NO, SKIP CLEARING
MOVE D5,D1 ;GET DEST ROWBYTES
MULU D7,D1 ;CALC DEST BYTES = ROWBYTES*HEIGHT
LSR.L #2,D1 ;GET LONG CNT OF LONGS
MOVE D1,D2 ;GET LOWORD IN D2
SWAP D1 ;GET HIWORD IN D1
MOVEQ #0,D3 ;USE AS SRC OF ZERO'S
MOVE.L A3,A0 ;POINT AT DEST
BRA.S @CLR
@1 MOVE.L D3,(A0)+
@CLR DBRA D2,@1
DBRA D1,@CLR
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][rrrrr...ggggg...bbbbb] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
; ASSUME: PIXELSIZE = 32
; CMPSIZE = 8
; CMPCOUNT = 3,4
NOPAD ADDQ #4,A3 ;POINT PAST END OF FIRST PIXEL
SUB CMPCOUNT(A2),A3 ;POINT TO FIRST CMP OF FIRST PIXEL
MOVE D5,D4 ;GET FINAL ROWBYTES
LSR #2,D4 ;GET PIXEL CNT **** ASSUMES PIXSIZE = 32
MULU CMPCOUNT(A2),D4 ;GET COMPRESSED ROWBYTES
BRA.S START4 ;GO TO LOOP START
MORE4 CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, GET WORD
JSR GetUByte ;ELSE GET A BYTE INTO D0
BRA.S @2 ;=>AND GO GET DATA
@1 JSR GETWORD ;GET A WORD INTO D0
@2 MOVE.L PACKBUF(A6),-(SP) ;PUSH ADDR OF BUFFER
MOVE.L (SP),SRCPTR(A6) ;PUT IN SRCPTR TOO
MOVE D0,-(SP) ;PUSH BYTECOUNT
JSR GetPicData ;GET PACKED DATA
if TheFuture then ; Build only for TheFuture <5>
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <4>
beq.s Abort
endif ; <5>
MOVE.L DSTBUF(A6),DSTPTR(A6) ;SET DSTPTR TO WINDING BUFFER
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
MOVE D4,-(SP) ;PUSH COMPRESSED ROWBYTES
_UnpackBits ;UNPACK INTO DATA HANDLE
MOVE CMPCOUNT(A2),D3 ;GET CMPCOUNT FOR LOOP <16Jun88 BAL>>
SUBQ #1,D3 ;MAKE IT ZERO BASED
MOVE.L DSTBUF(A6),A0 ;POINT TO UNWINDING BUFFER
MOVE D5,D0 ;GET ROWBYTES
LSR #2,D0 ;GET PIXEL WIDTH @@@@@
SUBQ #1,D0 ;MAKE IT ZERO BASED
@NXTCMP MOVE.L A3,A4 ;PTR INTO THIS CMP OF FIRST PIXEL
ADDQ #1,A3 ;POINT AT NEXT CMP
MOVE D0,D6 ;GET PIXEL CNT
@NXTPIX MOVE.B (A0)+,(A4) ;COPY COMPONENT
ADDQ #4,A4 ;BUMP TO NEXT PIXEL
DBRA D6,@NXTPIX
DBRA D3,@NXTCMP ; <16Jun88 BAL><
SUB CMPCOUNT(A2),A3 ;RESET A3 TO FIRSTCMP, FIRSTPIX
ADD D5,A3 ;BUMP TO NEXT DEST ROW
START4 DBRA D7,MORE4 ;LOOP HEIGHT ROWS
Abort move.l packHandle(a6), d0
beq done ;nil handle: must have used stack buffer
move.l d0, a0
_DisposHandle
BRA DONE ;CONTINUE
PixelPacking
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;SET SIZE OF PACKBUF
SUB D5,SP ;TO 2*ROWBYTES FOR LONG ALIGNMENT
MOVE.L SP,PACKBUF(A6) ;POINT TO PACKBUF
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][DATA] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
MOVE.L A3,DSTPTR(A6) ;INIT DSTPTR
BRA.S START3 ;GO TO LOOP START
MORE3 CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, GET WORD
JSR GetUByte ;ELSE GET A BYTE INTO D0
BRA.S @2 ;=>AND GO GET DATA
@1 JSR GETWORD ;GET A WORD INTO D0
@2 MOVE.L PACKBUF(A6),-(SP) ;PUSH ADDR OF BUFFER
MOVE.L (SP),SRCPTR(A6) ;PUT IN SRCPTR TOO
MOVE D0,-(SP) ;PUSH BYTECOUNT
JSR GetPicData ;GET PACKED DATA
if TheFuture then ; Build only in TheFuture <5>
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <4>
beq.s done
endif ; <5>
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
MOVE D5,-(SP) ;PUSH ROWBYTES
jsr UnPackWords ;UNPACK INTO DATA HANDLE
START3 DBRA D7,MORE3 ;LOOP HEIGHT ROWS
BRA.S DONE ;CONTINUE
SkipScans
;----------------------------------------------------------------
;
; PACKED FORMAT = [BYTECOUNT][DATA] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
move.w d5,d6 ;get rowbytes
mulu.w d7,d6 ;get rowbytes * height
BRA.S START5 ;GO TO LOOP START
MORE5 CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, GET WORD
JSR GetUByte ;ELSE GET A BYTE INTO D0
BRA.S @2 ;=>AND GO GET DATA
@1 JSR GETWORD ;GET A WORD INTO D0
@2 MOVE.L A3,-(SP) ;PUSH DST ADDR
MOVE D0,-(SP) ;PUSH BYTECOUNT
JSR GetPicData ;GET PACKED DATA
if TheFuture then ; DonÕt build until TheFuture is here <5>
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <4>
beq.s done
endif ; <5>
START5 DBRA D7,MORE5 ;LOOP HEIGHT ROWS
move.l a3,a0 ;point to output buffer
@1 clr.b (a0)+ ;clear out buffer
subq.l #1,d6 ;for all output pixels
bhi.s @1
BRA.S DONE ;CONTINUE
;----------------------------------------------------------------
;
;
; ROWBYTES < 8, DON'T USE PACKING
;
NOPACK MULU D7,D5 ;BYTECOUNT := HEIGHT * WIDTH
MOVE.L A3,-(SP) ;PUSH DATA POINTER
MOVE.l D5,-(SP) ;PUSH BYTECOUNT as a long
JSR GetBigPicData ;READ BITMAP DATA BITS
DONE MOVE.L MYDATA(A6),A0 ;GET DATA HANDLE
;_HUnlock ;AND UNLOCK IT
MOVE.L SAVEDSP(A6),SP ;RESTORE STACK POINTER
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'GETDPMDAT' ;UNLINK AND RETURN
GetPMData PROC EXPORT
IF (&TYPE('PATCHMAC2') = 'UNDEFINED') THEN
IMPORT GetPicData, GetUByte, GetWord, GetDirectPMData, GetBigPicData
ENDIF
;------------------------------------------------------
;
; PROCEDURE GetPMData(myDst: Ptr; myData: Handle);
;
; HANDLE SIZE IS SET TO ROWBYTES*(BOUNDS.BOTTOM-BOUNDS.TOP) EXTERNALLY
; Assume handle is locked externally since this routine will be called
; repeatedly during a banding operation.
;
PARAMSIZE EQU 8
MYDST EQU PARAMSIZE+8-4 ;DST PIXMAP POINTER
MYDATA EQU MYDST-4 ;DST DATA HANDLE
SRCPTR EQU -4 ;VAR POINTER TO SOURCE
DSTPTR EQU SRCPTR-4 ;VAR POINTER TO DST
PACKBUF EQU DSTPTR-4 ;POINTER TO PACKING BUFFER
SAVEDSP EQU PACKBUF-4 ;PRESERVE STACK POINTER
VARSIZE EQU SAVEDSP
LINK A6,#VARSIZE ;MAKE A STACK FRAME
MOVEM.L D4-D6/A2-A3,-(SP) ;SAVE WORK REGISTERS
MOVE.L SP,SAVEDSP(A6) ;PRESERVE STACK POINTER
MOVE.L MYDST(A6),A2 ;POINT TO BITMAP
MOVE.L MYDATA(A6),A0 ;GET DATA HANDLE
;_HLOCK ;(assume it is locked already) <16Jun88 BAL>
MOVE.L (A0),A3 ;GET DATA POINTER IN A3
MOVEQ #8,D6 ;GET USEFUL VALUE
MOVE BOUNDS+BOTTOM(A2),D4
SUB BOUNDS+TOP(A2),D4 ;HEIGHT := BOUNDS BOT - TOP
MOVE ROWBYTES(A2),D5 ;GET ROWBYTES
AND #nuRBMask,D5 ;CLEAR OFF FLAG BITS
CMP D6,D5 ;IS NEWROW < 8 ?
BLT.S NOPACK ;=>YES, DON'T UNPACK
tst.w ROWBYTES(A2) ;bitmap data? <29Mar89 BAL>
bpl.s UNPACK ;yes, must unpack <29Mar89 BAL>
cmp.w #16,pixelType(a2) ;DIRECT DATA? <22Jan89 BAL>
bne.s UNPACK ;NO, UNPACK IT <22Jan89 BAL>
CMP #1,PACKTYPE(A2) ;IS IT PACKED DIRECT DATA? <16Jun88 BAL>
beq.s NOPACK ;NO, DONT UNPackBits <16Jun88 BAL>
MOVEM.L (SP)+,D4-D6/A2-A3 ;RESTORE REGISTERS
UNLK A6 ;UNLINK AND RETURN
JMP GetDirectPMData ;let someone else do the work
UNPACK
;----------------------------------------------------------------
;
; MAKE SURE THE STACK IS ON A LONGWORD BOUNDARY (FOR FAST BUFFERS)
;
MOVE.L SP,D1 ;GET THE STACK POINTER
AND.B #$FC,D1 ;FORCE LONG ALIGNMENT
MOVE.L D1,SP ;USE IT
;----------------------------------------------------------------
;
; ALLOCATE PACKBUF ON THE STACK
;
SUB D5,SP ;SET SIZE OF PACKBUF
SUB D5,SP ;TO 2*ROWBYTES FOR LONG ALIGNMENT
MOVE.L SP,PACKBUF(A6) ;POINT TO PACKBUF
;----------------------------------------------------------------
;
; ROWBYTES >= 8, READ THE PACKED BIT/PIXMAP FROM THE PICTURE
;
; PACKED FORMAT = [BYTECOUNT][DATA] FOR EACH SCANLINE
;
; IF ROWBYTES > 250 THEN BYTECOUNT IS A WORD, ELSE IT IS A BYTE
;
MOVE.L A3,DSTPTR(A6) ;INIT DSTPTR
BRA.S START1 ;GO TO LOOP START
MORE1 CMP #250,D5 ;IS ROWBYTES > 250?
BGT.S @1 ;=>YES, GET WORD
JSR GetUByte ;ELSE GET A BYTE INTO D0
BRA.S @2 ;=>AND GO GET DATA
@1 JSR GETWORD ;GET A WORD INTO D0
@2 MOVE.L PACKBUF(A6),-(SP) ;PUSH ADDR OF BUFFER
MOVE.L (SP),SRCPTR(A6) ;PUT IN SRCPTR TOO
MOVE D0,-(SP) ;PUSH BYTECOUNT
JSR GetPicData ;GET PACKED DATA
if TheFuture then ; Build only for TheFuture <5>
cmp.w #AbortPicPlayBackErr,qdErr ;abort if our special error <4>
beq.s done
endif
PEA SRCPTR(A6) ;PUSH VAR SRCPTR
PEA DSTPTR(A6) ;PUSH VAR DSTPTR
MOVE D5,-(SP) ;PUSH ROWBYTES
_UnpackBits ;UNPACK INTO DATA HANDLE
START1 DBRA D4,MORE1 ;LOOP HEIGHT ROWS
BRA.S DONE ;CONTINUE
;
; ROWBYTES < 8, DON'T USE PACKING
;
NOPACK MULU D4,D5 ;BYTECOUNT := HEIGHT * WIDTH
MOVE.L A3,-(SP) ;PUSH DATA POINTER
MOVE.L D5,-(SP) ;PUSH BYTECOUNT
JSR GetBigPicData ;READ BITMAP DATA BITS
DONE MOVE.L MYDATA(A6),A0 ;GET DATA HANDLE
;_HUnlock ;AND UNLOCK IT (not this time) <16Jun88 BAL>
MOVE.L SAVEDSP(A6),SP ;RESTORE STACK POINTER
MOVEM.L (SP)+,D4-D6/A2-A3 ;RESTORE WORK REGISTERS
UNLINK PARAMSIZE,'GETPMDAT' ;UNLINK AND RETURN
GetBigPicData PROC EXPORT ;17Jun88 BAL
IMPORT GetPicData
;------------------------------------------------------------------
;
; FUNCTION GetBigPicData(dataPtr: QDPtr; byteCount: LONG);
;
; This is the same as GetPicData except the byteCount is a long
;
partSize EQU $4000
partShift EQU $E
MOVEM.L D7/A3-A4,-(SP) ;save a couple of registers
MOVE.L 20(SP),A3 ;get the pointer to data
MOVE.L 16(SP),A4 ;get data length
MOVE.L A4,D7 ;copy pointer
MOVEQ #partShift,D0 ;get a constant for the upcoming shift
LSR.L D0,D7 ;find the number of 16K "pages"
BEQ.S LeftOvers ;no, so do the remaining part of the picture
@1
MOVE.L A3,-(SP) ;PUSH DATA POINTER
MOVE #partSize,-(SP) ;move 16K of data
JSR GetPicData ;AND CALL GET PROC
ADD.W #partSize,A3 ;move data start pointer up
SUB.W #partSize,A4 ;subtract for remainder later
SUBQ.L #1,D7 ;decrease the number of pages
BNE.S @1 ;loop for each page
LeftOvers
MOVE.L A3,-(SP) ;PUSH DATA POINTER
MOVE.W A4,-(SP) ;move remainder
JSR GetPicData ;AND CALL GET PROC
MOVEM.L (SP)+,D7/A3-A4 ;restore registers
RTD_ 8 ;STRIP PARAMS AND RETURN
ENDPROC
IF hasCQD THEN
; PackWords and UnPackWords linked in from somewhere else.
ELSE
PackWords PROC EXPORT
EXPORT UnpackWords
;---------------------------------------------------------------------
;
; PROCEDURE PackWords(VAR srcPtr,dstPtr: Ptr; srcBytes: INTEGER);
;
; Packs one scanline of data, compressing equal words.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are shared with UnpackWords
;
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
MOVEM.L D3-D4/A2,-(SP) ;SAVE REGS
MOVE #128,D4 ;GET USEFUL VALUE
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR
MOVE.L (A0),A0 ;GET SRCPTR ITSELF
MOVE.L DSTPTR+12(SP),A1 ;GET VAR ADDR
MOVE.L (A1),A1 ;GET DSTPTR ITSELF
MOVE SRCBYTES+12(SP),D3 ;GET SRCBYTES
lsr.w #1,d3 ;make in to word count <BAL 25Mar89>
SUB #1,D3 ;INIT SRC DBRA COUNT
BLT DONE ;QUIT IF SRCBYTES <= 0
GoStart MOVE.w (A0)+,D0 ;GET FIRST word OF SRC <BAL 25Mar89>
BRA.S START ;AND GO TO LOOP START
FILLOP MOVE.w -2(A0),D0 ;PUT SRCDATA IN DO <BAL 25Mar89>
SUB A0,D2 ;COMPUTE FILLOP
asr.w #1,d2 ;make into word cnt
ADD D2,D3 ;UPDATE wordCOUNT
ADD #1,D2 ;-2..-128 -> -1..-127
MOVE.B D2,(A2) ;STORE FILLOP
START MOVEQ #127,D1 ;GET MAX wordCOUNT-1 FOR A RUN
CMP D4,D3 ;THAT MANY words LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
CMP.w (A0),D0 ;IS NEXT SRC THE SAME ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, USE COPY LOOP
CMP.w 2(A0),D0 ;THREE IN A ROW ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, USE COPY LOOP
BRA.S DOFILL ;YES, USE FILL LOOP
NXTCOPY MOVE.w (A0)+,D0 ;GET word OF SRC <BAL 25Mar89>
CMP.w (A0),D0 ;IS THE NEXT THE SAME ? <BAL 25Mar89>
BNE.S DOCOPY ;NO, CONTINUE
CMP.w 2(A0),D0 ;THREE IN A ROW ? <BAL 25Mar89>
BEQ.S COPYOP ;YES, END OF COPY RUN
DOCOPY MOVE.w D0,(A1)+ ;COPY DATA TO DST <BAL 25Mar89>
DBRA D1,NXTCOPY ;AND LOOP FOR MORE
ENDCOPY SUB A0,D2 ;COMPUTE COPYOP
NEG D2 ;NEGATE ONLY
asr.w #1,d2 ;make word count <BAL 25Mar89>
MOVE.B D2,(A2) ;INSTALL COPYOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
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
asr.w #1,d2 ;make word count <BAL 25Mar89>
ADD D2,D3 ;UPDATE BYTECOUNT
NOT D2 ;NEGATE AND SUBTRACT 1
MOVE.B D2,(A2) ;STORE COPYOP
MOVEQ #127,D1 ;GET MAX BYTECOUNT FOR A RUN
CMP D4,D3 ;THAT MANY BYTES LEFT?
BGE.S @1 ;=>YES, DO CHUNK OF 128
MOVE D3,D1 ;ELSE DO REMAINING BYTES
@1 MOVE.L A0,D2 ;REMEMBER SRCSTART
MOVE.L A1,A2 ;REMEMBER OPLOC
CLR.B (A1)+ ;RESERVE ROOM FOR OPCODE
DOFILL MOVE.w D0,(A1)+ ;COPY THE DATA word <BAL 25Mar89>
NXTFILL CMP.w (A0)+,D0 ;IS NEXT word THE SAME ? <BAL 25Mar89>
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 #2,A0 ;BACK UP FOR LAST word COMPARED <BAL 25Mar89>
SUB A0,D2 ;COMPUTE FILLOP
asr.w #1,d2 ;make word count <BAL 25Mar89>
MOVE.B D2,(A2) ;INSTALL FILLOP
SUB D4,D3 ;SUBTRACT NEXT CHUNK
BPL.S GoStart ;=>MORE TO DO, CONTINUE
DONE CLR.L D0 ;GET READY FOR WORD
MOVE SRCBYTES+12(SP),D0 ;GET SRCBYTES
MOVE.L SRCPTR+12(SP),A0 ;GET VAR ADDR OF SRCPTR
ADD.L D0,(A0) ;BUMP SRCPTR
MOVE.L DSTPTR+12(SP),A2 ;GET VAR ADDR OF DSTPTR
MOVE.L A1,(A2) ;UPDATE DSTPTR
MOVEM.L (SP)+,D3-D4/A2 ;RESTORE REGS
SHARE MOVE.L (SP)+,A0 ;POP RETURN ADDR
ADD #PARAMSIZE,SP ;STRIP PARAMS
JMP (A0) ;AND RETURN
;--------------------------------------------------------
;
; PROCEDURE UnpackWords(VAR srcPtr,dstPtr: Ptr; dstBytes: INTEGER);
;
; Unpacks one scanline of data, as compressed by PackWords.
; Returns updated srcPtr and dstPtr.
;
; Equates for parameters are the same as PackWords!
;
UnpackWords
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 word OF DATA <BAL 25Mar89>
MOVE.b (A0)+,(A1)+ ;COPY A word OF DATA <KON 6Sept89>
DBRA D1,@2 ;LOOP ALL COPY words
@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 <BAL 25Mar89>
lsl #8,d0 ;we could be on an odd address...<KON 6Sept89>
or.b (a0)+,d0 ;... so move two bytes <KON 6Sept89>
@4 MOVE.w D0,(A1)+ ;COPY IT TO DST <BAL 25Mar89>
DBRA D1,@4 ;LOOP ALL FILL words
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
ENDPROC
;-------------------- END OF Pack and UnPack Words ----------------
ENDIF ;hasCQD