-- UserTerminalImpl.mesa (last edited by: McJones on: August 28, 1980 11:44 AM)
-- This is currently crocked to use CreateForCode instead of Create to avoid a bug in the CSL display microcode that can’t cross 64K boundaries!!

DIRECTORY
BitBlt USING [BBTable],
DisplayFace USING [
Connect, Cursor, CursorPtr, cursorPosition, Disconnect, GetBitBltTable,
globalStateSize, hasBorder, hasBuffer, height, Initialize, InitializeCleanup,
pagesForBitmap, pixelsPerInch, SetBackground, SetBorderPattern,
SetCursorPattern, TurnOn, TurnOff, width],
DriverStartChain USING [Start],
Environment USING [PageCount, PageNumber, PageOffset],
KeyboardFace USING [keyboard],
MouseFace USING [position, SetPosition],
PilotSwitches USING [switches --.u--],
Process USING [MsecToTicks, SetTimeout],
ProcessInternal USING [AllocateNakedCondition],
ResidentHeap USING [MakeNode],
Runtime USING [CallDebugger],
Space USING [
Create, defaultBase, defaultWindow, Delete, Handle, LongPointer, Map,
nullHandle, virtualMemory, VMPageNumber],
SpecialSpace USING [CreateForCode, MakeResident, MakeSwappable],
System USING [CreateIntervalTimer, GetIntervalTime, Microseconds, TimerHandle],
UserTerminal,
Transaction USING [],
Zone USING [Base, Status];

UserTerminalImpl: MONITOR
IMPORTS
DisplayFace, OtherDrivers: DriverStartChain, KeyboardFace, MouseFace,
PilotSwitches, Process, ProcessInternal, ResidentHeap, Runtime, Space,
SpecialSpace, System, Transaction
EXPORTS DriverStartChain, UserTerminal
SHARES UserTerminal =

BEGIN OPEN UserTerminal;

-- Constants (modulo display hardware and processor)

pixelsPerInch: PUBLIC CARDINAL ← DisplayFace.pixelsPerInch;
screenHeight: PUBLIC CARDINAL [0..32767] ← DisplayFace.height;
screenWidth: PUBLIC CARDINAL [0..32767] ← DisplayFace.width;

mouse: PUBLIC LONG POINTER TO READONLY Coordinate ← LOOPHOLE[MouseFace.position];
cursor: PUBLIC LONG POINTER TO Coordinate ← LOOPHOLE[DisplayFace.cursorPosition];
keyboard: PUBLIC LONG POINTER TO READONLY ARRAY OF WORD ←
LOOPHOLE[KeyboardFace.keyboard];
hasBorder: PUBLIC BOOLEAN ← DisplayFace.hasBorder;

state: State ← disconnected;

GetState: PUBLIC ENTRY PROC RETURNS [State] = {RETURN[state]};

background: Background ← white;

GetBackground: PUBLIC ENTRY PROC RETURNS [Background] = {RETURN[background]};

bitmapBase: LONG POINTER ← NIL;

BitmapIsDisconnected: PUBLIC ERROR = CODE;

GetBitBltTable: PUBLIC ENTRY PROC RETURNS [BitBlt.BBTable] =
BEGIN
IF state = disconnected THEN RETURN WITH ERROR BitmapIsDisconnected;
RETURN[DisplayFace.GetBitBltTable[]]
END;

SetMousePosition: PUBLIC ENTRY PROC [newMousePosition: Coordinate] = {
MouseFace.SetPosition[[newMousePosition.x, newMousePosition.y]]};

saveCursor: ARRAY [0..16) OF WORD ← ALL[0];

GetCursorPattern: PUBLIC ENTRY PROC RETURNS [cursorPattern: CursorArray] = {
RETURN[saveCursor]};

SetCursorPattern: PUBLIC ENTRY PROC [cursorPattern: CursorArray] =
BEGIN
saveCursor ← cursorPattern;
DisplayFace.SetCursorPattern[@saveCursor];
END;

SetBorder: PUBLIC PROCEDURE [oddPairs, evenPairs: [0..377B]] = {
DisplayFace.SetBorderPattern[oddPairs, evenPairs]};

SetBackground: PUBLIC ENTRY PROC [new: Background] RETURNS [old: Background] =
BEGIN
IF (old ← background) = new THEN RETURN;
DisplayFace.SetBackground[
IF (background ← new) = white THEN white ELSE black];
END;

