// D0PackMB -- Pack a D0 .MB file for use with LRJ
// last edited January 27, 1982 5:10 PM, van Melle
// last edited August 6, 1980 9:46 AM
// Command line format is:
// D0PackMB xxx.MB xxx.BR [startlabel/startaddress] (xxx.MB startlabel/startaddress)* [symbol]
get "streams.d"
external
[ // O.S.
Closes
Endofs
MoveBlock
Noop
OpenFile
SetBlock
Wo; Ws; WriteBlock
Zero
fpComCm
// GP
SetupReadParam
ReadParam
// ReadMB
ReadMB
// WriteBR
StartBRfile
StartBRnames; BRname
StartBRlabels; BRlabel
StartBRcode; BRcode
EndBRblock
EndBRfile
]
structure BS: [ length byte; char↑1,255 byte ]
static
[ imx = -1
imap
imv
ni
sa
sav
]
let D0PackMB() be
[ let com = OpenFile(0, ksTypeReadOnly, charItem, 0, fpComCm)
let nv, swv = vec 100, vec 100
SetupReadParam(nv, swv, com, swv)
let inst = ReadParam("IW", ".MB file (input): ", nv, swv)
let outst = ReadParam("OW", ".BR file (output): ", nv, swv)
let svv = vec 100
sav = svv
let imp = vec 10000b // Imaginary to real address map
imap = imp
let imvec = vec 30000b // Holds resulting IM data, 3 words per instruction
imv = imvec
let name, nextname = vec 128, vec 128
let outcome = nil
let totalni = 0
// at this point, we have inst open on (first) mb file, outst on br file
// Command line is startlabel [ next.mb startlabel ]* [symbol]
StartBRfile(outst)
StartBRcode()
BRcode(0) // Bldr zeros the first word!
// But LRJ wants an extra word on the front anyway
MoveBlock(name, "RamImage", 5)
[ test Endofs(com)
ifso sa = 0
ifnot [ ReadParam($P, 0, svv, swv)
sa = readSA(svv)
]
ni = 0 // instruction counter
SetBlock(imp, -1, 10000b) // clear (-1) the virtual to real map
outcome = ReadMB(inst, 20, pmemproc, (sa eq -1? psymproc, Noop))
BRcode(imv, ni*3) // dump out instructions
let w0, w1, w2 = 7777b lshift 4, 0, sa
BRcode(lv w0, 3) // final entry has addr=7777, starting address
Closes(inst)
if outcome
then break // error occurred
Wo(ni); Ws("b instructions*N")
if Endofs (com) // more command line?
then break // no, done
ReadParam($P, 0, nextname, swv)
test Endofs(com) // more than one thing on com line?
ifso [ // no, nextname is a label for br file
if nextname!0
then MoveBlock(name, nextname, (nextname>>BS.length+1)/2)
break
]
ifnot [ inst = OpenFile(nextname, ksTypeReadOnly, wordItem, 0)
if inst eq 0
then [ Ws ("Error: can't open ")
Ws (nextname)
Ws ("*N")
break
]
totalni = totalni+ni
]
] repeat // do all mb files
EndBRblock()
Closes(com)
// now write label section of br file
StartBRnames()
BRname(#140, 0, name) // entry label xxx points at leading zero word
let len = name>>BS.length+1
for i = 0 to 4 do
name>>BS.char↑(len+i) = table[ $L; $a; $s; $t; 0]!i
name>>BS.length = len+3
BRname(#140, 0, name) // entry label xxxLast points at 7777 entry
EndBRblock()
StartBRlabels()
BRlabel(1, 0) // initialize the initial label
BRlabel(2, 1+totalni*3) // initialize the Last label
EndBRblock()
EndBRfile()
Closes(outst)
if sa eq -1
then [ Ws("Error: starting address not found*N") ]
if outcome
then [ Ws("Error: "); Ws(outcome); Ws("*N") ]
]
and readSA(sav) = valof
// Read starting address from string, return value if numeric or -1 if not
[ if sav>>BS.length eq 0 resultis -1 // null string
let sa = 0
for i = 1 to sav>>BS.length do
[ let c = sav>>BS.char↑i
test (c ge $0) & (c le $7)
ifso sa = sa*10b+c-$0
ifnot resultis -1
]
resultis sa
]
and pmemproc(memx, width, name) = valof
[ test (name!0 eq 1000b+$I) & (name!1 eq $M*400b)
ifso [ imx = memx; resultis pimproc ]
ifnot resultis Noop
]
and pimproc(addr, data) be
[ let ima = data!3
let p = imv+ni*3
p!0, p!1, p!2 = (ima lshift 4) + (data!2 rshift 12), data!0, data!1
imap!addr = ima
ni = ni+1
]
and psymproc(memx, value, name) be
// Look up a symbolic starting address
if (sa eq -1) & (memx eq imx) then // might have found it already
[ if name>>BS.length ne sav>>BS.length return
for i = 1 to name>>BS.length do
[ let c1 = name>>BS.char↑i
let c2 = sav>>BS.char↑i
if (c1 & not 40b) ne (c2 & not 40b) return // case shift
]
sa = imap!value
Ws(name); Ws(" ="); Wo(sa); Ws("*N")
]