-- File: ExecIcepick.mesa
-- edited by Levin, November 25, 1980 4:46 PM.
-- edited by Brotz, November 19, 1980 9:45 AM.

DIRECTORY
displayCommon: FROM "DisplayCommon",
dsD: FROM "DisplayDefs",
exD: FROM "ExceptionDefs",
inD: FROM "InteractorDefs",
intCommon: FROM "intCommon",
Inline,
LaurelExecImpDefs,
StreamDefs;

ExecIcepick: PROGRAM
IMPORTS disC: displayCommon, dsD, exD, intC: intCommon, Inline, StreamDefs
EXPORTS LaurelExecImpDefs
SHARES dsD =

BEGIN

OPEN LaurelExecImpDefs;


Movie: PUBLIC PROCEDURE [villain: STRING] =
BEGIN
pCursor: POINTER TO ARRAY [0 .. 15] OF CARDINAL = LOOPHOLE[431B];
icePick: ARRAY [0 .. 15] OF CARDINAL ←
[000016B, 000037B, 000037B, 000077B, 000376B, 000770B, 000760B, 000360B,
000540B, 001000B, 002000B, 004000B, 010000B, 020000B, 040000B, 100000B];
startX, cornerX, centerX: dsD.ScreenXCoord;
startY, cornerY, centerY: dsD.ScreenYCoord;
clock: CARDINAL;

MoveCursor: PROCEDURE [sx, sy, fx, fy, delay: CARDINAL] =
BEGIN
dx: INTEGER ← SELECT TRUE FROM sx = fx => 0, sx < fx => 8, ENDCASE => -8;
dy: INTEGER ← SELECT TRUE FROM sy = fy => 0, sy < fy => 8, ENDCASE => -8;
UNTIL dsD.cursorY↑ = fy DO
dsD.cursorX↑ ← dsD.cursorX↑ + dx;
dsD.cursorY↑ ← dsD.cursorY↑ + dy;
clock ← inD.realTimeClock↑;
UNTIL inD.realTimeClock↑ - clock >= delay DO ENDLOOP;
ENDLOOP;
END; -- of MoveCursor --

BlackHole: PROCEDURE [bitmap: dsD.BitMapPtr, width, height: CARDINAL] =
BEGIN
leftX, topY: CARDINAL ← 0;
BBTableSpace: TYPE = ARRAY[0 .. SIZE[dsD.Bbt]] OF WORD;
moveTable, clearTable: BBTableSpace;
moveBBT: dsD.BbtPtr ← AlignedBBTable[@moveTable];
clearBBT: dsD.BbtPtr ← AlignedBBTable[@clearTable];

AlignedBBTable: PROCEDURE [p: POINTER TO BBTableSpace] RETURNS [dsD.BbtPtr] =
BEGIN RETURN[LOOPHOLE[p + Inline.BITAND[p, 1]]]; END;

