mirror of
https://github.com/elliotnunn/boot3.git
synced 2025-01-02 20:29:19 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
1928 lines
60 KiB
Plaintext
1928 lines
60 KiB
Plaintext
;
|
|
; File: DrawPicture32Patch.a
|
|
;
|
|
; Contains: This patch gets loaded on Classic QD machines
|
|
;
|
|
; Written by: Konstantin Othmer
|
|
;
|
|
; Copyright: © 1987-1990 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <12> 3/23/91 KON csd, WRKSHT#SAH-QD-58: ReduceD3D4 would hang because MapRatio
|
|
; would return a zero result. I removed calls to MapRatio (since
|
|
; ReduceD3D4 does the same work) and changed ReduceD3D4 so it
|
|
; won't hang.
|
|
; <11> 1/14/91 KON Reduce Numer and Denom by GCD when drawing a picture. These
|
|
; overflow on higher DPI devices. [CEL]
|
|
; <10> 11/7/90 KON Fix display of 16-bit pixmaps (were drawn as all black). [smc]
|
|
; <9> 9/21/90 KON Added check for PICT2 header so we use the resolution adjusted
|
|
; rectangle for the header if the picture was created by
|
|
; openCPicture.
|
|
; <8> 9/17/90 dba Fix loop case for unpacking bits when the rectangle has a 0
|
|
; height. This was crashing while printing in Claris applications.
|
|
; <7> 9/11/90 KON Remove benign redefinition of pixmapTooDeepErr.
|
|
; <6> 8/2/90 gbm fix more warnings
|
|
; <5> 7/20/90 gbm get rid of excess equates
|
|
; <4> 4/4/90 KON Make into a linked patch
|
|
; <3> 3/29/90 KON Broke traps which load on all B&W machines to a new file
|
|
; AllB&WQDPatch.a. This makes the disk footprint much smaller.
|
|
; <2> 3/16/90 KON Add gWorld calls to PLUS, SE, and portable.
|
|
; <1.5> 12/4/89 KON Uses GrafTypes.m.a for include rather than ColorEqu.a.
|
|
; <1.4> 11/15/89 KON Now includes common file GetPMData.a and installs GetPMData as
|
|
; Trap $ABC4.
|
|
; <1.3> 11/9/89 KON Patch BitMapRgn only on Plus and SE
|
|
; <1.2> 11/7/89 KON Fixed font name/ID binding, added ptch for open picture and
|
|
; close picture
|
|
; <1.1> 11/7/89 BAL Added Font Name/ID binding, draw picture now works in low memory
|
|
; situations
|
|
; <1.0> 10/16/89 CCH Adding to EASE.
|
|
; 8/25/89 KON Added support for 16 & 32 bit picts for plus and SE
|
|
; PMAB270> 9/13/87 FJL Patch DrawPicture to first check for valid picture handle and
|
|
; pointer, then do GetState, make it non-purgeable, and SetState
|
|
; on return. At the request of Sheila, Phil and Scott.
|
|
; <PMA207> 7/16/87 EHB If device color table found, fill in pixel values
|
|
; <PMA157> 3/30/87 DBG Fixed bug where color table was freed even if there wasn't one.
|
|
; <S072> 2/27/87 DBG Added support for interpolated colors
|
|
; <S051> 2/19/87 DBG Fixed bug in interpretation of color table
|
|
;
|
|
|
|
|
|
;INITFILE EQU 0 ;set to 1 for standalone install, 0 for ptchInstall
|
|
;withFonts EQU 1 ;set to 1 to build with font name/ID binding
|
|
;wholeErrors EQU 1
|
|
|
|
|
|
;; INCLUDE 'SysErr.a'
|
|
; INCLUDE 'Traps.a'
|
|
; INCLUDE 'QuickEqu.a'
|
|
; INCLUDE 'SysEqu.a'
|
|
; INCLUDE 'GrafTypes.m.a'
|
|
; INCLUDE 'LinkedPatchMacros.a'
|
|
|
|
; RomBinds were here
|
|
|
|
PStdBits_SE_Portable EQU $0E00+(4*$EB)
|
|
PStdBits_Plus EQU $0C00+(4*$EB)
|
|
|
|
PStdGetPic_SE_Portable EQU $0E00+(4*$EE)
|
|
PStdGetPic_Plus EQU $0C00+(4*$EE)
|
|
|
|
IF (&TYPE('onMac') = 'UNDEFINED') THEN
|
|
onMac EQU 0
|
|
ENDIF
|
|
IF (&TYPE('onMacPP') = 'UNDEFINED') THEN
|
|
onMacPP EQU 0
|
|
ENDIF
|
|
noROM EQU 0
|
|
|
|
|
|
|
|
StdOpcodeProc PROC EXPORT
|
|
IMPORT GETWORD, GetLong,GetPicdata
|
|
;------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE StdOpcode(fromRect,toRect: Rect; opcode,version: INTEGER);
|
|
;
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (StdOpcode) (StdOpcode)
|
|
;
|
|
; GETS CALLED FOR OPCODE VALUES $0100-$FFFF
|
|
;
|
|
; OPCODE: $0100-$01FF 2 BYTES DATA
|
|
; $0200-$02FF 4 BYTES DATA
|
|
; ...
|
|
; $7F00-$7FFF 254 BYTES DATA
|
|
; $8000-$80FF 0 BYTES DATA
|
|
; $8100-$FFFF 4 BYTES SIZE + SIZE BYTES DATA
|
|
;
|
|
; THIS PROCEDURE READS THE OPCODE'S DATA AND IGNORES IT unless it's the header
|
|
; from a PICT 2 created by OpenCPicture. <20Sept90 KON>
|
|
;
|
|
;--------------------------------------------
|
|
;
|
|
; OFFSETS WITHIN A PICTURE PLAY STATE RECORD:
|
|
;
|
|
THERECT EQU 0 ;RECT
|
|
PENLOC EQU THERECT+8 ;POINT
|
|
TEXTLOC EQU PENLOC+4 ;POINT
|
|
OVALSIZES EQU TEXTLOC+4 ;POINT
|
|
FROMRECT EQU OVALSIZES+4 ;RECT
|
|
TORECT EQU FROMRECT+8 ;RECT
|
|
NUMER EQU TORECT+8 ;POINT
|
|
DENOM EQU NUMER+4 ;POINT
|
|
THECLIP EQU DENOM+4 ;RGNHANDLE
|
|
USERCLIP EQU THECLIP+4 ;RGNHANDLE
|
|
PLAYVERSION EQU USERCLIP+4 ;PICTURE VERSION
|
|
TXHFRAC EQU PLAYVERSION+2 ;FRACTIONAL TEXT POSITION
|
|
NEWHFRAC EQU TXHFRAC+2 ;UPDATED FRACTION RECIEVED
|
|
TEMPPIXPAT EQU NEWHFRAC+2 ;PIXPAT FOR PLAYING NEW PICS IN OLD PORTS
|
|
FontMappingTbl EQU TEMPPIXPAT+4 ;Handle to array of old,new font id pairs
|
|
PSreserve1 EQU FontMappingTbl+4 ;reserved
|
|
PSreserve2 EQU PSreserve1+4 ;reserved
|
|
PLAYREC EQU PSreserve2+4 ;TOTAL SIZE
|
|
|
|
;------------------------------------------------------
|
|
;
|
|
; New offsets in a PICT2 header record:
|
|
;
|
|
hdrVersion EQU 0 ;Word (=-2)
|
|
hdrReserved EQU hdrVersion+2 ;Word
|
|
hdrHRes EQU hdrReserved+2 ;Fixed
|
|
hdrVRes EQU hdrHRes+4 ;Fixed
|
|
hdrSrcRect EQU hdrVRes+4 ;Rect
|
|
hdrReserved2 EQU hdrSrcRect+8 ;Long
|
|
picHdrSize EQU hdrReserved2+4 ;size of a PICT2 header record
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE StdOpcode(fromRect,toRect: Rect; opcode,version: INTEGER);
|
|
;
|
|
; GETS CALLED FOR OPCODE VALUES $0100-$FFFF
|
|
;
|
|
; OPCODE: $0100-$01FF 2 BYTES DATA
|
|
; $0200-$02FF 4 BYTES DATA
|
|
; ...
|
|
; $7F00-$7FFF 254 BYTES DATA
|
|
; $8000-$80FF 0 BYTES DATA
|
|
; $8100-$FFFF 4 BYTES SIZE + SIZE BYTES DATA
|
|
;
|
|
; THIS PROCEDURE READS THE OPCODE'S DATA AND IGNORES IT
|
|
;
|
|
; A6 OFFSETS OF PARAMS AFTER LINK:
|
|
;
|
|
PARAMSIZE EQU 12
|
|
pFROMRECT EQU PARAMSIZE+8-4 ;LONG
|
|
pTORECT EQU pFROMRECT-4 ;LONG
|
|
OPCODE EQU pTORECT-2 ;WORD
|
|
VERSION EQU OPCODE-2 ;WORD
|
|
|
|
LINK A6,#0 ;NO LOCAL VARS
|
|
MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS
|
|
MOVE.L #256,D6 ;GET USEFUL NUMBER
|
|
SUB.L D6,SP ;ALLOCATE STACK BUFFER
|
|
|
|
MOVE OPCODE(A6),D0 ;GET THE OPCODE
|
|
BMI.S GETSIZE ;=>OP CONTAINS SIZE
|
|
LSR #8,D0 ;GET SIZE/2 IN LOW NIBBLE
|
|
ADD D0,D0 ;CALC SIZE
|
|
EXT.L D0 ;MAKE IT LONG
|
|
BRA.S SHARE ;=>USE COMMON CODE
|
|
GETSIZE AND #$7F00,D0 ;MASK THE OPCODE
|
|
BEQ.S DONE ;=>NO DATA BYTES
|
|
JSR GETLONG ;READ IN SIZE
|
|
SHARE MOVE.L D0,D7 ;SAVE WHOLE SIZE
|
|
NXTCHNK MOVE D6,D0 ;ASSUME SIZE >= 256
|
|
CMP.L D6,D7 ;IS SIZE >= 256?
|
|
BGE.S SIZEOK ;=>YES, SKIP 256 BYTES
|
|
MOVE D7,D0 ;ELSE SKIP REMAINING BYTES
|
|
SIZEOK MOVE.L SP,-(SP) ;PUSH BUFFER POINTER
|
|
MOVE D0,-(SP) ;PUSH BYTECOUNT
|
|
JSR GETPICDATA ;READ DATA INTO BUFFER
|
|
SUB.L D6,D7 ;SUBTRACT BUFSIZE FROM COUNT
|
|
BGT.S NXTCHNK ;=>GO SKIP NEXT CHUNK
|
|
|
|
;
|
|
; This stuff is taken from Pictures.a <20Sept90 KON>
|
|
;
|
|
cmp.w #ngHeaderOp,OPCODE(a6) ;pict2 header opcode? <18Jan90 KON>
|
|
bne.s done ;not a pict2 header opcode <18Jan90 KON>
|
|
cmp.w #$fffe,(sp) ;is it version -2 header? <18Jan90 KON>
|
|
bne.s done ;<27nov89 KON> <18Jan90 KON>
|
|
move.l pFromRect(a6),a1 ;point to playstate's FromRect
|
|
lea hdrSrcRect(sp),a0 ;point to sourceRect stored in header record
|
|
MOVE RIGHT(A0),D0
|
|
SUB LEFT(A0),D0 ;CALC SRC WIDTH
|
|
MOVE D0,DENOM+H-FromRect(A1) ;DENOM.H := SRC WIDTH
|
|
MOVE BOTTOM(A0),D0
|
|
SUB TOP(A0),D0 ;CALC SRC HEIGHT
|
|
MOVE D0,DENOM+V-FromRect(A1) ;DENOM.V := SRC HEIGHT
|
|
MOVE.L (A0)+,(A1)+
|
|
MOVE.L (A0)+,(A1)+ ;FROMRECT := PICFRAME
|
|
;
|
|
; end <20Sept90 KON>
|
|
;
|
|
DONE ADD.L D6,SP ;STRIP BUFFER
|
|
MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS
|
|
UNLINK PARAMSIZE,'STDPICPR' ;destroys condition codes
|
|
|
|
ENDPROC
|
|
|
|
;=========================================================================================
|
|
;=========================================================================================
|
|
;
|
|
; Add routines to calculate to reduce numer and denom by GCD
|
|
;
|
|
; These are called by DrawPicture and PicItem1
|
|
;
|
|
;=========================================================================================
|
|
;=========================================================================================
|
|
CalcGCD PROC EXPORT
|
|
; Routine returns GCD( d0, d1 ) using Euclidean method
|
|
; On Entry: D0 and D1 contain word size values to reduce
|
|
; On Exit: D0 and D1 both contain GCD
|
|
;
|
|
cmp.l d0,d1 ;while d0 != d1 (unsigned word compare)
|
|
beq.s @FoundGCD
|
|
bgt.s @D1isBigger ; if( d1 < d0 )
|
|
exg d0,d1 ; swap( d1, d0 )
|
|
@D1isBigger
|
|
sub d0,d1 ; d1 = d1 - d0
|
|
bra.s CalcGCD ;end while
|
|
@FoundGCD
|
|
rts ;d0 and d1 contain GCD
|
|
ENDPROC
|
|
|
|
ReduceD3D4 PROC EXPORT
|
|
IMPORT CalcGCD
|
|
; Routine returns ReduceD3D4( d3, d4 ) reduces d3.w and d4.w by GCD for
|
|
; both the low and high words
|
|
;
|
|
; On Entry: D3 and D4 contain two word size values to reduce
|
|
; On Exit: D3 and D4 contain reduced values
|
|
;
|
|
;
|
|
; Divide Numer and Denom for width and height by GCD to prevent overflow.
|
|
;
|
|
moveq #0,d0 ;make sure high word is zero for next 2 divides
|
|
move.l d0,d1 ;CalcGCD exchanges regs, so both need to be cleared
|
|
move.w d3,d0 ;D0 has denom.v, d1 has numer.v
|
|
beq.s @Done ;abort if zero.
|
|
move.w d4,d1 ;D0 has denom.v, d1 has numer.v
|
|
beq.s @Done ;abort if zero.
|
|
jsr CalcGCD ;returns GCD in d0
|
|
move.w d3,d1 ;D0 has denom.v, d1 has numer.v
|
|
divu.w d0,d1 ;dividing by GCD should never leave remainder
|
|
move.w d1,d3 ;save reduced numer.v
|
|
move.w d4,d1 ;D0 has denom.v, d1 has numer.v
|
|
divu.w d0,d1
|
|
move.w d1,d4 ;save reduced denom.v
|
|
;
|
|
; Now do width: Could have different scale factor than height did
|
|
;
|
|
swap d3 ;operate on high word
|
|
swap d4
|
|
move.w d3,d0 ;D0 has denom.h, d1 has numer.h
|
|
beq.s @DoneSwap ;abort if zero.
|
|
move.w d4,d1 ;D0 has denom.h, d1 has numer.h
|
|
beq.s @DoneSwap ;abort if zero.
|
|
jsr CalcGCD ;returns GCD in d0
|
|
move.w d3,d1 ;D0 has denom.h, d1 has numer.h
|
|
divu.w d0,d1 ;dividing by GCD should never leave remainder
|
|
move.w d1,d3 ;save reduced numer.h
|
|
move.w d4,d1 ;D0 has denom.h, d1 has numer.h
|
|
divu.w d0,d1
|
|
move.w d1,d4 ;save reduced denom.h
|
|
@DoneSwap
|
|
swap d3 ;put things back
|
|
swap d4
|
|
@Done
|
|
rts ;all done
|
|
;
|
|
; End <KON 7/1/91>
|
|
;
|
|
ENDPROC
|
|
|
|
INCLUDE 'DrawPicturePlusSE.a'
|
|
INCLUDE 'DrawPicturePortable.a'
|
|
|
|
;---------- broke out local procs from picItem1 for code sharing ------------
|
|
|
|
|
|
GETSBYTE FUNC EXPORT
|
|
IMPORT GetPicData
|
|
|
|
;------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO GET A SIGNED BYTE INTO D0 FROM PICTURE
|
|
;
|
|
CLR.B -(SP) ;ALLOCATE TEMP
|
|
MOVE.L SP,-(SP) ;PUSH ADDR OF TEMP
|
|
MOVE #1,-(SP) ;PUSH BYTECOUNT
|
|
JSR GetPicData ;GET DATA FROM THEPIC
|
|
MOVE.B (SP)+,D0 ;POP RESULT
|
|
EXT.W D0 ;SIGN EXTEND TO WORD
|
|
RTS
|
|
|
|
|
|
;-----------------End of breaking out local procs-----------------------------
|
|
|
|
|
|
GETLONG FUNC EXPORT
|
|
IMPORT GetPicData
|
|
;----------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO GET A LONG FROM PICTURE INTO D0
|
|
;
|
|
CLR.L -(SP) ;ALLOCATE TEMP
|
|
MOVE.L SP,-(SP) ;PUSH ADDR OF TEMP
|
|
MOVE #4,-(SP) ;PUSH BYTECOUNT
|
|
JSR GetPicData ;GET DATA FROM THEPIC
|
|
MOVE.L (SP)+,D0 ;RETURN ANSWER IN D0
|
|
RTS
|
|
|
|
|
|
MAPMODE FUNC EXPORT
|
|
;----------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO MAP COLOR QUICKDRAW MODES TO OLD MODES
|
|
;
|
|
CMP.W #$1F,D0 ;OLD MODE, OR UNKNOWN?
|
|
BLS.S DONEMODE ;SKIP OUT
|
|
CMP.W #$2F,D0 ;WITHIN CORRECT RANGE?
|
|
BLS.S @MAPIT ;SKIP IF SO
|
|
CMP.W #$32,D0 ;HILITE?
|
|
BEQ.S @MAPIT ;SKIP IF SO
|
|
CMP.W #$3A,D0 ;HILITE?
|
|
BNE.S DONEMODE ;NO, PASS THROUGH
|
|
@MAPIT
|
|
AND.W #7,D0 ;EXTRACT LOW 3 BITS
|
|
MOVE.B arithMode(D0.W),D0 ;GET EQUIVALENT MODE
|
|
DONEMODE
|
|
RTS ;QUIT
|
|
|
|
; [This table extracted from utils.a]
|
|
arithMode
|
|
; hilite
|
|
;avg addPin addOver subPin trans max subOver min
|
|
DC.B srcCopy, srcBic, srcXor, srcOr, srcOr, srcBic, srcXor, srcOr
|
|
|
|
|
|
SkipPicData PROC EXPORT
|
|
IMPORT GETPICDATA
|
|
;----------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO SKIP D0.L BYTES IN THE PICTURE
|
|
;
|
|
MOVEM.L D6/D7,-(SP) ;SAVE WORK REGISTERS
|
|
MOVE.L #256,D6 ;GET USEFUL NUMBER
|
|
SUB.L D6,SP ;ALLOCATE STACK BUFFER
|
|
|
|
MOVE.L D0,D7 ;SAVE WHOLE SIZE
|
|
BEQ.S IGDONE ;=>NO DATA, JUST RETURN
|
|
NXTCHNK MOVE D6,D0 ;ASSUME SIZE >= 256
|
|
CMP.L D6,D7 ;IS SIZE >= 256?
|
|
BGE.S IGSIZEOK ;=>YES, SKIP 256 BYTES
|
|
MOVE D7,D0 ;ELSE SKIP REMAINING BYTES
|
|
IGSIZEOK MOVE.L SP,-(SP) ;PUSH BUFFER POINTER
|
|
MOVE D0,-(SP) ;PUSH BYTECOUNT
|
|
JSR GETPICDATA ;READ DATA INTO BUFFER
|
|
SUB.L D6,D7 ;SUBTRACT BUFSIZE FROM COUNT
|
|
BGT.S NXTCHNK ;=>GO SKIP NEXT CHUNK
|
|
|
|
IGDONE ADD.L D6,SP ;STRIP BUFFER
|
|
MOVEM.L (SP)+,D6/D7 ;RESTORE WORK REGISTERS
|
|
RTS
|
|
|
|
|
|
GetPicTable PROC EXPORT
|
|
IMPORT GetPicData,GETLONG
|
|
;------------------------------------------------------
|
|
;
|
|
; PROCEDURE GetPicTable(CTabHandle);
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (GetPicTable) (GetPicTable)
|
|
;
|
|
;
|
|
JSR GETLONG ;GET SEED INTO D0
|
|
MOVE.L D0,-(SP) ;SAVE SEED
|
|
JSR GETLONG ;GET TRANSINDEX, SIZE INTO D0
|
|
MOVE.L D0,-(SP) ;SAVE TRANSINDEX,SIZE
|
|
MOVE D0,D2 ;GET SIZE INTO D2
|
|
ADDQ #1,D2 ;MAKE IT ONE BASED
|
|
MULU #CTENTRYSIZE,D2 ;GET SIZE OF TABLE
|
|
MOVE.L D2,D0 ;SAVE SIZE OF TABLE
|
|
ADD #CTREC,D0 ;ADD SIZE OF HEADER
|
|
MOVE.L 12(SP),A0 ;GET HANDLE
|
|
_SETHANDLESIZE ;RESIZE IT
|
|
BEQ.S @1 ;Skip if OK
|
|
MOVEQ #25, D0 ;Sayonara, sweetheart
|
|
_SysError
|
|
; ??? Should really be able to do better than this. Maybe if this fails,
|
|
; we should do an _EmptyHandle as a signal to the caller that we flopped???
|
|
@1
|
|
_HLock ;LOCK IT
|
|
MOVE.L (A0),A0 ;POINT TO CTAB
|
|
MOVE.L (SP)+,D0 ;GET TRANSINDEX,SIZE
|
|
MOVE.L (SP)+,(A0)+ ;COPY SEED TO CTAB
|
|
MOVE.L D0,(A0)+ ;COPY TRANSINDEX,SIZE
|
|
MOVE.L A0,-(SP) ;PUSH DST POINTER
|
|
MOVE D2,-(SP) ;PUSH BYTECOUNT
|
|
JSR GETPICDATA ;READ DATA FROM PICTURE
|
|
MOVE.L 4(SP),A0 ;GET HANDLE
|
|
_HUnlock ;UNLOCK IT
|
|
|
|
MOVE.L (A0),A0 ;point to table <PMA207>
|
|
TST transIndex(A0) ;device color table? <PMA207>
|
|
BPL.S @done ;=>no, just return <PMA207>
|
|
MOVE ctSize(A0),D0 ;get size of table <PMA207>
|
|
MOVEQ #0,D1 ;get first pixel value <PMA207>
|
|
ADDQ #ctRec,A0 ;point to first entry <PMA207>
|
|
@2 MOVE D1,(A0) ;stuff a pixel <PMA207>
|
|
ADDQ #ctEntrySize,A0 ;bump to next entry <PMA207>
|
|
ADDQ #1,D1 ;bump to next pixel value <PMA207>
|
|
DBRA D0,@2 ;repeat for all entries <PMA207>
|
|
|
|
@done MOVE.L (SP)+,(SP) ;STRIP PARAM
|
|
RTS ;AND RETURN
|
|
|
|
;
|
|
; GetPicData, getubyte, getword also appear in DrawPicture32Patch.a. They should
|
|
; only appear in one place xxxxx
|
|
;
|
|
|
|
GetPicData PROC EXPORT
|
|
;------------------------------------------------------------------
|
|
;
|
|
; PROCEDURE GetPicData(dataPtr: QDPtr; byteCount: INTEGER);
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (GetPicData) (GetPicData)
|
|
;
|
|
;
|
|
MOVE.L 6(SP),-(SP) ;COPY DATAPTR
|
|
MOVE.W 8(SP),-(SP) ;COPY BYTECOUNT
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
|
MOVE.L THEPORT(A0),A0 ;GET CURRENT GRAFPORT
|
|
MOVE.L GRAFPROCS(A0),D0 ;IS GRAFPROCS NIL ?
|
|
|
|
MOVE.L PStdGetPic_SE_Portable,A0 ;get piece of trap table (SE or Portable)
|
|
ENTRY GetPicDataStdGetPic
|
|
GetPicDataStdGetPic equ * - 2 ;fix the word in the above instruction on Plus
|
|
|
|
BEQ.S USESTD ;yes, use std proc
|
|
MOVE.L D0,A0
|
|
MOVE.L GETPICPROC(A0),A0 ;NO, GET GET PROC PTR
|
|
USESTD JSR (A0) ;AND CALL IT
|
|
MOVEQ #0,D0 ;CLEAR HIGH WORD
|
|
MOVE.W 4(SP),D0 ;GET BYTECOUNT
|
|
MOVE.L GRAFGLOBALS(A5),A0 ;POINT TO QUICKDRAW GLOBALS
|
|
ADD.L D0,PLAYINDEX(A0) ;BUMP PLAYINDEX
|
|
MOVE.L (SP)+,A0 ;RETURN ADDRESS
|
|
ADDQ #6,SP ;STRIP PARAMS
|
|
JMP (A0) ;RETURN
|
|
|
|
ENDPROC
|
|
|
|
FixStdGetPicInGetPicData INSTALLPROC (Plus)
|
|
IMPORT GetPicDataStdGetPic
|
|
|
|
lea GetPicDataStdGetPic,a0 ;point at above code
|
|
move.w #PStdGetPic_Plus,(a0) ;jam in the correct vector for the Mac. Plus
|
|
rts
|
|
|
|
ENDPROC
|
|
|
|
GETUBYTE FUNC EXPORT
|
|
IMPORT GetPicData
|
|
;------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO GET AN UNSIGNED BYTE INTO D0 FROM PICTURE
|
|
;
|
|
CLR.B -(SP) ;ALLOCATE TEMP
|
|
MOVE.L SP,-(SP) ;PUSH ADDR OF TEMP
|
|
MOVE #1,-(SP) ;PUSH BYTECOUNT
|
|
JSR GetPicData ;GET DATA FROM THEPIC
|
|
CLR D0 ;GET READY FOR BYTE
|
|
MOVE.B (SP)+,D0 ;POP RESULT INTO LO BYTE
|
|
RTS
|
|
|
|
|
|
GETWORD FUNC EXPORT
|
|
IMPORT GetPicData
|
|
;------------------------------------------------------
|
|
;
|
|
; LOCAL PROCEDURE TO GET A WORD FROM PICTURE INTO D0
|
|
;
|
|
CLR.W -(SP) ;ALLOCATE TEMP
|
|
MOVE.L SP,-(SP) ;PUSH ADDR OF TEMP
|
|
MOVE #2,-(SP) ;PUSH BYTECOUNT
|
|
JSR GetPicData ;GET DATA FROM THEPIC
|
|
MOVE (SP)+,D0 ;RETURN ANSWER IN D0
|
|
RTS
|
|
|
|
|
|
GetPicPixPat PROC EXPORT
|
|
IMPORT GetWord,GETPICDATA
|
|
IMPORT RGB2Pat,GETLONG,GetUByte
|
|
;------------------------------------------------------
|
|
;
|
|
; PROCEDURE GetPicPixPat(PatPtr);
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (GetPicPixPat) (GetPicPixPat)
|
|
;
|
|
;
|
|
|
|
; GET TYPE AND ONE BIT PATTERN FROM THE PICTURE
|
|
|
|
MOVEQ #10,D0 ;GET NUMBER OF BYTES
|
|
SUB D0,SP ;MAKE ROOM FOR TYPE, PATTERN
|
|
MOVE.L SP,-(SP) ;PUSH POINTER
|
|
MOVE D0,-(SP) ;PUSH BYTE COUNT
|
|
JSR GETPICDATA ;READ IN 10 BYTES
|
|
MOVE.L 14(SP),A0 ;GET PTR TO PATTERN
|
|
MOVE (SP)+,D1 ;GET TYPE
|
|
MOVE.L (SP)+,(A0)+ ;SAVE 1ST HALF PATTERN
|
|
MOVE.L (SP)+,(A0) ;SAVE 2ND HALF PATTERN
|
|
CMP.W #ditherPat,D1 ;IS IT A DITHER PATTERN?
|
|
BNE.S @1 ;No, just use pattern data
|
|
MOVEQ #6,D0 ;Size of RGB buffer
|
|
SUB.L D0,SP ;MAKE ROOM FOR RGB ON STACK
|
|
MOVE.L SP,-(SP) ;BUFFER ADDRESS
|
|
MOVE D0,-(SP) ;LENGTH
|
|
jsr GetPicData ;GET R, G, B
|
|
MOVE.L SP,A1 ;Point at RGB
|
|
JSR RGB2Pat ;Get pattern
|
|
ADDQ #6,SP ;Blow off RGB
|
|
MOVE.L 4(SP),A1 ;GET PAT PTR
|
|
MOVE.L D0,(A1)+ ;Copy gray pattern
|
|
MOVE.L D0,(A1)
|
|
BRA.S PATDONE ;No pixmap to skip
|
|
@1
|
|
|
|
; GET PIXMAP FROM THE PICTURE
|
|
MOVEQ #PMREC-4,D0 ;Size of record
|
|
SUB.W D0,SP ;Make handy buffer
|
|
MOVE.L SP,-(SP) ;Push PIXMAP pointer
|
|
MOVE.W D0,-(SP) ;Push length
|
|
JSR GetPicData ;Get the information
|
|
|
|
; SKIP THE COLOR TABLE.
|
|
JSR GETLONG ;Skip the seed
|
|
JSR GETLONG ;Get TRANSINDEX, SIZE
|
|
ADDQ #1,D0 ;Make size 1-based
|
|
MULU #CTENTRYSIZE,D0 ;Get size of table
|
|
JSR SkipPicData ;Skip the rest of the table
|
|
|
|
; SKIP PIXMAP DATA FROM PICTURE
|
|
|
|
LEA -4(SP),A1 ;GET PIXMAP POINTER
|
|
MOVE BOUNDS+BOTTOM(A1),D1 ;GET TOP OF PIXMAP
|
|
SUB BOUNDS+TOP(A1),D1 ;CALC HEIGHT OF PIXMAP
|
|
MOVE ROWBYTES(A1),D0 ;GET WIDTH OF PIXMAP
|
|
AND #RBMASK,D0 ;MASK OFF FLAG BITS
|
|
CMP #8,D0 ;IS ROWBYTES < 8
|
|
BLT.S @NOPACK ;=>YES, DON'T UNPACK
|
|
MOVEM.L D3-D4,-(SP) ;SAVE WORK REGS
|
|
MOVE D0,D3 ;SAVE ROWBYTES
|
|
MOVE D1,D4 ;SAVE HEIGHT
|
|
BRA.S @START1 ;GO TO LOOP START
|
|
@MORE1
|
|
CMP #250,D3 ;IS ROWBYTES > 250
|
|
BGT.S @3 ;=>YES, GET WORD
|
|
JSR GetUByte ;ELSE GET A BYTE INTO D0
|
|
BRA.S @2 ;=>AND GO GET DATA
|
|
@3 JSR GETWORD ;GET A WORD INTO D0
|
|
@2
|
|
SWAP D0 ;HIGH WORD
|
|
CLR.W D0 ;MAKE SURE IT'S 0
|
|
SWAP D0 ;GET BACK IN RIGHT ORDER
|
|
JSR SkipPicData ;Skip that much
|
|
@START1
|
|
DBRA D4,@MORE1 ;LOOP HEIGHT ROWS
|
|
MOVEM.L (SP)+,D3-D4 ;RESTORE WORK REGS
|
|
BRA.S @PIXDONE ;CONTINUE
|
|
;
|
|
; ROWBYTES < 8, DON'T USE PACKING
|
|
;
|
|
@NOPACK
|
|
MULU D1,D0 ;GET DATA SIZE
|
|
JSR SkipPicData ;Skip that much
|
|
@PIXDONE
|
|
ADD #PMREC-4,SP ;POP PIXMAP
|
|
PATDONE
|
|
MOVE.L (SP)+,(SP) ;STRIP PARAM
|
|
RTS ;AND RETURN
|
|
|
|
|
|
GetPM1Deep PROC EXPORT
|
|
IMPORT GetUByte,GetWord,GetPicData, patTBL
|
|
;------------------------------------------------------
|
|
;
|
|
; PROCEDURE GetPM1Deep(myDst: Ptr; xTab: Ptr; myData: Handle; targetRB: SHORT; mode SHORT); <19Feb87 DBG>
|
|
;
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (GetPM1Deep) (GetPM1Deep)
|
|
;
|
|
; HANDLE SIZE IS SET TO ROWBYTES*(BOUNDS.BOTTOM-BOUNDS.TOP) EXTERNALLY
|
|
;
|
|
PARAMSIZE EQU 16
|
|
MYDST EQU PARAMSIZE+8-4 ;DST PIXMAP POINTER
|
|
XTAB EQU MYDST-4 ;TRANSLATE TABLE POINTER <19Feb87 DBG>
|
|
MYDATA EQU XTAB-4 ;DST DATA HANDLE <19Feb87 DBG>
|
|
TARGETRB EQU MYDATA-2 ;TARGET ROWBYTES
|
|
MODE EQU TARGETRB-2 ;copybits copy mode (64 means dither)
|
|
|
|
SrcHndl EQU -4 ;VAR POINTER TO SOURCE
|
|
DSTPTR EQU SrcHndl-4 ;VAR POINTER TO DST
|
|
PACKBUF EQU DSTPTR-4 ;POINTER TO PACKING BUFFER
|
|
SAVEDSP EQU PACKBUF-4 ;PRESERVE STACK POINTER
|
|
BITSDST EQU SAVEDSP-4 ;CURRENT OUTPUT POINTER
|
|
MUSTMAP EQU BITSDST-2 ;NEED TO MAP?
|
|
LastError EQU MustMap-2 ;luminance error value
|
|
Direction EQU LastError-2 ;alternate directions for dither
|
|
VARSIZE EQU Direction
|
|
|
|
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 PIXMAP
|
|
MOVE.L MYDATA(A6),A0 ;GET DATA HANDLE
|
|
; _HLOCK ;LOCK IT DOWN
|
|
MOVE.L (A0),BITSDST(A6) ;GET DATA POINTER IN BITSDST
|
|
|
|
MOVE BOUNDS+BOTTOM(A2),D7
|
|
SUB BOUNDS+TOP(A2),D7 ;HEIGHT := BOUNDS BOT - TOP
|
|
|
|
MOVE ROWBYTES(A2),D5 ;GET ROWBYTES
|
|
SMI MUSTMAP(A6) ;SET FLAG IFF PIXMAP
|
|
AND #RBMASK,D5 ;CLEAR OFF FLAG BITS
|
|
;
|
|
; Here we calculate ROWBYTES + ROWBYTES/64, rounded up to an even number.
|
|
; The worst-case expansion from _PackBits is one extra byte for every
|
|
; 127 bytes of data. Rather than divide by 127, we divide by 64, the next
|
|
; lowest power of 2.
|
|
;
|
|
MOVE D5,D6 ;COPY ROWBYTES
|
|
ADD #63,D6 ;MAKE SURE TO ROUND UP!
|
|
LSR.W #6,D6 ;GET CEIL(ROWBYTES/64)
|
|
ADDQ.W #1,D6 ;ROUND UP...
|
|
BCLR #0,D6 ;...TO EVEN NUMBER
|
|
ADD D5,D6 ;SIZE OF PACKED BUFFER
|
|
CMP #8,D5 ;ROWBYTES < 8?
|
|
BGE.S @DOUNPACK ;=>NO, GO DO UNPACK
|
|
TST ROWBYTES(A2) ;BITMAP, NOT PIXMAP?
|
|
BPL NOPACK ;GO READ IT STRAIGHT IN
|
|
|
|
@DOUNPACK
|
|
TST.B MUSTMAP(A6) ;PIXMAP?
|
|
BEQ.S @GetRow ;=>NO, BITMAP
|
|
MOVE PIXELSIZE(A2),D4 ;=>YES, PIXMAP: GET BITS/PIXEL
|
|
cmp #32,d4 ;32 bit/pixel?
|
|
beq @getrow ;if so, skip get mask stuff
|
|
MOVE D4,D0 ;COPY IT
|
|
LSL.W #1,D0 ;DOUBLE IT
|
|
NEG.W D0 ;NEGATE IT
|
|
; ??? 64K ROM problem. Need to do LEA on 64K ROM. ???
|
|
_GetMaskTable ;GET MASK TABLE ADDRESS
|
|
MOVE (16*2*2)(A0,D0.W),D3 ;GET MASK FOR PIXEL
|
|
MOVE.L XTAB(A6),A4 ;XLATE TABLE POINTER <19Feb87 DBG>
|
|
CMP.W #1,D4 ;TEST BITS/PIXEL
|
|
BNE.S @GetRow ;IF <>1, MUST MAP
|
|
CMP.W #$0001,(A4) ;MAPPING NEEDED? <19Feb87 DBG>
|
|
SNE MUSTMAP(A6) ;IF NOT $0001, MUST MAP
|
|
|
|
;----------------------------------------------------------------
|
|
;
|
|
; Get unpacked data one row at a time
|
|
;
|
|
@GetRow
|
|
;
|
|
; Allocate handle for one row of source information
|
|
; and initialize various dither parameters
|
|
;
|
|
move.w #-127, LastError(a6) ;init luminance error (8-bit)
|
|
cmp.w #16,d4
|
|
bne @1
|
|
move.w #-15, LastError(a6) ;5-bit luminance error init
|
|
@1
|
|
move.w #0, direction(a6)
|
|
move RowBytes(A2),d0
|
|
and #RBMASK,d0
|
|
_NewHandle ;allocate handle for row of source info
|
|
bne.s ExitGetPM1Deep ;Exit with not equal set <Halloween89 KON>
|
|
|
|
move.l a0, SrcHndl(a6)
|
|
_HLock
|
|
;
|
|
; Do one row at a time
|
|
;
|
|
move Bounds+bottom(a2), d5 ;Save old bounds.bottom
|
|
move Bounds+top(a2), Bounds+bottom(a2) ;make bit/pix map ...
|
|
addq #1, Bounds+bottom(a2) ;...one row high
|
|
bra.s START1 ;start off the loop <8 dba>
|
|
|
|
GetRow1
|
|
move.l a2,-(sp) ;push source pixmap data
|
|
MOVE.L SrcHndl(A6),-(SP) ;put row of data here
|
|
IF INITFILE THEN
|
|
dc.w $A8F3 ;Test with open picture trap num
|
|
ELSE
|
|
dc.w $ABC4 ;_GetPMData
|
|
ENDIF
|
|
; JSR GETPMDATA ;AND READ IN PIXMAP DATA
|
|
move.l SrcHndl(a6),a0
|
|
move.l (a0),a0
|
|
JSR MapRow ;Map the row and place 1 bit/pixel in dst
|
|
|
|
START1 DBRA D7,GetRow1 ;LOOP HEIGHT ROWS
|
|
;----------------------------------------------------------------
|
|
;
|
|
; Dispose row handle and set bounds back
|
|
;
|
|
move d5, Bounds+bottom(a2) ;bounds.top was unchanged
|
|
move.l SrcHndl(a6),a0
|
|
_DisposHandle
|
|
BRA.S DONE ;CONTINUE
|
|
|
|
;----------------------------------------------------------------
|
|
; ROWBYTES < 8 and it's a bitmap, DON'T USE PACKING
|
|
; OR it's already 1 bit/pixel
|
|
;
|
|
NOPACK MULU D7,D5 ;BYTECOUNT := HEIGHT * WIDTH
|
|
MOVE.L BITSDST(A6),-(SP) ;PUSH DATA POINTER
|
|
MOVE D5,-(SP) ;PUSH BYTECOUNT
|
|
JSR GetPicData ;READ BITMAP DATA BITS
|
|
Done
|
|
move #0, d0 ;successfully created 1-bit bitmap <Halloween89 KON>
|
|
bra.s PMDone
|
|
ExitGetPM1Deep ;Error exit branches here <Halloween89 KON>
|
|
move #1, d0 ;d0 != 0 indicates error
|
|
PMDone MOVE.L SAVEDSP(A6),SP ;RESTORE STACK POINTER
|
|
MOVEM.L (SP)+,D3-D7/A2-A4 ;RESTORE WORK REGISTERS
|
|
UNLINK PARAMSIZE,'GETPMDAT' ;destroys condition codes
|
|
|
|
;-----------------------------------------------
|
|
;
|
|
; MapRow - internal utility to map a row to a one-bit-deep row
|
|
; and copy it into the target bitmap.
|
|
; Uses up-level stack frame. Source ptr passed in a0, destination in bitsdst
|
|
; d4.w has bits/pixel
|
|
MapRow
|
|
;
|
|
; Now it's time to actually shrink the bits.
|
|
; We build up a word of output at a time (since rowbytes is even, it doesn't
|
|
; matter if we convert a slop byte), then write it out. We have two loops:
|
|
; An outer one over words of output, and an inner one over words of input.
|
|
; In the interests of patch compactness, the only special case we make is
|
|
; if the number of colors is <= 32, in which case we keep the color mapping
|
|
; bitmap in D6 for speed.
|
|
;
|
|
MOVEM.W D4-D7/a3,-(SP) ;SAVE REGISTERS
|
|
MOVE BOUNDS+RIGHT(A2),D7 ;GET BOUNDS.RIGHT
|
|
SUB BOUNDS+LEFT(A2),D7 ;CALC WIDTH
|
|
MOVE.L BITSDST(A6),A1 ;Destination pointer
|
|
tst.b MustMap(a6)
|
|
bne.s MapRow1 ;need to map the row
|
|
;
|
|
; No mapping needed: copy bits to destination buffer
|
|
;
|
|
move.w rowbytes(a2),d7
|
|
and #RBMask, d7
|
|
sub #1, d7 ;zero base loop
|
|
@LOOP
|
|
move.b (a0)+,(a1)+
|
|
dbra d7,@loop
|
|
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES (HIWRD CLR)
|
|
and.l #$FFFF,d0
|
|
ADD.l D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
bra Shrunk
|
|
|
|
MapRow1
|
|
CMP.W #8,D4 ;8 BITS/PIXEL?
|
|
BEQ.S EIGHTLOOP ;=>YES, USE CUSTOM LOOP
|
|
cmp.w #32,d4
|
|
beq ThirtyTwoLOOP ;Use custom loop for 32bits/pixel <28AUG89 KON>
|
|
cmp.w #16,d4
|
|
beq SixteenBitLOOP ;Use custom loop for 16bits/pixel <28AUG89 KON>
|
|
;
|
|
; Start of the shrinking loop. A0 is source, A1 is destination, a4 points to translation table.
|
|
; We assume an even number of pixels per 16-bit word. They are isolated,
|
|
; one by one, and a one or zero or'd in to the output word we're building up.
|
|
;
|
|
@NEXTOUTWORD
|
|
MOVEQ #16,D6 ;BITS/OUTPUT WORD
|
|
MOVEQ #0,D2 ;OUTPUT WORD
|
|
@NEXTINWORD
|
|
MOVEQ #16,D1 ;BITS IN INPUT WORD
|
|
MOVE (A0)+,D5 ;GET NEXT INPUT WORD
|
|
@NEXTPIX
|
|
ROL.W D4,D5 ;ISOLATE NEXT PIXEL
|
|
MOVE D5,D0 ;GET COPY
|
|
AND D3,D0 ;GET PIXEL
|
|
LSL.W #1,D2 ;MAKE ROOM FOR NEW PIXEL
|
|
OR.B (A4,D0.W),D2 ;GET NEW PIXEL <19Feb87 DBG>
|
|
SUBQ #1,D7 ;ONE LESS PIXEL
|
|
SUBQ #1,D6 ;ONE LESS OUTPUT PIXEL
|
|
SUB D4,D1 ;BITS LEFT IN INPUT WORD
|
|
BGT.S @NEXTPIX ;IF SOME LEFT, GET NEXT PIX
|
|
TST D7 ;ANY INPUT LEFT?
|
|
BLE.S @1 ;NO, DONE WITH LINE
|
|
TST D6 ;ANY OUTPUT ROOM LEFT?
|
|
BGT.S @NEXTINWORD ;YES, GET NEXT INPUT WORD
|
|
MOVE D2,(A1)+ ;WRITE AN OUTPUT WORD
|
|
BRA.S @NEXTOUTWORD
|
|
@1
|
|
LSL.W D6,D2 ;LEFT JUSTIFY LAST WORD
|
|
MOVE D2,(A1)+ ;WRITE AN OUTPUT WORD
|
|
MOVEQ #0,D0 ;CLEAR OUT LONG
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
BRA SHRUNK ;EXIT
|
|
;
|
|
; Here is the custom loop for eight bit pixels. Principle is
|
|
; the same as the previous loop.
|
|
;
|
|
EIGHTLOOP
|
|
MOVEQ #0,D0 ;CLEAR PIXEL BUFFER/ROWBYTES
|
|
@NEXTOUTWORD
|
|
MOVEQ #15,D6 ;BITS/OUTPUT WORD (-1)
|
|
MOVEQ #0,D2 ;OUTPUT WORD
|
|
@NEXTPIX
|
|
MOVE.B (A0)+,D0 ;GET NEXT INPUT BYTE
|
|
LSL.W #1,D2 ;MAKE ROOM FOR NEW PIXEL
|
|
OR.B (A4,D0.W),D2 ;GET IT <19Feb87 DBG>
|
|
SUBQ #1,D7 ;ONE LESS PIXEL
|
|
BLE.S @1 ;IF NONE LEFT, DONE WITH ROW
|
|
DBRA D6,@NEXTPIX ;LOOP FOR NEXT PIXEL
|
|
MOVE D2,(A1)+ ;WRITE AN OUTPUT WORD
|
|
BRA.S @NEXTOUTWORD
|
|
@1
|
|
LSL.W D6,D2 ;LEFT JUSTIFY LAST WORD
|
|
MOVE D2,(A1)+ ;WRITE LAST OUTPUT WORD
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
bra SHRUNK ;exit <28AUG89 KON>
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; SCALES A SCANLINE OF PIXELS FROM 32 BIT DIRECT TO A B/W BitMap
|
|
; ASSUMES SRC IS COMPOSED OF FOUR BYTES OF THE FORM 'XRGB'
|
|
;
|
|
; D7: Number of pixels to convert
|
|
; A0: SRC BUFFER
|
|
; A1: DST BUFFER
|
|
|
|
ThirtyTwoLOOP
|
|
|
|
move.l #$80000000,d5 ;init offset into dst
|
|
moveq #0,d0 ; d0-d2 hold r,g,b values...
|
|
moveq #0,d1 ;...when calculating luminance...
|
|
moveq #0,d2 ;...and only low byte is used.
|
|
|
|
move.w LastError(a6),d3 ;get luminance error from last line
|
|
btst #6, mode+1(a6) ;do dithering?
|
|
beq.s NewOutputLong ;no
|
|
eori.w #1, direction(a6) ;if we dither, we scan ...
|
|
beq.s DoReverseThirtyTwoLoop ;... backwards every other time
|
|
NewOutputLong
|
|
moveq #0, d6 ;assume output value will be white
|
|
move.l #$80000000,d5 ; rotating mask
|
|
|
|
NextInputLong
|
|
move.l (a0)+,d4 ;get next long of src
|
|
|
|
move.b d4,d2 ; get the blue component
|
|
lsr.l #8,d4 ; get red,green in low word
|
|
move.b d4,d1 ; get the green component
|
|
lsr.w #8,d4 ; get red in low byte
|
|
move.b d4,d0 ; get the red component
|
|
|
|
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
|
|
|
|
add.w d1,d4
|
|
add.w d2,d4
|
|
add.w d2,d4
|
|
lsr.w #2,d4
|
|
add.w d0,d4
|
|
add.w d1,d4
|
|
add.w d1,d4
|
|
lsr.w #2,d4
|
|
btst #6, mode+1(a6)
|
|
beq.s NoDither
|
|
|
|
;
|
|
; add luminance to current error and compare to threshold
|
|
; if lum + err <= 0 then pixel is set.
|
|
;
|
|
add.w d4,d3 ;add luminance to error (slop)
|
|
ble.s SetBit
|
|
sub.w #255,d3
|
|
bra.s SetBitDone
|
|
;
|
|
; No Dithering: Use 50% theshold
|
|
NoDither
|
|
tst.b d4 ; check high bit of luminance
|
|
bmi.s SetBitDone ; if set, pixel is white (0), so skip
|
|
SetBit
|
|
or.l d5,D6 ; set pixel value
|
|
SetBitDone
|
|
sub #1, d7 ;done enough pixels?
|
|
beq.s @rowdone ;
|
|
lsr.l #1,d5 ;BUMP TO NEXT DST PIXEL
|
|
bne.s NextInputLong
|
|
move.l d6,(a1)+ ;save destination pixel values
|
|
bra.s NewOutputLong
|
|
|
|
@rowdone
|
|
MOVE.L D6,(A1)+ ;done: save current output value
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
move.w d3, LastError(a6) ;save luminance error for next line
|
|
bra shrunk
|
|
;
|
|
; Scan line in reverse direction
|
|
;
|
|
DoReverseThirtyTwoLoop
|
|
|
|
moveq #0,d4 ;clear high word of temp pixel count
|
|
move.w d7, d4 ;pixel count to temp register
|
|
lsl.l #2, d4 ;convert to long
|
|
add.l d4, a0 ;move to end of source
|
|
add.l #31<<2,d4 ;31<<2
|
|
lsr.l #5, d4 ;/4 to convert XRGB to pixels...
|
|
;... and /32 because 32 pixels/long...
|
|
;... and *4 because we 4 bytes/long
|
|
and.w #$fffc,d4 ;must end on word boundry
|
|
add.l d4, a1 ;move to end of destination
|
|
|
|
move d7, d4 ;find starting pixel position
|
|
sub.w #1, d4
|
|
and.w #$1f, d4 ;get pixel count mod 32
|
|
move.l #$80000000,d5
|
|
lsr.l d4, d5 ;move to starting pixel position
|
|
moveq #0, d6
|
|
bra.s ReverseNextInputLong
|
|
|
|
ReverseNewOutputLong
|
|
moveq #0,d6 ;assume output value will be white
|
|
moveq #$00000001,d5 ; rotating mask: start on right...
|
|
;...and move left
|
|
|
|
ReverseNextInputLong
|
|
move.l -(a0),d4 ;get long of src
|
|
|
|
move.b d4,d2 ; get the blue component
|
|
lsr.l #8,d4 ; get red,green in low word
|
|
move.b d4,d1 ; get the green component
|
|
lsr.w #8,d4 ; get red in low byte
|
|
move.b d4,d0 ; get the red component
|
|
|
|
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
|
|
|
|
add.w d1,d4
|
|
add.w d2,d4
|
|
add.w d2,d4
|
|
lsr.w #2,d4
|
|
add.w d0,d4
|
|
add.w d1,d4
|
|
add.w d1,d4
|
|
lsr.w #2,d4
|
|
|
|
add.w d4,d3 ;add luminance to error (slop)
|
|
bpl.s ReverseDitherSetBitDone
|
|
or.l d5,D6 ; set pixel value
|
|
bra.s ReverseSetBitDone
|
|
ReverseDitherSetBitDone
|
|
sub.w #255,d3
|
|
|
|
ReverseSetBitDone
|
|
sub #1, d7 ;done enough pixels?
|
|
beq.s @rowdone ;
|
|
lsl.l #1, d5 ;BUMP TO NEXT DST PIXEL
|
|
bne.s ReverseNextInputLong
|
|
move.l d6,-(a1) ;save destination pixel values
|
|
bra.s ReverseNewOutputLong
|
|
|
|
@rowdone
|
|
MOVE.L D6,-(A1) ;done: save current output value
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
move.w d3, LastError(a6) ;save luminance error for next line
|
|
bra shrunk
|
|
|
|
;------------------------------------------------------------------
|
|
;
|
|
; SCALES A SCANLINE OF PIXELS FROM 16 BIT DIRECT TO A B/W BitMap
|
|
; ASSUMES SRC IS COMPOSED OF one word OF THE FORM 'XRRRRRGGGGGBBBBB'
|
|
;
|
|
; D7: Number of pixels to convert
|
|
; A0: SRC BUFFER
|
|
; A1: DST BUFFER
|
|
|
|
SixteenBitLOOP
|
|
|
|
move.l #$80000000,d5 ;init offset into dst
|
|
moveq #0,d0 ; zero luninance rgb values
|
|
moveq #0,d1 ;
|
|
moveq #0,d2 ;
|
|
|
|
move.w LastError(a6),d3 ;get luminance error from last line
|
|
btst #6, mode+1(a6) ;do dithering?
|
|
beq.s NewOutputLong16 ;no
|
|
eori.w #1, direction(a6) ;if we dither, we scan ...
|
|
beq.s DoReverse16Loop ;... backwards every other time
|
|
|
|
NewOutputLong16
|
|
move.l #0, d6 ;assume output value will be white
|
|
move.l #$80000000,d5 ; rotating mask
|
|
|
|
NextInputWord16
|
|
move.w (a0)+,d4 ;get first word of src
|
|
|
|
move.b d4,d2 ; get the blue component
|
|
and.b #$1F,d2 ;save only bottom 5 bits
|
|
lsr.l #5,d4 ; get red,green in low word
|
|
move.b d4,d1 ; get the green component
|
|
and.b #$1F,d1 ;save only bottom 5 bits
|
|
lsr.w #5,d4 ; get red in low byte
|
|
move.b d4,d0 ; get the red component
|
|
and.b #$1F,d0 ;save only bottom 5 bits
|
|
|
|
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
|
|
|
|
add.w d1,d4
|
|
add.w d2,d4
|
|
add.w d2,d4
|
|
lsr.w #2,d4
|
|
add.w d0,d4
|
|
add.w d1,d4
|
|
add.w d1,d4
|
|
lsr.w #2,d4
|
|
btst #6, mode+1(a6)
|
|
beq.s NoDither16
|
|
;
|
|
; Do dithering
|
|
;
|
|
add.w d4,d3 ;add luminance to error (slop)
|
|
ble.s SetBit16
|
|
sub.w #$1F,d3 ;reset error (max luminance for five bits)
|
|
bra.s SetBitDone16
|
|
;
|
|
; No Dithering: Use 50% theshold
|
|
;
|
|
NoDither16
|
|
btst #4,d4 ; check bit 4 (high bit of luminance for 16 bit) <KON 2NOV90>
|
|
bne.s SetBitDone16 ; if set, pixel is white (0), so skip
|
|
SetBit16
|
|
or.l d5,D6 ; set pixel value
|
|
SetBitDone16
|
|
sub #1, d7 ;done enough pixels?
|
|
beq.s @rowdone ;
|
|
lsr.l #1,d5 ;BUMP TO NEXT DST PIXEL
|
|
bne.s NextInputWord16
|
|
move.l d6,(a1)+ ;save destination pixel values
|
|
bra.s NewOutputLong16
|
|
|
|
@rowdone
|
|
MOVE.L D6,(A1)+ ;done: save current output value
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
move.w d3, LastError(a6) ;save luminance error for next line
|
|
bra shrunk
|
|
;
|
|
; Scan line in reverse direction
|
|
;
|
|
DoReverse16Loop
|
|
|
|
moveq #0,d4 ;clear high word of temp pixel count
|
|
move.w d7, d4 ;pixel count to temp register
|
|
lsl.l #1, d4 ;convert to number of words
|
|
add.l d4, a0 ;move to end of source
|
|
add.l #15<<2,d4 ;adjust to round up
|
|
lsr.l #4, d4 ;/2 to convert 16 bit to number of pixels...
|
|
;... and /32 because 32 pixels/long...
|
|
;... and *2 because 2 bytes/word
|
|
and.w #$fffc,d4 ;must end on word boundry
|
|
add.l d4, a1 ;move to end of destination
|
|
|
|
move d7, d4 ;find starting pixel position
|
|
sub.w #1, d4
|
|
and.w #$1f, d4 ;get pixel count mod 32
|
|
move.l #$80000000,d5
|
|
lsr.l d4, d5 ;move to starting pixel position
|
|
moveq #0, d6
|
|
bra.s ReverseNextInputLong16
|
|
|
|
ReverseNewOutputLong16
|
|
moveq #0, d6 ;assume output value will be white
|
|
moveq #$00000001,d5 ; rotating mask: start on right...
|
|
;...and move left
|
|
|
|
ReverseNextInputLong16
|
|
move.w -(a0),d4 ;get word of src
|
|
|
|
move.b d4,d2 ; get the blue component
|
|
and.b #$1F,d2 ;save only bottom 5 bits
|
|
lsr.l #5,d4 ; get red,green in low word
|
|
move.b d4,d1 ; get the green component
|
|
and.b #$1F,d1 ;save only bottom 5 bits
|
|
lsr.w #5,d4 ; get red in low byte
|
|
move.b d4,d0 ; get the red component
|
|
and.b #$1F,d0 ;save only bottom 5 bits
|
|
|
|
; Compute Luminance = ((((((r+g)/2)+b)/2+r)/2)+g)/2
|
|
|
|
add.w d1,d4
|
|
add.w d2,d4
|
|
add.w d2,d4
|
|
lsr.w #2,d4
|
|
add.w d0,d4
|
|
add.w d1,d4
|
|
add.w d1,d4
|
|
lsr.w #2,d4
|
|
|
|
add.w d4,d3 ;add luminance to error (slop)
|
|
bpl.s ReverseDitherSetBitDone16
|
|
or.l d5,D6 ; set pixel value
|
|
bra.s ReverseSetBitDone16
|
|
|
|
ReverseDitherSetBitDone16
|
|
sub.w #$1F,d3
|
|
|
|
ReverseSetBitDone16
|
|
sub #1, d7 ;done enough pixels?
|
|
beq.s @rowdone ;
|
|
lsl.l #1, d5 ;BUMP TO NEXT DST PIXEL
|
|
bne ReverseNextInputLong16
|
|
move.l d6,-(a1) ;save destination pixel values
|
|
bra.s ReverseNewOutputLong16
|
|
|
|
@rowdone
|
|
MOVE.L D6,-(A1) ;done: save current output value
|
|
MOVE TARGETRB(A6),D0 ;GET TARGET ROWBYTES
|
|
and.l #$ffff,d0 ;clear hi word
|
|
ADD.L D0,BITSDST(A6) ;NEXT SCAN LINE
|
|
move.w d3, LastError(a6) ;save luminance error for next line
|
|
|
|
SHRUNK
|
|
MOVEM.W (SP)+,D4-D7/a3 ;Restore registers
|
|
RTS ;EXIT
|
|
|
|
ENDPROC
|
|
|
|
RGB2OLD PROC EXPORT
|
|
;-----------------------------------------------
|
|
;
|
|
; UTILITY TO CONVERT AN RGB (POINTED TO BY A1) VALUE
|
|
; TO AN OLD STYLE COLOR VALUE. RETURNS VALUE IN D0. CLOBBERS D0,D1
|
|
;
|
|
; USES HIGH BIT OF EACH COMPONENT TO SELECT RGB OFF (0) OR ON (1)
|
|
|
|
MOVEQ #0,D1 ; clear out D1
|
|
MOVE (A1)+,D1 ; get red
|
|
LSL.L #1,D1 ; get high bit
|
|
MOVE (A1)+,D1 ; get green
|
|
LSL.L #1,D1 ; get high bit
|
|
MOVE (A1)+,D1 ; get blue
|
|
LSL.L #1,D1 ; get high bit
|
|
SWAP D1 ; get RGB index
|
|
LSL.W #1,D1 ; Make a word index
|
|
MOVEQ #0,D0 ; clear out target
|
|
MOVE.W MapTBL(D1.W),D0 ; convert to planar value
|
|
RTS ; => all done
|
|
|
|
; TABLE TO MAP FROM 3 BIT RGB TO OLD-STYLE COLOR INDICES
|
|
|
|
MapTBL DC.W blackColor ; RBG = 0,0,0 -> black
|
|
DC.W blueColor ; RBG = 0,0,1 -> blue
|
|
DC.W greenColor ; RBG = 0,1,0 -> green
|
|
DC.W cyanColor ; RBG = 0,1,1 -> cyan
|
|
DC.W redColor ; RBG = 1,0,0 -> red
|
|
DC.W magentaColor ; RBG = 1,0,1 -> magenta
|
|
DC.W yellowColor ; RBG = 1,1,0 -> yellow
|
|
DC.W whiteColor ; RBG = 1,1,1 -> white
|
|
|
|
RGB2Pat PROC EXPORT
|
|
ENTRY RGB2Pixel
|
|
EXPORT PatTBL
|
|
;-----------------------------------------------
|
|
;
|
|
; UTILITY TO CONVERT AN RGB (POINTED TO BY A1) VALUE
|
|
; TO AN OLD STYLE GRAY PATTERN. RETURNS HALF-PATTERN IN D0. CLOBBERS D1.
|
|
;
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (RGB2Pat) (RGB2Pat)
|
|
;
|
|
; USES COMPUTED GRAY LEVEL TO SELECT A PATTERN
|
|
MOVE (A1)+,D1 ; Get Red
|
|
MULU #$4CCC,D1 ; Weight for Red
|
|
MOVE (A1)+,D0 ; Get Green
|
|
MULU #$970A,D0 ; Weight for Green
|
|
ADD.L D0,D1 ; Add in
|
|
MOVE (A1)+,D0 ; Get Blue
|
|
MULU #$1C28,D0 ; Weight for Blue
|
|
ADD.L D0,D1 ; Get sum: luminance of RGB
|
|
CLR D1 ; Clear low word
|
|
ROL.L #3,D1 ; Get high three bits (0-7)
|
|
LSL.W #2,D1 ; Get long offset
|
|
MOVE.L PatTBL(D1.W),D0 ; Get half-pattern
|
|
RTS
|
|
PatTBL
|
|
DC.L $FFFFFFFF ; Gray = 0 -> black
|
|
DC.L $DDFF77FF ; Gray = 1 -> 7/8 gray
|
|
DC.L $FF55FF55 ; Gray = 2 -> 3/4 gray
|
|
DC.L $EE55BB55 ; Gray = 3 -> 5/8 gray
|
|
DC.L $AA55AA55 ; Gray = 4 -> 1/2 gray
|
|
DC.L $88552255 ; Gray = 5 -> 3/8 gray
|
|
DC.L $88002200 ; Gray = 6 -> 1/8 gray
|
|
DC.L $00000000 ; Gray = 7 -> white
|
|
|
|
;-----------------------------------------------
|
|
;
|
|
; UTILITY TO CONVERT AN RGB (POINTED TO BY A0) VALUE <19Feb87 DBG>
|
|
; TO A SINGLE PIXEL. RETURNS VALUE IN D0.B. CLOBBERS D1.
|
|
;
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (RGB2Pixel) (RGB2Pixel)
|
|
;
|
|
; USES COMPUTED GRAY LEVEL TO SELECT A PATTERN
|
|
RGB2Pixel
|
|
MOVEQ #0,D1 ; Clear out
|
|
MOVE (A0)+,D1 ; Get Red <19Feb87 DBG>
|
|
MOVEQ #0,D0 ; Clear out
|
|
MOVE (A0)+,D0 ; Get Green <19Feb87 DBG>
|
|
ADD.L D0,D1 ; Add in
|
|
MOVE (A0)+,D0 ; Get Blue <19Feb87 DBG>
|
|
ADD.L D0,D1 ; Get sum
|
|
DIVU #3,D1 ; Compute unweighted Gray value
|
|
SGE D0 ; Should be 1 (black) if <$8000
|
|
NEG.B D0 ; Make single bit
|
|
RTS
|
|
|
|
MapRatio PROC EXPORT
|
|
;-------------------------------------------------------------
|
|
;
|
|
; PROCEDURE MapRatio(VAR numer, denom: Point; fromRect: Rect);
|
|
;
|
|
; Fix File Date Patch# Fix Routine(s) Routine(s) Fixed
|
|
;AppleSystemPatch DrawPicturePatch.a 01Jan1904 #??? (MapRatio) (MapRatio)
|
|
;
|
|
; Map ratio so that denom.h/.v = height/width of fromRect.
|
|
; This is so that later scaling of the numerator will have some
|
|
; range to work within.
|
|
;
|
|
; NOTE: Only necessary because fractional numer, denom not used
|
|
;
|
|
; numer.h := numer.h * fromWidth / denom.h
|
|
; denom.h := fromWidth
|
|
; numer.v := numer.v * fromHeight / denom.v
|
|
; denom.v := fromHeight
|
|
|
|
PARAMSIZE EQU 12 ; TOTAL BYTES OF PARAMS
|
|
NUMER EQU PARAMSIZE+8-4 ; LONG, ADDR OF POINT
|
|
DENOM EQU NUMER-4 ; LONG, ADDR OF POINT
|
|
FROMRECT EQU DENOM-4 ; LONG, ADDR OF RECT
|
|
|
|
LINK A6,#0 ; NO LOCALS
|
|
MOVEM.L D0-D1/A0-A2,-(SP) ; SAVE REGS
|
|
MOVE.L NUMER(A6),A0 ; point to numer
|
|
MOVE.L DENOM(A6),A1 ; point to denom
|
|
MOVE.L FROMRECT(A6),A2 ; point to fromRect
|
|
|
|
MOVE.W right(A2),D0 ; get fromRect right
|
|
SUB.W left(A2),D0 ; get fromWidth
|
|
MOVE.W h(A0),D1 ; get numer.h
|
|
MULU D0,D1 ; multiply by fromWidth
|
|
DIVU h(A1),D1 ; divide by denom.h
|
|
MOVE.W D1,h(A0) ; update numer.h
|
|
MOVE.W D0,h(A1) ; update denom.h
|
|
|
|
MOVE.W bottom(A2),D0 ; get fromRect bottom
|
|
SUB.W top(A2),D0 ; get fromHeight
|
|
MOVE.W v(A0),D1 ; get numer.v
|
|
MULU D0,D1 ; multiply by fromHeight
|
|
DIVU v(A1),D1 ; divide by denom.v
|
|
MOVE.W D1,v(A0) ; update numer.v
|
|
MOVE.W D0,v(A1) ; update denom.v
|
|
|
|
DONE MOVEM.L (SP)+,D0-D1/A0-A2 ; RESTORE REGS
|
|
UNLINK PARAMSIZE,'MAPRATIO' ;destroys condition codes
|
|
|
|
ENDPROC
|
|
|
|
;--------- BitMap to Region Added by KON 11/6/89 for Plus and SE only -----------
|
|
|
|
;________________________________________________________________________________
|
|
;
|
|
; FUNCTION BitMapRgn(region:RgnHandle; bMap:BitMap): OSErr; INLINE $A8D7;
|
|
; (BHogToRegion is debugging memory hog version)
|
|
;
|
|
; Given a region and bitmap, BitMapRgn makes the region a bounding
|
|
; region for the 'map. If it can't get memory it will return a
|
|
; Memory Manager-type error and an empty region gibbley. Note that
|
|
; the region might also be empty with no error (if the bounds is an
|
|
; empty rectangle or there are no 1 bits in the bitmap). Lastly,
|
|
; if the region would have to exceed 32K it returns a result of
|
|
; -500 (rgnTooBigErr).
|
|
;
|
|
; The bMap parameter may be a pointer to a bitmap, a pointer to a
|
|
; pixmap, or a pointer to a portBits field in a color grafport.
|
|
; In the latter two cases, if the pixmap is not 1-bit deep, an error
|
|
; result of -148 (pixmapTooDeepErr) is returned.
|
|
;
|
|
; (the nibble state machine idea is from the Finder MaskToRgn routine)
|
|
;
|
|
; History
|
|
; 2/19/88 RBB changed to take in washing and handle rect. & empties properly
|
|
; also now finds minimum rectangle to enclose region
|
|
; *** version of 2/22/88 ***
|
|
; 2/23/88 RBB putting in numerous optimizations recommended by Darin
|
|
; 4/4/88 RBB trying to re-do lost work from March
|
|
; DBA
|
|
; 3/28/89 CSD adjusted setup to know about pixmaps and portBits
|
|
; 5/18/89 BAL made classic QD friendly
|
|
;
|
|
;________________________________________________________________________________
|
|
;
|
|
;Theory
|
|
; We scan each line of the bitmap and pump inversion points (ip's) into the region
|
|
; to put the areas with ones in the bitmap into the region and the areas
|
|
; with zeroes outside the region.
|
|
;
|
|
; In order to keep track of where we are in "inversion land" we use two
|
|
; techniques:
|
|
|
|
; The first is a scanline buffer which records the changes
|
|
; (zeroes to ones and vice versa) as we go. Wherever a change occurs (a
|
|
; 1 next to a 0 in the buffer) we need to put out an inversion point.
|
|
|
|
; The second is a togglin' flag which tells us whether we are "inverted" or not.
|
|
; Since we use a state machine in the innermost (nibble) loop to churn out
|
|
; ip's, the input to the state machine must be complemented if the flag is set.
|
|
|
|
; The loop stuff looks like this:
|
|
; outer line loop (grows handle in anticipation of worst case for next line)
|
|
; longword loop for current line (puts out inter-long ip's as needed)
|
|
; loop for 4 nibbles in current long (calls state maching for each nibble)
|
|
;
|
|
;________________________________________________________________________________
|
|
|
|
|
|
BitMapRgnptch PROC EXPORT
|
|
|
|
BMFrame RECORD {A6Link},DECR
|
|
result DS.W 1
|
|
|
|
paramTop EQU *
|
|
|
|
regionH DS.L 1
|
|
bMapPtr DS.L 1
|
|
|
|
paramSize EQU paramTop-*
|
|
|
|
return DS.L 1
|
|
A6Link DS.L 1
|
|
|
|
rowLongs DS.L 1 ;number of longwords per line
|
|
rightMask DS.L 1 ;mask for rightmost long of each line
|
|
slHandle DS.L 1 ;handle to scanline buffer
|
|
numLines DS.W 1 ;number of lines in bitmap
|
|
rowNumBytes DS.W 1 ;rowbytes from the bitmap
|
|
startSize DS.W 1 ;size of region at start of line
|
|
lastLineH DS.L 1 ;last line (zeroes) handle
|
|
|
|
handSize DS.L 1 ;size of handle (avoid calls to GetHandleSize)
|
|
max2Add DS.L 1 ;worst case for bytes we could add for next line
|
|
|
|
localSize EQU *
|
|
ENDR
|
|
|
|
WITH BMFrame
|
|
LINK A6,#localSize
|
|
MOVEM.L A2-A5/D3-D7,-(SP) ;save work registers
|
|
|
|
CLR.L slHandle(A6) ;no scanline handle, yet
|
|
CLR.W result(A6) ;function result presumed zero at start
|
|
|
|
MOVE.L regionH(A6),A0
|
|
MOVE.L (A0),A2
|
|
MOVEQ #0,D0
|
|
MOVE.W (A2),D0 ;get size of region
|
|
MOVE.L D0,handSize(A6) ;save it long
|
|
|
|
;get boundary rectangle so we can tell how to process the bitmap
|
|
|
|
MOVE.L bMapPtr(A6),A1 ;get bitmap pointer
|
|
MOVE.W rowBytes(A1), D0 ;rowbytes
|
|
|
|
if hasCQD then
|
|
|
|
BPL.S @1 ;it's a bitmap so go ahead
|
|
BTST #isCPort, D0 ;is this a ptr to portBits?
|
|
BEQ.S @2 ;nope; it's a ptr to a pixmap
|
|
MOVE.L baseAddr(A1), A0 ;get the PixMapHandle
|
|
MOVE.L (A0), A1 ;and get the real ptr to pixmap
|
|
@2
|
|
CMP.W #1, pmPixelSize(A1) ;is it 1 bit per pixel deep?
|
|
BEQ.S @1 ;if yes, we're fine
|
|
MOVE.W #pixmapTooDeepErr, D0 ;return an error otherwise
|
|
BRA BMRBadEmpty ;clean up and bail out
|
|
@1
|
|
MOVE.W rowBytes(A1), rowNumBytes(A6) ;get the rowbytes from the bit/pixmap
|
|
ANDI.W #$7FFF, rowNumBytes(A6) ;mask off pixmap flag
|
|
|
|
else
|
|
|
|
MOVE.W rowBytes(A1), rowNumBytes(A6) ;get the rowbytes from the bit/pixmap
|
|
|
|
endif ;hasCQD
|
|
|
|
MOVE.L bounds+topLeft(A1),D2 ;get topLeft
|
|
MOVE.W bounds+right(A1),D0 ;get right
|
|
|
|
;figure the number of longs per row (according to width, not rowbytes)
|
|
;so we can get a scanline buffer
|
|
SUB.W D2,D0 ;right - left
|
|
BLE BMREmptyOut ;if empty rect. then empty region
|
|
EXT.L D0
|
|
MOVE.L D0,D4
|
|
ADD.L D4,D4 ;double width for 2 bytes/ip
|
|
ADDQ.L #4+2,D4 ;add 4 bytes for y value and $7FFF word
|
|
;add 2 more for the $7FFF if the last line
|
|
ADD.L D4,D4 ;double, just 'cause I feel like it!
|
|
MOVE.L D4,max2Add(A6) ;save max. bytes for a given line
|
|
|
|
MOVEQ #32,D7 ;(side effect: clear high word of D7)
|
|
DIVU D7,D0 ;number of longs = width/32
|
|
|
|
;get a mask for the rightmost long into rightMask
|
|
MOVE.L D0,D3 ;save remainder(hi word)
|
|
SWAP D3 ;get remainder from width/32
|
|
MOVEQ #-1,D1 ;default rightmost long mask
|
|
TST.W D3 ;zero remainder?
|
|
BEQ.S @0 ;yes, $FFFF is a good mask
|
|
ADDQ.W #1,D0 ;we need one more long
|
|
SUB.W D3,D7 ;32 - remainder = zero bits to shift in
|
|
ASL.L D7,D1 ;get proper mask
|
|
@0 MOVE.L D1,rightMask(A6)
|
|
EXT.L D0
|
|
MOVE.L D0,rowLongs(A6) ;save # of longs
|
|
ASL.L #2,D0 ;longs => bytes
|
|
|
|
;get the scanline buffer (D0 = number of bytes per line)
|
|
_NewHandle clear ;get a scanline buffer (of zeroes)
|
|
BNE BMRBadEmpty ;if we failed then return a NIL handle
|
|
|
|
MOVE.L A0,slHandle(A6) ;save buffer handle
|
|
|
|
;figure the number of lines
|
|
MOVE.L D2,D3
|
|
SWAP D3 ;get top
|
|
MOVE.W bounds+bottom(A1),D0 ;get bottom
|
|
SUB.W D3,D0 ;bottom - top
|
|
BLE BMREmptyOut ;if empty rect. then empty region
|
|
|
|
MOVE.W D0,numLines(A6) ;number of lines
|
|
MOVE.L baseAddr(A1),A4 ;point to start of map
|
|
MOVE.W #rgnData,D7 ;initial region size
|
|
|
|
;OK, now we start the loops.
|
|
; A1 will point to the bitmap long,
|
|
; A2 to the region.
|
|
; A3 points to the current scanline buffer long.
|
|
; A4 will point to the row in the map.
|
|
; A5 points to the current word (= size + A2)
|
|
; D1 holds the current long (modified).
|
|
; D2 holds the leftmost coordinate of bitmap.bounds.
|
|
; D3 has the y coordinate, and
|
|
; D4 the x coordinate (high word stays clear!).
|
|
; D5 has number of longs remaining for current line.
|
|
; D6 holds the (on or off) value of the "beam" (for the line).
|
|
; D7 holds the size outside the longword loop (used as scratch while nibbling).
|
|
; (we assume at the very end that D7's high word has remained clear)
|
|
|
|
BMRHScramLine
|
|
MOVE.L regionH(A6),A2
|
|
MOVE.L (A2),A2 ;point to start of region
|
|
|
|
BMRLineLoop
|
|
LEA (A2,D7.W),A5 ;point to new region start + size
|
|
|
|
MOVE.L handSize(A6),D1 ;get handle size
|
|
SUB.W D7,D1 ;handle size - region size
|
|
CMP.L max2Add(A6),D1 ;is there enough for worst case on next line?
|
|
BGE.S @1 ;skippy if so
|
|
|
|
MOVE.L handSize(A6),D0 ;get handle size
|
|
ADD.L max2Add(A6),D0 ;add more than enough for worst case on next line
|
|
MOVE.L D0,handSize(A6) ;save new size
|
|
MOVE.L regionH(A6),A0 ;region handle
|
|
_SetHandleSize
|
|
BNE BMRBadEmpty ;if we failed then return a NIL handle
|
|
BRA.S BMRHScramLine ;rederef. handle and recompute current pointer
|
|
@1
|
|
|
|
MOVE.W D2,D4 ;get current x coordinate from left
|
|
MOVEQ #0,D6 ;beam initially off
|
|
MOVE.L A4,A1 ;start of current line into map pointer
|
|
MOVE.L rowLongs(A6),D5 ;longs remaining for current line
|
|
MOVE.L slHandle(A6),A3 ;A3 points to the current "differences" long
|
|
MOVE.L (A3),A3
|
|
|
|
; Note: within this loop we assume that nothing will be done to move the heap
|
|
|
|
MOVE.W D3,D0 ;get y position
|
|
BSR OutputRgnWord ;output y pos to region
|
|
|
|
MOVE.W D7,startSize(A6) ;save size at line start (a la Derwood)
|
|
BRA NextBMRLong ;enter the long loop
|
|
|
|
BMRLongLoop
|
|
MOVE.L (A1)+,D0 ;fetch the next long for this line
|
|
BMRLastLEntry
|
|
MOVE.L (A3),D1 ;get differences long
|
|
|
|
EOR.L D0,D1 ;compute the differences
|
|
BNE BMRDiff ;if not the same, skip ahead
|
|
|
|
BMRSame
|
|
;since we want to skip this long (it matches the previous line) we need to
|
|
;put out an ip if the beam is on
|
|
TST.B D6 ;beam on?
|
|
BEQ.S @1 ;skip if not
|
|
MOVE.W D4,(A5)+ ;pump it out
|
|
MOVEQ #0,D6 ;beam off
|
|
|
|
@1
|
|
ADD.W #32,D4 ;slip to next long's x coordinate
|
|
@2 ADDQ.W #4,A3 ;to next changes buffer long
|
|
BRA NextBMRLong
|
|
|
|
;----------------------------------------------------------------------------------------
|
|
|
|
; Start of State Machine
|
|
|
|
; Handle state 0001
|
|
|
|
BMRState1
|
|
ADDQ.W #3,D4 ;bump x by 3
|
|
State1Common
|
|
MOVE.W D4,(A5)+ ;generate one
|
|
;Tog1StateDone
|
|
ADDQ.W #1,D4 ;bump x by one more
|
|
TogStateDone
|
|
NOT.B D6 ;toggle state
|
|
RTS
|
|
|
|
; Handle state 0010
|
|
|
|
BMRState2
|
|
ADDQ.W #2,D4 ;bump x by 2
|
|
MOVE.W D4,(A5)+ ;generate one
|
|
Gen1BumpBy1
|
|
BSR.S Gen1InvPoint ;and another one
|
|
BumpBy1
|
|
ADDQ.W #1,D4 ;bump once more
|
|
RTS ;state doesn't change
|
|
|
|
; Handle state 0011
|
|
|
|
BMRState3
|
|
ADDQ.W #2,D4 ;bump x by 2
|
|
MOVE.W D4,(A5)+ ;generate one
|
|
ADDQ.W #2,D4 ;bump
|
|
BRA.S TogStateDone ;toggle the state
|
|
|
|
; Handle state 0100
|
|
|
|
BMRState4
|
|
BSR.S Gen1InvPoint
|
|
BSR.S Gen1InvPoint
|
|
BumpBy2
|
|
ADDQ.W #2,D4
|
|
RTS
|
|
|
|
; Handle state 0101
|
|
|
|
BMRState5
|
|
BSR.S BMRState4 ;start out as state 4
|
|
SUBQ #1,D4
|
|
BRA.S State1Common ;use common code
|
|
|
|
; Handle state 0110
|
|
|
|
BMRState6
|
|
BSR.S Gen1InvPoint
|
|
ADDQ.W #1,D4
|
|
BRA.S Gen1BumpBy1
|
|
|
|
; Handle state 0111
|
|
|
|
BMRState7
|
|
BSR.S Gen1InvPoint
|
|
ADDQ.W #3,D4
|
|
BRA.S TogStateDone
|
|
|
|
; Gen1InvPoint bumps x by one and then generates a horizontal inversion point
|
|
|
|
Gen1InvPoint
|
|
ADDQ.W #1,D4 ;bump by 1, first
|
|
MOVE.W D4,(A5)+ ;add x value (ip) to region
|
|
RTS
|
|
|
|
; Handle State 1000
|
|
|
|
BMRState8
|
|
MOVE.W D4,(A5)+
|
|
BSR.S Gen1InvPoint
|
|
ADDQ.W #3,D4
|
|
RTS
|
|
|
|
; Handle State 1001
|
|
|
|
BMRState9
|
|
MOVE.W D4,(A5)+
|
|
BSR.S Gen1InvPoint
|
|
ADDQ.W #2,D4
|
|
BRA.S State1Common
|
|
|
|
; Handle State 1010 (most complicated case)
|
|
|
|
BMRState10
|
|
MOVE.W D4,(A5)+
|
|
BSR.S Gen1InvPoint
|
|
BSR.S Gen1InvPoint
|
|
BRA.S Gen1BumpBy1
|
|
|
|
; Handle State 1011
|
|
|
|
BMRState11
|
|
MOVE.W D4,(A5)+
|
|
BSR.S Gen1InvPoint
|
|
BSR.S Gen1InvPoint
|
|
ADDQ.W #2,D4
|
|
BRA.S TogStateDone
|
|
|
|
; Handle State 1100
|
|
|
|
BMRState12
|
|
MOVE.W D4,(A5)+
|
|
ADDQ.W #2,D4
|
|
MOVE.W D4,(A5)+
|
|
BRA.S BumpBy2
|
|
|
|
; Handle State 1101
|
|
|
|
BMRState13
|
|
BSR.S BMRState12
|
|
SUBQ #1,D4
|
|
BRA.S State1Common
|
|
|
|
; Handle State 1110
|
|
|
|
BMRState14
|
|
MOVE.W D4,(A5)+
|
|
ADDQ.W #3,D4
|
|
MOVE.W D4,(A5)+
|
|
BRA.S BumpBy1
|
|
|
|
; State table
|
|
|
|
BMRHandler
|
|
BRA.S BMRState0
|
|
BRA.S BMRState1
|
|
BRA.S BMRState2
|
|
BRA.S BMRState3
|
|
|
|
BRA.S BMRState4
|
|
BRA.S BMRState5
|
|
BRA.S BMRState6
|
|
BRA.S BMRState7
|
|
|
|
BRA.S BMRState8
|
|
BRA.S BMRState9
|
|
BRA.S BMRState10
|
|
BRA.S BMRState11
|
|
|
|
BRA.S BMRState12
|
|
BRA.S BMRState13
|
|
BRA.S BMRState14
|
|
|
|
; Handle State 15 or 1111
|
|
|
|
BMRState15
|
|
MOVE.W D4,(A5)+ ;generate one now
|
|
NOT.B D6 ;toggle the state
|
|
|
|
; Handle State 0 or 0000
|
|
|
|
BMRState0
|
|
ADDQ.W #4,D4
|
|
RTS
|
|
|
|
; End of the State Guys
|
|
|
|
;----------------------------------------------------------------------------------------
|
|
|
|
BMRDiff
|
|
MOVE.L D0,(A3)+ ;fix up scanline buffer for next time
|
|
|
|
; this long is different from the last one, so output a bunch
|
|
; of inversion points by pumping it through the state machine, a nibble
|
|
; at a time.
|
|
|
|
MOVEQ #3,D7 ;4 bytes to process (D7 high word clear)
|
|
MOVEQ #0,D0 ;prevent need to mask for first nibble
|
|
|
|
; here is the loop where we feed it through a nibble at a time.
|
|
; it's worth it to special case a whole byte of 0
|
|
|
|
BMRByteLoop
|
|
ROL.L #8,D1 ;get next (topmost) byte
|
|
TST.B D1 ;is it zero?
|
|
BNE.S BMRNibble ;if not, 4 bits at a time
|
|
|
|
TST.B D6
|
|
BNE.S BMRNibble ;if beam on, must pass through
|
|
|
|
;the top 8 are zero, so we can save some time
|
|
|
|
ADDQ.W #8,D4 ;bump x
|
|
BRA.S BMRNextByte
|
|
|
|
;take care of the rightmost long for a line
|
|
|
|
BMRLastLong
|
|
MOVE.L (A1),D0 ;fetch the long from the bitmap
|
|
AND.L rightMask(A6),D0 ;mask off right bits that aren't in map
|
|
BRA BMRLastLEntry ;go process this long
|
|
|
|
; handle the first nibble
|
|
|
|
BMRNibble
|
|
MOVE.B D1,D0 ;get byte
|
|
EOR.B D6,D0 ;invert nibble when beam is on
|
|
LSR.B #4,D0 ;get 1st nibble
|
|
ADD.W D0,D0 ;double for word index
|
|
|
|
JSR BMRHandler(D0.W) ;invoke the handler
|
|
|
|
; handle the second nibble
|
|
|
|
MOVE.B D1,D0 ;get byte again
|
|
EOR.B D6,D0 ;invert nibble when beam is on
|
|
AND.W #%1111,D0 ;mask to it
|
|
ADD.W D0,D0 ;double for word index
|
|
|
|
JSR BMRHandler(D0.W) ;invoke the handler
|
|
|
|
BMRNextByte
|
|
DBRA D7,BMRByteLoop ;loop for all 8 nibbles
|
|
|
|
; bump to the next long
|
|
|
|
NextBMRLong
|
|
SUBQ.W #1,D5 ;decrement longword index
|
|
BGT BMRLongLoop ;not at end, loop for whole line
|
|
BEQ.S BMRLastLong ;process last long for this line
|
|
|
|
; we've reached the end of the (this) line
|
|
BMREOL
|
|
MOVE.W A5,D7 ;current region pointer
|
|
SUB.W A2,D7 ;figga region size
|
|
CMP.W startSize(A6),D7 ;did we add inv. pts to this line?
|
|
BEQ.S BMRNoLine ;br = no, so back up
|
|
BLT BMR32KErr ;if the size decreased, we overflowed
|
|
|
|
; if the state is on, generate one last inversion point
|
|
|
|
TST.B D6
|
|
BEQ.S @1
|
|
|
|
MOVE.W D4,(A5)+ ;generate a last one
|
|
ADDQ.W #2,D7 ;keep sizable advantage
|
|
@1
|
|
|
|
; end the scan line with the traditional $7FFF
|
|
|
|
BSR.S OutputLastRgnWord
|
|
|
|
BMREOL2
|
|
ADDQ.W #1,D3 ;bump y position
|
|
MOVE.W D2,D4 ;start x at left again
|
|
ADD.W rowNumBytes(A6),A4 ;bump to next row in map
|
|
SUBQ.W #1,numLines(A6)
|
|
BGT BMRLineLoop ;if we're not done then do next line
|
|
BLT.S BMRFinis ;br if really done
|
|
|
|
; as the last line process an imaginary line of zeroes to end the regionÉ
|
|
MOVE.L rowLongs(A6),D0
|
|
ASL.L #2,D0 ;longs => bytes
|
|
_NewHandle clear ;get a full line of zero bits
|
|
BNE.S BMRBadEmpty ;if we failed then return a NIL handle
|
|
MOVE.L A0,lastLineH(A6) ;save handle
|
|
MOVE.L (A0),A4 ;start of current line
|
|
BRA BMRHScramLine ;do this last one (and rederef handle)
|
|
|
|
BMRNoLine
|
|
SUBQ.L #2,A5 ;back up pointer
|
|
SUBQ.W #2,D7 ;back down size
|
|
BRA.S BMREOL2 ;go for next line
|
|
|
|
; Append the "end of line" token to the region
|
|
|
|
OutputLastRgnWord
|
|
MOVE.W #$7FFF,D0
|
|
|
|
; OutputRgnWord takes the word in D0, appends it to the region,
|
|
; and leaves the condition codes set for ADDQ.W D7 (which contains the length)
|
|
|
|
OutputRgnWord
|
|
MOVE.W D0,(A5)+ ;put a word to the region
|
|
ADDQ.W #2,D7 ;ink the size
|
|
RTS
|
|
|
|
|
|
; all done so clean up, output the final $7FFF
|
|
BMRFinis
|
|
MOVE.L lastLineH(A6),A0
|
|
_DisposHandle ;get rid of that last line of zeroes
|
|
|
|
CMP.W #10,D7 ;is region empty of inversion points?
|
|
BEQ.S BMREmptyOut ;skip if so (it's an empty region)
|
|
|
|
BSR.S OutputLastRgnWord ;put End-O-Region ($7FFF) word
|
|
BMI.S BMR32KErr ;if we went negative, we overflowed!
|
|
|
|
; find the smallest rectangle that encompasses all the inversion points
|
|
; A0 will point to the current region word, A1 to the start of the line
|
|
; D1 will have the smallest x, D2 the largest x, D4 will contain $7FFF
|
|
; D3 gets the smallest y value (which we know at the start)
|
|
|
|
LEA rgnData(A2),A0 ;point A0 past the rgnBBox
|
|
MOVE.W #$7FFF,D4
|
|
MOVE.W D4,D1 ;smallest x so far = $7FFF
|
|
MOVE.W #$8000,D2 ;largest x so far = -32768
|
|
MOVE.W (A0),D3 ;smallest y there is
|
|
BRA.S BMRPackStart ;enter loop
|
|
|
|
BMRPackY
|
|
MOVE.L A0,A1 ;remember where the y value is (sort of)
|
|
|
|
CMP.W (A0)+,D1 ;less than smallest x so far?
|
|
BLE.S @1 ;skip if not
|
|
MOVE.W -2(A0),D1 ;new smallest x
|
|
|
|
@1 CMP.W (A0)+,D4 ;end of line?
|
|
BNE.S @1 ;if not then keep looking
|
|
|
|
CMP.W -4(A0),D2 ;last x greater than largest x so far?
|
|
BGE.S BMRPackStart ;skip if not
|
|
MOVE.W -4(A0),D2 ;new largest x
|
|
|
|
BMRPackStart
|
|
MOVE.W (A0)+,D0 ;get next word (y value or $7FFF)
|
|
CMP.W D4,D0 ;if $7FFF then we're done
|
|
BNE.S BMRPackY ;otherwise loop
|
|
|
|
SWAP D3 ;top into top word
|
|
MOVE.W D1,D3 ;left into bottom word
|
|
MOVE.W -2(A1),D4 ;bottom (from last y at start of line)
|
|
SWAP D4 ;move bottom to high word
|
|
MOVE.W D2,D4 ;get right
|
|
|
|
CMP.W #28,D7 ;size = 28? (do we have a rect. region?)
|
|
BEQ.S BMRRect ;skip if so
|
|
|
|
BRA.S BMROut ;return complex region
|
|
|
|
;the region would exceed 32K, so we have to error out, man
|
|
BMR32KErr
|
|
MOVE.W #rgnTooBigErr,D0 ;if >32K needed return error
|
|
|
|
;we come here after failing a SetHandleSize (or NewHandle)
|
|
BMRBadEmpty
|
|
MOVE.W D0,result(A6) ;OSErr function result
|
|
|
|
; emptify the region on errors (or when it should be empty with no error)
|
|
BMREmptyOut
|
|
MOVE.L regionH(A6),A0 ;handle to region
|
|
MOVE.L (A0),A2 ;point to it
|
|
CLR.L D3 ;(0, 0) to topLeft
|
|
CLR.L D4 ;(0, 0) to botRight
|
|
|
|
BMRRect
|
|
MOVEQ #10,D7 ;the size of the region = 10
|
|
|
|
;output the region with size (longword, high word clear) in D7
|
|
;D3 comes in with topLeft, D4 with botRight
|
|
BMROut
|
|
MOVE.W D7,(A2)+ ;the size of the region
|
|
MOVE.L D3,(A2)+ ;topLeft to rgnBBox
|
|
MOVE.L D4,(A2) ;botRight to rgnBBox
|
|
MOVE.L D7,D0 ;size
|
|
MOVE.L regionH(A6),A0 ;handle to region
|
|
_SetHandleSize
|
|
|
|
BMRDspSL
|
|
MOVE.L slHandle(A6),A0
|
|
_DisposHandle ;get rid of the scanline buffer (even if NIL)
|
|
|
|
BMRDone
|
|
MOVEM.L (SP)+,A2-A5/D3-D7 ;restore work registers
|
|
UNLK A6
|
|
MOVE.L (SP)+,A0 ;pop return address
|
|
ADD #paramSize,SP ;pop params
|
|
JMP (A0)
|
|
ENDWITH
|
|
|
|
;-------------End of BitMap to Region Code Addition 11/6/89 --------------
|
|
|