--mstone May 2, 1981 12:57 PM --Low level screen functions DIRECTORY ScreenDefs: FROM "ScreenDefs", 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", GriffinDefs: FROM "GriffinDefs"; ScreenFns: PROGRAM IMPORTS InlineDefs,GriffinMemoryDefs, DisplayDefs,MiscDefs,SegmentDefs, ImageDefs,GriffinDefs, BitBltDefs, HBltDefs 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]; 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]; --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; ClearScreen[]; 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; --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, firstEnd,lastEnd: EndType]= BEGIN JNC ← junction; Width ← width; CurrentBrush ← CodedBrushes[Width]; Grey ← grey; fEnd ← firstEnd; lEnd ← lastEnd; 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] = BEGIN fillGrey ← grey; 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]; }; 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 ← BLTBank#0; BBT.sbca ← currentScreen.bitmap.bits;} ELSE BBT.slbca ← MakeLongPointer[currentScreen.bitmap.bits,currentScreen.bitmap.bank]; 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 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]; 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; END.