-- ROMMakerCommon.mesa -- cell subroutines to run within Chipmonk -- last modified by E. McCreight, February 2, 1982 6:46 PM -- written by E. McCreight, August 7, 1981 3:52 PM DIRECTORY ChipUserInt, InlineDefs, ppdddefs, ppddefs, ppdefs, RomMakerDefs, StringDefs; RomMakerCommon: PROGRAM IMPORTS ChipUserInt, InlineDefs, ppdddefs, ppddefs, ppdefs, StringDefs EXPORTS RomMakerDefs = PUBLIC BEGIN OPEN ChipUserInt, ppdddefs, ppddefs, ppdefs, RomMakerDefs; lpp: listPtr ← NIL; dirFactor: ARRAY Direction OF Point ← [ -- vertical -- [x: 0, y: 1], -- horizontal -- [x: 1, y: 0], -- diagonal -- [x: 1, y: 1], -- up -- [x: 0, y: -1], -- down -- [x: 0, y: 1], -- left -- [x: -1, y: 0], -- right -- [x: 1, y: 0], -- upAndLeft -- [x: -1, y: -1], -- upAndRight -- [x: 1, y: -1], -- downAndLeft -- [x: -1, y: 1], -- downAndRight -- [x: 1, y: 1]]; FindCell: PROCEDURE [ cellFamily: STRING, member: STRING, required: BOOLEAN ← FALSE, vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [Cell] = BEGIN OPEN StringDefs; s: STRING ← [100]; s.length ← 0; AppendString[to: s, from: cellFamily]; AppendString[to: s, from: member]; FOR cp: LONG POINTER TO cList ← cellList, cp.nxt WHILE cp # NIL DO IF StringDefs.EquivalentString[cp.name, s] THEN BEGIN c: Cell ← cp.ob; IF vCompat # NIL THEN CheckPitchCompatability[c, vCompat, vertical]; IF hCompat # NIL THEN CheckPitchCompatability[c, hCompat, horizontal]; RETURN[c]; END; ENDLOOP; IF required THEN {Explain["Missing cell in family [Confirm]"L, s]; SIGNAL Punt}; RETURN[NIL]; END; FindDCell: PROCEDURE [ cellFamily, memberPrefix: STRING, required: BOOLEAN ← FALSE, vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [d: DCell] = BEGIN OPEN StringDefs; originalLength: INTEGER ← memberPrefix.length; member: STRING ← [50]; member.length ← 0; AppendString[to: member, from: memberPrefix]; AppendString[to: member, from: "0"L]; d[FALSE] ← FindCell[cellFamily, member, FALSE, vCompat, hCompat]; member.length ← originalLength; AppendString[to: member, from: "1"L]; d[TRUE] ← FindCell[cellFamily, member, FALSE, vCompat, hCompat]; IF d[FALSE]=NIL THEN d[FALSE] ← FindCell[cellFamily, memberPrefix, required, vCompat, hCompat]; IF d[TRUE]=NIL THEN d[TRUE] ← d[FALSE]; CheckPitchCompatability[d[FALSE], d[TRUE], diagonal]; END; -- of FindDCell FindDCellPr: PROCEDURE [ cellFamily, memberPrefix: STRING, required: BOOLEAN ← FALSE, vCompat: Cell ← NIL, hCompat: Cell ← NIL] RETURNS [p: DCellPr] = BEGIN OPEN StringDefs; originalLength: INTEGER ← memberPrefix.length; member: STRING ← [50]; member.length ← 0; AppendString[to: member, from: memberPrefix]; AppendString[to: member, from: "0"L]; p[FALSE] ← FindDCell[cellFamily, member, required, vCompat, hCompat]; member.length ← originalLength; AppendString[to: member, from: "1"L]; p[TRUE] ← FindDCell[cellFamily, member, required, vCompat, hCompat]; CheckPitchCompatability[p[FALSE][FALSE], p[TRUE][FALSE], diagonal]; END; -- of FindDCell CheckPitchCompatability: PROCEDURE [ c1, c2: Cell, dir: Direction, rep1: Point ← [1, 1], rep2: Point ← [1, 1]] = BEGIN OPEN StringDefs; FindCellName: PROCEDURE [c: Cell] RETURNS [STRING] = BEGIN FOR cp: LONG POINTER TO cList ← cellList, cp.nxt WHILE cp # NIL DO IF c = cp.ob THEN RETURN[cp.name] ENDLOOP; RETURN[""]; END; IF c1#NIL AND c2#NIL AND Offset[, c1, dir, rep1]#Offset[, c2, dir, rep2] THEN BEGIN cellNames: STRING ← [50]; cellNames.length ← 0; AppendString[to: cellNames, from: FindCellName[c1]]; AppendString[to: cellNames, from: " - "L]; AppendString[to: cellNames, from: FindCellName[c2]]; SELECT dir FROM vertical, up, down => Explain["Incompatible cell vertical pitches [Confirm]"L, cellNames]; horizontal, left, right => Explain["Incompatible cell horizontal pitches [Confirm]"L, cellNames]; ENDCASE => Explain["Incompatible cell sizes [Confirm]"L, cellNames]; SIGNAL Punt; END; END; -- of CheckPitchCompatability Repeat: PROCEDURE[p: Point, cell: Cell, corner: Direction ← topLeft, dir: Direction ← horizontal, rep: locNum ← 1, midCell: Cell ← NIL, midGap: locNum ← 0, altCell: Cell ← NIL, altMod: INTEGER ← 0, name, midName: NameGroup ← nilNameGroup] = BEGIN GetCell: PROCEDURE[i: INTEGER] RETURNS[Cell] = {RETURN[ IF i>0 AND altCell#NIL AND altMod>0 AND (i MOD altMod)#0 THEN altCell ELSE cell]}; RepeatArbitrary[p: p, cp: GetCell, corner: corner, dir: dir, rep: rep, midCell: midCell, midGap: midGap, name: name, midName: midName]; END; RepeatArbitrary: PROCEDURE[p: Point, cp: PROCEDURE[i: INTEGER] RETURNS[Cell], corner: Direction ← topLeft, dir: Direction ← upAndLeft, rep: INTEGER ← 1, midCell: Cell ← NIL, midGap: locNum ← 0, name, midName: NameGroup ← nilNameGroup] = BEGIN cellSize: Point ← CellSize[cp[0]]; midCellSize: Point ← CellSize[midCell]; SELECT corner FROM topRight => p.x ← p.x-cellSize.x; bottomLeft => p.y ← p.y-cellSize.y; bottomRight => p ← [x: p.x-cellSize.x, y: p.y-cellSize.y]; ENDCASE => NULL; SELECT dir FROM vertical, up, down => BEGIN FOR iy: INTEGER IN [0..rep) DO PlaceCell[p: p, cell: cp[iy], rep: [0, iy], midCellSize: midCellSize, midGap: [0, midGap], name: name]; ENDLOOP; FOR iy: INTEGER IN [0..MidCellRep[midGap, rep-1, cellSize.y]) DO PlaceCell[p: [p.x, p.y+(iy+1)*cellSize.y*CellsPerGap[midGap, cellSize.y]+iy*midCellSize.y], cell: midCell, name: midName]; ENDLOOP; END; horizontal, left, right => BEGIN FOR ix: INTEGER IN [0..rep) DO PlaceCell[p: p, cell: cp[ix], rep: [ix, 0], midCellSize: midCellSize, midGap: [midGap, 0], name: name]; ENDLOOP; FOR ix: INTEGER IN [0..MidCellRep[midGap, rep-1, cellSize.x]) DO PlaceCell[ p: [p.x+(ix+1)*cellSize.x*CellsPerGap[midGap, cellSize.x]+ix*midCellSize.x, p.y], cell: midCell, name: midName]; ENDLOOP; END; ENDCASE => NULL; END; -- of RepeatArbitrary CellsPerGap: PROCEDURE[gap, sizePerCell: locNum] RETURNS[INTEGER] = {RETURN[(gap+sizePerCell-1)/sizePerCell] -- ceiling --}; MidCellRep: PROCEDURE[gap, nCells, sizePerCell: locNum] RETURNS[INTEGER] = BEGIN cellsPerGap: INTEGER ← CellsPerGap[gap, sizePerCell]; RETURN[IF cellsPerGap=0 THEN 0 ELSE nCells/cellsPerGap]; END; MakeMidGrid: PROCEDURE[p: Point, cell: Cell, rep: Point, midVCell, midHCell, midVHCell: Cell ← NIL, midGap: Point ← [0,0]] = BEGIN cellSize: Point ← CellSize[cell]; midCellSize: Point ← [x: CellSize[midVCell].x, y: CellSize[midHCell].y]; sizePerGap: Point ← [x: cellSize.x*CellsPerGap[midGap.x, cellSize.x], y: cellSize.y*CellsPerGap[midGap.y, cellSize.y]]; midCellRep: Point ← [x: MidCellRep[midGap.x, rep.x-1, cellSize.x], y: MidCellRep[midGap.y, rep.y-1, cellSize.y]]; FOR ix: INTEGER IN [0..rep.x) DO FOR iy: INTEGER IN [0..midCellRep.y) DO PlaceCell[p: [p.x, p.y+sizePerGap.y+iy*(sizePerGap.y+midCellSize.y)], cell: midHCell, rep: [ix, 0], midCellSize: CellSize[midVHCell], midGap: midGap]; ENDLOOP; ENDLOOP; FOR ix: INTEGER IN [0..midCellRep.x) DO Repeat[p: [p.x+sizePerGap.x+ix*(sizePerGap.x+midCellSize.x), p.y], cell: midVCell, dir: vertical, rep: rep.y, midCell: midVHCell, midGap: midGap.y]; ENDLOOP; END; -- of MakeMidGrid PlaceCell: PROCEDURE[p: Point, cell: Cell, rep: Point ← [0,0], midCellSize: Point ← [0,0], midGap: Point ← [0,0], name: NameGroup ← nilNameGroup] = BEGIN IF cell#NIL THEN BEGIN cp: Point ← Offset[p: p, cell: cell, dir: diagonal, rep: rep, midCellSize: midCellSize, midGap: midGap]; lp: listPtr ← makeList[cell, cp.x, cp.y, 0, 0]; AddInstName[lp, name, rep]; lpp ← insertList[lpp, lp]; END; END; AddInstName: PROCEDURE[lp: listPtr, name: NameGroup, rep: Point] = BEGIN OPEN StringDefs; ComputeIndex: PROCEDURE[i: INTEGER, coef: Point] RETURNS[indx: INTEGER] = BEGIN k: INTEGER ← coef.x*i+coef.y; RETURN[IF k<0 THEN 0 ELSE k]; END; s: STRING ← [100]; tp: LONG POINTER TO text prop ← NIL; xIndx: INTEGER ← ComputeIndex[rep.x, name.x]; yIndx: INTEGER ← ComputeIndex[rep.y, name.y]; IF lp=NIL OR name.basicName=NIL THEN RETURN; s.length ← 0; AppendString[to: s, from: name.basicName]; IF xIndx#0 OR yIndx#0 THEN AppendChar[s: s, c: '-]; IF xIndx#0 THEN AppendDecimal[s: s, n: xIndx]; IF yIndx#0 THEN BEGIN AppendChar[s: s, c: '-]; AppendDecimal[s: s, n: yIndx]; END; tp ← GetSpace[SIZE[text prop]]; tp↑ ← [nxt: lp.props, varpart: text[s: newString[s]]]; lp.props ← tp; END; -- of AddInstName DirSize: PROCEDURE[size: Point, dir: Direction ← diagonal] RETURNS[Point] = {RETURN[ [x: dirFactor[dir].x*size.x, y: dirFactor[dir].y*size.y]]}; CellSize: PROCEDURE[cell: Cell, dir: Direction ← diagonal] RETURNS[Point] = {RETURN[IF cell=NIL THEN [0,0] ELSE DirSize[size: [x: cell.size[0], y: cell.size[1]], dir: dir]]}; Offset: PROCEDURE[p: Point ← [0, 0], cell: Cell, dir: Direction, rep: Point ← [0, 0], midCell: Cell ← NIL, midCellSize: Point ← [0,0], midGap: Point ← [0, 0], includeTerminalMid: BOOLEAN ← TRUE] RETURNS [Point] = BEGIN midRep: Point ← IF includeTerminalMid THEN rep ELSE [x: rep.x-1, y: rep.y-1]; midCellSize ← IF midCell#NIL THEN CellSize[midCell, dir] ELSE DirSize[midCellSize, dir]; RETURN[IF cell=NIL THEN p ELSE [x: p.x+rep.x*CellSize[cell, dir].x+ MidCellRep[midGap.x, midRep.x, CellSize[cell].x]* midCellSize.x, y: p.y+rep.y*CellSize[cell, dir].y+ MidCellRep[midGap.y, midRep.y, CellSize[cell].y]* midCellSize.y]]; END; BlockSize: PROCEDURE [cell: Cell, rep: Point ← [1, 1], midCell: Cell ← NIL, midGap: Point ← [0, 0]] RETURNS [Point] = {RETURN[Offset[cell: cell, rep: rep, midCell: midCell, midGap: midGap, p: [0,0], dir: diagonal, includeTerminalMid: FALSE]]}; MakeNewCell: PROCEDURE [name: STRING, lpp: listPtr] RETURNS [cp: LONG POINTER TO cList] = BEGIN min: Point ← [LAST[locNum], LAST[locNum]]; max: Point ← [FIRST[locNum], FIRST[locNum]]; lp: listPtr; FOR lp ← lpp, lp.nxt WHILE lp # NIL DO ii: [0..1] ← IF InlineDefs.BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1; min ← [MIN[min.x, lp.lx], MIN[min.y, lp.ly]]; max ← [ MAX[max.x, lp.lx + lp.ob.size[ii]], MAX[ max.y, lp.ly + lp.ob.size[ii + 1]]]; ENDLOOP; FOR lp ← lpp, lp.nxt WHILE lp # NIL DO lp.lx ← lp.lx - min.x; lp.ly ← lp.ly - min.y; lp.selected ← FALSE; ENDLOOP; cp ← alocCList[]; cp.nxt ← cellList; cellList ← cp; cp.ob ← makeCell[max.x - min.x, max.y - min.y, 0, lpp]; cp.name ← name; END; -- of MakeNewCell AddToMasterList: PROCEDURE[lpp: listPtr] = BEGIN min: Point ← [LAST[locNum], LAST[locNum]]; max: Point ← [FIRST[locNum], FIRST[locNum]]; lp: listPtr; FOR lp ← lpp, lp.nxt WHILE lp # NIL DO ii: [0..1] ← IF InlineDefs.BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1; min ← [MIN[min.x, lp.lx], MIN[min.y, lp.ly]]; max ← [ MAX[max.x, lp.lx + lp.ob.size[ii]], MAX[ max.y, lp.ly + lp.ob.size[ii + 1]]]; ENDLOOP; FOR lp ← masterList, lp.nxt WHILE lp # NIL DO IF lp.selected THEN BEGIN lp.selected ← FALSE; reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE]; END; ENDLOOP; FOR lp ← lpp, lp WHILE lp # NIL DO p: listPtr ← lp; lp ← p.nxt; p.nxt ← NIL; p.lx ← p.lx - min.x + xx; p.ly ← p.ly - min.y + yy; p.selected ← TRUE; masterList ← insertList[masterList, p]; ENDLOOP; putMark[xx, yy]; reDrawRect[ [x1: xx, x2: xx+max.x-min.x, y1: yy, y2: yy+max.y-min.y], 0, TRUE, TRUE, FALSE]; anyChanges ← sinceIOchanges ← TRUE; END; -- of AddToMasterList DrawCell: PROCEDURE [obp: Cell] = BEGIN lp: listPtr ← makeList[obp.p.anotherme[obp], xx, yy, 0, 0]; obp.returnable ← FALSE; masterList ← insertList[masterList, lp]; selNewThing[masterList, lp, TRUE]; putMark[xx, yy]; reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE]; anyChanges ← sinceIOchanges ← TRUE; END; -- of DrawCell END. -- of RomMakerCommon