--d.wyatt December 11, 1980  9:34 AM
--nbitmapfns.mesa
DIRECTORY
	BitBltDefs: FROM "BitBltDefs",
	LongDefs: FROM "LongDefs", --long BITBLT different for D0,Alto
	GeneralDisplayDefs: FROM "GeneralDisplayDefs",
	GraphicsDefs: FROM "GraphicsDefs",
	InlineDefs: FROM "InlineDefs",
	SystemDefs: FROM "SystemDefs",
	SegmentDefs: FROM "SegmentDefs";

BitmapFns: PROGRAM IMPORTS LongDefs, InlineDefs, SegmentDefs, SystemDefs EXPORTS GraphicsDefs =
BEGIN OPEN GeneralDisplayDefs;

Machine: SegmentDefs.MachineType = SegmentDefs.GetMemoryConfig[].AltoType;
DMachine: BOOLEAN = (Machine = D0) OR (Machine = Dorado);

Screen: POINTER TO GraphicsDefs.Bitmap ← NIL;
Scale: PROCEDURE [factor,c: CARDINAL] RETURNS [CARDINAL] = INLINE
BEGIN RETURN[(CARDINAL[c*factor])/10];END;

--data structures for D0 style color display
colorData: TYPE = MACHINE DEPENDENT RECORD
 [	addr: [0..16),
	r,g,b,unused: BOOLEAN,
	data: [0..256)
 ];
colorEntry: TYPE = RECORD
 [	red,green,blue: colorData
 ];
colorTable: TYPE = RECORD --must be hexAligned
 [	front: ARRAY [0..2) OF UNSPECIFIED,
	entry: ARRAY [0..16) OF colorEntry,
	back: ARRAY [0..10) OF UNSPECIFIED,
	hexAlignPad: ARRAY [0..16) OF UNSPECIFIED
 ];

--data structures for D1 style color display from GeneralDisplayDefs

--data structure for Alto type displays
DCB: TYPE = MACHINE DEPENDENT RECORD 
	[ Link: POINTER TO DCB,
	  Resolution: [0..1],
	  Invert: [0..1],
	  Offset: [0..100B),
	  Width: [0..400B),
	  Bitmap: POINTER TO ARRAY OF UNSPECIFIED,
	  Long: BOOLEAN,
	  Height: [0..77777B],
	  LongBitmap: LONG POINTER TO ARRAY OF UNSPECIFIED
	];
DCBSeal: POINTER = LOOPHOLE[177423B];

--global variables
ColorBitmap: POINTER TO POINTER = LOOPHOLE[414B];
ColorBitmapBank: POINTER TO CARDINAL = LOOPHOLE[415B];
ColorMap: POINTER TO POINTER = LOOPHOLE[416B];
ColorMapBank: POINTER TO CARDINAL = LOOPHOLE[417B];
ColorCtrlBlk: ColorControlBlock;
AChanCtrlBlk: ChannelControlBlock;
ColorMonitor: MonitorControlBlock;
cx: ARRAY [0..SIZE[colorTable]] OF UNSPECIFIED;
ColorTable: POINTER TO colorTable ← @cx[LOOPHOLE[@cx,CARDINAL] MOD 16];
ColorTable8: POINTER TO ATableImage;
x,xx: ARRAY [0..SIZE[BitBltDefs.BBTable]] OF UNSPECIFIED;
DCBhead: POINTER TO POINTER TO DCB = LOOPHOLE[420B];
SetPointBLT: POINTER TO BitBltDefs.BBTable ←
	@x[LOOPHOLE[@x,CARDINAL] MOD 2];
BLT: POINTER TO BitBltDefs.BBTable ←
	@xx[LOOPHOLE[@xx,CARDINAL] MOD 2];

DefaultAllocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER] ← 
BEGIN
IF DMachine THEN RETURN [SegmentDefs.LongDataSegmentAddress[
					SegmentDefs.NewDataSegment[
						SegmentDefs.DefaultXMBase,(nwords+255)/256]]]
ELSE RETURN[SystemDefs.AllocateSegment[nwords]];
END;
DefaultFree: PROCEDURE [XVM: LONG POINTER] ←
BEGIN
IF DMachine THEN
	SegmentDefs.DeleteDataSegment[SegmentDefs.LongVMtoDataSegment[XVM]]
ELSE SystemDefs.FreeSegment[InlineDefs.LowHalf[XVM]];
END;

SetXMAlloc: PUBLIC PROCEDURE [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER]] =
BEGIN
DefaultAllocate ← Allocate;
DefaultFree ← Free;
END;

GetXMAlloc: PUBLIC PROCEDURE RETURNS [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER]] =
BEGIN
RETURN[DefaultAllocate,DefaultFree];
END;

--even dot distribution, maximum flicker
--GrayThresholds: ARRAY [0..16) OF CARDINAL ←
--	[	00,08,02,10, 
--		14,04,12,06,
--		03,11,01,09,
--		13,07,15,05	
--	];
GrayThresholds: ARRAY [0..16) OF CARDINAL ←
	[	15,01,05,11, --minimum flicker
		06,08,12,02,
		07,09,13,03,	
		14,00,04,10 
	];
