--color screenfns
--M. Stone May 12, 1981 6:21 PM
DIRECTORY
ScreenDefs: FROM "ScreenDefs",
GraphicsDefs: FROM "GraphicsDefs",
GeneralDisplayDefs: FROM "GeneralDisplayDefs",
BcplOps: FROM "BcplOps",
PointDefs: FROM "PointDefs" USING [ScrPt,X,Y],
InlineDefs: FROM "InlineDefs",
ImageDefs: FROM "ImageDefs",
MiscDefs: FROM "MiscDefs",
BitBltDefs: FROM "BitBltDefs",
GriffinMemoryDefs: FROM "GriffinMemoryDefs",
DisplayDefs: FROM "DisplayDefs",
EncodingDefs: FROM "EncodingDefs",
SegmentDefs: FROM "SegmentDefs",
HBltDefs: FROM "HBltDefs",
AltoDefs: FROM "AltoDefs",
AltoDisplay: FROM "AltoDisplay",
ControllerDefs: FROM "ControllerDefs",
GriffinDefs: FROM "GriffinDefs";
ScreenFns: PROGRAM IMPORTS InlineDefs,GriffinMemoryDefs, DisplayDefs,MiscDefs,SegmentDefs,
ImageDefs,GriffinDefs, BitBltDefs, HBltDefs, GraphicsDefs, ControllerDefs EXPORTS ScreenDefs =
BEGIN OPEN ScreenDefs,PointDefs;
memConfig: SegmentDefs.MemoryConfig ← SegmentDefs.GetMemoryConfig[];
alto: BOOLEAN ← (memConfig.AltoType=AltoIIXM);
CUItem: ImageDefs.CleanupItem ← [NIL,ImageDefs.CleanupMask[Finish]+ImageDefs.CleanupMask[Abort],Cleanup];
ColorCUItem: ImageDefs.CleanupItem ← [NIL,ImageDefs.AllReasons,ColorCleanup];
currentScreen: Screen ← [[0,0,0,0,NIL], 0,0,0,0];
TY,BY,LX,RX: INTEGER;
initTY,initBY,initLX,initRX: INTEGER;
CLIP: BOOLEAN ← TRUE;
CULL: BOOLEAN ← FALSE;
FNC: BitBltDefs.BBoperation;
HBltBBT: HBltDefs.HBptr;
BBT,FillBBT,hgridBBT,vgridBBT,ScanBBT: BitBltDefs.BBptr;
BLTBank: SegmentDefs.BankIndex ← 0;
DCBBank: POINTER TO CARDINAL = LOOPHOLE[177751B];
myDCB: POINTER TO AltoDisplay.LongDCB;
color: DisplayDefs.Background ← white;
FIRSTSCREEN: BOOLEAN ← TRUE;
allOnes: ARRAY[0..3] OF CARDINAL ← ALL[177777B];
hgrid: ARRAY[0..3] OF CARDINAL ← [100200B,77577B ,100200B,0];
colorScreen: POINTER TO GraphicsDefs.Bitmap ← NIL;
--returns the current screen
GetCurrentScreen: PUBLIC PROCEDURE RETURNS[ScreenPtr] =
BEGIN
RETURN[@currentScreen];
END;
--clears the current screen
ClearScreen: PUBLIC PROCEDURE =
BEGIN
tl: ScrPt ← [LX,TY];
br: ScrPt ← [RX,BY];
EraseBox[tl,br];
END;
--defines the current screen
SetScreen: PUBLIC PROCEDURE [screen: ScreenPtr] =
BEGIN OPEN AltoDisplay;
currentScreen ← screen↑;
BLTBank ← currentScreen.bitmap.bank;
hgridBBT.dbmr ← vgridBBT.dbmr ← BBT.dbmr ← ScanBBT.dbmr ← FillBBT.dbmr ← HBltBBT.dbmr
← screen.bitmap.nWords;
IF alto THEN BEGIN
hgridBBT.dbca ← vgridBBT.dbca ← BBT.dbca ← ScanBBT.dbca ←
FillBBT.dbca ← HBltBBT.dbca ← screen.bitmap.bits;
hgridBBT.destalt ← vgridBBT.destalt ← BBT.destalt ← ScanBBT.destalt ←
FillBBT.destalt ← HBltBBT.destalt ← screen.bitmap.bank#0;
hgridBBT.unused ← vgridBBT.unused ← BBT.unused ← ScanBBT.unused ←
FillBBT.unused ← screen.bitmap.bank;
END
ELSE BEGIN
hgridBBT.sbca ← BBT.sbca ← ScanBBT.sbca ← FillBBT.sbca ← NIL;
hgridBBT.dbca ← vgridBBT.dbca ← BBT.dbca ← ScanBBT.dbca ←
FillBBT.dbca ← NIL;
hgridBBT.dlbca ← vgridBBT.dlbca ← BBT.dlbca ← ScanBBT.dlbca ←
FillBBT.dlbca ← MakeLongPointer[screen.bitmap.bits,BLTBank];
vgridBBT.slbca ← BASE[vgrid];
END;
hgridBBT.ptrs ← vgridBBT.ptrs ← BBT.ptrs ← ScanBBT.ptrs ←
FillBBT.ptrs ← (IF alto THEN short ELSE long);
initLX ←LX ← currentScreen.lx;
initRX ←RX ← currentScreen.rx;
initTY ←TY ← currentScreen.ty;
initBY ←BY ← currentScreen.by;
--this clears the entire bitmap
CLIP ← FALSE;
EraseBox[[0,0],[screen.bitmap.nBits,screen.bitmap.nLines]];
CLIP ← FALSE;
myDCB ← AllocateEven[SIZE[LongDCB]];
myDCB↑←[next: DCBnil, resolution: high, background: white, indenting: 0,width: screen.bitmap.nWords, bitmap: (IF alto THEN screen.bitmap.bits ELSE LOOPHOLE[177423B]), tag: (IF alto THEN short ELSE long), height: screen.bitmap.nLines/2, longBitmap: (IF alto THEN NIL ELSE MakeLongPointer[screen.bitmap.bits,BLTBank])];
DisplayDefs.DisplayOff[color];
DCBchainHead↑←LOOPHOLE[myDCB];
IF alto THEN BEGIN
DCBBank↑ ← 4*screen.bitmap.bank;
ImageDefs.AddCleanupProcedure[@CUItem];
END;
END;
--do this before exiting, or you won't see display in executive
Cleanup: ImageDefs.CleanupProcedure =
BEGIN
AltoDisplay.DCBchainHead↑←NIL;
DCBBank↑ ← 0;
END;
saveMonitor: POINTER TO GeneralDisplayDefs.MonitorControlBlock ← @foo;
foo: GeneralDisplayDefs.MonitorControlBlock ← [0,LOOPHOLE[0],NIL,NIL,NIL];
ColorCleanup: ImageDefs.CleanupProcedure =
BEGIN
IF why=Finish OR why=Abort THEN {
GraphicsDefs.SetRed[0,0];
GraphicsDefs.SetGreen[0,0];
GraphicsDefs.SetBlue[0,0];
WaitAWhile[200];
};
saveMonitor ← GeneralDisplayDefs.pMonitorHead↑;
IF why=OutLd THEN GeneralDisplayDefs.pMonitorHead↑ ← saveMonitor
ELSE GeneralDisplayDefs.pMonitorHead↑ ← NIL;
WaitAWhile[500]; -- wait
END;
DisplayWait:PROCEDURE[t:CARDINAL] =
BEGIN
now:LONG CARDINAL ← MiscDefs.CurrentTime[];
WHILE MiscDefs.CurrentTime[] < now + t DO NULL; ENDLOOP;
END;
WaitAWhile: PROCEDURE[millisecs: CARDINAL] =
BEGIN
i,j: CARDINAL;
FOR i IN [0..millisecs] DO
FOR j IN [0..2000] DO ENDLOOP;
ENDLOOP;
END;
--changes clipping edges of current screen. Must stay inside initial clip window
SetClipEdges: PUBLIC PROCEDURE [tl,br: PointDefs.ScrPt] = {
--clip clipping window
[tl,br] ← ClipToScreen[tl,br];
IF br[X]<tl[X] OR br[Y]<tl[Y] THEN CULL ← TRUE
ELSE {CULL ← FALSE;
currentScreen.lx ← LX ← tl[X];
currentScreen.rx ← RX ← br[X];
currentScreen.ty ← TY ← tl[Y];
currentScreen.by ← BY ← br[Y];
};
};
ClipToScreen: PUBLIC PROC [tl,br: ScrPt] RETURNS [ScrPt, ScrPt] =
BEGIN
IF tl[X]>RX OR br[X]<LX OR tl[Y]>BY OR br[Y]<TY
THEN {RETURN[[0,0],[-1,-1]]};
IF tl[X] < initLX THEN tl[X] ← initLX;
IF br[X] >initRX THEN br[X] ← initRX;
IF tl[Y] < initTY THEN tl[Y] ← initTY;
IF br[Y] >initBY THEN br[Y] ← initBY;
RETURN[tl,br];
END;
ClipPointToScreen: PUBLIC PROC [pt: ScrPt] RETURNS [ScrPt] =
BEGIN
IF pt[X] < initLX THEN pt[X] ← initLX;
IF pt[X] >initRX THEN pt[X] ← initRX;
IF pt[Y] < initTY THEN pt[Y] ← initTY;
IF pt[Y] >initBY THEN pt[Y] ← initBY;
RETURN[pt];
END;
ResetClipEdges: PUBLIC PROCEDURE =
BEGIN OPEN PointDefs;
tl: PointDefs.ScrPt ← [initLX,initTY];
br: PointDefs.ScrPt ← [initRX,initBY];
SetClipEdges[tl,br];
END;
ClipOn: PUBLIC PROCEDURE =
BEGIN
CLIP ← TRUE;
END;
PrimeClipper: PUBLIC PROC [tl,br: PointDefs.ScrPt] RETURNS [ClipperState] =
BEGIN
IF tl[X] > RX OR tl[Y] > BY OR br[X] < LX OR br[Y] < TY THEN RETURN[cull];
IF tl[X] IN [LX..RX] AND tl[Y] IN [TY..BY]
AND br[X] IN [LX..RX] AND br[Y] IN [TY..BY]
THEN {CLIP ← FALSE; RETURN[inside]};
CLIP ← TRUE;
RETURN[clip];
END;
SetFunction: PUBLIC PROCEDURE [fnc: BitBltDefs.BBoperation] =
BEGIN
FNC ← fnc;
ScanBBT.function ← HBltBBT.function ←
(IF FNC=erase THEN erase ELSE replace);
END;
-- This routine "scan converts" a chain encoding and draws
left: INTEGER = 0;
right: INTEGER = 1;
CodedBrush: TYPE = ARRAY [left..right] OF BrushSide;
BrushSide: TYPE =DESCRIPTOR FOR ARRAY OF INTEGER;
CodedBrushes: ARRAY [1..8] OF CodedBrush;
CurrentBrush: CodedBrush;
LineInProgress: BOOLEAN ← FALSE;
xleft, xright: ARRAY [0..7] OF INTEGER;
leftBrush: BrushSide;
rightBrush: BrushSide;
brushSize: INTEGER;
topIndex: INTEGER;
topY: INTEGER; -- top of brush
centerX: INTEGER;
LastLinePointX: INTEGER;
LastLinePointY: INTEGER;
DrawNextDot: PUBLIC PROCEDURE[pt: PointDefs.ScrPt]=
BEGIN OPEN PointDefs;
dx, dy, brushIndex, rangeIndex, temp: INTEGER;
-- initialize the xranges arrays when starting a line
IF NOT LineInProgress THEN
BEGIN
leftBrush ← CurrentBrush[left];
rightBrush ← CurrentBrush[right];
brushSize ← LENGTH[leftBrush];
topIndex ← 0;
topY ← pt[Y] - brushSize/2; -- top of brush
centerX ← pt[X];
LineInProgress ← TRUE;
FOR brushIndex IN [0..brushSize) DO
xleft[brushIndex] ← centerX + leftBrush[brushIndex];
xright[brushIndex] ← centerX + rightBrush[brushIndex];
ENDLOOP;
LastLinePointX ← pt[X];
LastLinePointY ← pt[Y];
RETURN;
END;
-- main loop for processing a point
dx ← pt[X] - LastLinePointX;
dy ← pt[Y] - LastLinePointY;
IF dx NOT IN [-1..1] THEN BEGIN
EndLine[];
DrawNextDot[pt];
RETURN;
END;
centerX ← centerX + dx;
SELECT dy FROM
-1 => BEGIN -- move brush up
IF (topIndex ← topIndex -1) < 0
THEN topIndex ← topIndex + brushSize;
-- topIndex now points to bottom of xRanges
-- now write out lowest scan line.
DrawHLine[(topY + brushSize -1), xleft[topIndex],
xright[topIndex]];
-- and reset for new entries
xleft[topIndex] ← 606;
xright[topIndex] ← 0;
topY ← topY - 1;
END;
1 => BEGIN -- move brush down
-- first write out top scan line
DrawHLine[topY, xleft[topIndex], xright[topIndex]];
-- and reset for new entries
xleft[topIndex] ← 606;
xright[topIndex] ← 0;
IF (topIndex ← topIndex +1) >= brushSize
THEN topIndex ← 0;
topY ← topY + 1;
END;
0 => NULL;
ENDCASE => BEGIN
EndLine[];
DrawNextDot[pt];
RETURN;
END;
rangeIndex ← topIndex;
FOR brushIndex IN [0..brushSize)
DO IF xleft[rangeIndex] >
(temp ← centerX + leftBrush[brushIndex])
THEN xleft[rangeIndex] ← temp;
IF xright[rangeIndex] <
(temp ← centerX + rightBrush[brushIndex])
THEN xright[rangeIndex] ← temp;
IF (rangeIndex ← rangeIndex + 1) >= brushSize
THEN rangeIndex ← 0;
ENDLOOP;
LastLinePointX ← pt[X];
LastLinePointY ← pt[Y];
END;
EndLine: PUBLIC PROCEDURE =
BEGIN
-- cleanup remaining brush lines when finished
brushIndex: INTEGER;
IF NOT LineInProgress THEN RETURN;
FOR brushIndex IN [0..brushSize)
DO
DrawHLine[topY, xleft[topIndex], xright[topIndex]];
topY ← topY + 1;
IF (topIndex ← topIndex +1) >= brushSize
THEN topIndex ← 0;
ENDLOOP;
LineInProgress ← FALSE;
END;
--line drawing stuff. Keeps info about last point, so can have MoveTo, DrawTo
--type operation. Does brute force clipping, including culling.
--all lines have width, so some of this looks more like polygons
JNC: JunctionType;
Width: INTEGER;
Grey: GreyType;
fEnd,lEnd: EndType;
XY: PointDefs.ScrPt;
SetLineParms: PUBLIC PROCEDURE
[junction: JunctionType,
width: INTEGER,
grey: GreyType,
color: ColorMapIndex,
firstEnd,lastEnd: EndType]=
BEGIN
JNC ← junction;
Width ← width;
CurrentBrush ← CodedBrushes[Width];
Grey ← grey;
fEnd ← firstEnd;
lEnd ← lastEnd;
GraphicsDefs.SetGrayLevel[color];
END;
StartLine: PUBLIC PROCEDURE[pt: PointDefs.ScrPt] =
BEGIN OPEN PointDefs;
XY ← pt;
DrawNextDot[XY];
END;
--uses junction type
DrawTo: PUBLIC PROCEDURE[pt: PointDefs.ScrPt] =
BEGIN OPEN PointDefs;
DrawToShort[pt];
EndLine[];
END;
--splines use this one alot, uses round jnc
DrawToShort: PUBLIC PROCEDURE[pt: PointDefs.ScrPt] =
BEGIN OPEN PointDefs;
--makes jump to DrawDot (a common case) as fast as possible
IF (ABS[pt[X]-XY[X]]<=1 AND ABS[pt[Y]-XY[Y]] <=1) THEN DrawNextDot[pt]
ELSE BEGIN
E: INTEGER ←0;
S: INTEGER ← Y;
L: INTEGER ← X;
IncS: INTEGER ← 1; --point increments
IncL: INTEGER ← 1;
EIncS: INTEGER ← pt[X]-XY[X]; --error increments. S,L are direction, not size
EIncL: INTEGER ← pt[Y]-XY[Y];
--IncL goes with EIncS, and IncS goes with EIncL in this section
IF ABS[EIncS] < ABS[EIncL] THEN BEGIN --45-90 octant
T: INTEGER ← L;
EInc: INTEGER ← EIncL;
L ← S; EIncL ← EIncS;
S ← T; EIncS ← EInc;
END;
--following assures that S error increment is positive, the other is negative, and the point increments
--are the correct signs
IF EIncL < 0 THEN IncS ← -1 ELSE EIncL ← -EIncL;
IF EIncS < 0 THEN BEGIN IncL ← -1; EIncS ← - EIncS; END;
--now IncL goes with EIncL and IncS with EIncS
UNTIL pt[L] = XY[L] DO
E ← E + EIncL;
XY[L] ← XY[L]+IncL;
IF ABS[E + EIncS] < ABS[E] THEN BEGIN
XY[S] ← XY[S]+IncS;
E ← E+EIncS;
END;
DrawNextDot[XY];
ENDLOOP;
XY ← pt; --should be true anyway
END; --to make the jump to DrawDot as fast as possible
END;
--returns true if point is inside window.
--assumes point will have a 8 by 8 bitmap blitted around it
DrawSingleDot: PUBLIC PROCEDURE[pt: PointDefs.ScrPt] =
BEGIN
DrawNextDot[pt];
EndLine[];
END;
BLTBlockInScreen: PUBLIC PROCEDURE[src: BlockPtr, tl: PointDefs.ScrPt, fnc: BitBltDefs.BBoperation]=
BEGIN OPEN PointDefs;
dlx,dty,drx,dby: INTEGER;
--I want edges
dlx ← tl[X]; dty ← tl[Y];
drx ← dlx + src.w -1;
dby ← dty + src.h -1;
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF dlx>RX OR drx<LX OR dty>BY OR dby<TY THEN RETURN; --cull
IF dlx < LX THEN dlx ← LX;
IF drx >RX THEN drx ← RX;
IF dty < TY THEN dty ← TY;
IF dby >BY THEN dby ← BY;
END;
IF currentScreen.bitmap.bank#0 AND BLTBank#currentScreen.bitmap.bank
THEN MiscDefs.CallDebugger["Impossible XBITBLT"];
BBT.sourcealt ← src.bitmap.bank#0;
BBT.destalt ←currentScreen.bitmap.bank#0 ;
BBT.sourcetype ← block;
BBT.function ← fnc;
BBT.dlx ← dlx;
BBT.dty ← dty;
BBT.dw ← drx-dlx+1;
BBT.dh ← dby - dty +1;
IF alto THEN BBT.sbca ← src.bitmap.bits
ELSE BBT.slbca ← MakeLongPointer[src.bitmap.bits,src.bitmap.bank];
BBT.sbmr ← src.bitmap.nWords;
BBT.slx ← src.lx+(dlx-tl[X]);
BBT.sty ← src.ty+(dty-tl[Y]);
BitBltDefs.BITBLT[BBT];
END;
BLTGreyBlockInScreen: PUBLIC PROCEDURE[src: BlockPtr, tl: PointDefs.ScrPt, fnc: BitBltDefs.BBoperation,grey: GreyType]=
BEGIN OPEN PointDefs;
dlx,dty,drx,dby: INTEGER;
--I want edges
dlx ← tl[X]; dty ← tl[Y];
drx ← dlx + src.w -1;
dby ← dty + src.h -1;
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF dlx>RX OR drx<LX OR dty>BY OR dby<TY THEN RETURN; --cull
IF dlx < LX THEN dlx ← LX;
IF drx >RX THEN drx ← RX;
IF dty < TY THEN dty ← TY;
IF dby >BY THEN dby ← BY;
END;
IF src.bitmap.bank#0 AND BLTBank#0
THEN MiscDefs.CallDebugger["Impossible BitBlt"];
BBT.sourcealt ← src.bitmap.bank#0;
BBT.destalt ← BLTBank#0;
BBT.sourcetype ← andgray;
BBT.function ← fnc;
IF alto THEN BBT.sbca ← src.bitmap.bits
ELSE BBT.slbca ← MakeLongPointer[src.bitmap.bits,src.bitmap.bank];
BBT.sbmr ← src.bitmap.nWords;
BBT.dlx ← dlx;
BBT.dty ← dty;
BBT.dw ← drx-dlx+1;
BBT.dh ← dby - dty +1;
BBT.slx ← src.lx+(dlx-tl[X]);
BBT.sty ← src.ty+(dty-tl[Y]);
BBT.gray0 ← grey[(dty+1) MOD 4];
BBT.gray1 ← grey[(dty+2) MOD 4];
BBT.gray2 ← grey[(dty+3) MOD 4];
BBT.gray3 ← grey[dty MOD 4];
BitBltDefs.BITBLT[BBT];
END;
fillGrey: GreyType;
SetFillParms: PUBLIC PROCEDURE [grey: GreyType, color: ColorMapIndex] =
BEGIN
fillGrey ← grey;
GraphicsDefs.SetGrayLevel[color];
END;
HFill: PUBLIC PROCEDURE[y,lx,dx: INTEGER] =
BEGIN
HLine[y,lx,lx+dx-1, fillGrey];
END;
DrawHLine: PROCEDURE[y,lx,rx: INTEGER] =
BEGIN
HLine[y,lx,rx, Grey];
END;
HLine: PROCEDURE[y,lx,rx: INTEGER, grey: GreyType] =
BEGIN
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR y>BY OR y<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
END;
IF alto THEN {
HBltBBT.gray ← grey[(y+1) MOD 4];
HBltBBT.x1 ← lx;
HBltBBT.y ← y;
HBltBBT.x2 ← rx;
HBltDefs.XHBlt[HBltBBT,BLTBank];
}
ELSE {
ScanBBT.gray0 ← grey[(y+1) MOD 4];
ScanBBT.dlx ← lx;
ScanBBT.dty ← y;
ScanBBT.dw ← rx-lx+1;
BitBltDefs.BITBLT[ScanBBT];
GraphicsDefs.ReplaceGray[lx,y,rx,y,colorScreen];
};
END;
VFill: PUBLIC PROCEDURE[x,ty,by: INTEGER] =
BEGIN
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF x>RX OR x<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
END;
FillBBT.dlx ← x;
FillBBT.dty ← ty;
FillBBT.dw ← 1;
FillBBT.dh ← by-ty+1;
FillBBT.function ← IF FNC=erase THEN erase ELSE replace;
FillBBT.gray0 ← fillGrey[(ty+1) MOD 4];
FillBBT.gray1 ← fillGrey[(ty+2) MOD 4];
FillBBT.gray2 ← fillGrey[(ty+3) MOD 4];
FillBBT.gray3 ← fillGrey[ty MOD 4];
BitBltDefs.BITBLT[FillBBT];
END;
MoveScreenBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt,dx,dy: INTEGER] =
BEGIN
--clip the destination only
lx: INTEGER ← tl[X]+dx; ty: INTEGER ← tl[Y]+dy; --simpler this way on a number of counts
rx: INTEGER ← lx+br[X]-tl[X]; by: INTEGER ← ty+br[Y]-tl[Y];
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
--first line should take care of this... IF rx < lx OR by < ty THEN RETURN;
END;
BBT.dlx ← lx;
BBT.dty ← ty;
BBT.dw ← rx-lx+1;
BBT.dh ← by-ty+1;
BBT.slx ← tl[X];
BBT.sty ← tl[Y];
BBT.function ← replace;
BBT.sbmr ← BBT.dbmr;
IF alto THEN BBT.sourcealt ← BBT.destalt
ELSE BBT.slbca ← BBT.dlbca;
BitBltDefs.BITBLT[BBT];
END;
InvertBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt] =
BEGIN OPEN PointDefs;
lx: INTEGER ← tl[X]; ty: INTEGER ← tl[Y]; --simpler this way on a number of counts
rx: INTEGER ← br[X]; by: INTEGER ← br[Y];
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
END;
FillBBT.dlx ← lx;
FillBBT.dty ← ty;
FillBBT.dw ← rx-lx+1;
FillBBT.dh ← by-ty+1;
FillBBT.gray0 ← FillBBT.gray1 ← FillBBT.gray2 ← FillBBT.gray3 ← allOnes[0];
FillBBT.function ← invert;
BitBltDefs.BITBLT[FillBBT];
END;
EraseBox: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt] =
BEGIN
EraseBoxInternal[tl,br,TRUE];
END;
EraseBoxBW: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt] =
BEGIN
EraseBoxInternal[tl,br,FALSE];
END;
EraseBoxInternal: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt, color: BOOLEAN] =
BEGIN OPEN PointDefs;
lx: INTEGER ← tl[X]; ty: INTEGER ← tl[Y]; --simpler this way on a number of counts
rx: INTEGER ← br[X]; by: INTEGER ← br[Y];
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
END;
FillBBT.dlx ← lx;
FillBBT.dty ← ty;
FillBBT.dw ← rx-lx+1;
FillBBT.dh ← by-ty+1;
FillBBT.gray0 ← FillBBT.gray1 ← FillBBT.gray2 ← FillBBT.gray3 ← allOnes[0];
FillBBT.function ← erase;
BitBltDefs.BITBLT[FillBBT];
IF color THEN GraphicsDefs.EraseArea[lx,ty,rx,by,colorScreen];
END;
BoxFill: PUBLIC PROCEDURE[tl,br: PointDefs.ScrPt] =
BEGIN OPEN PointDefs;
lx: INTEGER ← tl[X]; ty: INTEGER ← tl[Y]; --simpler this way on a number of counts
rx: INTEGER ← br[X]; by: INTEGER ← br[Y];
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
END;
FillBBT.dlx ← lx;
FillBBT.dty ← ty;
FillBBT.dw ← rx-lx+1;
FillBBT.dh ← by-ty+1;
FillBBT.function ← FNC;
FillBBT.gray0 ← fillGrey[(ty+1) MOD 4];
FillBBT.gray1 ← fillGrey[(ty+2) MOD 4];
FillBBT.gray2 ← fillGrey[(ty+3) MOD 4];
FillBBT.gray3 ← fillGrey[ty MOD 4];
BitBltDefs.BITBLT[FillBBT];
END;
ngridpieces: INTEGER ← 0;
gridT: INTEGER ← 3;
GetGridParameters: PUBLIC PROCEDURE
RETURNS[center: PointDefs.ScrPt,hgridlx,hgridrx,vgridty,vgridby,gridt: INTEGER]=
BEGIN
pt: PointDefs.ScrPt;
IF currentScreen.bitmap.bits=NIL THEN ERROR;
ngridpieces ← 1+(initBY-initTY)/8;
pt ← [(initRX-initLX)/2, (initBY-initTY)/2];
pt ← GriffinDefs.Grid[pt];
RETURN[pt,initLX,initRX,initTY,initBY,gridT];
END;
BltVGrid: PUBLIC PROCEDURE[lx: INTEGER ]=
BEGIN
ty: INTEGER ← GriffinDefs.Grid[[0,initTY]][Y];
rx: INTEGER ← lx+gridT-1;
THROUGH [0..ngridpieces] DO
BltGridPiece[lx,ty,rx,ty+7];
ty ← ty+8;
ENDLOOP;
END;
BltGridPiece: PROCEDURE [lx,ty,rx,by: INTEGER] =
BEGIN
tl: ScrPt ← [lx,ty]; --save it
--always clip the vgrid since it can extend outside of the
--active region of the screen. Right thing to do would be to
--construct the vgrid pieces as a function of the full screen size
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
vgridBBT.dlx ← lx;
vgridBBT.dty ← ty;
vgridBBT.dw ← rx-lx+1;
vgridBBT.dh ← by-ty+1;
vgridBBT.slx ← lx-tl[X];
vgridBBT.sty ← ty-tl[Y];
BitBltDefs.BITBLT[vgridBBT];
END;
BltHGrid: PUBLIC PROCEDURE[ty: INTEGER ]=
BEGIN
lx: INTEGER ← initLX;
rx: INTEGER ← initRX;
by: INTEGER ← ty+gridT-1;
IF CLIP THEN BEGIN
IF CULL THEN RETURN;
IF lx>RX OR rx<LX OR ty>BY OR by<TY THEN RETURN; --cull
IF lx < LX THEN lx ← LX;
IF rx >RX THEN rx ← RX;
IF ty < TY THEN ty ← TY;
IF by >BY THEN by ← BY;
END;
hgridBBT.dlx ← lx;
hgridBBT.dty ← ty;
hgridBBT.dw ← rx-lx+1;
hgridBBT.dh ← by-ty+1;
hgridBBT.gray0 ← hgrid[(ty+1) MOD 4];
hgridBBT.gray1 ← hgrid[(ty+2) MOD 4];
hgridBBT.gray2 ← hgrid[(ty+3) MOD 4];
hgridBBT.gray3 ← hgrid[ty MOD 4];
BitBltDefs.BITBLT[hgridBBT];
END;
MakeLongPointer: PROCEDURE[ptr: POINTER, bank: CARDINAL] RETURNS [LONG POINTER] =
MACHINE CODE BEGIN
END;
AllocateEven: PROCEDURE[len: CARDINAL] RETURNS[POINTER]=
BEGIN
ptr: POINTER ← GriffinMemoryDefs.Allocate[len+1];
IF InlineDefs.BITAND[LOOPHOLE[ptr,CARDINAL],1]=1 THEN ptr←ptr+1;
RETURN[ptr];
END;
vgrid: DESCRIPTOR FOR ARRAY [0..7] OF CARDINAL ← DESCRIPTOR[AllocateEven[8],8];
vgrid[0] ← 120000B;
vgrid[1] ← vgrid[2] ← vgrid[3] ← vgrid[4] ← vgrid[5] ← vgrid[6] ← vgrid[7] ← 40000B;
--set up BBTables
BBT ← AllocateEven[SIZE[BitBltDefs.BBTable]];
BBT↑ ← [ptrs: short, pad: 0,sourcealt: FALSE,destalt:TRUE ,sourcetype: block, function: paint,unused: ,dbca: ,dbmr: , dlx: ,dty: ,dw: ,dh: ,sbca: NIL,sbmr: 0,slx: 0,sty: 0, gray0: ,gray1: ,gray2: ,gray3: ,slbca: NIL ,dlbca: NIL];
HBltBBT ← AllocateEven[SIZE[HBltDefs.HBTable]];
HBltBBT↑ ← [pad: 0,function: replace,destalt: TRUE, dbca: ,dbmr: ,y: ,x1: ,x2: ,gray: ];
ScanBBT ← AllocateEven[SIZE[BitBltDefs.BBTable]];
ScanBBT↑ ← [ptrs: short, pad: 0,sourcealt: FALSE,destalt:TRUE ,sourcetype:
gray, function: replace,unused: ,dbca: ,dbmr: , dlx: ,dty: ,dw: ,dh:
1,sbca: NIL,sbmr: 0,slx: 0,sty: 0, gray0: ,gray1: ,gray2: ,gray3: ,slbca: NIL ,dlbca: NIL];
FillBBT ← AllocateEven[SIZE[BitBltDefs.BBTable]];
FillBBT↑ ← [ptrs: short, pad: 0,sourcealt: FALSE ,destalt:TRUE ,sourcetype: gray, function: replace,unused: ,dbca: ,dbmr: , dlx: ,dty: ,dw: ,dh: ,sbca: NIL,sbmr: 0,slx: 0,sty: 0, gray0: ,gray1: ,gray2: ,gray3: ,slbca: NIL ,dlbca: NIL];
vgridBBT ← AllocateEven[SIZE[BitBltDefs.BBTable]];
vgridBBT↑ ← [ptrs: short, pad: 0,sourcealt: FALSE ,destalt:TRUE ,sourcetype: block, function: replace,unused: ,dbca: ,dbmr: , dlx: ,dty: ,dw: ,dh: ,sbca: @vgrid[0],sbmr: 1,slx: 0,sty: 0, gray0: 0,gray1: 0,gray2: 0,gray3:0 ,slbca: NIL ,dlbca: NIL];
hgridBBT ← AllocateEven[SIZE[BitBltDefs.BBTable]];
hgridBBT↑ ← [ptrs: short, pad: 0,sourcealt: FALSE,destalt:TRUE ,sourcetype: gray, function: replace,unused: ,dbca: ,dbmr: , dlx: ,dty: ,dw: ,dh: ,sbca: NIL,sbmr: 0,slx: 0,sty: 0, gray0: 100200B,gray1:77577B ,gray2: 100200B,gray3:0 ,slbca: NIL ,dlbca: NIL];
-- Initialize coded brushes
BEGIN OPEN GriffinMemoryDefs;
CodedBrushes[1] ←
[DESCRIPTOR[Allocate[1],1],DESCRIPTOR[Allocate[1],1]];
CodedBrushes[1][left][0]← 0;
CodedBrushes[1][right][0]← 0;
CodedBrushes[2] ←
[DESCRIPTOR[Allocate[2],2],DESCRIPTOR[Allocate[2],2]];
CodedBrushes[2][left][0]← -1;
CodedBrushes[2][left][1]← -1;
CodedBrushes[2][right][0]← 0;
CodedBrushes[2][right][1]← 0;
CodedBrushes[3] ←
[DESCRIPTOR[Allocate[3],3],DESCRIPTOR[Allocate[3],3]];
CodedBrushes[3][left][0]← 0;
CodedBrushes[3][left][1]← -1;
CodedBrushes[3][left][2]← 0;
CodedBrushes[3][right][0]← 0;
CodedBrushes[3][right][1]← 1;
CodedBrushes[3][right][2]← 0;
CodedBrushes[4] ←
[DESCRIPTOR[Allocate[4],4],DESCRIPTOR[Allocate[4],4]];
CodedBrushes[4][left][0]← -1;
CodedBrushes[4][left][1]← -2;
CodedBrushes[4][left][2]← -2;
CodedBrushes[4][left][3]← -1;
CodedBrushes[4][right][0]← 0;
CodedBrushes[4][right][1]← 1;
CodedBrushes[4][right][2]← 1;
CodedBrushes[4][right][3]← 0;
END;
colorScreen ← GraphicsDefs.TurnOnGraphics[8,FALSE,80];
WaitAWhile[40];
ImageDefs.AddCleanupProcedure[@ColorCUItem];
GraphicsDefs.SetRed[0,377B,colorScreen];
GraphicsDefs.SetGreen[0,377B,colorScreen];
GraphicsDefs.SetBlue[0,377B,colorScreen];
ControllerDefs.InitColorMap[TRUE];
END.