ColorDisplayHeadDorado.mesa
Last edited by Doug Wyatt on December 8, 1983 2:00 pm
Last edited by Andrew Birrell on December 20, 1983 2:10 pm
DIRECTORY
Basics USING [bitsPerWord, BITAND, BITOR, BITSHIFT, LongDiv, LongDivMod, LongMult, LowHalf],
ColorDisplayFace USING [Color, DisplayType, Mode],
DeviceCleanup USING [Await, Item, Reason],
DoradoInputOutput USING [InputNoPE, RWMufMan],
PrincOps USING [PageCount, PageNumber, wordsPerPage],
ProcessorFace USING [GetClockPulses, microsecondsPerHundredPulses];
ColorDisplayHeadDorado: PROGRAM
IMPORTS Basics, DeviceCleanup, DoradoInputOutput, ProcessorFace
EXPORTS ColorDisplayFace = {
ErrorHalt: PROC = {ERROR};
Base: TYPE = LONG BASE POINTER;
first64K: Base = LOOPHOLE[LONG[0]];
RPtr: TYPE = Base RELATIVE POINTER; -- relative to absolute address 0
rpNIL: RPtr = LOOPHOLE[0];
Mode: TYPE = ColorDisplayFace.Mode;
Color: TYPE = ColorDisplayFace.Color;
DisplayType: TYPE = ColorDisplayFace.DisplayType;
CSBState: TYPE = MACHINE DEPENDENT RECORD [mcb: MCBPtr];
csb: LONG POINTER TO CSBState = LOOPHOLE[LONG[177414B]];
Monitor control block
MCBPtr: TYPE = Base RELATIVE POINTER TO MCB; -- in first64k
MCB:
TYPE =
MACHINE
DEPENDENT
RECORD [
seal: CARDINAL ← mcbSeal,
flags: MCBFlags,
achanCB: ChanCBPtr,
bchanCB: ChanCBPtr,
colorCB: ColorCBPtr
];
mcbSeal: CARDINAL = 177456B;
Flag: TYPE = BOOLEAN ← FALSE;
MCBFlags:
TYPE =
MACHINE
DEPENDENT
RECORD [
unused: [0..777B] ← 0,
m: Flag, -- minimixer (unimplemented)
vc: Flag, -- vertical control
hc: Flag, -- horizontal control
clk: Flag, -- clock
a: Flag, -- A table
b: Flag, -- B table
c: Flag -- C table
];
Channel control block
ChanCBPtr: TYPE = Base RELATIVE POINTER TO ChanCB; -- in first64k
ChanCB:
TYPE =
RECORD [
link: ChanCBPtr ← rpNIL, -- next ChanCB in chain, or NIL
wordsPerLine: CARDINAL, -- words per bitmap scanline
bitmap: LONG POINTER ← NIL, -- pointer to bitmap bits (must be even)
linesPerField: CARDINAL, -- scan lines per field (bitmap height / 2)
pixelsPerLine: CARDINAL, -- visible pixels/scanline + 377B
leftMargin: CARDINAL, -- left margin + marginOffset[monitortype]
scan: ScanControl -- scan control word (see below)
];
pplOffset: CARDINAL = 377B; -- offset for pixelsPerLine
Margin offsets for various monitors
AltoTerminal: 107B, Ramtek525: 66B, Ramtek1000: 0,
ConracRQB525: 66B, ConracRQB875: 107B, ConracRQB1225: 0,
Scan control word
ScanControl:
TYPE =
MACHINE
DEPENDENT
RECORD [
unused: [0..77B] ← 0,
mode24: BOOLEAN, -- 24 bit per pixel mode
aChannelOnly: BOOLEAN, -- if TRUE, disable B channel
bBypass: BOOLEAN, -- B channel bypassed to BTable
a8b2: BOOLEAN, -- 8 bits from A, 2 bits from B (a6b4 if FALSE)
res: ScanRes ← full, -- resolution
size: [0..17B] ← 1 -- bits per pixel; must be 1, 2, 4, or 8
];
ScanRes: TYPE = MACHINE DEPENDENT{quarter(0), half(2), full(3)};
Color control block
ColorCBPtr: TYPE = Base RELATIVE POINTER TO ColorCB; -- in first64k
ColorCB:
TYPE =
MACHINE
DEPENDENT
RECORD [
aTable(0:0..31): LONG POINTER TO ATableImage, -- pointer to color table A
bTable(2:0..31): LONG POINTER TO BCTableImage, -- pointer to color table B
cTable(4:0..31): LONG POINTER TO BCTableImage, -- pointer to color table C
miniMixer(6:0..31): LONG POINTER TO MiniMixerImage ← NIL, -- pointer to MiniMixer table
vcontrol(10B:0..47): VControl, -- vertical control
hcontrol(13B:0..47): HControl, -- horizontal control
ccontrol(16B:0..15): CControl, -- clock control
reserved(17B:0..15): CARDINAL ← 0
];
Vertical control information (loaded via vc flag)
VControl:
TYPE =
MACHINE
DEPENDENT
RECORD [
VBtoVS: [0..377B], VStoVS: [0..377B],
VStoVB: CARDINAL,
VisibleLines: CARDINAL];
Horizontal control information (loaded via hc flag)
HControl:
TYPE =
MACHINE
DEPENDENT
RECORD [
HRamMaxAddr: CARDINAL,
HBLeadLength: [0..377B], HSTrailAddr: [0..377B],
HBTrailLength: CARDINAL];
Clock control information (loaded via clk flag)
CControl:
TYPE =
MACHINE
DEPENDENT
RECORD [
zero: [0..17B] ← 0, mul: [0..377B], div: [0..17B]];
ATableIndex: TYPE = [0..1024);
ATableImage: TYPE = ARRAY ATableIndex OF ATableEntry;
BCTableIndex: TYPE = [0..256);
BCTableImage: TYPE = ARRAY BCTableIndex OF BCTableEntry;
MiniMixerIndex: TYPE = [0..256);
MiniMixerImage: TYPE = ARRAY MiniMixerIndex OF MiniMixerEntry;
ATableEntry:
TYPE =
MACHINE
DEPENDENT
RECORD [
zeroL(0:0..3): [0..17B] ← 0, -- always zero
redL(0:4..7): [0..17B], -- low order 4 bits of red value
blue(0:8..15): [0..377B], -- blue value
zeroH(1:0..3): [0..17B] ← 0, -- always zero
green(1:4..11): [0..377B], -- green value
redH(1:12..15): [0..17B] -- high order 4 bits of red value
];
BCTableEntry:
TYPE =
MACHINE
DEPENDENT
RECORD [
zero(0:0..7): [0..377B] ← 0, -- always zero
value(0:8..15): [0..377B] -- table value
];
MiniMixerEntry:
TYPE =
MACHINE
DEPENDENT
RECORD [
address(0:0..7): [0..377B], data(0:8..15): [0..377B]];
Interface variables
The following are valid as soon as the module start code has run (see Start)
globalStateSize: PUBLIC NAT ← SIZE[MCB]+3*SIZE[ChanCB]+SIZE[ColorCB]; -- for Initialize
displayType: PUBLIC DisplayType ← none; -- display type; 0 means display not available
oldRev: BOOLEAN ← FALSE; -- TRUE if color board has an old revision level (less than Cj)
ramtek525: CARDINAL = 1; -- displayType for Ramtek or Hitachi 525 line monitor
hitachi3619: CARDINAL = 2; -- displayType for Hitachi UHR monitor
pixelsPerInch: PUBLIC NAT ← 0; -- Size of a pixel
mixedRG: PUBLIC BOOLEAN ← TRUE; -- in fullmode, red and green alternate in A bitmap
width,height: PUBLIC NAT ← 0; -- Dimensions of current raster in pixels
baseA,baseB: PUBLIC LONG POINTER ← NIL; -- bitmap addresses
bplA,bplB: PUBLIC NAT ← 0; -- bitmap bits per line
Internal globals
screenwidth,screenheight: CARDINAL; -- screen dimensions in pixels
initialized: BOOLEAN ← FALSE; -- control blocks are allocated
connected: BOOLEAN ← FALSE; -- bitmaps and tables are allocated, globals are set
turnedon: BOOLEAN ← FALSE; -- display is on, bitmaps and tables are resident
fullmode: BOOLEAN ← FALSE; -- connected in 24 bit per pixel mode
mapmode: BOOLEAN ← FALSE; -- connected in a mapped mode
The following globals are valid when initialized=TRUE (see Initialize)
first64k-relative pointers to global state:
rpMCB: MCBPtr ← rpNIL;
rpTChan: ChanCBPtr ← rpNIL;
rpAChan: ChanCBPtr ← rpNIL;
rpBChan: ChanCBPtr ← rpNIL;
rpColor: ColorCBPtr ← rpNIL;
long pointers to same:
mcb: LONG POINTER TO MCB ← NIL;
tchan: LONG POINTER TO ChanCB ← NIL;
achan: LONG POINTER TO ChanCB ← NIL;
bchan: LONG POINTER TO ChanCB ← NIL;
color: LONG POINTER TO ColorCB ← NIL;
The following globals are valid when connected=TRUE (see Connect)
bppA,bppB: [0..LAST[INTEGER]] ← 0; -- bits per pixel
showA,showB: BOOLEAN ← FALSE; -- to be shown
atable: LONG POINTER TO ATableImage ← NIL;
btable,ctable: LONG POINTER TO BCTableImage ← NIL; -- used only in fullmode
ashift,bshift: INTEGER ← 0;
amask,bmask: WORD ← 0;
Initialize:
PUBLIC
PROC [globalState:
LONG
POINTER] = {
alloc: RPtr ← LOOPHOLE[Basics.LowHalf[LOOPHOLE[globalState]]];
end: RPtr ← LOOPHOLE[Basics.LowHalf[LOOPHOLE[globalState+globalStateSize]]];
Alloc:
PROC[words:
CARDINAL]
RETURNS[RPtr] =
INLINE {
p: RPtr ← alloc; alloc ← alloc + words; RETURN[p] };
IF initialized THEN ErrorHalt[];
Allocate from globalState block:
mcb ← @first64K[rpMCB ← Alloc[SIZE[MCB]]];
tchan ← @first64K[rpTChan ← Alloc[SIZE[ChanCB]]];
achan ← @first64K[rpAChan ← Alloc[SIZE[ChanCB]]];
bchan ← @first64K[rpBChan ← Alloc[SIZE[ChanCB]]];
color ← @first64K[rpColor ← Alloc[SIZE[ColorCB]]];
IF LOOPHOLE[alloc,CARDINAL]>LOOPHOLE[end,CARDINAL] THEN ErrorHalt[];
tchan^ ← [link: rpNIL, wordsPerLine: 0, bitmap:
NIL, linesPerField: 0,
pixelsPerLine: pplOffset, leftMargin: 0, scan: ];
color^ ← [aTable: NIL, bTable: NIL, cTable: NIL, vcontrol: , hcontrol: , ccontrol: ];
mcb^ ← [flags: [], achanCB: rpNIL, bchanCB: rpNIL, colorCB: rpColor];
initialized ← TRUE;
};
Lg: TYPE = [0..4); -- logarithm base 2
lg1: Lg = 0; lg2: Lg = 1; lg4: Lg = 2; lg8: Lg = 3;
Exp: PROC[lg: Lg] RETURNS[CARDINAL] = INLINE { RETURN[Basics.BITSHIFT[1,lg]] }; -- 2^lg
PagesForWords:
PROC[words:
LONG
CARDINAL]
RETURNS[
CARDINAL] =
INLINE {
q,r: CARDINAL; [q,r] ← Basics.LongDivMod[words,PrincOps.wordsPerPage];
RETURN[IF r>0 THEN q+1 ELSE q] };
WordsForPages:
PROC[pages:
CARDINAL]
RETURNS[
LONG
CARDINAL] =
INLINE {
RETURN[Basics.LongMult[pages,PrincOps.wordsPerPage]] };
LPFromPage:
PROC[page: PrincOps.PageNumber]
RETURNS[
LONG
POINTER] =
INLINE {
RETURN[LOOPHOLE[Basics.LongMult[page, PrincOps.wordsPerPage]]] };
words per line, guaranteed to be even; resulting width in pixels >= w
Wpl:
PROC[w:
CARDINAL, lbpp: Lg]
RETURNS[
CARDINAL] =
INLINE {
bits: CARDINAL ← w*Exp[lbpp]; RETURN[((bits+31)/32)*2] };
WordsForBitmap:
PROC[w,h:
CARDINAL, lbpp: Lg]
RETURNS[
LONG
CARDINAL] =
INLINE {
RETURN[Basics.LongMult[Wpl[w,lbpp],h]] };
HasMode:
PUBLIC
PROC[mode: Mode]
RETURNS[
BOOLEAN] = {
IF displayType=none THEN RETURN[FALSE]; -- no display
old revision boards can't run both channels at the same time
IF oldRev AND (mode.full OR (mode.useA AND mode.useB)) THEN RETURN[FALSE];
IF mode.full
THEN {
SELECT displayType
FROM
ramtek525 => RETURN[TRUE];
hitachi3619 => RETURN[FALSE];
ENDCASE; -- drop through
}
ELSE {
a,b: CARDINAL ← 0; -- bits per pixel
IF mode.useA THEN a ← Exp[mode.lgBitsPerPixelA];
IF mode.useB THEN b ← Exp[mode.lgBitsPerPixelB];
IF a>8 OR b>4 OR (a+b)>10 THEN RETURN[FALSE]; -- limits of Dorado hardware
SELECT displayType
FROM
ramtek525 => RETURN[TRUE]; -- all possible modes supported
hitachi3619 => RETURN[a<8 OR b=0]; -- can't use B channel if a=8
ENDCASE; -- drop through
};
ErrorHalt[]; -- bogus displayType ("can't happen")
RETURN[FALSE];
};
PagesForMode:
PUBLIC
PROC[mode: Mode]
RETURNS[PrincOps.PageCount] = {
a,b: CARDINAL ← 0; -- bits per pixel
words: LONG CARDINAL ← 0;
IF NOT HasMode[mode] THEN RETURN[0];
words ← SIZE[ATableImage]; -- atable always required
IF mode.full
THEN {
a ← 16; b ← 8; -- bitmap A has double pixels
words ← words + 2*SIZE[BCTableImage]; -- need 2 more color tables
}
ELSE {
IF mode.useA THEN a ← Exp[mode.lgBitsPerPixelA]; -- bitmap A
IF mode.useB THEN b ← Exp[mode.lgBitsPerPixelB]; -- bitmap B
};
words ← words + Basics.LongMult[(a+b)*screenwidth/Basics.bitsPerWord,screenheight];
RETURN[PagesForWords[words]];
};
MapIndex:
PROC[a,b:
CARDINAL]
RETURNS[ATableIndex] =
INLINE {
OPEN Basics;
RETURN[BITOR[BITAND[BITSHIFT[a,ashift],amask],BITAND[BITSHIFT[b,bshift],bmask]]] };
SetSize:
PROC[mode: Mode, pages: PrincOps.PageCount]
RETURNS[
BOOLEAN] = {
w: CARDINAL ← screenwidth;
h: CARDINAL ← screenheight;
avail: LONG CARDINAL ← 0;
extra: CARDINAL ← 0;
IF pages>=PagesForMode[mode] THEN { width ← w; height ← h; RETURN[TRUE] };
IF NOT mode.full THEN RETURN[FALSE];
avail ← WordsForPages[pages]; -- available words
extra ← SIZE[ATableImage] + 2*SIZE[BCTableImage]; -- overhead for tables
IF avail>extra THEN avail ← avail - extra ELSE RETURN[FALSE];
Shrink the raster width, observing necessary constraints.
Bitmaps must have an even number of words per line, so width must shrink
in steps of 4 pixels. Each 4 pixels of width require 6*h words.
w ← 4*Basics.LongDiv[avail,6*h];
IF w<screenwidth/2
THEN {
w ← screenwidth/2;
Shrink the raster height. Bitmaps must have an even number of lines,
so height must shrink in steps of 2. Each 2 lines require 3*w words.
h ← 2*Basics.LongDiv[avail,3*w];
};
IF h>0 THEN { width ← w; height ← h; RETURN[TRUE] } ELSE RETURN[FALSE];
};
Connect:
PUBLIC
PROC [mode: Mode,
firstPage: PrincOps.PageNumber, nPages: PrincOps.PageCount] = {
allocBegin: LONG POINTER ← LPFromPage[firstPage]; -- beginning address
allocLimit: LONG CARDINAL = WordsForPages[nPages]; -- maximum words available
allocCount: LONG CARDINAL ← 0; -- words allocated so far
Alloc:
PROC[words:
LONG
CARDINAL]
RETURNS[
LONG
POINTER] =
INLINE {
p: LONG POINTER ← allocBegin + allocCount; allocCount ← allocCount + words;
IF allocCount>allocLimit THEN ErrorHalt[]; RETURN[p] };
AllocBitmap:
PROC[bpl:
CARDINAL]
RETURNS [
LONG
POINTER] =
INLINE {
RETURN[Alloc[Basics.LongMult[bpl/Basics.bitsPerWord,height]]] };
IF NOT initialized OR NOT HasMode[mode] OR connected THEN ErrorHalt[];
IF NOT SetSize[mode,nPages] THEN ErrorHalt[];
SELECT displayType
FROM
ramtek525 => {
color.vcontrol ← [VBtoVS: 3B, VStoVS: 3B, VStoVB: 20B, VisibleLines: 240];
color.hcontrol ← [HRamMaxAddr: 379, HBLeadLength: 6, HSTrailAddr: 28, HBTrailLength: 25];
color.ccontrol ← [mul: 130B, div: 14B];
tchan.leftMargin ← 65B };
hitachi3619 => {
color.vcontrol ← [VBtoVS: 3B, VStoVS: 3B, VStoVB: 14B, VisibleLines: 512];
color.hcontrol ← [HRamMaxAddr: 629, HBLeadLength: 6, HSTrailAddr: 61, HBTrailLength: 49];
color.ccontrol ← [mul: 163B, div: 17B];
tchan.leftMargin ← 172 -- a guess -- };
ENDCASE => ErrorHalt[];
Allocate bitmaps first; they must begin at even addresses
IF mode.full
THEN {
double the pixel clock rate
SELECT displayType
FROM
ramtek525 => color.ccontrol ← [mul: 130B, div: 16B];
ENDCASE => ErrorHalt[];
tchan.scan ← [mode24: TRUE, aChannelOnly: FALSE, bBypass: TRUE, a8b2: TRUE];
adjust leftMargin to compensate for the faster pixel clock
tchan.leftMargin ← 2*tchan.leftMargin + 40B--HWindow-- + 40B--marginCounter--;
baseA ← AllocBitmap[bplA ← 2*8*width]; -- double pixels in bitmap A
baseB ← AllocBitmap[bplB ← 8*width];
bppA ← bppB ← 8; showA ← showB ← TRUE;
color.aTable ← atable ← Alloc[SIZE[ATableImage]];
color.bTable ← btable ← Alloc[SIZE[BCTableImage]];
color.cTable ← ctable ← Alloc[SIZE[BCTableImage]];
atable^ ← ALL[[redH: 0, redL: 0, blue: 0, green: 0]];
btable^ ← ALL[[value: 0]]; ctable^ ← ALL[[value: 0]];
fullmode ← TRUE }
ELSE {
tchan.scan ← [mode24: FALSE, aChannelOnly: ~mode.useB, bBypass: FALSE, a8b2: bppB<=2];
IF mode.useA
THEN {
bppA ← Exp[mode.lgBitsPerPixelA];
bplA ← width*bppA;
baseA ← AllocBitmap[bplA];
showA ← TRUE };
IF mode.useB
THEN {
bppB ← Exp[mode.lgBitsPerPixelB];
bplB ← width*bppB;
baseB ← AllocBitmap[bplB];
showB ← TRUE };
color.aTable ← atable ← Alloc[SIZE[ATableImage]];
atable^ ← ALL[[redH: 0, redL: 0, blue: 0, green: 0]];
mapmode ← TRUE };
set up for MapIndex
IF tchan.scan.a8b2 THEN { ashift ← 10-bppA; amask ← 1774B; bshift ← 2-bppB; bmask ← 0003B }
ELSE { -- a6b4 -- ashift ← 10-bppA; amask ← 1760B; bshift ← 4-bppB; bmask ← 0017B };
set up channel control blocks; use tchan for a template
tchan.pixelsPerLine ← width+pplOffset; tchan.linesPerField ← height/2;
IF bppA>0
THEN { achan^ ← tchan^; achan.bitmap ← baseA;
achan.wordsPerLine ← bplA/Basics.bitsPerWord; achan.scan.size ← bppA };
IF bppB>0
THEN { bchan^ ← tchan^; bchan.bitmap ← baseB;
bchan.wordsPerLine ← bplB/Basics.bitsPerWord; bchan.scan.size ← bppB };
tchan.pixelsPerLine ← 0 + pplOffset; -- now make tchan a dummy control block
IF fullmode
THEN {
achan fetches two bitmap pixels per screen pixel
bchan runs at half resolution: 2 pixel clocks for each pixel from the bitmap
achan.pixelsPerLine ← bchan.pixelsPerLine ← 2*width+pplOffset;
bchan.scan.res ← half;
horizontal control is measured in pixel clock periods
color.hcontrol.HRamMaxAddr ← 2*color.hcontrol.HRamMaxAddr;
color.hcontrol.HBLeadLength ← 2*color.hcontrol.HBLeadLength;
color.hcontrol.HSTrailAddr ← 2*color.hcontrol.HSTrailAddr;
color.hcontrol.HBTrailLength ← 2*color.hcontrol.HBTrailLength;
};
connected ← TRUE;
};
Disconnect:
PUBLIC
PROC = {
IF NOT connected THEN ErrorHalt[];
IF turnedon THEN TurnOff[];
color.aTable ← NIL; color.bTable ← color.cTable ← NIL;
achan.bitmap ← bchan.bitmap ← NIL;
width ← height ← 0;
baseA ← baseB ← NIL; bplA ← bplB ← 0; bppA ← bppB ← 0;
showA ← showB ← FALSE;
atable ← NIL; btable ← ctable ← NIL;
fullmode ← mapmode ← connected ← FALSE;
};
TurnOn:
PUBLIC
PROC = {
IF (NOT connected) OR turnedon THEN RETURN;
mcb.flags ← [vc: TRUE, hc: TRUE, clk: TRUE, a: TRUE];
mcb.achanCB ← rpTChan; -- plug in dummy control block to establish scan mode
csb.mcb ← rpMCB;
WHILE mcb.flags.a DO ENDLOOP; -- wait for microcode to notice everything
IF fullmode THEN mcb.flags ← [b: TRUE, c: TRUE];
mcb.achanCB ← (IF showA THEN rpAChan ELSE rpNIL); -- show bitmap A
mcb.bchanCB ← (IF showB THEN rpBChan ELSE rpNIL); -- show bitmap B
turnedon ← TRUE;
};
TurnOff:
PUBLIC
PROC = {
asave: ATableEntry;
bsave,csave: BCTableEntry;
IF NOT turnedon THEN RETURN;
mcb.achanCB ← mcb.bchanCB ← rpNIL; -- disable bitmaps
asave ← atable[0];
atable[0] ← [redH: 0, redL: 0, green: 0, blue: 0]; -- black
mcb.flags.a ← TRUE;
IF fullmode
THEN {
bsave ← btable[0]; csave ← ctable[0];
btable[0] ← ctable[0] ← [value: 0];
mcb.flags.b ← mcb.flags.c ← TRUE;
};
Wait[]; -- be sure the microcode is no longer touching bitmaps or color tables
csb.mcb ← rpNIL;
atable[0] ← asave;
IF fullmode THEN { btable[0] ← bsave; ctable[0] ← csave };
turnedon ← FALSE;
};
Show:
PUBLIC
PROC[a,b:
BOOLEAN] = {
IF bppA>0 THEN showA ← a;
IF bppB>0 THEN showB ← b;
IF turnedon
THEN {
mcb.achanCB ← (IF showA THEN rpAChan ELSE rpNIL);
mcb.bchanCB ← (IF showB THEN rpBChan ELSE rpNIL);
};
};
GetColor:
PUBLIC
PROC[pixelA,pixelB:
CARDINAL]
RETURNS[r,g,b: Color] = {
IF mapmode
THEN {
index: ATableIndex ← MapIndex[pixelA,pixelB];
entry: ATableEntry ← atable[index];
RETURN[r: entry.redH*16+entry.redL, g: entry.green, b: entry.blue];
}
ELSE RETURN[0,0,0];
};
SetColor:
PUBLIC
PROC[pixelA,pixelB:
CARDINAL, r,g,b: Color] = {
IF mapmode
THEN {
index: ATableIndex ← MapIndex[pixelA,pixelB];
atable[index] ← [redH: r/16, redL: r MOD 16, blue: b, green: g];
IF turnedon THEN mcb.flags.a ← TRUE;
};
};
GetRedMap:
PUBLIC
PROC[in: Color]
RETURNS[out: Color] = {
IF fullmode
THEN {
index: ATableIndex ← MapIndex[in,0];
entry: ATableEntry ← atable[index];
RETURN[entry.redH*16+entry.redL] }
ELSE RETURN[0];
};
GetGreenMap:
PUBLIC
PROC[in: Color]
RETURNS[out: Color] = {
IF fullmode THEN RETURN[ctable[in].value] ELSE RETURN[0];
};
GetBlueMap:
PUBLIC
PROC[in: Color]
RETURNS[out: Color] = {
IF fullmode THEN RETURN[btable[in].value] ELSE RETURN[0];
};
SetRedMap:
PUBLIC
PROC[in,out: Color] = {
IF fullmode
THEN {
index: ATableIndex ← MapIndex[in,0];
atable[index] ← [redH: out/16, redL: out MOD 16, green: 0, blue: 0];
IF turnedon THEN mcb.flags.a ← TRUE; };
};
SetGreenMap:
PUBLIC
PROC[in,out: Color] = {
IF fullmode
THEN { ctable[in] ← [value: out];
IF turnedon THEN mcb.flags.c ← TRUE; };
};
SetBlueMap:
PUBLIC
PROC[in,out: Color] = {
IF fullmode
THEN { btable[in] ← [value: out];
IF turnedon THEN mcb.flags.b ← TRUE; };
};
Initialization
minFPS: CARDINAL = 30; -- minimum number of frames per second
maxPulsesPerRefresh:
LONG
CARDINAL = 2*
--for safety--
(
LONG[100]*
--pulsesPerHundredPulses-- 1000000
--microsecondsPerSecond--)/
(LONG[minFPS]*ProcessorFace.microsecondsPerHundredPulses);
Wait:
PROC =
INLINE { timeDone:
LONG
CARDINAL ← ProcessorFace.GetClockPulses[];
WHILE ProcessorFace.GetClockPulses[] - timeDone < maxPulsesPerRefresh DO ENDLOOP };
InitializeCleanup:
PUBLIC
PROC = {
OPEN DeviceCleanup;
item: Item;
reason: Reason;
state: CSBState;
DO
reason ← Await[@item];
SELECT reason
FROM
turnOff => { state ← csb^; csb.mcb ← rpNIL; Wait[] };
turnOn => { csb^ ← state };
ENDCASE;
ENDLOOP;
};
Start
{
hasColorBoard: BOOLEAN ← (DoradoInputOutput.InputNoPE[360B] # 0);
IF hasColorBoard
THEN {
device:
MACHINE
DEPENDENT
RECORD[type: [0..17B], junk: [0..7777B]] ←
DoradoInputOutput.InputNoPE[361B];
SELECT device.type
FROM
17B => {
displayType ← ramtek525;
screenwidth ← 640; -- must be a multiple of 32
screenheight ← 480; -- must be a multiple of 2
pixelsPerInch ← 64; -- *** approximate ***
};
16B => {
displayType ← hitachi3619;
screenwidth ← 1024; -- must be a multiple of 32
screenheight ← 1024; -- must be a multiple of 2
pixelsPerInch ← 72; -- *** approximate ***
};
ENDCASE => ErrorHalt[]; -- unknown display type
determine whether an old rev DispY board is installed
oldRev ← (DoradoInputOutput.RWMufMan[[useDMD: FALSE, dMuxAddr: 3107B]].dMuxData # 0);
};
csb^ ← [mcb: rpNIL];
};
}.