GrayLevel: CARDINAL ← 0;
Gray0,Gray1,Gray2,Gray3: CARDINAL ← 177777B;

SetGrayThresholds: PUBLIC PROCEDURE [new: POINTER TO ARRAY [0..0) OF CARDINAL,
outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	1=> 
		BEGIN
		i: CARDINAL;
		FOR i IN [0..16] DO GrayThresholds[i] ← new[i];
		ENDLOOP;
		END;
	4=>
		BEGIN 
		i: CARDINAL;
		ColorTable.front ← ALL[0];
		ColorTable.back ← ALL[0];
		FOR i IN [0..17B] DO
			ColorTable.entry[i].red ← [i,TRUE,FALSE,FALSE,FALSE,new[i]];
			ColorTable.entry[i].green ← [i,FALSE,TRUE,FALSE,FALSE,new[i]];
			ColorTable.entry[i].blue ← [i,FALSE,FALSE,TRUE,FALSE,new[i]];
		ENDLOOP;
		END;
	8=>
		BEGIN
		i: CARDINAL;
		FOR i IN [0..1024) DO
			ColorTable8[i].zeroHigh ← ColorTable8[i].zeroLow ← 0;
		ENDLOOP;
		FOR i IN [0..256) DO
			ColorTable8[i*4] ← [0,new[i] MOD 16,new[i],0,new[i],new[i]/16];
		ENDLOOP;
		pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
		END;
	ENDCASE=>ERROR;
END;

halftoneWord: TYPE = MACHINE DEPENDENT RECORD
 [	unused: [0..7777B],
	val1,val2,val3,val4: BOOLEAN
 ];
SetGrayLevel: PUBLIC PROCEDURE [intensity: CARDINAL,
outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
 1=>
	BEGIN
	h: halftoneWord;
	value,scanline: CARDINAL;
	
	IF GrayLevel = intensity THEN RETURN;
	GrayLevel ← intensity;
	
	FOR scanline IN [0..4) DO
		h.val1 ← intensity <= GrayThresholds[scanline*4+0];
		h.val2 ← intensity <= GrayThresholds[scanline*4+1];
		h.val3 ← intensity <= GrayThresholds[scanline*4+2];
		h.val4 ← intensity <= GrayThresholds[scanline*4+3];
		h.unused ← 0;
		value ← LOOPHOLE[h];
		value ← value + value*16;
		value ← value + value*256;
		SELECT scanline FROM
			0=> Gray0←value;
			1=> Gray1←value;
			2=> Gray2←value;
			3=> Gray3←value;
			ENDCASE;
	ENDLOOP;
	END;
 4=>
	BEGIN
	intensity ← 15 - MIN[intensity,15];
	Gray0 ← Gray1 ← Gray2 ← Gray3 ←
		intensity + intensity*16 + intensity*256 + intensity*4096;
	END;
 8=> Gray0 ← Gray1 ← Gray2 ← Gray3 ← intensity + intensity*256;
 ENDCASE=>ERROR;
BLT.gray0 ← Gray0;BLT.gray1 ← Gray1;
BLT.gray2 ← Gray2;BLT.gray3 ← Gray3;
END;

--a hack
--only works for 8 bits/pixel.  pattern is 8 bits, set low, high, gray0-gray3
SetHalfTone: PUBLIC PROCEDURE[black,white: CARDINAL, pattern: CARDINAL] =
BEGIN
i: CARDINAL;
highblack: CARDINAL ← black * 256;
highwhite: CARDINAL ← white * 256;
gray: ARRAY[0..3] OF CARDINAL ← ALL[0];
FOR i IN [0..3] DO
	gray[i] ← (IF InlineDefs.BITAND[pattern,1]=0 THEN black ELSE white);
	gray[i] ← (IF InlineDefs.BITAND[pattern,2]=0
		THEN gray[i]+highblack ELSE gray[i]+highwhite);
	pattern ← pattern/4;	--shift it
	ENDLOOP;
Gray0 ← gray[0];
Gray1 ← gray[1];
Gray2 ← gray[2];
Gray3 ← gray[3];
BLT.gray0 ← Gray0;BLT.gray1 ← Gray1;
BLT.gray2 ← Gray2;BLT.gray3 ← Gray3;
END;

SetRed: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = 
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>BEGIN ColorTable8[gray*4].redHigh ← newVal/16;
		ColorTable8[gray*4].redLow ← newVal MOD 16;
		pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
		END;
	ENDCASE;
END;

SetGreen: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = 
BEGIN 
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>BEGIN
		ColorTable8[gray*4].green ← newVal;
		pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
		END;
	ENDCASE;
END;

SetBlue: PUBLIC PROCEDURE[gray: [0..256),newVal: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] = 
BEGIN 
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>BEGIN
		ColorTable8[gray*4].blue ← newVal;
		pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
		END;
	ENDCASE;
END;

GetRed: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = 
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>RETURN[ColorTable8[gray*4].redHigh*16+ColorTable8[gray*4].redLow];
	ENDCASE=>RETURN[0];
END;

GetGreen: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = 
BEGIN 
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>RETURN[ColorTable8[gray*4].green];
	ENDCASE=>RETURN[0];
END;

GetBlue: PUBLIC PROCEDURE[gray: [0..256),outputDevice: POINTER TO GraphicsDefs.Bitmap ← NIL] RETURNS [CARDINAL] = 
BEGIN 
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
	8=>RETURN[ColorTable8[gray*4].blue];
	ENDCASE=>RETURN[0];
END;

GetGrayBlock: PUBLIC PROCEDURE RETURNS [gray0,gray1,gray2,gray3: CARDINAL] =
BEGIN RETURN [Gray0,Gray1,Gray2,Gray3];END;

SetDefaultBitmap: PUBLIC PROCEDURE [width,height: CARDINAL] =
BEGIN
IF Screen = NIL THEN --ought to be able to return a couple of screens...
	Screen ← SystemDefs.AllocateHeapNode[SIZE[GraphicsDefs.Bitmap]];
Screen.nBits ← width;
Screen.nLines ← height;
END;

TurnOnGraphics: PUBLIC PROCEDURE  [bitsPerPixel: CARDINAL ← 1,portraitMode: BOOLEAN ← TRUE,scalePercent: CARDINAL ← 100] RETURNS [POINTER TO GraphicsDefs.Bitmap] =
BEGIN
scaleFactor: CARDINAL ← scalePercent/10;
IF Screen = NIL THEN --ought to be able to return a couple of screens...
	BEGIN
	Screen ← SystemDefs.AllocateHeapNode[SIZE[GraphicsDefs.Bitmap]];
	SELECT bitsPerPixel FROM
		1=> IF portraitMode THEN
				BEGIN
				Screen.nBits ← (608*10)/scaleFactor;
				Screen.nLines ← (800*10)/scaleFactor;
				END
			ELSE
				BEGIN
				Screen.nBits ← (800*10)/scaleFactor;
				Screen.nLines ← (608*10)/scaleFactor;
				END;
		4,8=> IF portraitMode THEN
				BEGIN
				Screen.nBits ← (640*10)/scaleFactor;
				Screen.nLines ← (480*10)/scaleFactor;
				END
			ELSE
				BEGIN
				Screen.nBits ← (480*10)/scaleFactor;
				Screen.nLines ← (640*10)/scaleFactor;
				END;
		ENDCASE=> ERROR;
	END;
Screen.nBitsPerPixel ← bitsPerPixel;
Screen.portraitMode ← portraitMode;
Screen.scaleFactor ← scaleFactor;
Screen.nWords ← IF portraitMode
	THEN 2*bitsPerPixel*((Scale[scaleFactor,Screen.nBits]+31)/32)
	ELSE 2*bitsPerPixel*((Scale[scaleFactor,Screen.nLines]+31)/32) ;
SetPointBLT↑ ← [ptrs: long,pad: 0,sourcealt: FALSE,sourcetype: gray,
	dw: Screen.nBitsPerPixel,dh: 1,
	destalt: ,function: ,dbca: NIL,dbmr: ,dlx:,dty:,
	gray0: 177777B,gray1: 177777B,gray2: 177777B,gray3:177777B,
 	sbca: NIL,unused: 0,sbmr: 0,slx:,sty:,slbca:,dlbca:];
BLT↑ ← [ptrs: long,pad: 0,sourcealt: FALSE,sourcetype: gray,
	dw: ,dh: ,
	destalt: ,function: ,dbca: NIL,dbmr: ,dlx:,dty:,
	gray0: 177777B,gray1: 177777B,gray2: 177777B,gray3:177777B,
 	sbca: NIL,unused: 0,sbmr: 0,slx:,sty:,slbca:,dlbca:];
SELECT Screen.nBitsPerPixel FROM
 1=>
	BEGIN
	myDCB: POINTER TO DCB ←
		IF DMachine THEN SystemDefs.AllocateHeapNode[SIZE[DCB]+1]
		ELSE SystemDefs.AllocateSegment[Screen.nWords*Screen.nLines+SIZE[DCB]+1];
	myScreen: LONG POINTER TO ARRAY OF UNSPECIFIED ←
		IF DMachine THEN DefaultAllocate[Screen.nWords*Screen.nLines+1] ELSE NIL;
	IF InlineDefs.BITAND[LOOPHOLE[InlineDefs.LowHalf[myScreen],CARDINAL],1]=1 THEN
		myScreen←myScreen+1;
	IF InlineDefs.BITAND[LOOPHOLE[myDCB,CARDINAL],1]=1 THEN
		myDCB←myDCB+1;
	IF DMachine THEN
		BEGIN
		Screen.bank←InlineDefs.HighHalf[myScreen];
		Screen.bits←InlineDefs.LowHalf[myScreen];
		END
	ELSE
		BEGIN
		Screen.bank ← 0;
		Screen.bits ← LOOPHOLE[myDCB+SIZE[DCB]];
		END;
	myDCB↑←[Link: LOOPHOLE[0],Resolution: 0,Invert: 0,Offset: 0,
		Width: Screen.nWords,
		Bitmap: IF DMachine THEN DCBSeal ELSE LOOPHOLE[Screen.bits],
		Long: DMachine,Height: Screen.nLines/2,LongBitmap: myScreen];
	EraseArea[0,0,Screen.nBits,Screen.nLines];
	DCBhead↑←myDCB;
	END;
 4=>
	BEGIN
	normalThresholds: ARRAY [0..17B] OF CARDINAL ←
		[0,17,34,51,68,85,102,119,136,153,170,187,204,221,238,255];
	SetGrayThresholds[LOOPHOLE[@normalThresholds]];
	ColorBitmap↑ ← LOOPHOLE[0];	--InlineDefs.LowHalf[longP];
	ColorBitmapBank↑ ← 4;	--InlineDefs.HighHalf[longP];
	ColorMap↑ ← ColorTable;
	ColorMapBank↑ ← 0;
	Screen.bank ← 4;	--1;
	Screen.bits←LOOPHOLE[ColorBitmap↑];
	EraseArea[0,0,Screen.nBits,Screen.nLines];
	END;
 8=>
	BEGIN
	normalThresholds: ARRAY [0..256) OF CARDINAL;
	i: CARDINAL;
	FOR i IN [0..256) DO normalThresholds[i] ← i;ENDLOOP;
	ColorTable8 ← SystemDefs.AllocateSegment[SIZE[ATableImage]];
	Screen.bank ← 4;
	Screen.bits←NIL;
	ColorCtrlBlk ←
	 [	ATable: ColorTable8,
		BTable: NIL,CTable: NIL,MiniMixer: NIL,
		VBlank: [VBtoVS: 3,VStoVS: 3],VStoVB: 20B,VisibleLines: 240,
		HRamMaxAddr: 379,HBlank: [HBLeadLength: 6,HSTrailAddr: 47B],
		HBTrailLength: 16B,PClock: [unused: 0,PClockMul: 130B,PClockDiv: 14B],
		reserved: 0
	 ];
	AChanCtrlBlk ←
	 [	NIL,Screen.nWords,MakeLongPointer[Screen.bits,Screen.bank],
		Screen.nLines/2,Screen.nBits+377B,MarginOffset[Ramtek525],
		[unused: 0,
		 b24BitsPerPixel: FALSE,AByPass: FALSE,BByPass: FALSE,A8B2: TRUE,
		 Resolution: full,Size8: TRUE,Size4:FALSE,Size2: FALSE,Size1: FALSE
		]
	 ];
	ColorMonitor ←
	 [	177456B,[0,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE],
		@AChanCtrlBlk,NIL,@ColorCtrlBlk
	 ];
	EraseArea[0,0,Screen.nBits,Screen.nLines];
	pMonitorHead↑ ← @ColorMonitor;
	SetGrayThresholds[LOOPHOLE[@normalThresholds]];
	END;
 ENDCASE => ERROR;
RETURN[Screen];
END;

GetDefaultBitmapHandle: PUBLIC PROCEDURE RETURNS [POINTER TO GraphicsDefs.Bitmap] =
BEGIN RETURN[Screen];END;

--first, the dummy routines using default bitMap (Screen)
PutPoint: PUBLIC PROCEDURE[x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL]=
	BEGIN SetPoint[x,y,replace,b];END;
ErasePoint: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetPoint[x,y,erase,b];END;
XorPoint: PUBLIC PROCEDURE [x,y: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetPoint[x,y,invert,b];END;

PutLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetLine[x1,y1,x2,y2,replace,b];END;
EraseLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetLine[x1,y1,x2,y2,erase,b];END;
XorLine: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetLine[x1,y1,x2,y2,invert,b];END;

PutArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetArea[x1,y1,x2,y2,paint,b];END;
EraseArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetArea[x1,y1,x2,y2,erase,b];END;
XorArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetArea[x1,y1,x2,y2,invert,b];END;
ReplaceArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetArea[x1,y1,x2,y2,replace,b];END;

PutGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetGray[x1,y1,x2,y2,paint,b];END;
EraseGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetGray[x1,y1,x2,y2,erase,b];END;
XorGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetGray[x1,y1,x2,y2,invert,b];END;
ReplaceGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap ← NIL] =
	BEGIN SetGray[x1,y1,x2,y2,replace,b];END;

PutBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] =
	BEGIN SetBitmap[b,x,y,paint,dest];END;
EraseBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] =
	BEGIN SetBitmap[b,x,y,erase,dest];END;
XorBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap] =
	BEGIN SetBitmap[b,x,y,invert,dest];END;
ReplaceBitmap: PUBLIC PROCEDURE[b: POINTER TO GraphicsDefs.Bitmap,x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap]=
	BEGIN SetBitmap[b,x,y,replace,dest];END;

--and the real guys
SetPoint: PUBLIC PROCEDURE [x,y: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;
IF NOT x IN [0..b.nBits) THEN RETURN;
IF NOT y IN [0..b.nLines) THEN RETURN;	-- save your ass
IF b.portraitMode THEN
	BEGIN x ← Scale[b.scaleFactor,x];y ← Scale[b.scaleFactor,y];END
ELSE
	BEGIN t: CARDINAL ← Scale[b.scaleFactor,b.nLines-y];y ← Scale[b.scaleFactor,x];x ← t;END;
SetPointBLT.function ← fn;
SetPointBLT.dlbca ← MakeLongPointer[b.bits,b.bank];
SetPointBLT.dbmr ← b.nWords;
SetPointBLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel];
SetPointBLT.dty ← y;
LongDefs.BITBLT[SetPointBLT];
END;


MakeLongPointer: PROCEDURE [ptr: POINTER,bank: UNSPECIFIED] RETURNS [LONG POINTER] = MACHINE CODE BEGIN END;

