-- File CIFVersatecUtils.mesa
-- Written by Martin Newell, June 1980
-- Last updated: July 21, 1981 2:37 PM

DIRECTORY

CIFDevicesDefs: FROM "CIFDevicesDefs" USING [MaxLENGTHLayerArray],
CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [ScreenParams],
CIFVersatecScanDefs: FROM "CIFVersatecScanDefs" USING
[VersatecScanConvert],
CIFVersatecTypeDefs: FROM "CIFVersatecTypeDefs" USING [Edge,
EdgeRecord, EdgeAngle],
CIFVersatecUtilsDefs: FROM "CIFVersatecUtilsDefs" USING
[VStripeWidth],
InlineDefs: FROM "InlineDefs" USING[LongCOPY],
Mopcodes: FROM "Mopcodes" USING [zWBL],
SegmentDefs: FROM "SegmentDefs" USING[NewDataSegment, DefaultXMBase,
LongDataSegmentAddress],
SystemDefs: FROM "SystemDefs" USING[AllocateHeapNode, FreeHeapNode],
TrapezoidDefs: FROM "TrapezoidDefs" USING[TrapezoidBlock, TrapezoidBlt],
VersatecDefs: FROM "VersatecDefs" USING [StartVersatecPlot, EndVersatecPlot,
WriteVersatecLine];

CIFVersatecUtils: PROGRAM
IMPORTS CIFUtilitiesDefs, CIFVersatecScanDefs, InlineDefs, SegmentDefs, SystemDefs, TrapezoidDefs, VersatecDefs
EXPORTS CIFVersatecUtilsDefs =

BEGIN OPEN CIFDevicesDefs, CIFUtilitiesDefs, CIFVersatecScanDefs, CIFVersatecTypeDefs, CIFVersatecUtilsDefs, InlineDefs, Mopcodes, SegmentDefs, SystemDefs, TrapezoidDefs, VersatecDefs;

VersatecNextStripe: PUBLIC PROCEDURE =
BEGIN --finish off and output current stripe, and step to next
VersatecScanConvert[VStripeTop, FALSE];
VersatecScanConvert[VStripeTop, TRUE];
VersatecOutStripe[];
VersatecClearStripe[TRUE];
VStripeBottom ← VStripeTop;
VStripeTop ← VStripeTop + VStripeHeight;
END;

OutputStripesUntil: PUBLIC PROCEDURE[y: REAL] =
BEGIN
WHILE y>=VStripeTop DO VersatecNextStripe[]; ENDLOOP;
END;

VersatecMakeEdge: PUBLIC PROCEDURE [xstart,ystart,xend,yend: REAL, up: BOOLEAN]
RETURNS[edge: Edge] =
BEGIN
--make edge of appropriate type
dx: REAL;
dy: REAL ← yend-ystart;
IF dy<=0 THEN RETURN[NIL];
dx ← xend-xstart;
IF dx=0 THEN
BEGIN --make vertical edge
edge ← AllocateVerticalEdge[];
edge↑ ← [
next: ,
xstart: xstart,
ystart: ystart,
yend: yend,
lastouty: ystart,
mate: NIL,
up: up,
flagout: FALSE,
vert: TRUE,
var: vertical[]
];
END
ELSE
BEGIN --make oblique edge
edge ← AllocateObliqueEdge[];
edge↑ ← [
next: ,
xstart: xstart,
ystart: ystart,
yend: yend,
lastouty: ystart,
mate: NIL,
up: up,
flagout: FALSE,
vert: FALSE,
var: oblique[
xend: xend,
slope: dx/dy
]
];
END;
RETURN[edge];
END;

VersatecAllocateStripe: PUBLIC PROCEDURE =
BEGIN
--allocate space for VStripeHeight+1 lines (last one never output, but copied to 1st after buffer output to provide overlap)
vPages: CARDINAL;
[DisplayLongAddress, DisplayWidthWords, ] ← ScreenParams[];
VStripeWidthWords ← (VStripeWidth+15)/16;
VStripeWidthBytes ← VStripeWidthWords*2;
VStripeWords ← VStripeWidthWords*(VStripeHeight+1);
vPages ← (VStripeWords+255)/256;
VStripeLongAddress ← LongDataSegmentAddress[NewDataSegment[DefaultXMBase,vPages]];
END;

