-- cbitfns.mesa (used in Chipmonk)
-- last modified by E. McCreight, December 20, 1982 10:24 AM
DIRECTORY
BitBltDefs,
GeneralDisplayDefs,
multiGraphicsDefs,
InlineDefs,
SystemDefs,
SegmentDefs,
ZoneAllocDefs;
cbitfns: MONITOR IMPORTS BitBltDefs, InlineDefs, multiGraphicsDefs,
SegmentDefs, SystemDefs, ZoneAllocDefs
EXPORTS multiGraphicsDefs =
BEGIN OPEN GeneralDisplayDefs,multiGraphicsDefs,InlineDefs;
Machine: SegmentDefs.MachineType = SegmentDefs.GetMemoryConfig[].AltoType;
DMachine: BOOLEAN = (Machine = D0) OR (Machine = Dorado);
Dor: BOOLEAN = Machine = Dorado;
Screen: BitmapPtr ← NIL;
--data structures for D0 style color display
colorData: TYPE = MACHINE DEPENDENT RECORD
[ addr: [0..16),
r,g,b,unused: BOOLEAN,
data: [0..256)
];
colorEntry: TYPE = RECORD
[ red,green,blue: colorData
];
colorTable: TYPE = RECORD --must be hexAligned
[ front: ARRAY [0..2) OF UNSPECIFIED,
entry: ARRAY [0..16) OF colorEntry,
back: ARRAY [0..10) OF UNSPECIFIED,
hexAlignPad: ARRAY [0..16) OF UNSPECIFIED
];
--data structures for D1 style color display from GeneralDisplayDefs
--global variables
ColorBitmap: POINTER TO POINTER = LOOPHOLE[414B];
ColorBitmapBank: POINTER TO CARDINAL = LOOPHOLE[415B];
ColorMap: POINTER TO POINTER = LOOPHOLE[416B];
ColorMapBank: POINTER TO CARDINAL = LOOPHOLE[417B];
ColorCtrlBlk: ColorControlBlock;
AChanCtrlBlk: ChannelControlBlock;
ColorMonitor: MonitorControlBlock;
ColorTablePlace:CARDINAL=26250B;
ColorTable: LONG POINTER TO colorTable ← LOOPHOLE[1200000B+ColorTablePlace];
ColorTable8: POINTER TO ATableImage;
ColorWord: CARDINAL ← 0;
freeBLTBlocks: BLTBlockPtr ← NIL;
mdsz: MDSZone = ZoneAllocDefs.GetTheMDSZone[];
AllocateBLT: PUBLIC ENTRY PROC RETURNS[bb: BLTBlockPtr] =
BEGIN
IF freeBLTBlocks#NIL THEN
{bb ← freeBLTBlocks; freeBLTBlocks ← freeBLTBlocks.next}
ELSE
BEGIN
bb ← mdsz.NEW[BLTBlock];
IF LOOPHOLE[@bb.blk, CARDINAL] MOD 2 # 0 THEN -- even-word align
bb ← LOOPHOLE[LOOPHOLE[bb, CARDINAL]+1, BLTBlockPtr];
bb.next ← NIL;
bb.blk ← [ptrs: IF DMachine THEN long ELSE short,
pad: 0, sourcealt: FALSE, sourcetype: gray,
dbca: NIL,
gray0: 177777B, gray1: 177777B, gray2: 177777B, gray3:177777B,
sbca: NIL, unused: 0, sbmr: 0];
END;
END;
FreeBLT: PUBLIC ENTRY PROC [bb: BLTBlockPtr] =
{bb.next ← freeBLTBlocks; freeBLTBlocks ← bb};
SetColorTable: PUBLIC PROC [new: POINTER TO ARRAY [0..0) OF CARDINAL,
outputDevice: BitmapPtr ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
IF NOT Dor THEN
BEGIN -- a Dolphin
i: CARDINAL;
ColorTable↑.front ← ALL[0];
ColorTable↑.back ← ALL[0];
FOR i IN [0..17B] DO
ColorTable↑.entry[i].red ← [i,TRUE,FALSE,FALSE,FALSE,new[i*3]];
ColorTable↑.entry[i].green ← [i,FALSE,TRUE,FALSE,FALSE,new[i*3+1]];
ColorTable↑.entry[i].blue ← [i,FALSE,FALSE,TRUE,FALSE,new[i*3+2]];
ENDLOOP;
END
ELSE
BEGIN -- a Dorado
i: CARDINAL;
FOR i IN [0..1024) DO
ColorTable8[i].zeroHigh ← ColorTable8[i].zeroLow ← 0;
ENDLOOP;
FOR i IN [0..16) DO
ColorTable8[i*4] ← ColorTable8[i*4*16] ←
[0,(255-new[i*3]) MOD 16,(255-new[i*3+2]),0,(255-new[i*3+1]),(255-new[i*3])/16];
ENDLOOP;
pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
END;
END;
halftoneWord: TYPE = MACHINE DEPENDENT RECORD
[ unused: [0..7777B],
val1,val2,val3,val4: BOOLEAN
];
GetColorGray: PUBLIC PROC [c: Color] RETURNS[GrayPattern] =
BEGIN
IF c>255 THEN
BEGIN -- two colors, in alternation
combin: CARDINAL = BITAND[255,c];
pat1: CARDINAL = combin + BITSHIFT[combin,8];
pat2: CARDINAL = BITOR[BITSHIFT[pat1,4],BITSHIFT[combin,-4]];
RETURN[[pat1,pat2,pat1,pat2,pat1,pat2,pat1]];
END
ELSE
BEGIN
pixCol: CARDINAL = BITAND[c, 15];
halfcw: CARDINAL = BITOR[BITSHIFT[pixCol, 4], pixCol];
cw: CARDINAL = BITOR[BITSHIFT[halfcw, 8], halfcw]; -- pixCol replicated four times
SELECT c-pixCol FROM
0 => RETURN[ALL[cw]]; -- every pixel set to pixCol
ENDCASE =>
BEGIN
m: GrayPattern ← GetMaskGray[c];
FOR i: GrayPatternIndex IN GrayPatternIndex DO
m[i] ← BITAND[m[i], cw];
ENDLOOP;
RETURN[m];
END;
END;
END;
GetMaskGray: PUBLIC PROC [c: Color] RETURNS[GrayPattern] =
BEGIN
pixCol: [0..16) = BITAND[c, 15];
RETURN[SELECT c-pixCol FROM
16 => [7400B,7400B,17B,17B,7400B,7400B,17B],
-- The pattern
-- .*..
-- .*..
-- ...*
-- ...*
32 => [7417B,170360B,7417B,170360B,7417B,170360B,7417B],
-- The pattern
-- .*.*
-- *.*.
-- .*.*
-- *.*.
48 => [7400B,7400B,0,0,7400B,7400B,0],
-- The pattern
-- .*..
-- .*..
-- ....
-- ....
64 => [170377B,177760B,170377B,177760B,170377B,177760B,170377B],
-- The pattern
-- *.**
-- ***.
-- *.**
-- ***.
ENDCASE => ALL[177777B] -- all bits --];
END;
-- The following Set/Get routines seem to be no-ops for Chipmonk's 4-bits-per-point
-- color display.
SetRed: PUBLIC PROC[gray: [0..256),newVal: [0..256),outputDevice: BitmapPtr ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>BEGIN ColorTable8[gray*4].redHigh ← newVal/16;
ColorTable8[gray*4].redLow ← newVal MOD 16;
pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
END;
ENDCASE;
END;
SetGreen: PUBLIC PROC[gray: [0..256),newVal: [0..256),outputDevice: BitmapPtr ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>BEGIN
ColorTable8[gray*4].green ← newVal;
pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
END;
ENDCASE;
END;
SetBlue: PUBLIC PROC[gray: [0..256),newVal: [0..256),outputDevice: BitmapPtr ← NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>BEGIN
ColorTable8[gray*4].blue ← newVal;
pMonitorHead.Flags ← [0,FALSE,FALSE,FALSE,FALSE,TRUE,TRUE,TRUE];
END;
ENDCASE;
END;
GetRed: PUBLIC PROC[gray: [0..256),outputDevice: BitmapPtr ← NIL] RETURNS [CARDINAL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>RETURN[ColorTable8[gray*4].redHigh*16+ColorTable8[gray*4].redLow];
ENDCASE=>RETURN[0];
END;
GetGreen: PUBLIC PROC[gray: [0..256),outputDevice: BitmapPtr ← NIL] RETURNS [CARDINAL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>RETURN[ColorTable8[gray*4].green];
ENDCASE=>RETURN[0];
END;
GetBlue: PUBLIC PROC[gray: [0..256),outputDevice: BitmapPtr ← NIL] RETURNS [CARDINAL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
SELECT outputDevice.nBitsPerPixel FROM
8=>RETURN[ColorTable8[gray*4].blue];
ENDCASE=>RETURN[0];
END;
TurnOnColor: PUBLIC PROC [bitsPerPixel: CARDINAL ← 1,portraitMode: BOOLEAN ← TRUE,scalePercent: CARDINAL ← 100, initColor: Color] RETURNS [BitmapPtr] =
BEGIN
scaleFactor: CARDINAL ← scalePercent/10;
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 ← (640*10)/scaleFactor;
Screen.nLines ← (481*10)/scaleFactor;
END
ELSE
BEGIN
Screen.nBits ← (481*10)/scaleFactor;
Screen.nLines ← (640*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) ;
IF NOT Dor THEN
BEGIN
i:CARDINAL;
temp:ARRAY[0..47] OF CARDINAL;
FOR i IN [0..47] DO
temp[i]←i*4;
ENDLOOP;
SetColorTable[LOOPHOLE[@temp]];
ColorBitmap↑ ← LOOPHOLE[0]; --InlineDefs.LowHalf[longP];
ColorBitmapBank↑ ← 4; --InlineDefs.HighHalf[longP];
ColorMap↑ ← LOOPHOLE[ColorTablePlace];
ColorMapBank↑ ← 5;
Screen.bank ← 4; --1;
Screen.bits←LOOPHOLE[ColorBitmap↑];
EraseColorArea[0,0,Screen.nBits,Screen.nLines, initColor];
END
ELSE
BEGIN
temp:ARRAY[0..47] OF CARDINAL;
i: CARDINAL;
FOR i IN [0..47] DO
temp[i]←i*4;
ENDLOOP;
ColorTable8 ← SystemDefs.AllocateSegment[SIZE[ATableImage]];
Screen.bank ← 4;
Screen.bits←LOOPHOLE[0];
ColorCtrlBlk ←
[ ATable: ColorTable8,
BTable: NIL,CTable: NIL,MiniMixer: NIL,
VBlank: [VBtoVS: 3,VStoVS: 3],VStoVB: 20B,VisibleLines: 240,
HRamMaxAddr: 379,HBlank: [HBLeadLength: 6,HSTrailAddr: 47B],
HBTrailLength: 16B,PClock: [unused: 0,PClockMul: 130B,PClockDiv: 14B],
reserved: 0
];
AChanCtrlBlk ←
[ NIL,Screen.nWords,MakeLongPointer[Screen.bits,Screen.bank],
Screen.nLines/2,(Screen.nWords*16)/bitsPerPixel+377B,
MarginOffset[Ramtek525],
[unused: 0,
b24BitsPerPixel: FALSE,AByPass: FALSE,BByPass: FALSE,A8B2: TRUE,
Resolution: full,Size8: FALSE,Size4:TRUE,Size2: FALSE,Size1: FALSE
]
];
ColorMonitor ←
[ 177456B,[0,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE],
@AChanCtrlBlk,NIL,@ColorCtrlBlk
];
ReplaceColorArea[0,0,Screen.nBits,Screen.nLines, initColor];
pMonitorHead↑ ← @ColorMonitor;
SetColorTable[LOOPHOLE[@temp]];
END;
RETURN[Screen];
END;
KillGraphics:PUBLIC PROC[outputDevice:BitmapPtr←NIL] =
BEGIN
IF outputDevice = NIL THEN outputDevice ← Screen;
IF outputDevice = NIL THEN RETURN;
IF NOT Dor THEN
BEGIN
ColorBitmap↑ ← LOOPHOLE[0]; --InlineDefs.LowHalf[longP];
ColorBitmapBank↑ ← 0; --InlineDefs.HighHalf[longP];
ColorMap↑ ← LOOPHOLE[0];
ColorMapBank↑ ← 0;
END ELSE pMonitorHead↑←NIL;
END;
logTable: ARRAY [1..8] OF CARDINAL = [0,1,2,2,3,3,3,3];
SetColorFromSource: PUBLIC PROC [source: BitmapPtr, x,y: INTEGER,
fn: BitBltDefs.BBoperation, sourceType: BitBltDefs.BBsourcetype ← block,
gray: GrayPatternPtr ← NIL, dest: BitmapPtr ← NIL] =
BEGIN
BLT: BLTBlockPtr;
x2,y2: INTEGER;
sx,sy,dy: INTEGER ← 0;
logBitsPerPixel: CARDINAL;
IF dest = NIL THEN dest ← Screen;
logBitsPerPixel ← logTable[dest.nBitsPerPixel];
x2 ← x+source.nBits-1;
y2 ← y+source.nLines-1;
IF x >= INTEGER[dest.nBits] OR y >= INTEGER[dest.nLines] THEN RETURN;
IF x2 >= INTEGER[dest.nBits] THEN x2 ← dest.nBits - 1;
IF y2 >= INTEGER[dest.nLines] THEN BEGIN dy ← y2-(INTEGER[dest.nLines]-1);y2 ← dest.nLines-1;END;
IF x < 0 THEN BEGIN sx ← -x;x ← 0;END;
IF y < 0 THEN BEGIN sy ← -y;y ← 0;END;
IF NOT dest.portraitMode THEN
BEGIN t: CARDINAL;
t ← (INTEGER[dest.nLines]-1)-y;y ← x;
x ← (INTEGER[dest.nLines]-1)-y2;
y2 ← MIN[x2,y+INTEGER[source.nBits]-1];x2 ← MIN[t,x+INTEGER[source.nLines]-1];
sy ← sx;sx ← dy;
END;
BLT ← AllocateBLT[];
IF gray#NIL THEN LOOPHOLE[@BLT.blk.gray0, GrayPatternPtr]↑ ← gray↑;
BLT.blk.sourcetype ← sourceType;
BLT.blk.function ← fn;
BLT.blk.dlbca ← MakeLongPointer[dest.bits,dest.bank];
BLT.blk.dbmr ← dest.nWords;
BLT.blk.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel];
BLT.blk.dty ← y;
BLT.blk.dw ← InlineDefs.BITSHIFT[(x2+1-x),logBitsPerPixel];
BLT.blk.dh ← (y2+1-y);
BLT.blk.slbca ← MakeLongPointer[source.bits,source.bank];
BLT.blk.sbmr ← source.nWords;
BLT.blk.slx ← sx;
BLT.blk.sty ← sy;
BitBltDefs.BITBLT[@BLT.blk];
FreeBLT[BLT];
END;
SetColorPoint: PUBLIC PROC [x, y: INTEGER, fn: BitBltDefs.BBoperation,
c: Color ← 0, b: BitmapPtr ← NIL, cGray: GrayPatternPtr ← NIL] =
BEGIN
BLT: BLTBlockPtr;
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← logTable[b.nBitsPerPixel];
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]-1)-y;y ← x;x ← t;END;
BLT ← AllocateBLT[];
LOOPHOLE[@BLT.blk.gray0, GrayPatternPtr]↑ ← IF cGray#NIL THEN cGray↑
ELSE GetColorGray[c];
BLT.blk.sourcetype ← gray;
BLT.blk.dw ← Screen.nBitsPerPixel;
BLT.blk.dh ← 1;
BLT.blk.function ← fn;
BLT.blk.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.blk.dbmr ← b.nWords;
BLT.blk.dlx ← InlineDefs.BITSHIFT[x,logBitsPerPixel];
BLT.blk.dty ← y;
BitBltDefs.BITBLT[@BLT.blk];
FreeBLT[BLT];
END;
SetColorLine: PUBLIC PROC [x1,y1,x2,y2: INTEGER, fn: BitBltDefs.BBoperation,
c: Color ← 0, b: BitmapPtr ← NIL, cGray: GrayPatternPtr ← NIL] =
BEGIN
fpOff:INTEGER = 20000B;
BLT: BLTBlockPtr;
logBitsPerPixel: CARDINAL;
dx,dy,oi,nn,partl,pinc:INTEGER;
li:LONG INTEGER;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← logTable[b.nBitsPerPixel];
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;
dx←x2-x1;dy←y2-y1;
BLT ← AllocateBLT[];
LOOPHOLE[@BLT.blk.gray0, GrayPatternPtr]↑ ← IF cGray#NIL THEN cGray↑
ELSE GetColorGray[c];
BLT.blk.sourcetype ← gray;
BLT.blk.function ← fn;
BLT.blk.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.blk.dbmr ← b.nWords;
BLT.blk.sty ← 0; --DORADO looks here
IF ABS[dx]>ABS[dy] THEN
BEGIN
BLT.blk.dh ← 1;
IF dx<0 THEN BEGIN t:INTEGER;t←x1;x1←x2;x2←t;t←y1;y1←y2;
y2←t;dx←-dx;dy←-dy;END;
oi←IF dy<0 THEN -1 ELSE IF dy=0 THEN 0 ELSE 1;
li←ABS[dy];
li←li*fpOff;
li←li/dx;
pinc←InlineDefs.LowHalf[li];
partl←0;
UNTIL x1>=x2 DO
nn←0;
UNTIL partl>fpOff OR nn>=dx DO
nn←nn+1;
partl←partl+pinc;
ENDLOOP;
--must worry about off-screen
BLT.blk.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.blk.dw ← InlineDefs.BITSHIFT[nn,logBitsPerPixel];
BLT.blk.dty ← y1;
partl←partl-fpOff;
y1←y1+oi;
x1←x1+nn;
BitBltDefs.BITBLT[@BLT.blk];
ENDLOOP;
END
ELSE
BEGIN
BLT.blk.dw ← b.nBitsPerPixel;
IF dy<0 THEN BEGIN t:INTEGER;t←x1;x1←x2;x2←t;t←y1;y1←y2;
y2←t;dx←-dx;dy←-dy;END;
oi←IF dx<0 THEN -1 ELSE IF dx=0 THEN 0 ELSE 1;
li←ABS[dx];
li←li*fpOff;
li←li/dy;
pinc←InlineDefs.LowHalf[li];
partl←0;
UNTIL y1>=y2 DO
nn←0;
UNTIL partl>fpOff OR nn>=dy DO
nn←nn+1;
partl←partl+pinc;
ENDLOOP;
--must worry about off-screen
BLT.blk.dty ← y1;
BLT.blk.dh ← nn;
BLT.blk.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
partl←partl-fpOff;
x1←x1+oi;
y1←y1+nn;
BitBltDefs.BITBLT[@BLT.blk];
ENDLOOP;
END;
FreeBLT[BLT];
END;
SetupColorAreaBLT: PUBLIC PROC [BLT: BLTBlockPtr,
x1,y1,x2,y2: INTEGER, fn: BitBltDefs.BBoperation, b: BitmapPtr ← NIL] =
BEGIN
logBitsPerPixel: CARDINAL;
IF b = NIL THEN b ← Screen;
logBitsPerPixel ← logTable[b.nBitsPerPixel];
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 -- rotate by 90 degrees
t: INTEGER;
t ← (INTEGER[b.nLines]-1)-y1; y1 ← x1;
x1 ← (INTEGER[b.nLines]-1)-y2; y2 ← x2; x2 ← t;
END;
BLT.blk.sourcetype ← gray;
BLT.blk.destalt←FALSE;
BLT.blk.dlbca ← MakeLongPointer[b.bits,b.bank];
BLT.blk.dbmr ← b.nWords;
BLT.blk.dlx ← InlineDefs.BITSHIFT[x1,logBitsPerPixel];
BLT.blk.dty ← y1;
BLT.blk.dw ← InlineDefs.BITSHIFT[(x2+1-x1),logBitsPerPixel];
BLT.blk.dh ← (y2+1-y1);
BLT.blk.sty ← 0; --DORADO looks here
BLT.blk.function ← fn;
END;
END.