SetLine: PUBLIC PROCEDURE [x1,y1,x2,y2: INTEGER,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
hstep,vstep,hsign,vsign,count: INTEGER;
horizontal: BOOLEAN;
xMax,yMax: INTEGER;
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;

IF b.portraitMode THEN
	BEGIN
	x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2];
	xMax ← Scale[b.scaleFactor,b.nBits];yMax ← Scale[b.scaleFactor,b.nLines];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1];x1 ← t;
	t ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t;
	xMax ← Scale[b.scaleFactor,b.nLines];yMax ← Scale[b.scaleFactor,b.nBits];
	END;

SetPointBLT.function ← fn;
SetPointBLT.dbmr ← b.nWords;
SetPointBLT.dlbca ← MakeLongPointer[b.bits,b.bank];

hstep ← x1-x2;
vstep ← y1-y2;
hsign ← IF hstep >= 0 THEN 1 ELSE -1;
vsign ← IF vstep >= 0 THEN 1 ELSE -1;
horizontal←ABS[hstep] > ABS[vstep];
count ← IF  horizontal THEN ABS[vstep]+(ABS[hstep]-ABS[vstep])/2
 ELSE ABS[hstep]+(ABS[vstep]-ABS[hstep])/2 ;

SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];SetPointBLT.dty ← y2;
IF INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN LongDefs.BITBLT[SetPointBLT];

