diff --git a/Makefile b/Makefile index 4f959eb..a82b047 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -TARGETS := test undump -LIBS := binary.pas ihex.pas -FPC_FLAGS := -g +TARGETS := test dump undump +LIBS := binary.pas common.pas ihex.pas +FPC_FLAGS := -g -Mtp FPC := fpc $(FPC_FLAGS) .PHONY: all @@ -13,6 +13,9 @@ clean: test: test.pas $(LIBS) $(FPC) $@.pas -undump: undump.pas binary.pas ihex.pas +undump: undump.pas $(LIBS) + $(FPC) $@.pas + +dump: dump.pas $(LIBS) $(FPC) $@.pas diff --git a/binary.pas b/binary.pas index 2cdd42d..cb90476 100644 --- a/binary.pas +++ b/binary.pas @@ -1,6 +1,22 @@ +{ + binary.pas contains procedures and functions for dealing + with binary data. +} + type -BStr = String[2]; { String representing a u8. } -WStr = String[4]; { String representing a u16. } +BStr = String[2]; { String representing a u8. } +WStr = String[4]; { String representing a u16. } +BinFile = File of Byte; + + +Procedure ExpandFile(var fil : BinFile; var pos : Integer; pad : Integer); +var + i : Integer; +begin + for i := 1 to pad do Write(fil, Byte(0)); + pos := FilePos(fil); +end; + function ValidHexDigit(bval: Byte): Boolean; var diff --git a/common.pas b/common.pas new file mode 100644 index 0000000..b836b67 --- /dev/null +++ b/common.pas @@ -0,0 +1,38 @@ +{ + common.pas + + Common functionality that's useful across my toolkit. + + TYPES + - FilePath is a string used for storing filenames on CP/M. + + Procedures: + - Procedure ExpandFile(var fil : BinFile; var pos : Integer; pad : Integer); +} + +type +FilePath = String[12]; + + +function IMax(a, b : Integer): Integer; +begin + if a > b then IMax := a else IMax := b; +end; + + +function BMax(a, b : Byte): Byte; +begin + if a > b then BMax := a else BMax := b; +end; + + +function IMin(a, b : Integer): Integer; +begin + if a > b then IMin := b else IMin := a; +end; + + +function BMin(a, b : Byte): Byte; +begin + if a > b then BMin := b else BMin := a; +end; diff --git a/dump.pas b/dump.pas new file mode 100644 index 0000000..174d912 --- /dev/null +++ b/dump.pas @@ -0,0 +1,50 @@ +program dump; + +{ + dump emulates the version of DUMP.COM that comes with some + CP/M distributions. +} + +{$I 'binary.pas'} +{$I 'common.pas'} + + +procedure DumpChunk( + var src : BinFile; + var dst : Text; + var addr : Integer, + var chunk : Byte); +var + buffer : array [1 .. 16] of Byte; +begin + Write(dst, WriteWord(addr)); + Write(dst, ' '); + + + +end; + +procedure DumpFile(var src : BinFile; var dst : Text); +var + Address : Integer; + Size : Integer; + Buffer : array [1 .. 16] of Byte; + Chunk : Byte; +begin + Address := 0; + Size := FileSize(src); + Chunk := IMin($10, Size); + + FillChar(Buffer, $10, $0); + WriteLn('Chunk: ', Chunk); +end; + + +var + inf : BinFile; +begin + Assign(inf, 'dump.bin'); + Reset(inf); + + DumpFile(inf, Output); +end. \ No newline at end of file diff --git a/kcpmtk.txt b/kcpmtk.txt new file mode 100644 index 0000000..d3b577b --- /dev/null +++ b/kcpmtk.txt @@ -0,0 +1,84 @@ +KCPMTK : KYLE'S CP/M TOOLKIT + +This is a collection of programs and source libraries that are +useful for working with CP/M. + + +TOOLS + +- DUMP.COM, UNDUMP.COM + + DUMP outputs a hexadecimal-encoded version of a file along with + an address counter. UNDUMP takes this output and can return an + Intel hex version or produce a binary file. + + The original purpose of this repository was to write UNDUMP, which + reverses the output of the DUMP.COM utility. After working with a + CP/M which didn't have DUMP.COM, I wrote my own version. + +- DOWNLOAD.COM, UPLOAD.COM + + A pair of tools that mimics the utility shipped with the RC2014, + which comes by way of Grant Searle's tools. + + +LIBRARIES + +1. COMMON.PAS + +COMMON is a collection of routines that are, you guessed it, commonly +useful. + + Types + ----- + + - FilePath is a string used for storing filenames on CP/M. + + +2. BINARY.PAS + +BINARY is a collection of routines for handling binary data. It has +functions for dealing with digits (e.g. Byte values in the range +$0 .. $F), bytes, and words. When dealing with invalid values, the +code returns 0 instead of a garbage value. This is an arbitrary +choice. + + Types + ----- + + - BStr ('byte string') defines a string for containing an hex- + encoded byte. + - WStr ('word string') defines a string for containing a hex- + encoded word. + - BinFile is a file of bytes. + + Procedures + ---------- + + - Procedure ExpandFile(var fil : BinFile; var pos : Integer; pad : Integer); + + ExpandFile will pad out the file with enough bytes. The `pos` parameter + is used to track the file position after expansion. + + - function ValidHexDigit(bval: Byte): Boolean; + + Returns True if the byte is between the range of $0 .. $F. + + - function ReadDigit(bchr: Char): Byte; + + ReadDigit converts a single character representing an octal, decimal, + or hexadecimal digit to a byte; the octal and decimal support are + incidental. + + - function ReadByte(bstr : BStr): Byte; + function ReadWord(bstr : WStr): Integer; + + Given a string that contains a hex-encoded byte or word, return the + decoded value. + + - function WriteByte(bval : Byte): BStr; + function WriteWord(bval : Integer): WStr; + + Given a byte or word value, return its hex-encoded string + representation. + diff --git a/test.pas b/test.pas index 31e3f0f..93e5771 100644 --- a/test.pas +++ b/test.pas @@ -13,4 +13,6 @@ begin begin WriteLn(I, '->', WriteByte(I)); end; + + LowVideo; end. diff --git a/undump.pas b/undump.pas index eefdcf9..c72ca6a 100644 --- a/undump.pas +++ b/undump.pas @@ -1,82 +1,151 @@ program undump; { - undump is a program to take the output from dump - and put it into binary format. + undump is a program to take the output fr + and put it into binary format. } +{$I 'common.pas'} {$I 'binary.pas'} {$I 'ihex.pas'} -type -FilePath = String[12]; - -Procedure DumpIHex(iname, oname : FilePath); -var - inf : Text; - outf : Text; - line : LnStr; - rec : IRec; -begin - if iname <> '' then - begin - Assign(inf, iname); - Reset(inf); - end else inf := Input; - - if oname <> '' then - begin - Assign(outf, oname); - Rewrite(outf); - end else outf := Output; - - while not EOF(inf) do - begin - ReadLn(inf, line); - if (Line <> '') then - begin - rec := RdDumpLn(line); - WrRec(rec, outf); - end; - end; - - Close(inf); - Writeln(outf, IRecEOF); - Flush(outf); - Close(outf); -end; - procedure PrnHelp; begin WriteLn('UNDUMP V1.0'); WriteLn('Converts DUMP.COM output to Intel Hex format'); WriteLn(''); WriteLn('Usage:'); - WriteLn(' UNDUMP.COM INFILE OUTFILE'); + WriteLn(' UNDUMP.COM [-BH] [INFILE] OUTFILE'); + WriteLn(' If only one argumet is given, it will be assigned'); + WriteLn(' to the output file and input will be set to standard'); + WriteLn(' output.'); + WriteLn(''); + WriteLn('Options:'); + WriteLn(' -B : Write in binary format (the default is Intel'); + WriteLn(' hex format.'); + WriteLn(' -H : Show this help message.'); + Halt; end; +Procedure DumpIHex(iname, oname : FilePath); +var + inf : Text; + outf : Text; + line : LnStr; + rec : IRec; + nlc : Byte; { newline count } +begin + nlc := 0; + if iname <> '' then + begin + Assign(inf, iname); + Reset(inf); + end else inf := Input; + + if oname <> '' then + begin + Assign(outf, oname); + Rewrite(outf); + end else outf := Output; + + while not EOF(inf) do + begin + ReadLn(inf, line); + if (Line <> '') then + begin + rec := RdDumpLn(line); + WrRec(rec, outf); + nlc := 0; + end else nlc := nlc + 1; + + if nlc > 0 then Exit; + + end; + + Close(inf); + Writeln(outf, IRecEOF); + Flush(outf); + Close(outf); +end; + + +Procedure DumpBinary(iname, oname : FilePath); +var + inf : Text; + outf : File of Byte; + line : LnStr; + rec : IRec; + nlc : Byte; { newline count } + i : Byte; + pos : Integer; +begin + nlc := 0; + if iname <> '' then + begin + Assign(inf, iname); + Reset(inf); + end else inf := Input; + + if oname = '' then + PrnHelp; + + Assign(outf, oname); + Rewrite(outf); + + while not EOF(inf) do + begin + ReadLn(inf, line); + if (Line <> '') then + begin + rec := RdDumpLn(line); + pos := FilePos(outf); + if pos > rec.Addr then + ExpandFile(outf, pos, pos-rec.Addr); + if pos <> rec.Addr then Seek(outf, rec.Addr-pos); + for i := 1 to rec.Count do + Write(outf, rec.Data[i]); + nlc := 0; + end else nlc := nlc + 1; + if nlc > 0 then Exit; + end; + + Close(inf); + Close(outf); +end; + var i, argc : Integer; - rec : irec; opts : record + Binary : Boolean; ShoVer : Boolean; InFile : FilePath; OutFile : FilePath; end; - param : String[255]; + param : String[32]; + paramc : Char; begin - opts.ShoVer := False; - opts.InFile := ''; + opts.Binary := False; + opts.ShoVer := False; + opts.InFile := ''; opts.OutFile := ''; - argc := ParamCount; + argc := ParamCount; + i := 1; - for i := 1 to ParamCount do + param := ParamStr(i); + while param[1] = '-' do begin - if ParamStr(i) = '-h' or ParamStr(i) = 'H' then - begin - opts.ShoVer := True; - argc := argc - 1; + paramc := UpCase(param[2]); + + case paramc of + 'B': opts.Binary := True; + 'H': opts.ShoVer := True; + else + PrnHelp; end; + + i := i + 1; + param := ParamStr(i); + argc := argc - 1; end; if opts.ShoVer then PrnHelp(); @@ -86,9 +155,12 @@ begin if i = 1 then opts.OutFile := ParamStr(ParamCount); if i > 1 then begin - InFile := ParamStr(i); - OutFile := ParamStr(i+1); + opts.InFile := ParamStr(i); + opts.OutFile := ParamStr(i+1); end; - DumpIHex(InFile, OutFile); + if opts.Binary then + DumpBinary(opts.InFile, opts.OutFile) + else + DumpIHex(opts.InFile, opts.OutFile); end.