moveBBT↑ ← dsD.Bbt
[func: dsD.replace + dsD.source,
dbca: bitmap, dbmr: (width+15)/16, dlx: , dty: ,
dw: , dh: , sbca: bitmap, sbmr: (width+15)/16,
slx: , sty: ];
clearBBT↑ ← dsD.Bbt
[func: dsD.replace + dsD.gray,
dbca: bitmap, dbmr: (width+15)/16, dlx: , dty: ,
dw: , dh: , sbca: , sbmr: ,
slx: , sty: , gray: [0, 0, 0, 0]];
IF width MOD 2 = 1 THEN
BEGIN
clearBBT.dw ← 1; clearBBT.dh ← height;
clearBBT.dlx ← leftX + (width ← width - 1); clearBBT.dty ← topY;
dsD.BitBlt[clearBBT];
END;
IF height MOD 2 = 1 THEN
BEGIN
clearBBT.dw ← width; clearBBT.dh ← 1;
clearBBT.dlx ← leftX; clearBBT.dty ← topY + (height ← height - 1);
dsD.BitBlt[clearBBT];
END;
DO
dx, dy: CARDINAL;
SELECT TRUE FROM
width = 0 OR height = 0 => EXIT;
width > height => {dx ← 4; dy ← 2};
width < height => {dx ← 2; dy ← 4};
ENDCASE => {dx ← 2; dy ← 2};
moveBBT.dw ← width/2 - dx; moveBBT.dh ← height/2 - dy;
moveBBT.dlx ← leftX + dx; moveBBT.dty ← topY + dy;
moveBBT.slx ← leftX; moveBBT.sty ← topY;
dsD.BitBlt[moveBBT];
moveBBT.dlx ← moveBBT.dlx + moveBBT.dw;
moveBBT.slx ← moveBBT.dlx + dx;
dsD.BitBlt[moveBBT];
moveBBT.dty ← moveBBT.dty + moveBBT.dh;
moveBBT.sty ← moveBBT.dty + dy;
dsD.BitBlt[moveBBT];
moveBBT.dlx ← leftX + dx;
moveBBT.slx ← leftX;
dsD.BitBlt[moveBBT];
clearBBT.dw ← width; clearBBT.dh ← dy;
clearBBT.dlx ← leftX; clearBBT.dty ← topY;
dsD.BitBlt[clearBBT];
clearBBT.dty ← topY + height - dy;
dsD.BitBlt[clearBBT];
clearBBT.dw ← dx; clearBBT.dh ← height;
clearBBT.dty ← topY;
dsD.BitBlt[clearBBT];
clearBBT.dlx ← leftX + width - dx;
dsD.BitBlt[clearBBT];
leftX ← leftX + dx; width ← width - 2*dx;
topY ← topY + dy; height ← height - 2*dy;
ENDLOOP;
END; -- of BlackHole --

-- First, invert screen except for exceptions region.
disC.patchDCBPtr↑ ← dsD.DCB
[next: intC.exceptionsRegion.dcb,
resolution: high,
background: black,
indenting: intC.mailCommandRegion.dcb.indenting,
width: dsD.bmWidth,
bitmap: disC.bitMapPtr,
height: (intC.exceptionsRegion.topY - intC.mailCommandRegion.topY) / 2];
disC.firstDCB.background ← black;
disC.firstDCB.next ← disC.patchDCBPtr;
dsD.ClearRectangle[inD.leftMargin, inD.rightMargin,
intC.exceptionsRegion.topY, intC.exceptionsRegion.topY + dsD.lineHeight];

-- Set ice pick.
centerX ← inD.leftMargin + 8 * dsD.bmWidth;
centerY ← (intC.exceptionsRegion.topY + intC.mailCommandRegion.topY) / 2 - 15;
startX ← cornerX ← centerX + 48;
cornerY ← centerY - 48;
startY ← cornerY + 320;
StreamDefs.CursorTrack[FALSE];
dsD.ChangeCursor[invisibleCursor];
dsD.cursorX↑ ← startX;
dsD.cursorY↑ ← startY;
Inline.COPY[from:@icePick, to: pCursor, nwords: 16];
exD.DisplayExceptionString["Arrghh! THE ICE PICK!!"L];

-- Move to center along trajectory.
MoveCursor[startX, startY, cornerX, cornerY, 2];
MoveCursor[cornerX, cornerY, centerX, centerY, 1];

-- Display bad bcd message.
exD.DisplayExceptionString[villain];

-- invert rest of screen.
intC.exceptionsRegion.dcb.background ← black;

-- Suck in screen.
BlackHole[bitmap: disC.bitMapPtr, width: dsD.bmWidth * 16,
height: disC.patchDCBPtr.height * 2];

-- Blacken exceptions Region.
exD.ClearExceptionsRegion[];

-- Pregnant pause.
clock ← inD.realTimeClock↑;
UNTIL inD.realTimeClock↑ - clock >= 250 DO ENDLOOP;

-- Last look at exceptions region
intC.exceptionsRegion.dcb.background ← white;

-- Die.
exD.SysBug[];

END; -- of Movie --


END. -- of ExecIcepick --