-- bbitfns.mesa
-- last edited by McCreight, December 17, 1982 12:29 PM
DIRECTORY
BitBltDefs,
GeneralDisplayDefs,
multiGraphicsDefs,
InlineDefs,
SystemDefs,
SegmentDefs;
bbitfns: PROGRAM IMPORTS BitBltDefs, InlineDefs, multiGraphicsDefs,
SegmentDefs, SystemDefs
EXPORTS multiGraphicsDefs =
BEGIN OPEN GeneralDisplayDefs,multiGraphicsDefs;
Machine: SegmentDefs.MachineType = SegmentDefs.GetMemoryConfig[].AltoType;
DMachine: BOOLEAN = (Machine = D0) OR (Machine = Dorado);
Screen: POINTER TO Bitmap ← NIL;
--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
DCBhead: POINTER TO POINTER TO DCB = LOOPHOLE[420B];
SetPointBLT: BLTBlockPtr ← AllocateBLT[];
BLT: BLTBlockPtr ← AllocateBLT[];
DefaultAllocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER] ←
BEGIN
IF DMachine THEN RETURN [SegmentDefs.LongDataSegmentAddress[
SegmentDefs.NewDataSegment[
SegmentDefs.DefaultANYBase,(nwords+255)/256]]]
ELSE RETURN[SystemDefs.AllocateSegment[nwords]];
END;
DefaultFree: PROCEDURE [XVM: LONG POINTER] ←
BEGIN
END;
DefaultAllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER] ←
BEGIN
IF DMachine THEN RETURN [SegmentDefs.LongDataSegmentAddress[
SegmentDefs.NewDataSegment[
SegmentDefs.DefaultANYBase,(nwords+255)/256]]]
ELSE RETURN[SystemDefs.AllocateSegment[nwords]];
END;
SetXMAlloc: PUBLIC PROCEDURE [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER],AllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER]] =
BEGIN
DefaultAllocate ← Allocate;
DefaultFree ← Free;
DefaultAllocateFromBank ← AllocateFromBank;
END;
GetXMAlloc: PUBLIC PROCEDURE RETURNS [Allocate: PROCEDURE [nwords: CARDINAL] RETURNS [LONG POINTER],Free: PROCEDURE [LONG POINTER],AllocateFromBank: PROCEDURE [nwords: CARDINAL,bank: CARDINAL] RETURNS [LONG POINTER]] =
BEGIN
RETURN[DefaultAllocate,DefaultFree,DefaultAllocateFromBank];
END;
GrayThresholds: ARRAY [0..16) OF CARDINAL ←
[15,01,05,11, --minimum flicker
06,08,12,02,
07,09,13,03,
14,00,04,10
];
GrayArray: ARRAY [0..16) OF GrayPattern;
currentGray: PUBLIC GrayPattern;
SetGrayMap: PUBLIC PROCEDURE[idx,g0,g1,g2,g3:CARDINAL] =
{GrayArray[idx]←[g0,g1,g2,g3,g0,g1,g2]};
SetGrayThresholds: PUBLIC PROCEDURE [new: POINTER TO ARRAY [0..0) OF CARDINAL,
outputDevice: POINTER TO Bitmap ← NIL] =
BEGIN
i: CARDINAL;
IF outputDevice = NIL THEN outputDevice ← Screen;
FOR i IN [0..16) DO GrayThresholds[i] ← new[i];
ENDLOOP;
END;
InitGrayMaps: PUBLIC PROCEDURE =
BEGIN
FOR idx: [0..16) IN [0..16) DO
FOR scanline: [0..4) IN [0..4) DO
value: CARDINAL ← 0;
FOR j: [0..3] IN [0..3] DO
value ← InlineDefs.BITOR[InlineDefs.BITSHIFT[value, 1],
(IF idx <= GrayThresholds[scanline*4+j] THEN 10421B ELSE 0)];
ENDLOOP;
GrayArray[idx][scanline] ← value;
IF scanline<3 THEN GrayArray[idx][scanline+4] ← value;
ENDLOOP;
ENDLOOP;
END;
SetGrayLevel: PUBLIC PROCEDURE [intensity: CARDINAL] =
{currentGray←GrayArray[intensity]};
GetGrayBlock: PUBLIC PROCEDURE RETURNS [gray0,gray1,gray2,gray3: CARDINAL] =
{RETURN [currentGray[0],currentGray[1],currentGray[2],currentGray[3]]};
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[Bitmap]];
Screen.nBits ← width;
Screen.nLines ← height;
END;
TurnOnGraphics: PUBLIC PROCEDURE [bitsPerPixel: CARDINAL ← 1,portraitMode: BOOLEAN ← TRUE,scalePercent: CARDINAL ← 100] RETURNS [POINTER TO Bitmap] =
BEGIN
scaleFactor: CARDINAL ← scalePercent/10;
myDCB: POINTER TO DCB ;
myScreen: LONG POINTER TO ARRAY OF UNSPECIFIED ;
IF Screen = NIL THEN --ought to be able to return a couple of screens...
BEGIN
Screen ← SystemDefs.AllocateHeapNode[SIZE[Bitmap]];
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;
END;
Screen.nBitsPerPixel ← bitsPerPixel;
Screen.portraitMode ← portraitMode;
Screen.scaleFactor ← scaleFactor;
Screen.nWords ← IF portraitMode
THEN 2*bitsPerPixel*((Screen.nBits+31)/32)
ELSE 2*bitsPerPixel*((Screen.nLines+31)/32) ;
SetPointBLT.blk ← [ptrs: IF DMachine THEN long ELSE short,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.blk ← [ptrs: IF DMachine THEN long ELSE short,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:];
myDCB ←
IF DMachine THEN SystemDefs.AllocateHeapNode[SIZE[DCB]+1]
ELSE SystemDefs.AllocateSegment[Screen.nWords*Screen.nLines+SIZE[DCB]+1];
myScreen ←
IF DMachine THEN MakeLongPointer[LOOPHOLE[26400B],5]
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;
InitGrayMaps[];
RETURN[Screen];
END;
GetDefaultBitmapHandle: PUBLIC PROCEDURE RETURNS[POINTER TO Bitmap] =
BEGIN
RETURN[Screen];
END;
SetPoint: PUBLIC PROCEDURE [x,y: INTEGER,fn: BitBltDefs.BBoperation,b: POINTER TO Bitmap] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← 0;
IF NOT x IN [0..INTEGER[b.nBits]) THEN RETURN;
IF NOT y IN [0..INTEGER[b.nLines]) THEN RETURN;-- save your ass
IF NOT b.portraitMode THEN
BEGIN t: INTEGER ← INTEGER[b.nLines]-y;y ← x;x ← t;END;
SetPointBLT.blk.function ← fn;
SetPointBLT.blk.dlbca ← MakeLongPointer[b.bits,b.bank];
SetPointBLT.blk.dbca ← b.bits;
SetPointBLT.blk.dbmr ← b.nWords;
SetPointBLT.blk.dlx ← x;
SetPointBLT.blk.dty ← y;
BitBltDefs.BITBLT[@SetPointBLT.blk];
END;
solidGray: GrayPattern ← solid;
SetArea: PUBLIC PROCEDURE [x1,y1,x2,y2: INTEGER,fn: BitBltDefs.BBoperation,
gray: GrayPatternPtr ← NIL, b: POINTER TO Bitmap] =
BEGIN
BLT: BLTBlockPtr;
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← 0;
IF x1 > x2 THEN BEGIN t: INTEGER ← x1;x1 ← x2;x2 ← t;END;
IF y1 > y2 THEN BEGIN t: INTEGER ← y1;y1 ← y2;y2 ← t;END;
IF x2 < 0 OR y2 < 0 OR
x1 >= INTEGER[b.nBits] OR y1 >= INTEGER[b.nLines]
THEN RETURN;
x1 ← MAX[0,x1];y1 ← MAX[0,y1];
x2 ← MIN [x2,INTEGER[b.nBits]-1];y2 ← MIN[y2,INTEGER[b.nLines]-1];
IF NOT b.portraitMode THEN
BEGIN t: INTEGER;
t ← (INTEGER[b.nLines]-1)-y1;y1 ← x1;
x1 ← (INTEGER[b.nLines]-1)-y2;y2 ← x2;x2 ← t;
END;
BLT ← AllocateBLT[];
BLT.blk.sourcetype ← gray;
BLT.blk.function ← fn;
BLT.blk.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.blk.dbca ← b.bits;
BLT.blk.dbmr ← b.nWords;
BLT.blk.dlx ← x1;
BLT.blk.dty ← y1;
BLT.blk.dw ← (x2+1-x1);
BLT.blk.dh ← (y2+1-y1);
SetupBitBltGray[BLT, IF gray#NIL THEN gray ELSE @solidGray];
BitBltDefs.BITBLT[@BLT.blk];
FreeBLT[BLT];
END;
END.