MakeLongPointer: PROCEDURE[low,high: UNSPECIFIED]
RETURNS[LONG POINTER] = MACHINE CODE
BEGIN --nothing to do-- END;

BreakLongPointer: PROCEDURE[lptr: LONG POINTER]
RETURNS[low,high: UNSPECIFIED] = MACHINE CODE
BEGIN --nothing to do-- END;


VersatecOutStripe: PUBLIC PROCEDURE =
BEGIN
--***copy part to screen for testing
versatecAddress: LONG POINTER ← VStripeLongAddress;
displayAddress: LONG POINTER ← DisplayLongAddress;
offset: CARDINAL ← MAX[0,DisplayOffset];
offset ← MIN[VStripeWidthWords-DisplayWidthWords,offset];
THROUGH [1..VStripeHeight] DO
LongCOPY[versatecAddress+offset,DisplayWidthWords,displayAddress];
WriteVersatecLine[versatecAddress, VStripeWidthBytes];
versatecAddress ← versatecAddress + VStripeWidthWords;
displayAddress ← displayAddress + DisplayWidthWords;
ENDLOOP;
END;

VersatecClearStripe: PUBLIC PROCEDURE[overlap: BOOLEAN] =
--If overlap then copy line number VStripeHeight to line number 0 and
-- clear lines 1..VStripeHeight inclusive, otherwise
-- clear lines 0..VStripeHeight inclusive
BEGIN
first: CARDINAL;
IF overlap THEN
BEGIN
--copy line number VStripeHeight to line number 0
LongCOPY[VStripeLongAddress + VStripeWords - VStripeWidthWords,
VStripeWidthWords, VStripeLongAddress];
first ← VStripeWidthWords;
END
ELSE first ← 0;
--clear lines first..VStripeHeight inclusive
LongStore[0,VStripeLongAddress + first]; --zero in 1st word
LongCOPY[VStripeLongAddress + first, VStripeWords - first - 1,
VStripeLongAddress + first + 1]; --copy it to all others
END;

LongStore: PROCEDURE[v: UNSPECIFIED, address: LONG POINTER] = MACHINE CODE
BEGIN zWBL,0; END;

LoadStipple: PUBLIC PROCEDURE[layer:CARDINAL, v0,v1,v2,v3: CARDINAL] =
BEGIN
Stipple[layer] ← [v0,v1,v2,v3];
END;

AllocateVerticalEdge: PUBLIC PROCEDURE RETURNS[Edge] =
BEGIN
RETURN[AllocateHeapNode[SIZE[vertical EdgeRecord]]];
END;

AllocateObliqueEdge: PUBLIC PROCEDURE RETURNS[Edge] =
BEGIN
RETURN[AllocateHeapNode[SIZE[oblique EdgeRecord]]];
END;

FreeEdge: PUBLIC PROCEDURE[edge: Edge] =
BEGIN
FreeHeapNode[edge];
END;

--

EdgeLessThan: PUBLIC PROCEDURE[e1,e2: Edge, y: REAL] RETURNS[BOOLEAN] =
BEGIN
--orders up/down within slope within x
x1: REAL ← XatY[e1,y];
x2: REAL ← XatY[e2,y];
RETURN[x1<x2 OR (x1=x2 AND (Slope[e1]<Slope[e2] OR (Slope[e1]=Slope[e2] AND e1.up)))];
END;

XatY: PUBLIC PROCEDURE[edge: Edge, y: REAL] RETURNS[x: REAL] =
BEGIN
RETURN[
WITH e:edge SELECT IF edge.vert THEN vertical ELSE oblique FROM
oblique => --i.e. oblique
SELECT TRUE FROM
y=e.ystart => e.xstart,
y=e.yend => e.xend,
ENDCASE => e.xstart + (y-e.ystart)*e.slope, --must compute from consistent end!
ENDCASE => edge.xstart --i.e. vertical
];
END;

