preparing to do a cp/m cleanup

i wrote most of this up to here on a linux laptop, but some
changes need to be made to get it working with CP/M-80.
This commit is contained in:
Kyle Isom 2023-10-03 20:59:03 -07:00
parent a43054deec
commit a60a6a3f59
7 changed files with 325 additions and 60 deletions

View File

@ -1,6 +1,6 @@
TARGETS := test undump TARGETS := test dump undump
LIBS := binary.pas ihex.pas LIBS := binary.pas common.pas ihex.pas
FPC_FLAGS := -g FPC_FLAGS := -g -Mtp
FPC := fpc $(FPC_FLAGS) FPC := fpc $(FPC_FLAGS)
.PHONY: all .PHONY: all
@ -13,6 +13,9 @@ clean:
test: test.pas $(LIBS) test: test.pas $(LIBS)
$(FPC) $@.pas $(FPC) $@.pas
undump: undump.pas binary.pas ihex.pas undump: undump.pas $(LIBS)
$(FPC) $@.pas
dump: dump.pas $(LIBS)
$(FPC) $@.pas $(FPC) $@.pas

View File

@ -1,6 +1,22 @@
{
binary.pas contains procedures and functions for dealing
with binary data.
}
type type
BStr = String[2]; { String representing a u8. } BStr = String[2]; { String representing a u8. }
WStr = String[4]; { String representing a u16. } 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; function ValidHexDigit(bval: Byte): Boolean;
var var

38
common.pas Normal file
View File

@ -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;

50
dump.pas Normal file
View File

@ -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.

84
kcpmtk.txt Normal file
View File

@ -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.

View File

@ -13,4 +13,6 @@ begin
begin begin
WriteLn(I, '->', WriteByte(I)); WriteLn(I, '->', WriteByte(I));
end; end;
LowVideo;
end. end.

View File

@ -1,82 +1,151 @@
program undump; program undump;
{ {
undump is a program to take the output from dump undump is a program to take the output fr
and put it into binary format. and put it into binary format.
} }
{$I 'common.pas'}
{$I 'binary.pas'} {$I 'binary.pas'}
{$I 'ihex.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; procedure PrnHelp;
begin begin
WriteLn('UNDUMP V1.0'); WriteLn('UNDUMP V1.0');
WriteLn('Converts DUMP.COM output to Intel Hex format'); WriteLn('Converts DUMP.COM output to Intel Hex format');
WriteLn(''); WriteLn('');
WriteLn('Usage:'); 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; Halt;
end; 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 var
i, argc : Integer; i, argc : Integer;
rec : irec;
opts : record opts : record
Binary : Boolean;
ShoVer : Boolean; ShoVer : Boolean;
InFile : FilePath; InFile : FilePath;
OutFile : FilePath; OutFile : FilePath;
end; end;
param : String[255]; param : String[32];
paramc : Char;
begin begin
opts.ShoVer := False; opts.Binary := False;
opts.InFile := ''; opts.ShoVer := False;
opts.InFile := '';
opts.OutFile := ''; opts.OutFile := '';
argc := ParamCount; argc := ParamCount;
i := 1;
for i := 1 to ParamCount do param := ParamStr(i);
while param[1] = '-' do
begin begin
if ParamStr(i) = '-h' or ParamStr(i) = 'H' then paramc := UpCase(param[2]);
begin
opts.ShoVer := True; case paramc of
argc := argc - 1; 'B': opts.Binary := True;
'H': opts.ShoVer := True;
else
PrnHelp;
end; end;
i := i + 1;
param := ParamStr(i);
argc := argc - 1;
end; end;
if opts.ShoVer then PrnHelp(); if opts.ShoVer then PrnHelp();
@ -86,9 +155,12 @@ begin
if i = 1 then opts.OutFile := ParamStr(ParamCount); if i = 1 then opts.OutFile := ParamStr(ParamCount);
if i > 1 then if i > 1 then
begin begin
InFile := ParamStr(i); opts.InFile := ParamStr(i);
OutFile := ParamStr(i+1); opts.OutFile := ParamStr(i+1);
end; end;
DumpIHex(InFile, OutFile); if opts.Binary then
DumpBinary(opts.InFile, opts.OutFile)
else
DumpIHex(opts.InFile, opts.OutFile);
end. end.