DIRECTORY Basics, Commander USING [CommandProc, Register], CommandTool, Convert, FS USING [Error, StreamOpen], IntelHex, IO, Rope; MBImpl: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, FS, Basics, IntelHex, IO, Rope = BEGIN iName: Rope.ROPE; oName: Rope.ROPE; mbName: Rope.ROPE; token: Rope.ROPE; iS: IO.STREAM _ NIL; oS: IO.STREAM _ NIL; out: IO.STREAM; argv: CommandTool.ArgumentVector; Mode: TYPE = {both, even, odd}; mode: Mode; FileType: TYPE = {hex, ascii, binary}; DataItem: TYPE = RECORD [address, value: INT]; FileItem: TYPE = RECORD [name: Rope.ROPE, type: FileType, address: INT, count: INT, fileOffset: INT]; Lose: SIGNAL = CODE; myIStream: IntelHex.IStream _ [ endof: myEndOf, get: myGetByte, GetPosition: myGetPosition, SetPosition: mySetPosition ]; myOStream: IntelHex.OStream _ [ PutEndRecord: myPutEndRecord, PutStartRecord: myPutStartRecord, DataByte: myDataByte ]; BitOp: TYPE = PROC [a, b: CARDINAL] RETURNS [CARDINAL]; And: BitOp = INLINE { RETURN[Basics.BITAND[a,b]]; }; Shift: BitOp = INLINE { RETURN[Basics.BITSHIFT[a,b]]; }; WordOp: TYPE = PROC [a: LONG CARDINAL] RETURNS [CARDINAL]; Low: WordOp = INLINE { RETURN[Basics.LowHalf[a]]; }; High: WordOp = INLINE { RETURN[Basics.HighHalf[a]]; }; WordCk: PROC [c: CARDINAL] RETURNS [CARDINAL] = { v: Basics.BytePair _ LOOPHOLE[c]; RETURN [v.low+v.high]; }; CkSum: PROC [c: CARDINAL] RETURNS [CARDINAL] = { v: INTEGER _ And[c, 377B]; v _ -v; v _ And[v, 377B]; RETURN [LOOPHOLE[v, CARDINAL]]; }; myPutEndRecord: IntelHex.PutEndRecordProc = { NULL; }; myPutStartRecord: IntelHex.PutStartRecordProc = { NULL; }; InitLocalStorage: PROC = { maxadr _ 0; }; GetHex: PROC [s: Rope.ROPE] RETURNS [CARDINAL] = { c: CARDINAL _ 0; neg: BOOLEAN _ FALSE; FOR i: INT IN [0..s.Length[]) DO SELECT s.Fetch[i] FROM '- => neg _ TRUE; IN ['0..'9] => c _ (c*16)+(s.Fetch[i]-'0); IN ['a..'f] => c _ (c*16)+(s.Fetch[i]-'a)+10; IN ['A..'F] => c _ (c*16)+(s.Fetch[i]-'A)+10; ENDCASE; ENDLOOP; IF neg THEN c _ 0-c; RETURN[c]; }; Byte: TYPE = [0..377B]; DataRec: TYPE = RECORD [s: PACKED SEQUENCE size: NAT OF Byte]; data: REF DataRec; maxadr, rombase, romsize: INT; dataList: LIST OF REF DataItem; fileList: LIST OF REF FileItem; myDataByte: IntelHex.DataByteProc = { locadr: CARDINAL; intadr: INT _ LOOPHOLE[adr]; IF intadr<0 THEN { out.PutF[" Address outside range of INT!\n"]; SIGNAL Lose; }; IF intadrLAST[CARDINAL] THEN { out.PutF[" Address outside 64K!\n"]; SIGNAL Lose; }; intadr _ intadr-rombase; SELECT mode FROM even => { IF And[Low[intadr], 1] # 0 THEN RETURN; intadr _ intadr/2; -- right shift }; odd => { IF And[Low[intadr], 1] = 0 THEN RETURN; intadr _ intadr/2; -- right shift }; ENDCASE; IF intadr >= romsize THEN RETURN; locadr _ Low[intadr]; IF locadr > maxadr THEN maxadr _ locadr; data[locadr] _ d; }; OByte: PROC [x: CARDINAL] = INLINE { oS.PutChar[LOOPHOLE[x]]; }; OWord: PROC [x: CARDINAL] = INLINE { oS.PutChar[LOOPHOLE[Basics.HighByte[x]]]; oS.PutChar[LOOPHOLE[Basics.LowByte[x]]]; }; MakeMBFile: PROC = { namelength: INT _ mbName.Length[]; OWord[4]; -- boilerplate OWord[1]; -- memorynumber OWord[8]; -- memorywidth in bits FOR i: INT IN [0..namelength) DO OByte[mbName.Fetch[i]-0C]; ENDLOOP; OByte[0]; -- ASCIZ end of string IF And[Low[namelength], 1] = 0 THEN OByte[0]; OWord[2]; -- set current memory and location OWord[1]; -- memorynumber again OWord[0]; -- location FOR i: INT IN [0..maxadr] DO OWord[1]; -- memory data word OWord[0]; -- source line number (not used) OWord[Shift[data[i], 8]]; -- left justified ENDLOOP; OWord[0]; -- end of file }; myEndOf: IntelHex.EndOfProc = { RETURN[iS.EndOf[]]; }; myGetByte: IntelHex.GetByteProc = { RETURN[LOOPHOLE[iS.GetChar[]]]; }; myGetPosition: IntelHex.GetPositionProc = { RETURN[iS.GetIndex[]]; }; mySetPosition: IntelHex.SetPositionProc = { iS.SetIndex[p]; }; myPutC: IntelHex.PutCharProc = { out.PutChar[c]; }; ProcessBinaryFile: PROC [f: REF FileItem] = { address: INT _ f.address; THROUGH [0..f.count) DO myDataByte[adr: address, d: Basics.LowByte[myGetByte[]]]; address _ address + 1; ENDLOOP; }; ProcessAsciiFile: PROC [f: REF FileItem] = { address, value: INT; token: Rope.ROPE; out.PutF[" "]; DO token _ IO.GetTokenRope[iS].token; IF token.Length[] = 0 THEN EXIT; address _ GetHex[token]; token _ IO.GetTokenRope[iS].token; IF token.Length[] = 0 THEN EXIT; value _ GetHex[token]; WHILE ~iS.EndOf[] AND iS.GetChar[] # '\n DO NULL ENDLOOP; out.PutF["(%04x, %02x) ", IO.int[address], IO.int[value]]; myDataByte[adr: address, d: Basics.LowByte[Low[value]]]; ENDLOOP; out.PutF["\n"]; }; Main: Commander.CommandProc = { argIndex: NAT _ 1; NextToken: PROC RETURNS [t: Rope.ROPE] = { IF argIndex >= argv.argc THEN RETURN [NIL]; t _ argv[argIndex]; argIndex _ argIndex + 1; }; Case: PROC [c: Rope.ROPE] RETURNS [BOOL] = { RETURN [Rope.Equal[c, token, FALSE]]; }; out _ cmd.out; argv _ CommandTool.Parse[cmd ! CommandTool.Failed => {msg _ errorMsg; CONTINUE; }]; IF argv = NIL THEN RETURN[$Failure, msg]; mode _ both; rombase _ 0; romsize _ 2048; dataList _ NIL; fileList _ NIL; iS _ NIL; oS _ NIL; DO token _ NextToken[]; IF token.Length[]=0 THEN EXIT; SELECT TRUE FROM Case["-hexfile"] => { fileList _ CONS[NEW[FileItem _ [name: NextToken[], type: hex, address: 0, count: 0, fileOffset: 0]], fileList]; }; Case["-outputfile"] => oName _ NextToken[]; Case["-mbname"] => mbName _ NextToken[]; Case["-even"] => mode _ even; Case["-odd"] => mode _ odd; Case["-both"] => mode _ both; Case["-romsize"] => romsize _ Convert.IntFromRope[NextToken[]]; Case["-baseaddress"] => rombase _ GetHex[NextToken[]]; Case["-fixup"] => { dataAddress, dataValue: INT; dataAddress _ GetHex[NextToken[]]; dataValue _ GetHex[NextToken[]]; dataList _ CONS[NEW[DataItem _ [address: dataAddress, value: dataValue]], dataList]; }; Case["-binaryfile"] => { fileName: Rope.ROPE; fileAddress, fileCount: INT; fileName _ NextToken[]; fileAddress _ GetHex[NextToken[]]; fileCount _ Convert.IntFromRope[NextToken[]]; fileList _ CONS[NEW[FileItem _ [name: fileName, type: binary, address: fileAddress, count: fileCount, fileOffset: 0]], fileList]; }; Case["-keyfile"] => { fileName: Rope.ROPE; fileAddress, fileCount, fileOffset: INT; fileName _ NextToken[]; fileAddress _ GetHex[NextToken[]]; fileCount _ Convert.IntFromRope[NextToken[]]; fileOffset _ GetHex[NextToken[]]; fileList _ CONS[NEW[FileItem _ [name: fileName, type: binary, address: fileAddress, count: fileCount, fileOffset: fileOffset]], fileList]; }; Case["-fixupfile"] => { fileList _ CONS[NEW[FileItem _ [name: NextToken[], type: ascii, address: 0, count: 0, fileOffset: 0]], fileList]; }; ENDCASE => { out.PutF["Unknown switch token: %s\n", IO.rope[token]]; LOOP; }; ENDLOOP; IF romsize NOT IN[0..LAST[NAT]] THEN { out.PutF["Romsize must be positive and less than 32768!\n"]; GOTO Cleanup; }; IF oName.Length[] = 0 THEN { out.PutF[" no output file specified\n"]; GOTO Cleanup; }; IF mbName.Length[] = 0 THEN mbName _ oName; out.PutF[" output file = %s\n", IO.rope[oName]]; out.PutF[" mb file name = %s\n", IO.rope[mbName]]; out.PutF[" rom size = %d bytes\n", IO.int[romsize]]; out.PutF[" rom address = %x\n", IO.int[rombase]]; data _ NEW[DataRec[Basics.LowHalf[romsize]]]; oS _ FS.StreamOpen[oName, $create]; InitLocalStorage[]; WHILE fileList # NIL DO iName _ fileList.first.name; out.PutF[" file: %s, type=%s, address=%04x, count = %d\n", IO.rope[fileList.first.name], IO.rope[SELECT fileList.first.type FROM hex => "hex", binary => "binary", ascii => "ascii", ENDCASE => ERROR], IO.int[fileList.first.address], IO.int[fileList.first.count]]; iS _ FS.StreamOpen[iName ! FS.Error => TRUSTED { out.PutF["ObjToMB %s: no such file\n", IO.rope[iName]]; GOTO Cleanup; };]; iS.SetIndex[fileList.first.fileOffset]; SELECT fileList.first.type FROM hex => { IF NOT IntelHex.ProcessFile[in: myIStream, out: myOStream, errs: myPutC ! Lose => { iS.Close[]; GOTO Cleanup; }] THEN out.PutF[" Hex File processing of %s failed*n", IO.rope[iName]]; }; ascii => ProcessAsciiFile[fileList.first]; binary => ProcessBinaryFile[fileList.first]; ENDCASE => ERROR; iS.Close[]; iS _ NIL; fileList _ fileList.rest; ENDLOOP; WHILE dataList # NIL DO out.PutF[" fixup: address = %04x, data = %04x\n", IO.int[dataList.first.address], IO.int[dataList.first.value]]; myDataByte[adr: dataList.first.address, d: Basics.LowByte[Low[dataList.first.value]]]; myDataByte[adr: dataList.first.address+1, d: Basics.HighByte[Low[dataList.first.value]]]; dataList _ dataList.rest; ENDLOOP; MakeMBFile[]; GOTO Cleanup; EXITS Cleanup => { IF iS#NIL THEN iS.Close[]; IF oS#NIL THEN oS.Close[]; oName _ NIL; iName _ NIL; data _ NIL; dataList _ NIL; fileList _ NIL; }; }; Commander.Register["ObjToMb", Main, "Convert Intel format binary object files to .mb files"]; END. October 4, 1981 3:06 PM, LStewart; Created December 23, 1981 3:31 PM, LStewart; Suppress duplicate address records 2-Jan-82 11:45:27, LStewart; Use IntelHex6 January 7, 1982 11:22 AM, LStewart; Fewer extended address records January 7, 1982 5:52 PM, LStewart; MB files March 19, 1982 4:20 pm, L. Stewart, convert to Cedar 2.5.1 May 5, 1982 4:42 pm, L. Stewart, extensions, Cedar 3 March 19, 1983 5:46 pm, L. Stewart, Cedar 4.0 April 29, 1983 1:17 pm, L. Stewart, added keyfile facility June 12, 1983 5:24 pm, L. Stewart, Cedar 4.2 December 22, 1983 3:39 pm, L. Stewart, Cedar 5 ¾MBImpl.mesa Last Modified: Stewart December 22, 1983 3:39 pm Converts an Intel absolute loader format file into An MB format file for Prom blowing. sum of bytes, contribution to checksum The checksum is the value making sum of checked bytes equal zero. Write an end record. Write a start record. Write a data record after every byte filling a paragraph Write a new extended address record first thing and thereafter when the bank changes. pad to word boundary Mainline code process file list process data list documentation: Rope.ROPE = "Optional arguments in [], default values in (), explanations in {}, '* => repeatable\nObjToMb -hexfile inputfilename -outputfile outputfilename [-even -odd -both (both)] [-baseaddress HexRomBaseAddress (0)] [-romsize DecimalRomSize (2048)] [-fixup HexAddress HexValue]* [-binaryfile filename address count] [-keyfile filename address count fileOffset] [-fixupfile filename] [-mbname filename]\n"; Mainline code �Ê û˜Jšœ ™ Jšœ2™2Jšœ2™2Jšœ#™#J˜šÏk ˜ J˜Jšœ �œ˜(Jšœ ˜ J˜Jš�œ�œ˜J˜ Jš�œ˜Jšœ˜J˜—Jšœ�œ�˜Jš�œ"�œ�œ˜IJš�˜Jšœ �œ˜Jšœ �œ˜Jšœ �œ˜Jšœ �œ˜Jšœ�œ�œ�œ˜Jšœ�œ�œ�œ˜Jšœ�œ�œ˜Jšœ!˜!Jšœ�œ˜J˜ Jšœ �œ˜&Jšœ �œ�œ�œ˜.Jš œ �œ�œ �œ�œ �œ�œ˜eJ˜Jšœ�œ�œ˜J˜˜J˜J˜J˜J˜J˜J˜—˜J˜J˜!J˜J˜J˜—Jš Ïnœ�œ�œ�œ�œ�œ˜7J˜Jšœ �œ�œ�œ ˜4Jšœ�œ�œ�œ ˜8J˜Jšžœ�œ�œ�œ�œ�œ�œ˜:J˜Jšœ�œ�œ˜4Jšœ�œ�œ˜6J˜Jšœ&™&š žœ�œ�œ�œ�œ˜1Jšœ�œ˜!Jš�œ˜J˜J˜—JšœA™Aš žœ�œ�œ�œ�œ˜0Jšœ�œ˜J˜J˜Jš�œ�œ�œ˜J˜J˜—Jšœ™˜-Jš�œ˜J˜J˜—Jšœ™˜1Jš�œ˜J˜J˜—šžœ�œ˜J˜ J˜J˜—š žœ�œ �œ�œ�œ˜2šœ�œ˜Jšœ�œ�œ˜—š�œ�œ�œ�˜ š�œ �˜Jšœ �œ˜Jš�œ(˜*Jš�œ+˜-Jš�œ+˜-Jš�œ˜—Jš�œ˜—Jš�œ�œ ˜Jš�œ˜ J˜J˜—Jšœ8™8Jšœ3™3Jšœ!™!Jšœ�œ ˜Jš œ �œ�œ�œ�œ�œ�œ˜>Jšœ�œ ˜Jšœ�œ˜Jšœ �œ�œ�œ ˜Jšœ �œ�œ�œ ˜J˜˜%Jšœ�œ˜Jšœ�œ�œ˜š�œ �œ˜J˜-Jš�œ˜ J˜—Jš�œ�œ�œ˜š�œ�œ�œ�œ˜J˜$Jš�œ˜ J˜—J˜š�œ�˜˜ Jš�œ�œ�œ˜(JšœÏc˜"J˜—˜Jš�œ�œ�œ˜(JšœŸ˜"J˜—Jš�œ˜Jš�œ�œ�œ˜!J˜Jš�œ�œ˜(J˜J˜J˜——Jš žœ�œ�œ�œ�œ˜@šžœ�œ�œ�œ˜$Jšœ �œ˜)Jšœ �œ˜(J˜J˜—šž œ�œ˜Jšœ �œ˜"Jšœ Ÿ˜Jšœ Ÿ˜Jšœ Ÿ˜!š�œ�œ�œ�˜ J˜Jš�œ˜—Jšœ Ÿ˜!Jšœ™Jš�œ�œ ˜-Jšœ Ÿ"˜-Jšœ Ÿ˜ Jšœ Ÿ ˜š�œ�œ�œ �˜Jšœ Ÿ˜Jšœ Ÿ ˜+JšœŸ˜+Jš�œ˜—Jšœ Ÿ˜J˜J˜—Jšœ �œ˜6Jšœ$�œ�œ˜FJšœ,�œ˜EJ˜>J˜J˜3J˜šžœ�œ�œ˜-Jšœ �œ ˜š�œ�˜J˜9J˜Jš�œ˜—J˜J˜—šžœ�œ�œ˜,Jšœ�œ˜Jšœ �œ˜J˜š�˜Jšœ�œ˜"Jš�œ�œ�œ˜ J˜Jšœ�œ˜"Jš�œ�œ�œ˜ J˜Jš �œ �œ�œ�œ�œ˜9Jšœ�œ�œ ˜:J˜8Jš�œ˜—J˜J˜J˜—Jšœ ™ J˜J˜Jšœ �œ˜šž œ�œ�œ �œ˜*Jš�œ�œ�œ�œ˜+J˜J˜J˜—š žœ�œ �œ�œ�œ˜,Jš�œ�œ˜%J˜—J˜JšœF�œ˜SJš�œ�œ�œ�œ˜)J˜ J˜ J˜Jšœ �œ˜Jšœ �œ˜Jšœ�œ˜ Jšœ�œ˜ J˜š�˜J˜Jš�œ�œ�œ˜š�œ�œ�˜˜Jšœ �œ�œ\˜oJ˜—J˜+J˜(J˜J˜J˜J˜@J˜7˜Jšœ�œ˜J˜"J˜ Jšœ �œ�œA˜TJ˜—˜Jšœ�œ˜Jšœ�œ˜J˜J˜"J˜-Jšœ �œ�œn˜�J˜—˜Jšœ�œ˜Jšœ$�œ˜(J˜J˜"J˜-J˜!Jšœ �œ�œw˜ŠJ˜—˜Jšœ �œ�œ^˜qJ˜—š�œ˜ Jšœ'�œ˜7Jš�œ˜J˜——Jš�œ˜—š �œ �œ�œ�œ�œ�œ˜&J˜