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˜