-- 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