-- 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.