UNTIL (x1 = x2) AND (y1 = y2) DO
	IF count >= ABS[vstep] THEN	-- go horizontal
		BEGIN
		x2 ← x2 + hsign;
		count ← count - ABS[vstep];
		IF horizontal AND INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN 
			BEGIN
			SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];
			SetPointBLT.dty ← y2;
			LongDefs.BITBLT[SetPointBLT];
			END;
		END
	ELSE BEGIN
		y2 ← y2+vsign;
		count ← count + ABS[hstep];
		IF NOT horizontal AND INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN  
			BEGIN
			SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];
			SetPointBLT.dty ← y2;
			LongDefs.BITBLT[SetPointBLT];
			END;
		END;
	ENDLOOP;
SetPointBLT.dlx ← InlineDefs.BITSHIFT[x2,logBitsPerPixel];SetPointBLT.dty ← y2;
IF INTEGER[x2] IN [0..xMax) AND INTEGER[y2] IN [0..yMax) THEN LongDefs.BITBLT[SetPointBLT];

END;

SetArea: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;

IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END;
IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END;
IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR
	INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines]
	THEN RETURN;
x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]];
x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1];
IF b.portraitMode THEN
	BEGIN
	x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1];
	x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t;
	END;

BLT.sourcetype ← gray;
BLT.function ← fn;
BLT.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.dbmr ← b.nWords;
BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.dty ← y1;
BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel];
BLT.dh ← (y2+1-y1);
BLT.gray0 ← BLT.gray1 ← BLT.gray2 ← BLT.gray3 ← 177777B;
LongDefs.BITBLT[BLT];
BLT.gray0 ← Gray0;BLT.gray1 ← Gray1;
BLT.gray2 ← Gray2;BLT.gray3 ← Gray3;
END;

SetGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,fn: BitBltDefs.BBoperation,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;

IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END;
IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END;
IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR
	INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines]
	THEN RETURN;
x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]];
x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1];
IF b.portraitMode THEN
	BEGIN
	x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1];
	x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t;
	END;

BLT.sourcetype ← gray;
BLT.function ← fn;
BLT.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.dbmr ← b.nWords;
BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.dty ← y1;
BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel];
BLT.dh ← (y2+1-y1);
BLT.sty ← 0; --DORADO looks here
LongDefs.BITBLT[BLT];
END;