Slope: PROCEDURE[edge: Edge] RETURNS[slope: REAL] = INLINE
BEGIN
RETURN[WITH e:edge SELECT IF edge.vert THEN vertical ELSE oblique FROM
oblique => e.slope,
ENDCASE => 0 --i.e.vertical
];
END;

black: ARRAY [0..4) OF CARDINAL ← [177777B,177777B,177777B,177777B];

InitVersatecOut: PUBLIC PROCEDURE[fileName: STRING, height: CARDINAL] =
BEGIN
IF VStripeLongAddress=NIL THEN VersatecAllocateStripe[];
VersatecClearStripe[FALSE]; --clear overlap line
VStripeBottom ← 0;
VStripeTop ← VStripeHeight;
StartVersatecPlot[fileName, VStripeWidth, height];
END;

FinishVersatecOut: PUBLIC PROCEDURE[y: REAL] =
BEGIN
UNTIL VStripeBottom>y+1 DO --1+ is kludge to make sure it all gets out
VersatecNextStripe[];
ENDLOOP;
VersatecOutStripe[];
EndVersatecPlot[];
END;

HorLine: PUBLIC PROCEDURE[xleft,xright,y: REAL] =
BEGIN
t: TrapezoidBlock;
IF xleft=xright THEN RETURN;
t ← [
ystart: y - VStripeBottom,
yend: y - VStripeBottom,
xsleft: xleft,
xsright: xright,
xeleft: xleft,
xeright: xright,
function: paint,
xbase: VStripeLongAddress,
xwords: VStripeWidthWords,
texture: @black
];
TrapezoidBlt[@t];
END;

DrawTrap: PUBLIC PROCEDURE[left: Edge, ystart: REAL, right: Edge, yend: REAL, layer: CARDINAL] =
BEGIN --draw left and right edges
--left edge
t: TrapezoidBlock ← [
ystart: ystart - VStripeBottom,
yend: yend - VStripeBottom,
xsleft: XatY[left,ystart],
xsright: ,
xeleft: XatY[left,yend],
xeright: ,
function: paint,
xbase: VStripeLongAddress,
xwords: VStripeWidthWords,
texture: @black
];
t.xsright ← t.xsleft;
t.xeright ← t.xeleft;
TrapezoidBlt[@t];
--stipple
t.xsright ← XatY[right,ystart];
t.xeright ← XatY[right,yend];
t.texture ← @Stipple[layer];
TrapezoidBlt[@t];
--right edge
t.xsleft ← t.xsright;
t.xeleft ← t.xeright;
t.texture ← @black;
TrapezoidBlt[@t];
END;

VStripeLongAddress: LONG POINTER ← NIL; --full address of versatec bitmap buffer
DisplayLongAddress: LONG POINTER; --full address of display bitmap buffer
DisplayWidthWords: CARDINAL;
DisplayOffset: INTEGER ← 0; --in words - controls what part of VStripe is copied to screen. Set in debugger

VStripeBottom,VStripeTop: REAL; --limits to be mapped onto current stripe
VStripeHeight: CARDINAL = 128; --this MUST be a multiple of 4 for stipple phase to work
--***should be wired to required buffer height
VStripeWidthWords: CARDINAL; --required buffer width in words
VStripeWidthBytes: CARDINAL; --required buffer width in bytes
VStripeWords: CARDINAL;
--required buffer size in words

Stipple: ARRAY [0..MaxLENGTHLayerArray) OF ARRAY [0..4) OF CARDINAL ←
ALL[[177777B,177777B,177777B,177777B]];--undef

--Set up default stipples
Stipple[0] ← [ 0, 0,010421B, 0];
--implant
Stipple[1] ← [042104B,010421B,042104B,010421B];
--diffusion
Stipple[2] ← [010421B,104210B,042104B,021042B];
--poly
Stipple[3] ← [167356B,135673B,114631B,073567B];
--contact
Stipple[4] ← [ 0, 0,021042B,104210B];
--metal
Stipple[5] ← [ 0,021042B,042104B,104210B];
--buried
Stipple[6] ← [ 0,021042B,052525B,021042B];
--glass
Stipple[7] ← [177777B,177777B,177777B,177777B];
--undef


END.