bitmapSpace: Space.Handle ← Space.nullHandle;

SetState: PUBLIC ENTRY PROC [new: State] RETURNS [old: State] =
BEGIN
IF (old ← state) = new THEN RETURN;
IF old = disconnected THEN
BEGIN
swapUnitSize: Environment.PageCount = 50;
bitmapSpace ← SpecialSpace.CreateForCode[
size: DisplayFace.pagesForBitmap, parent: Space.virtualMemory,
base: Space.defaultBase];
IF PilotSwitches.switches.u = up THEN
FOR offset: CARDINAL ← 0, offset + swapUnitSize WHILE
offset + swapUnitSize <= DisplayFace.pagesForBitmap DO
[] ← Space.Create[size: swapUnitSize, parent: bitmapSpace, base: offset]
ENDLOOP;
IF ~DisplayFace.hasBuffer THEN
Space.Map[space: bitmapSpace, window: Space.defaultWindow];
bitmapBase ← Space.LongPointer[bitmapSpace];
DisplayFace.Connect[Space.VMPageNumber[bitmapSpace]];
IF new = (state ← off) THEN RETURN;
END; -- assert state = on or off, and state#new
SELECT new FROM
on =>
BEGIN
IF ~DisplayFace.hasBuffer THEN SpecialSpace.MakeResident[bitmapSpace];
DisplayFace.TurnOn[];
END;
off, disconnected =>
BEGIN
DisplayFace.TurnOff[];
WaitForVerticalRetrace[];
WaitForVerticalRetrace[];
IF ~DisplayFace.hasBuffer THEN SpecialSpace.MakeSwappable[bitmapSpace];
END;
ENDCASE => ERROR;
IF new = disconnected THEN
BEGIN
DisplayFace.Disconnect[];
Space.Delete[bitmapSpace];
bitmapSpace ← Space.nullHandle;
bitmapBase ← NIL;
END;
state ← new;
END;

hardwareVerticalRetrace: LONG POINTER TO CONDITION;
verticalRetrace, blinkTime: CONDITION;
meFirst: BOOLEAN ← TRUE;
microsecondsPerScanLine: CARDINAL = 14; -- should be in terms of DisplayFace

BlinkDisplay: PUBLIC ENTRY PROCEDURE =
BEGIN OPEN DisplayFace;
SetBackground[IF background = white THEN black ELSE white]; -- invert display
WAIT blinkTime;
SetBackground[IF background = white THEN white ELSE black]; -- put it back
END;

-- Miscellaneous

WaitForScanLine: PUBLIC PROCEDURE [scanLine: INTEGER] =
BEGIN
WaitForScanLineZero: ENTRY PROCEDURE = INLINE
BEGIN WaitForVerticalRetrace[] END;
WaitForScanLineZero[];
IF scanLine = 0 OR CARDINAL[scanLine] > screenHeight THEN NULL
ELSE
BEGIN OPEN System;
timer: TimerHandle = CreateIntervalTimer[];
interval: Microseconds = scanLine*microsecondsPerScanLine;
UNTIL GetIntervalTime[timer] >= interval DO ENDLOOP
END
END;

WaitForVerticalRetrace: INTERNAL PROCEDURE =
BEGIN
IF meFirst THEN
BEGIN
meFirst ← FALSE;
WAIT hardwareVerticalRetrace;
BROADCAST verticalRetrace;
meFirst ← TRUE
END
ELSE WAIT verticalRetrace
END;

-- Initialization

Start: PUBLIC PROCEDURE =
BEGIN
mask: WORD;
headGlobalP: Zone.Base RELATIVE POINTER;
s: Zone.Status;
[headGlobalP, s] ← ResidentHeap.MakeNode[DisplayFace.globalStateSize, a16];
IF s # okay THEN Runtime.CallDebugger["Zone error in UserTerminalImpl"L];
[cv: hardwareVerticalRetrace, mask: mask] ←
ProcessInternal.AllocateNakedCondition[];
DisplayFace.Initialize[headGlobalP, mask];
DisplayFace.InitializeCleanup[];
Process.SetTimeout[@blinkTime, Process.MsecToTicks[100]];
OtherDrivers.Start[];
END;

END.

July 31, 1980 9:54 AM
McJonesUse pagesForBitmap, GetBitBltTable from DisplayFace
August 28, 1980 11:44 AM
McJonesConvert to ProcessInternal.AllocateNakedCondition