MaskGray: PUBLIC PROCEDURE [x1,y1,x2,y2: CARDINAL,b: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← SELECT b.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;

IF INTEGER[x1] > INTEGER[x2] THEN BEGIN t: CARDINAL ← x1;x1 ← x2;x2 ← t;END;
IF INTEGER[y1] > INTEGER[y2] THEN BEGIN t: CARDINAL ← y1;y1 ← y2;y2 ← t;END;
IF INTEGER[x2] < 0 OR INTEGER[y2] < 0 OR
	INTEGER[x1] >= INTEGER[b.nBits] OR INTEGER[y1] >= INTEGER[b.nLines]
	THEN RETURN;
x1 ← MAX[0,INTEGER[x1]];y1 ← MAX[0,INTEGER[y1]];
x2 ← MIN [x2,b.nBits-1];y2 ← MIN[y2,b.nLines-1];
IF b.portraitMode THEN
	BEGIN
	x1 ← Scale[b.scaleFactor,x1];y1 ← Scale[b.scaleFactor,y1];x2 ← Scale[b.scaleFactor,x2];y2 ← Scale[b.scaleFactor,y2];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[b.scaleFactor,(b.nLines-1)-y1];y1 ← Scale[b.scaleFactor,x1];
	x1 ← Scale[b.scaleFactor,(b.nLines-1)-y2];y2 ← Scale[b.scaleFactor,x2];x2 ← t;
	END;

BLT.sourcetype ← andgray;
BLT.function ← replace;
BLT.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.dbmr ← b.nWords;
BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.dty ← y1;
BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel];
BLT.dh ← (y2+1-y1);
BLT.slbca ← MakeLongPointer[b.bits,b.bank];
BLT.sbmr ← b.nWords;
BLT.slx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.sty ← y1;
LongDefs.BITBLT[BLT];
END;

SetBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,
	x,y: CARDINAL,fn: BitBltDefs.BBoperation,dest: POINTER TO GraphicsDefs.Bitmap] =
BEGIN
x2,y2: CARDINAL;
sx,sy,dy: CARDINAL ← 0;
logBitsPerPixel: CARDINAL;
IF dest = NIL THEN dest ← Screen;
logBitsPerPixel ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;
x2 ← x+b.nBits-1;
y2 ← y+b.nLines-1;

IF x >= dest.nBits OR y >= dest.nLines THEN RETURN;
IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1;
IF y2 >= dest.nLines THEN BEGIN dy ← y2-(dest.nLines-1);y2 ← dest.nLines-1;END;
IF INTEGER[x] < 0 THEN BEGIN sx ← -x;x ← 0;END;
IF INTEGER[y] < 0 THEN BEGIN sy ← -y;y ← 0;END;

IF dest.portraitMode THEN
	BEGIN
	x ← Scale[dest.scaleFactor,x];y ← Scale[dest.scaleFactor,y];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2];
	sx ← Scale[dest.scaleFactor,sx];sy ← Scale[dest.scaleFactor,sy];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[dest.scaleFactor,(dest.nLines-1)-y];y ← Scale[dest.scaleFactor,x];
	x ← Scale[dest.scaleFactor,(dest.nLines-1)-y2];
	y2 ← MIN[Scale[dest.scaleFactor,x2],y+Scale[dest.scaleFactor,b.nBits]-1];x2 ← MIN[t,x+Scale[dest.scaleFactor,b.nLines]-1];
	sy ← Scale[dest.scaleFactor,sx];sx ← Scale[dest.scaleFactor,dy];
	END;

BLT.sourcetype ← block;
BLT.function ← fn;
BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank];
BLT.dbmr ← dest.nWords;
BLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel];
BLT.dty ← y;
BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x),logBitsPerPixel];
BLT.dh ← (y2+1-y);
BLT.slbca ← MakeLongPointer[b.bits,b.bank];
BLT.sbmr ← b.nWords;
BLT.slx ← InlineDefs.BITSHIFT[sx,logBitsPerPixel];
BLT.sty ← sy;
LongDefs.BITBLT[BLT];
END;

PutGrayBitmap: PUBLIC PROCEDURE [b: POINTER TO GraphicsDefs.Bitmap,
	x,y: CARDINAL,dest: POINTER TO GraphicsDefs.Bitmap ← NIL] =
BEGIN
x2,y2: CARDINAL;
sx,sy,dy: CARDINAL ← 0;
logBitsPerPixel: CARDINAL;
IF dest = NIL THEN dest ← Screen;
logBitsPerPixel ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;
x2 ← x+b.nBits-1;
y2 ← y+b.nLines-1;

IF x >= dest.nBits OR y >= dest.nLines THEN RETURN;
IF x2 >= dest.nBits THEN x2 ← dest.nBits - 1;
IF y2 >= dest.nLines THEN BEGIN dy ← y2-(dest.nLines-1);y2 ← dest.nLines-1;END;
IF INTEGER[x] < 0 THEN BEGIN sx ← -x;x ← 0;END;
IF INTEGER[y] < 0 THEN BEGIN sy ← -y;y ← 0;END;

IF dest.portraitMode THEN
	BEGIN
	x ← Scale[dest.scaleFactor,x];y ← Scale[dest.scaleFactor,y];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2];
	sx ← Scale[dest.scaleFactor,sx];sy ← Scale[dest.scaleFactor,sy];
	END
