-- ROMImpl.mesa
-- a program to run within Chipmonk
-- last modified by E. McCreight, November 20, 1981 1:00 PM
-- written by E. McCreight, August 7, 1981 3:52 PM
DIRECTORY
ChipUserInt,
MB,
ppddefs,
ppdefs,
RomMakerDefs,
SegmentDefs,
StreamDefs,
StringDefs;
RomImpl: PROGRAM
IMPORTS
ChipUserInt, MB, ppdefs, RomMakerDefs,
SegmentDefs, StreamDefs
EXPORTS RomMakerDefs =
BEGIN OPEN ChipUserInt, ppddefs, ppdefs, RomMakerDefs;
CantBuildRom: PROCEDURE[why, explanation: STRING ← NIL] =
{Explain[what: "Can't build Rom [Confirm]", why: why,
explanation: explanation]};
BuildRom: PUBLIC PROCEDURE[] =
BEGIN
romDecoder, romData: DCellPr;
romDecoderTopLeftCorner, romDecoderLeftMid,
romDecoderBottomLeftCorner: Cell;
romDecoderTop, romDecoderTopMid: Cell;
romDecoderMidV, romDecoderMidH, romDecoderMidVH: Cell;
romDecoderBottom, romDecoderBottomMid: Cell;
romDecoderDataTop, romDecoderData, romDecoderDataMid,
romDecoderDataBottom: Cell;
romDataTopMid, romDataBottomMid, romOutMuxMid: Cell;
romDataMidV, romDataMidH, romDataMidVH: Cell;
romDataTopRightCorner, romDataRight, romDataRightMid,
romDataBottomRightCorner: Cell;
romDecoderLeft, romDataTop, romDataBottom, romOutMux: DCell;
-- column: FALSE => even column, TRUE => odd column
decodeCell, dataCell: Cell; -- samples for measurements
FindRomCells: PROCEDURE [cellFamily: STRING] =
BEGIN
romDecoder ← FindDCellPr[cellFamily: cellFamily, required: TRUE,
memberPrefix: "Decoder"L];
decodeCell ← romDecoder[TRUE][FALSE];
-- MidV is a vertical column of cells, MidH is a
-- horizontal row of cells, and MidVH is the cell that
-- happens at their intersections.
romDecoderMidH ← FindCell[
cellFamily: cellFamily, member: "DecoderMidH"L, hCompat: decodeCell];
romDecoderMidV ← FindCell[
cellFamily: cellFamily, member: "DecoderMidV"L, vCompat: decodeCell];
romDecoderMidVH ← FindCell[
cellFamily: cellFamily, member: "DecoderMidVH"L, hCompat: romDecoderMidV,
vCompat: romDecoderMidH,
required: romDecoderMidV#NIL AND romDecoderMidH#NIL];
romData ← FindDCellPr[cellFamily: cellFamily, required: TRUE,
memberPrefix: "Data"L];
dataCell ← romData[FALSE][FALSE];
CheckPitchCompatability[decodeCell, dataCell, vertical, [1, 2], [1, 1]];
romDataMidH ← FindCell[
cellFamily: cellFamily, member: "DataMidH"L, hCompat: dataCell,
vCompat: romDecoderMidH,
required: romDecoderMidH#NIL];
romDataMidV ← FindCell[
cellFamily: cellFamily, member: "DataMidV"L, vCompat: dataCell];
romDataMidVH ← FindCell[
cellFamily: cellFamily, member: "DataMidVH"L, hCompat: romDataMidV,
vCompat: romDataMidH,
required: romDataMidV#NIL AND romDataMidH#NIL];
romDecoderLeft ← FindDCell[
cellFamily: cellFamily, memberPrefix: "DecoderLeft"L, vCompat: decodeCell];
romDecoderLeftMid ← FindCell[
cellFamily: cellFamily, member: "DecoderLeftMid"L, vCompat: romDecoderMidH,
required: romDecoderMidH#NIL];
romDecoderTopLeftCorner ← FindCell[
cellFamily: cellFamily, member: "DecoderTopLeftCorner"L];
romDecoderBottomLeftCorner ← FindCell[
cellFamily: cellFamily, member: "DecoderBottomLeftCorner"L];
romDecoderTop ← FindCell[
cellFamily: cellFamily, member: "DecoderTop"L, hCompat: decodeCell];
romDecoderTopMid ← FindCell[
cellFamily: cellFamily, member: "DecoderTopMid"L, hCompat: romDecoderMidV,
required: romDecoderMidV#NIL];
romDecoderBottom ← FindCell[
cellFamily: cellFamily, member: "DecoderBottom"L, hCompat: decodeCell];
romDecoderBottomMid ← FindCell[
cellFamily: cellFamily, member: "DecoderBottomMid"L, hCompat: romDecoderMidV,
required: romDecoderMidV#NIL];
romDecoderData ← FindCell[
cellFamily: cellFamily, member: "DecoderData"L, vCompat: dataCell];
romDecoderDataTop ← FindCell[
cellFamily: cellFamily, member: "DecoderDataTop"L, hCompat: romDecoderData];
romDecoderDataMid ← FindCell[
cellFamily: cellFamily, member: "DecoderDataMid"L, hCompat: romDecoderData,
vCompat: romDecoderMidH,
required: romDecoderMidH#NIL];
romDecoderDataBottom ← FindCell[
cellFamily: cellFamily, member: "DecoderDataBottom"L,
hCompat: romDecoderData];
romDataTop ← FindDCell[
cellFamily: cellFamily, memberPrefix: "DataTop"L, hCompat: dataCell];
romDataTopMid ← FindCell[
cellFamily: cellFamily, member: "DataTopMid"L, hCompat: romDataMidV,
required: romDataMidV#NIL];
romDataBottom ← FindDCell[
cellFamily: cellFamily, memberPrefix: "DataBottom"L, hCompat: dataCell];
romDataBottomMid ← FindCell[
cellFamily: cellFamily, member: "DataBottomMid"L, hCompat: romDataMidV,
required: romDataMidV#NIL];
romOutMux ← FindDCell[cellFamily: cellFamily, memberPrefix: "OutMux"L];
CheckPitchCompatability[dataCell, romOutMux[FALSE], horizontal, [2, 1], [1, 1]];
romOutMuxMid ← FindCell[
cellFamily: cellFamily, member: "OutMuxMid"L, hCompat: romDataMidV,
required: romOutMux[FALSE]#NIL AND romDataMidV#NIL];
romDataTopRightCorner ← FindCell[
cellFamily: cellFamily, member: "DataTopRightCorner"L];
romDataRight ← FindCell[
cellFamily: cellFamily, member: "DataRight"L, vCompat: dataCell];
romDataRightMid ← FindCell[
cellFamily: cellFamily, member: "DataRightMid"L, vCompat: romDataMidH,
required: romDataMidH#NIL];
romDataBottomRightCorner ← FindCell[
cellFamily: cellFamily, member: "DataBottomRightCorner"L];
END; -- of FindRomCells
bodyHeight, decoderDataX, dataX, dataRightX: locNum;
decoderWidth, wordsPerDataRow, wordCount, wordWidth,
logWordsPerDataRow: INTEGER;
dataMidHGap, decodeMidVGap, dataMidVGap: locNum ← 0;
invertData: BOOLEAN;
fileName, memName, cellFamily, romName: STRING ← NIL;
s: StreamDefs.StreamHandle ← NIL;
mb: MB.MBHandle ← NIL;
mbMem: MB.MBMemoryPtr ← NIL;
BEGIN ENABLE Punt => GOTO ExitRom; -- for EXITS
fileName ← RequestString[""L, "Data file:"L, ".mb format"L];
fileName ← FixExtension[fileName, ".mb"L];
s ← StreamDefs.NewWordStream[
fileName, StreamDefs.Read !
SegmentDefs.FileNameError => {
CantBuildRom["Can't find .mb file"L, name]; GOTO ExitRom}];
mb ← MB.ReadMB[
s, uz !
MB.IllegalMBFormat =>
{CantBuildRom["Isn't .mb format"L, fileName]; GOTO ExitRom}];
memName ← RequestString[,, "Memory name in .mb file:"L];
mbMem ← MB.FindMBMemory[mb, memName];
IF mbMem = NIL THEN {CantBuildRom["Memory isn't in .mb file"L, memName]; GOTO ExitRom};
cellFamily ← RequestString[,, "Cell family:"L];
FindRomCells[cellFamily];
wordsPerDataRow ← 1; logWordsPerDataRow ← 0;
IF romOutMux[FALSE]#NIL THEN
BEGIN
t: INTEGER ← RequestInteger["Words per row:"L, "(power of 2)"L];
FOR wordsPerDataRow ← 1, 2*wordsPerDataRow WHILE wordsPerDataRow<t DO
logWordsPerDataRow ← logWordsPerDataRow+1;
ENDLOOP;
END;
MB.ReCast[mem: mbMem, newWordWidth: mbMem.width*wordsPerDataRow];
invertData ← HeSaysYes["Shall I invert the data?"L];
IF HeSaysYes["Is a missing data cell equivalent to either"L,
"real data cell?"L] THEN
MB.SuppressDefaultWords[mem: mbMem,
default: HeSaysYes[s1:"Which one?"L, s3: "(0 or 1)"L]#invertData];
[decoderWidth, wordCount, wordWidth] ← MB.AnalyzeMemory[mbMem];
decoderWidth ← decoderWidth+logWordsPerDataRow;
wordCount ← wordCount + (wordCount MOD 2)+2*logWordsPerDataRow;
IF romDataMidH#NIL THEN
dataMidHGap ← CellSize[dataCell].y*
RequestInteger["Data cells vertically per mid cell row?"L];
IF romDecoderMidV#NIL THEN
decodeMidVGap ← CellSize[decodeCell].x*
RequestInteger["Decoder cells horizontally per mid cell column?"L];
IF romDataMidV#NIL THEN
dataMidVGap ← CellSize[dataCell].x*
RequestInteger["Data cells horizontally per mid cell column?"L];
bodyHeight ← BlockSize[cell: decodeCell, rep: [x: 1, y: wordCount],
midCell: romDataMidH, midGap: [dataMidVGap, dataMidHGap]].y;
decoderDataX ← BlockSize[cell: decodeCell, rep: [x: decoderWidth, y: 1],
midCell: romDecoderMidV, midGap: [decodeMidVGap, dataMidHGap]].x;
dataX ← decoderDataX+CellSize[romDecoderData].x;
dataRightX ← dataX+BlockSize[cell: dataCell, rep: [x: wordWidth, y: 1],
midCell: romDataMidV, midGap: [dataMidVGap, dataMidHGap]].x;
Repeat[
cell: romDecoderLeft[FALSE], p: [0,0], corner: topRight,
dir: down, rep: wordCount,
midCell: romDecoderLeftMid, midGap: dataMidHGap,
altCell: romDecoderLeft[TRUE], altMod: 2];
Repeat[
cell: romDecoderTopLeftCorner, p: [0,0], corner: bottomRight];
Repeat[
cell: romDecoderBottomLeftCorner, p: [0, bodyHeight], corner: topRight];
Repeat[
cell: romDecoderTop, p: [0,0], corner: bottomLeft,
rep: decoderWidth,
midCell: romDecoderTopMid, midGap: decodeMidVGap];
Repeat[
cell: romDecoderBottom, p: [0, bodyHeight], corner: topLeft,
dir: right, rep: decoderWidth,
midCell: romDecoderBottomMid, midGap: decodeMidVGap,
name: [basicName: "Addr"L, x: [-1, decoderWidth-1]]];
Repeat[cell: romDecoderDataTop,
p: [decoderDataX, 0], corner: bottomLeft];
Repeat[
cell: romDecoderData, p: [decoderDataX, 0], dir: down, rep: wordCount/2,
midCell: romDecoderDataMid, midGap: dataMidHGap];
Repeat[cell: romDecoderDataBottom, p: [decoderDataX, bodyHeight]];
Repeat[cell: romDataTop[FALSE],
p: [dataX, 0], corner: bottomLeft, dir: right, rep: wordWidth,
midCell: romDataTopMid, midGap: dataMidVGap,
altCell: romDataTop[TRUE], altMod: 2];
Repeat[cell: romDataTopRightCorner,
p: [dataRightX, 0], corner: bottomLeft];
Repeat[cell: romDataRight, p: [dataRightX, 0], dir: down, rep: wordCount/2,
midCell: romDataRightMid, midGap: dataMidHGap];
Repeat[cell: romDataBottomRightCorner, p: [dataRightX, bodyHeight]];
IF wordsPerDataRow=1 THEN
Repeat[cell: romDataBottom[FALSE],
p: [dataX, bodyHeight], dir: right, rep: wordWidth,
midCell: romDataBottomMid, midGap: dataMidVGap,
altCell: romDataBottom[TRUE], altMod: 2,
name: [basicName: "Data"L, x: [1, 0]]]
ELSE
Repeat[cell: romOutMux[FALSE],
p: [dataX, bodyHeight], dir: right, rep: wordWidth/2,
midCell: romOutMuxMid, midGap: dataMidVGap,
altCell: romOutMux[TRUE], altMod: wordsPerDataRow/2,
name: [basicName: "Data"L, x: [2, 0]]];
MakeDecoderBlock[cells: romDecoder, p: [0, 0], rep: [decoderWidth, wordCount],
pairsToDataArray: logWordsPerDataRow, mem: mbMem,
midCellSize: [x: CellSize[romDecoderMidV].x, y: CellSize[romDecoderMidH].y],
midGap: [decodeMidVGap, dataMidHGap],
invertAddress: HeSaysYes["Shall I invert address inputs?"L]];
MakeMidGrid[p: [0,0], cell: decodeCell, rep: [decoderWidth, wordCount],
midVCell: romDecoderMidV, midHCell: romDecoderMidH, midVHCell: romDecoderMidVH,
midGap: [decodeMidVGap, dataMidHGap]];
MakeDataBlock[cells: romData, p: [dataX, 0], rep: [wordWidth, wordCount/2],
decodePairs: logWordsPerDataRow, mem: mbMem,
midCellSize: [x: CellSize[romDataMidV].x, y: CellSize[romDataMidH].y],
midGap: [dataMidVGap, dataMidHGap],
invertData: invertData,
invertAddress: HeSaysYes["Extra inversion for address decode"L,
"in data array?"L]];
MakeMidGrid[p: [dataX,0], cell: dataCell, rep: [wordWidth, wordCount/2],
midVCell: romDataMidV, midHCell: romDataMidH, midVHCell: romDataMidVH,
midGap: [dataMidVGap, dataMidHGap]];
romName ← RequestString[,, "Name of completed Rom cell:"L];
IF romName#NIL AND romName.length>0 THEN
BEGIN
DrawCell[MakeNewCell[romName, lpp].ob];
romName ← NIL; -- gave string body to cell
END
ELSE AddToMasterList[lpp];
lpp ← NIL; -- gave away list
EXITS ExitRom => NULL;
END;
flushDel[lpp];
IF fileName # NIL THEN FreeString[fileName];
IF memName # NIL THEN FreeString[memName];
IF cellFamily # NIL THEN FreeString[cellFamily];
IF romName # NIL THEN FreeString[romName];
IF s # NIL THEN s.destroy[s];
anyChanges ← sinceIOchanges ← TRUE;
END; -- of BuildRom
MakeDecoderBlock: PROCEDURE [cells: DCellPr, p, rep: Point,
pairsToDataArray: INTEGER, mem: MB.MBMemoryPtr,
midCellSize: Point ← [0,0], midGap: Point ← [0,0],
invertAddress: BOOLEAN ← FALSE] =
BEGIN -- high-order bit on the left, bits passed straight
-- through for data block decoding on the right. Assumes
-- that data block decoding happens in the top
-- 2*pairsToDataArray data rows.
w: MB.MBWordPtr ← mem.words;
FOR iy: INTEGER IN [0..2*pairsToDataArray) DO -- trivial decode
FOR ix: INTEGER IN [0..rep.x) DO
rightColumn: BOOLEAN ← ix = rep.x-1-iy/2;
PlaceCell[p, cells[
rightColumn AND ((iy MOD 2=0)#invertAddress)]
[rightColumn AND ((iy MOD 2#0)#invertAddress)],
[ix, iy], midCellSize, midGap];
ENDLOOP;
ENDLOOP;
FOR iy: INTEGER IN [2*pairsToDataArray..rep.y) DO
loc: LONG CARDINAL ← w.location;
FOR ix: INTEGER IN [rep.x-pairsToDataArray..rep.x) DO
PlaceCell[p, cells[FALSE][FALSE], [ix, iy], midCellSize, midGap];
ENDLOOP;
FOR ix: INTEGER DECREASING IN
[0..rep.x-pairsToDataArray) DO
PlaceCell[p, cells[((loc MOD 2)#0)#invertAddress]
[((loc MOD 2)=0)#invertAddress],
[ix, iy], midCellSize, midGap];
loc ← loc/2;
ENDLOOP;
IF w.nextWord # NIL THEN w ← w.nextWord;
ENDLOOP;
END;
MakeDataBlock: PROCEDURE [cells: DCellPr, p, rep: Point, decodePairs: INTEGER,
mem: MB.MBMemoryPtr,
midCellSize: Point ← [0,0], midGap: Point ← [0,0],
invertAddress, invertData: BOOLEAN ← FALSE] =
BEGIN
w0: MB.MBWordPtr;
mask: INTEGER ← 1;
FOR iy: INTEGER IN [0..decodePairs) DO
FOR ix: INTEGER IN [0..rep.x) DO
t: BOOLEAN ← ix MOD 2*mask >= mask;
PlaceCell[p, cells[t#invertAddress][t=invertAddress],
[ix, iy], midCellSize, midGap];
ENDLOOP;
mask ← 2*mask;
ENDLOOP;
w0 ← mem.words;
FOR iy: INTEGER IN [decodePairs..rep.y) DO
w1: MB.MBWordPtr ← IF w0.nextWord # NIL THEN w0.nextWord ELSE w0;
FOR ix: INTEGER IN [0..rep.x) DO
PlaceCell[p, cells[w0.value[ix]#invertData]
[w1.value[ix]#invertData], [ix, iy], midCellSize, midGap];
ENDLOOP;
w0 ← w1.nextWord;
ENDLOOP;
END;
END. -- of RomImpl