-- XDisplayDefs.mesa
-- Mesa 6 version (won't work on Alto)
-- Last changed by Doug Wyatt, May 31, 1980  2:17 PM

-- Extended memory display for AltoIIXM and D-machines

XDisplayDefs: DEFINITIONS =
BEGIN

XDisplayError: SIGNAL;

-- The Display Bank

-- Alto hardware limitations require all displayed bitmaps to reside
-- in the same bank. XDisplay maintains a "current display bank" which
-- is initialized (to an alternate bank if possible) when an image
-- is started.

BankIndex: TYPE = [0..3];

LPRec: TYPE = MACHINE DEPENDENT RECORD
	[ptr: POINTER, unused: [0..37777B]←0, bank: BankIndex];

LPBank: PROCEDURE[lp: LONG POINTER] RETURNS[BankIndex] =
	INLINE { RETURN[LOOPHOLE[lp,LPRec].bank] };
LPPtr: PROCEDURE[lp: LONG POINTER] RETURNS[POINTER] =
	INLINE { RETURN[LOOPHOLE[lp,LPRec].ptr] };
LP: PROCEDURE[p: POINTER, b: BankIndex] RETURNS[LONG POINTER] =
	INLINE { RETURN[LOOPHOLE[LPRec[ptr: p, bank: b]]] };

dBank: PRIVATE BankIndex; -- the current display bank
DBank: PROCEDURE RETURNS[BankIndex] = INLINE { RETURN[dBank] };

-- AllocDSegment and FreeDSegment allocate and free segments in the
-- current display bank.
AllocDSegment: PROCEDURE[pages: CARDINAL] RETURNS[LONG POINTER];
FreeDSegment: PROCEDURE[LONG POINTER];


-- Bitmaps

BitmapDescriptor: TYPE = RECORD
	[
	base: LONG POINTER,
	raster,lines: CARDINAL
	];
BMPtr: TYPE = POINTER TO BitmapDescriptor;

BMSize,BMDisplaySize: PROCEDURE[bm: BMPtr, width,height: CARDINAL];

AllocBitmap: PROCEDURE[BMPtr];
FreeBitmap: PROCEDURE[BMPtr];

ClearBitmap: PROCEDURE[bm: BMPtr];

-- Display management

maxWidth: CARDINAL = 608; -- in bits
maxHeight: CARDINAL = 808; -- in lines

DcbResolution: TYPE = MACHINE DEPENDENT {high(0),low(1)};
-- (low does not work on D-machines)

DcbBackground: TYPE = MACHINE DEPENDENT {white(0),black(1)};

Dcb: TYPE = PRIVATE MACHINE DEPENDENT RECORD
	[
	next: DcbPtr ← dcbNIL,
	resolution: DcbResolution ← high,
	background: PUBLIC DcbBackground ← white,
	indent: PUBLIC [0..77B] ← 0, -- in words
	width: PUBLIC [0..377B] ← 0, -- in words, must be even
	bitmap: POINTER ← NIL, -- must be even
	tag: MACHINE DEPENDENT {short(0),long(1)} ← short,
	height: PUBLIC [0..77777B] ← 0, -- in double scan lines
	lbitmap: LONG POINTER ← NIL
	];

DcbPtr: TYPE = POINTER TO Dcb;

dcbNIL: DcbPtr = LOOPHOLE[0];
-- This value is hardware-dependent. Use dcbNIL rather than NIL.

dcbChain: PRIVATE POINTER TO DcbPtr = LOOPHOLE[420B];

DcbArray: TYPE = PRIVATE ARRAY [0..SIZE[Dcb]+1) OF UNSPECIFIED;

DcbInit: PROCEDURE[POINTER TO DcbArray] RETURNS[DcbPtr];

-- The idea is to use DcbInit as follows
--  dcba: DcbArray;
--  dcb: DcbPtr ← DcbInit[@dcba];

EnumerateDcbs: PROCEDURE
	[Proc: PROCEDURE[DcbPtr] RETURNS[BOOLEAN]]
	RETURNS[DcbPtr];
LinesAbove: PROCEDURE[dcb: DcbPtr] RETURNS[CARDINAL];
LinesRemaining: PROCEDURE RETURNS[CARDINAL] =
	INLINE { RETURN[maxHeight-LinesAbove[dcbNIL]] };
FirstDcb: PROCEDURE RETURNS[DcbPtr] = INLINE { RETURN[dcbChain↑] };
NextDcb: PROCEDURE[dcb: DcbPtr] RETURNS[DcbPtr] = INLINE { RETURN[dcb.next] };
InsertDcb: PROCEDURE[dcb,otherdcb: DcbPtr];
RemoveDcb: PROCEDURE[dcb: DcbPtr];
Displayed: PROCEDURE[dcb: DcbPtr] RETURNS[BOOLEAN];
DcbOrigin: PROCEDURE[dcb: DcbPtr] RETURNS[CARDINAL,CARDINAL] =
	INLINE { RETURN[16*dcb.indent,LinesAbove[dcb]] };
-- DcbOrigin returns the x,y location in screen coordinates of the
-- upper left corner of a displayed bitmap.

DcbBitmap: PROCEDURE[dcb: DcbPtr, bm: BMPtr] = INLINE { pDcbBitmap↑[dcb,bm] };
pDcbBitmap: PRIVATE POINTER TO PROCEDURE[DcbPtr,BMPtr];


-- BitBlt tables and such

BBSourceType: TYPE = MACHINE DEPENDENT {block,complement,andgray,gray};
-- block:      BBSourceType=0   Source = SourceBitmap
-- complement: BBSourceType=1   Source = NOT SourceBitmap
-- andgray:    BBSourceType=2   Source = SourceBitmap AND GrayBlock
-- gray:       BBSourceType=3   Source = GrayBlock

BBOperation: TYPE = MACHINE DEPENDENT {replace,paint,invert,erase};
-- replace: BBOperation=0   Destination ← Source
-- paint:   BBOperation=1   Destination ← Source OR Destination
-- invert:  BBOperation=2   Destination ← Source XOR Destination
-- erase:   BBOperation=3   Destination ← (NOT Source) AND Destination

BBTable: TYPE = PRIVATE MACHINE DEPENDENT RECORD
	[ 
	ptrs: MACHINE DEPENDENT {Alto, D0} ← Alto, -- use short (Alto) or long (D0) pointers
	pad: [0..777B] ← 0,
	sourcealt: BOOLEAN ← FALSE, -- TRUE to use alternate memory bank
	destalt: BOOLEAN ← FALSE, -- TRUE to use alternate memory bank
	sourcetype: PUBLIC BBSourceType ← gray,
	operation: PUBLIC BBOperation ← replace,
	unused: CARDINAL ← 0,
	dbca: POINTER ← NIL, -- destination BaseCoreAddress
	dbmr: CARDINAL ← 0, -- destination raster width(in words)
	dlx: PUBLIC CARDINAL ← 0, -- destination left x
	dty: PUBLIC CARDINAL ← 0, -- destination top y
	dw: PUBLIC CARDINAL ← 0, -- destination width
	dh: PUBLIC CARDINAL ← 0, -- destination height
	sbca: POINTER ← NIL, -- source BaseCoreAddress
	sbmr: CARDINAL ← 0, -- source raster width(in words)
	slx: PUBLIC CARDINAL ← 0, -- source left x
	sty: PUBLIC CARDINAL ← 0, -- source top y
	gray: PUBLIC ARRAY [0..4) OF CARDINAL ← [0,0,0,0], -- four words of "gray"
	-- used only by Long BitBlt (D-machines)
	slbca: LONG POINTER ← NIL, -- source long BaseCoreAddress
	dlbca: LONG POINTER ← NIL, -- destination long BaseCoreAddress
	-- not used by BitBlt; may be used for bounds checking
	sbmh,dbmh: CARDINAL ← 0 -- source and destination bitmap heights
	];

BBPtr: TYPE = POINTER TO BBTable;

BBArray: TYPE = PRIVATE ARRAY [0..SIZE[BBTable]+1) OF UNSPECIFIED;
BBAPtr: TYPE = POINTER TO BBArray;

BBInit: PROCEDURE[BBAPtr] RETURNS[BBPtr];

-- The idea is to use BBInit as follows
--  bba: BBArray;
--  bb: BBPtr ← BBInit[@bba];

BBSource: PROCEDURE[bb: BBPtr, bm: BMPtr] =
	INLINE {
	bb.sbca←LPPtr[bb.slbca←bm.base]; bb.sourcealt←LPBank[bm.base]#0;
	bb.sbmr←bm.raster; bb.sbmh←bm.lines;
	};

BBDest: PROCEDURE[bb: BBPtr, bm: BMPtr] =
	INLINE {
	bb.dbca←LPPtr[bb.dlbca←bm.base]; bb.destalt←LPBank[bm.base]#0;
	bb.dbmr←bm.raster; bb.dbmh←bm.lines;
	};

-- The following should be set before BitBlt is called
--  sourcetype, operation, BBDest, dlx,dty, dw,dh (always)
--  BBSource, slx,sty (if sourcetype is block, complement, or andgray)
--  gray (if sourcetype is andgray or gray)

BitBlt: PROCEDURE[bb: BBPtr] = INLINE { pBitBlt↑[bb,LPBank[bb.dlbca]] };
pBitBlt: PRIVATE POINTER TO PROCEDURE[BBPtr,BankIndex];

XDisplay: PROGRAM;

END.