--MfbSupportImpl.mesa
--Created by Jeff Weinstein on 22-May-87  1:16:59

DIRECTORY
  BitBlt,
  MfbSupport;
  
MfbSupportImpl: PROGRAM IMPORTS BitBlt EXPORTS MfbSupport =
  BEGIN
  
  Alu:TYPE = MfbSupport.Alu;
  
  Point:TYPE = MfbSupport.Point;
  Box:TYPE = MfbSupport.Box;
  
  AluToSrcFunc:ARRAY Alu OF BitBlt.SrcFunc = [null, null, null, null, complement, null, null, null, complement, complement, complement, null, complement, complement, complement, complement];
  
  AluToDstFunc:ARRAY Alu OF BitBlt.DstFunc = [null, and, null, null, and, null, xor, or, null, xor, null, null, null, or, and, null];
  
  ClearBrick:ARRAY [0..16) OF CARDINAL ← [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
  SetBrick:ARRAY [0..16) OF CARDINAL ← [0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH, 0FFFFH];
  
  MfbBitBltBlock:PUBLIC PROCEDURE[destAddr:LONG POINTER, destWidth:CARDINAL, alu:Alu, pPoints:LONG POINTER TO ARRAY [0..0) OF Point, numBoxes:CARDINAL, pBoxes:LONG POINTER TO ARRAY [0..0) OF Box] =
    BEGIN
    bbTblSpace:BitBlt.BBTableSpace;
    bbPtr:BitBlt.BBptr;
    destWordWidth:CARDINAL ← destWidth/16;
    blockAddr:LONG POINTER;
    
    bbPtr ← BitBlt.AlignedBBTable[ip:@bbTblSpace];
    IF alu = GXclear THEN
      blockAddr ← LOOPHOLE[LONG[@ClearBrick], LONG POINTER]
    ELSE
      blockAddr ← LOOPHOLE[LONG[@SetBrick], LONG POINTER];
    
    FOR i:CARDINAL IN [0..numBoxes) DO
      bbPtr↑ ← [dst:[word:LOOPHOLE[LOOPHOLE[destAddr,LONG CARDINAL] + pBoxes[i].y1*destWordWidth + (pBoxes[i].x1/16),LONG POINTER], bit:pBoxes[i].x1 MOD 16],
        dstBpl:destWidth,
	src:[word:blockAddr, bit:0],
	srcDesc:[gray[[yOffset:0, widthMinusOne:0, heightMinusOne:15]]],
	width:pBoxes[i].x2 - pBoxes[i].x1,
	height:pBoxes[i].y2 - pBoxes[i].y1,
	flags:[gray:TRUE, srcFunc:null, dstFunc:null]];
      BitBlt.BITBLT[bbPtr];
      ENDLOOP;
    END;

  
  MfbBitBlt:PUBLIC PROCEDURE[srcAddr:LONG POINTER, srcWidth:CARDINAL, destAddr:LONG POINTER, destWidth:CARDINAL, alu:Alu, pPoints:LONG POINTER TO ARRAY [0..0) OF Point, numBoxes:CARDINAL, pBoxes:LONG POINTER TO ARRAY [0..0) OF Box] =
    BEGIN
    direction:BitBlt.Direction;
    bbTblSpace:BitBlt.BBTableSpace;
    bbPtr:BitBlt.BBptr;
    srcWordWidth:CARDINAL ← srcWidth/16;
    destWordWidth:CARDINAL ← destWidth/16;
    
    bbPtr ← BitBlt.AlignedBBTable[ip:@bbTblSpace];
    
    
    FOR i:CARDINAL IN [0..numBoxes) DO
      IF pPoints[i].y < pBoxes[i].y1 THEN
        direction ← backward
      ELSE
        direction ← forward;
      
      bbPtr↑ ← [dst:[word:LOOPHOLE[LOOPHOLE[destAddr,LONG CARDINAL] + pBoxes[i].y1*destWordWidth + (pBoxes[i].x1/16), LONG POINTER], bit:pBoxes[i].x1 MOD 16],
        dstBpl:destWidth,
	src:[word:LOOPHOLE[LOOPHOLE[srcAddr,LONG CARDINAL] + pPoints[i].y*srcWordWidth + pPoints[i].x/16, LONG POINTER], bit:pPoints[i].x MOD 16],
	srcDesc:[srcBpl[destWidth]],
	width:pBoxes[i].x2 - pBoxes[i].x1,
	height:pBoxes[i].y2 - pBoxes[i].y1,
	flags:[direction:direction, srcFunc:AluToSrcFunc[alu], dstFunc:AluToDstFunc[alu]]];
      BitBlt.BITBLT[bbPtr];
      ENDLOOP;
    END;
    
    
  END...