ELSE
	BEGIN t: CARDINAL;
	t ← Scale[dest.scaleFactor,(dest.nLines-1)-y];y ← Scale[dest.scaleFactor,x];
	x ← Scale[dest.scaleFactor,(dest.nLines-1)-y2];
	y2 ← MIN[Scale[dest.scaleFactor,x2],y+Scale[dest.scaleFactor,b.nBits]-1];x2 ← MIN[t,x+Scale[dest.scaleFactor,b.nLines]-1];
	sy ← Scale[dest.scaleFactor,sx];sx ← Scale[dest.scaleFactor,dy];
	END;

--first, erase
BLT.sourcetype ← block;
BLT.function ← erase;
BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank];
BLT.dbmr ← dest.nWords;
BLT.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel];
BLT.dty ← y;
BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x),logBitsPerPixel];
BLT.dh ← (y2+1-y);
BLT.slbca ← MakeLongPointer[b.bits,b.bank];
BLT.sbmr ← b.nWords;
BLT.slx ← sx;
BLT.sty ← sy;
LongDefs.BITBLT[BLT];

--now, paint gray bits
BLT.sourcetype ← andgray;
BLT.function ← paint;
LongDefs.BITBLT[BLT];
END;

TransferRectangle: PUBLIC PROCEDURE [src,dest: POINTER TO GraphicsDefs.Bitmap,
	srcRectangle,destRectangle: POINTER TO GraphicsDefs.Rectangle,
	fn: BitBltDefs.BBoperation ← replace,type: BitBltDefs.BBsourcetype ← block] =
BEGIN
srcWidth,destWidth,srcHeight,destHeight: CARDINAL;
myBitmap: GraphicsDefs.Bitmap;
myRectangle: GraphicsDefs.Rectangle;
svd: POINTER TO GraphicsDefs.Bitmap ← NIL;
svdRectangle: POINTER TO GraphicsDefs.Rectangle;
x,y,count: CARDINAL;
dy: CARDINAL ← 0;
logBitsPerPixel: CARDINAL ← SELECT dest.nBitsPerPixel FROM 1=>0,2=>1,4=>2,ENDCASE=>3;
funnyFinishProc: PROCEDURE =
	BEGIN
	BLT.slbca ← MakeLongPointer[dest.bits,dest.bank];
	BLT.dlbca ← MakeLongPointer[svd.bits,svd.bank];
	BLT.dbmr ← svd.nWords;
	BLT.slx ← BLT.sty ← 0;
	BLT.dlx ← svdRectangle.x1;
	BLT.dty ← svdRectangle.y1;
	BLT.dw ← destWidth;
	BLT.dh ← destHeight;
	BLT.sbmr ← dest.nWords;
	BLT.function ← fn;
	BLT.sourcetype ← type;
	LongDefs.BITBLT[BLT];
	SystemDefs.FreeSegment[dest.bits];
	END;

--first check trivial exclusion
IF	(srcRectangle.x1 > INTEGER[src.nBits]) OR
	(INTEGER[srcRectangle.x2] < 0) OR
	(srcRectangle.y1 > INTEGER[src.nLines]) OR
	(INTEGER[srcRectangle.y2] < 0) OR
	(INTEGER[destRectangle.x2] < 0) OR
	(INTEGER[destRectangle.y2] < 0) THEN 
		BEGIN
		gotcha: BOOLEAN;
		gotcha ← TRUE;
		RETURN;
		END;

--clipping for safety, not accuracy (will cause distortion...)
	IF CARDINAL[destRectangle.x1] >= dest.nBits OR 
		CARDINAL[destRectangle.y1] >= dest.nLines THEN RETURN;
	IF CARDINAL[destRectangle.x2] >= dest.nBits THEN 
		destRectangle.x2 ← dest.nBits-1;
	IF CARDINAL[destRectangle.y2] >= dest.nLines THEN 
		BEGIN 
		dy ← destRectangle.y2-(dest.nLines-1);
		destRectangle.y2 ← dest.nLines-1;
		END;

srcWidth ← (srcRectangle.x2 - srcRectangle.x1)+1;
destWidth ← (destRectangle.x2 - destRectangle.x1)+1;
srcHeight ← (srcRectangle.y2 - srcRectangle.y1)+1;
destHeight ← (destRectangle.y2 - destRectangle.y1)+1;

BLT.sourcetype ← type;
BLT.function ← fn;
BLT.dlbca ← MakeLongPointer[dest.bits,dest.bank];
BLT.dbmr ← dest.nWords;
BLT.slbca ← MakeLongPointer[src.bits,src.bank];
BLT.sbmr ← src.nWords;
IF srcWidth = destWidth AND srcHeight = destHeight THEN --easy
	BEGIN
	x1: CARDINAL ← destRectangle.x1;
	y1: CARDINAL ← destRectangle.y1;
	x2: CARDINAL ← destRectangle.x2;
	y2: CARDINAL ← destRectangle.y2;
	sx: CARDINAL ← srcRectangle.x1;
	sy: CARDINAL ← srcRectangle.y1;
	
	IF INTEGER[x1] < 0 THEN BEGIN sx ← sx-x1;x1 ← 0;END;
	IF INTEGER[y1] < 0 THEN BEGIN sy ← sy-y1;y1←0;END;
	IF dest.portraitMode THEN
		BEGIN
		x1 ← Scale[dest.scaleFactor,x1];y1 ← Scale[dest.scaleFactor,y1];x2 ← Scale[dest.scaleFactor,x2];y2 ← Scale[dest.scaleFactor,y2];
		BLT.slx ← InlineDefs.BITSHIFT[Scale[dest.scaleFactor,sx],logBitsPerPixel];
		BLT.sty ← Scale[dest.scaleFactor,sy];
		END
	ELSE
		BEGIN t: CARDINAL ← Scale[dest.scaleFactor,(dest.nLines-1)-y1];y1 ← Scale[dest.scaleFactor,x1];
		x1 ← Scale[dest.scaleFactor,(dest.nLines-1)-y2];y2 ← Scale[dest.scaleFactor,x2];x2 ← t;
		BLT.slx ←
			InlineDefs.BITSHIFT[Scale[dest.scaleFactor,dy+(src.nLines-1)-srcRectangle.y2],logBitsPerPixel];
		BLT.sty ← Scale[dest.scaleFactor,sx];
		IF INTEGER[BLT.slx] < 0 THEN 
			BEGIN 
			x1 ← InlineDefs.BITSHIFT[x1-BLT.slx,-logBitsPerPixel];BLT.slx←0;
			END;
		END;
	
	BLT.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel];
	BLT.dh ← (y2+1-y1);
	BLT.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
	BLT.dty ← y1;
	LongDefs.BITBLT[BLT];
	RETURN;
	END; --easy case

--rescaling case
BLT.function ← replace;
BLT.sourcetype ← block;
IF (destHeight < srcHeight) OR (fn # replace) OR (type # block) THEN
	BEGIN
	svd ← dest;
	dest ← @myBitmap;
	dest.bank ← 0;
	dest.nWords ← (destWidth+15)/16;
--note: if fn = paint:
--	1) we could allocate ((..)*srcHeight), and be smarter later
--	2) we could ignore this if destHeight=srcHeight
	dest.nLines ← destHeight;
	dest.bits ← SystemDefs.AllocateSegment[((destWidth+15)/16)*
		MAX[srcHeight,destHeight]];
	dest.nBitsPerPixel ← svd.nBitsPerPixel;
	BLT.dbmr ← dest.nWords;
	BLT.dlbca ← dest.bits;

	myRectangle ← [0,0,destWidth-1,destHeight-1];
	svdRectangle ← destRectangle;
	destRectangle ← @myRectangle;
	END;

BLT.dty ← destRectangle.y1;
BLT.dw ← dest.nBitsPerPixel;
BLT.dh ← srcHeight;
BLT.slx ← srcRectangle.x1;
BLT.sty ← srcRectangle.y1;

count ← 0;
FOR x IN [CARDINAL[destRectangle.x1]..CARDINAL[destRectangle.x2]] DO
	BLT.dlx ← x;
	LongDefs.BITBLT[BLT];
	count ← count+srcWidth;
	IF count >= destWidth THEN
	DO
		BLT.slx ← BLT.slx + 1;
		count ← count - destWidth;
		IF count < destWidth THEN BEGIN BLT.function←replace;EXIT;END;
		BLT.function←paint;
		LongDefs.BITBLT[BLT];
	ENDLOOP;
ENDLOOP;
IF destHeight = srcHeight THEN 
	BEGIN
	IF svd # NIL THEN funnyFinishProc[];
	RETURN;
	END;

BLT.dlx ← destRectangle.x1;
BLT.dw ← destWidth;
BLT.dh ← 1;
BLT.slx ← destRectangle.x1;
BLT.sbmr ← BLT.dbmr;
BLT.slbca ← BLT.dlbca;
count ← 0;
IF destHeight > srcHeight THEN
	BEGIN
	BLT.sty ← destRectangle.y1 + srcHeight-1;
	FOR y DECREASING IN [CARDINAL[destRectangle.y1]..CARDINAL[destRectangle.y2]] DO
		BLT.dty ← y;
		LongDefs.BITBLT[BLT];
		count ← count + srcHeight;
		IF count >= destHeight THEN
			BEGIN
			BLT.sty ← BLT.sty-1;
			count ← count - destHeight;
			END;
	ENDLOOP;
	END;
IF destHeight < srcHeight THEN
	BEGIN
	BLT.sty ← destRectangle.y1;
	FOR y IN [CARDINAL[destRectangle.y1]..CARDINAL[destRectangle.y2]] DO
		BLT.dty ← y;
		LongDefs.BITBLT[BLT];
		count ← count + srcHeight;
		DO
			BLT.sty ← BLT.sty+1;
			count ← count - destHeight;
			IF count < destHeight THEN BEGIN BLT.function←replace;EXIT;END;
			BLT.function←paint;
			LongDefs.BITBLT[BLT];
		ENDLOOP;
	ENDLOOP;
	END;
IF svd # NIL THEN funnyFinishProc[];
END;

END.