From 114ceaf32c0969a318ec330a26a1ed5c5f4b2b47 Mon Sep 17 00:00:00 2001 From: AK6DN Date: Tue, 10 Mar 2020 22:25:01 -0700 Subject: [PATCH] Added RSX-11 format .obj file reader (as default), set BIN format as default output --- README.md | 67 ++++++++++++------- obj2bin.pl | 191 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 170 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 812df0f..e39fccd 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,18 @@ If run with no options, it prints a usage screen: ``` -obj2bin.pl v2.0 by Don North (perl 5.022) +obj2bin.pl v2.1 by Don North (perl 5.03) Usage: ./obj2bin.pl [options...] arguments --help output manpage and exit --debug enable debug mode --verbose verbose status reporting - --boot M9312 boot prom - --console M9312 console/diagnostic prom - --binary binary program load image - --ascii ascii m9312 program load image - --bytes=N bytes per block on output + --boot M9312 boot prom .hex + --console M9312 console/diagnostic prom .hex + --binary binary program load image .bin [default] + --ascii ascii m9312 program load image .txt + --rt11 read .obj files in RT11 format + --rsx11 read .obj files in RSX11 format [default] + --bytes=N bytes per block on output hex format --nocrc inhibit output of CRC-16 in hex format --logfile=LOGFILE logging message file --outfile=OUTFILE output .hex/.txt/.bin file @@ -28,14 +30,19 @@ NAME SYNOPSIS obj2bin.pl [--help] [--debug] [--verbose] [--boot] [--console] [--binary] - [--ascii] [--bytes=N] [--nocrc] [--logfile=LOGFILE] --outfile=BINFILE - OBJFILE... + [--ascii] [--rt11] [--rsx11] [--bytes=N] [--nocrc] [--logfile=LOGFILE] + --outfile=BINFILE OBJFILE DESCRIPTION - Converts a Macro-11 object file to various output formats, including M9312 - boot and console PROM, straight binary records, ASCII format for M9312 - console load commands, and loadable absolute binary program images (.BIN) - files. + Converts a Macro-11 object files to various output formats, including + M9312 boot and console PROM, straight binary records, ASCII format for + M9312 console load commands, and loadable absolute binary program images + (.BIN) files. + + Multiple .psect/.asect ops are supported, as well as all local + (non-global) relocation directory entries. + + Supports either RT-11 or RSX-11 format object files. OPTIONS The following options are available: @@ -57,19 +64,29 @@ OPTIONS Generate a hex PROM file image suitable for programming into an M9312 console/diagnostic prom (1024x4 geometry). + --ascii + Generate a a sequence of 'L addr' / 'D data' commands for downloading + a program via a terminal emulator thru the M9312 user command + interface. Suitable only for really small test programs. + --binary Generate binary format load records of the program image (paper tape format) for loading into SIMH or compatible simulators. These files can also be copied onto XXDP filesystems to generate runnable program images (used to write custom diaqnostics). - --ascii - Generate a a sequence of 'L addr' / 'D data' commands for downloading - a program via a terminal emulator thru the M9312 user command - interface. Suitable only for really small test programs. + Binary format is the default if no other option is specified. If more + than one option is specified the last one takes effect. - Exactly ONE of --boot, --console, --binary, or --ascii must be - specified. + --rt11 + Read input object files in RT-11 format. + + --rsx11 + Read input object files in RSX-11 format. + + RSX-11 object file format is the default if no other option is + specified. If more than one option is specified the last one takes + effect. --bytes=N For hex format output files, output N bytes per line (default 16). @@ -95,10 +112,10 @@ ERRORS "Can't open input file '$file'" -- bad filename or unreadable file - "Error: Improper object file format (1)" -- valid record must start with - 0x01 + "Error: Improper object file format (1)" -- valid RT-11 record must start + with 0x01 - "Error: Improper object file format (2)" -- second byte must be 0x00 + "Error: Improper object file format (2)" -- second RT-11 byte must be 0x00 "Error: Improper object file format (3)" -- third byte is low byte of record length @@ -109,7 +126,7 @@ ERRORS "Error: Improper object file format (5)" -- bytes five thru end-1 are data bytes - "Error: Improper object file format (6)" -- last byte is checksum + "Error: Improper object file format (6)" -- last RT-11 byte is checksum "Error: Bad checksum exp=0x%02X rcv=0x%02X" -- compare rcv'ed checksum vs exp'ed checksum @@ -121,9 +138,9 @@ EXAMPLES obj2bin.pl --verbose --boot --out 23-751A9.hex 23-751A9.obj - obj2bin.pl --verbose --binary --out memtest.bin memtest.obj + obj2bin.pl --verbose --binary --rt11 --out memtest.bin memtest.obj - obj2bin.pl --verbose --binary --out prftst.bin prftst.obj mac/printf.obj + obj2bin.pl --verbose --binary --rsx11 --out prftst.bin prftst.obj mac/printf.obj AUTHOR Don North - donorth @@ -140,4 +157,6 @@ HISTORY 2017-04-01 v1.9 donorth - Renamed from obj2hex.pl to obj2bin.pl 2017-05-04 v1.95 donorth - Updated capability to read multiple input .obj files. 2020-03-06 v2.0 donorth - Updated help documentation and README.md file. + 2020-03-10 v2.1 donorth - Broke down and added RSX-11 input format option. + ``` diff --git a/obj2bin.pl b/obj2bin.pl index 4eed710..ca395ba 100644 --- a/obj2bin.pl +++ b/obj2bin.pl @@ -47,6 +47,8 @@ S<[--boot]> S<[--console]> S<[--binary]> S<[--ascii]> +S<[--rt11]> +S<[--rsx11]> S<[--bytes=N]> S<[--nocrc]> S<[--logfile=LOGFILE]> @@ -63,6 +65,8 @@ binary program images (.BIN) files. Multiple .psect/.asect ops are supported, as well as all local (non-global) relocation directory entries. +Supports either RT-11 or RSX-11 format object files. + =head1 OPTIONS The following options are available: @@ -91,6 +95,12 @@ an M9312 boot prom (512x4 geometry, only low half used). Generate a hex PROM file image suitable for programming into an M9312 console/diagnostic prom (1024x4 geometry). +=item B<--ascii> + +Generate a a sequence of 'L addr' / 'D data' commands for downloading +a program via a terminal emulator thru the M9312 user command interface. +Suitable only for really small test programs. + =item B<--binary> Generate binary format load records of the program image (paper @@ -98,14 +108,19 @@ tape format) for loading into SIMH or compatible simulators. These files can also be copied onto XXDP filesystems to generate runnable program images (used to write custom diaqnostics). -=item B<--ascii> +Binary format is the default if no other option is specified. +If more than one option is specified the last one takes effect. -Generate a a sequence of 'L addr' / 'D data' commands for downloading -a program via a terminal emulator thru the M9312 user command interface. -Suitable only for really small test programs. +=item B<--rt11> -Exactly ONE of B<--boot>, B<--console>, B<--binary>, or B<--ascii> -must be specified. +Read input object files in RT-11 format. + +=item B<--rsx11> + +Read input object files in RSX-11 format. + +RSX-11 object file format is the default if no other option is specified. +If more than one option is specified the last one takes effect. =item B<--bytes=N> @@ -139,9 +154,9 @@ C -- bad option or missing file(s) C -- bad filename or unreadable file -C -- valid record must start with 0x01 +C -- valid RT-11 record must start with 0x01 -C -- second byte must be 0x00 +C -- second RT-11 byte must be 0x00 C -- third byte is low byte of record length @@ -149,7 +164,7 @@ C -- fourth byte is high byte of record C -- bytes five thru end-1 are data bytes -C -- last byte is checksum +C -- last RT-11 byte is checksum C -- compare rcv'ed checksum vs exp'ed checksum @@ -161,9 +176,9 @@ Some examples of common usage: obj2bin.pl --verbose --boot --out 23-751A9.hex 23-751A9.obj - obj2bin.pl --verbose --binary --out memtest.bin memtest.obj + obj2bin.pl --verbose --binary --rt11 --out memtest.bin memtest.obj - obj2bin.pl --verbose --binary --out prftst.bin prftst.obj mac/printf.obj + obj2bin.pl --verbose --binary --rsx11 --out prftst.bin prftst.obj mac/printf.obj =head1 AUTHOR @@ -182,6 +197,7 @@ Modification history: 2017-04-01 v1.9 donorth - Renamed from obj2hex.pl to obj2bin.pl 2017-05-04 v1.95 donorth - Updated capability to read multiple input .obj files. 2020-03-06 v2.0 donorth - Updated help documentation and README.md file. + 2020-03-10 v2.1 donorth - Broke down and added RSX-11 input format option. =cut @@ -202,7 +218,7 @@ BEGIN { unshift(@INC, $FindBin::Bin); # external local modules # generic defaults -my $VERSION = 'v2.0'; # version of code +my $VERSION = 'v2.1'; # version of code my $HELP = 0; # set to 1 for man page output my $DEBUG = 0; # set to 1 for debug messages my $VERBOSE = 0; # set to 1 for verbose messages @@ -215,7 +231,8 @@ my %excaddr; # words to be skipped in rom crc calc my $rombase; # base address of rom image my $romsize; # number of rom addresses my $romfill; # rom fill pattern -my $romtype = 'NONE'; # default rom type +my $romtype = 'BINA'; # default rom type is BINARY +my $objtype = 'RSX11'; # default object file format is RSX11 my $bytesper = -1; # bytes per block in output file my $nocrc = 0; # output CRC16 as last word unless set my $outfile = undef; # output filename @@ -229,6 +246,8 @@ my $NOERROR = GetOptions( "help" => \$HELP, "console" => sub { $romtype = 'DIAG'; }, "binary" => sub { $romtype = 'BINA'; }, "ascii" => sub { $romtype = 'ASC9'; }, + "rt11" => sub { $objtype = 'RT11'; }, + "rsx11" => sub { $objtype = 'RSX11'; }, "bytes=i" => \$bytesper, "nocrc" => \$nocrc, "outfile=s" => \$outfile, @@ -264,11 +283,13 @@ unless ($NOERROR --help output manpage and exit --debug enable debug mode --verbose verbose status reporting - --boot M9312 boot prom - --console M9312 console/diagnostic prom - --binary binary program load image - --ascii ascii m9312 program load image - --bytes=N bytes per block on output + --boot M9312 boot prom .hex + --console M9312 console/diagnostic prom .hex + --binary binary program load image .bin [default] + --ascii ascii m9312 program load image .txt + --rt11 read .obj files in RT11 format + --rsx11 read .obj files in RSX11 format [default] + --bytes=N bytes per block on output hex format --nocrc inhibit output of CRC-16 in hex format --logfile=LOGFILE logging message file --outfile=OUTFILE output .hex/.txt/.bin file @@ -627,53 +648,99 @@ sub read_rec ($) { my @dat = (); my @suf = (); - # Object file format consists of blocks, optionally preceded, separated, and - # followed by zeroes. Each block consists of: - # - # 001 --- - # 000 | - # lo(length) | - # hi(length) > 'length' bytes - # databyte1 | - # : | - # databyteN --- - # checksum - # + if ($objtype eq 'RT11') { - # skip over strings of 0x00; exit OK if hit EOF - do { return () unless $cnt = read($fh, $buf, 1); } while (ord($buf) == 0); + # RT-11 object file format consists of blocks, optionally preceded, separated, and + # followed by zeroes. Each block consists of: + # + # 001 --- + # 000 | + # lo(length) | + # hi(length) > 'length' bytes + # databyte1 | + # : | + # databyteN --- + # checksum + # - # valid record starts with (1) - $err = 1 unless $cnt == 1 && ord($buf) == 1; - push(@pre, ord($buf)); + # skip over strings of 0x00; exit OK if hit EOF + do { return () unless $cnt = read($fh, $buf, 1); } while (ord($buf) == 0); - # second byte must be (0) - $cnt = read($fh, $buf, 1); - $err = 2 unless $cnt == 1 && ord($buf) == 0; - push(@pre, ord($buf)); + # valid record starts with (1) + $err = 1 unless $cnt == 1 && ord($buf) == 1; + push(@pre, ord($buf)); - # third byte is low byte of record length - $cnt = read($fh, $buf, 1); - $err = 3 unless $cnt == 1; - $len = ord($buf); - push(@pre, ord($buf)); + # second byte must be (0) + $cnt = read($fh, $buf, 1); + $err = 2 unless $cnt == 1 && ord($buf) == 0; + push(@pre, ord($buf)); - # fourth byte is high byte of record length - $cnt = read($fh, $buf, 1); - $err = 4 unless $cnt == 1; - $len += ord($buf)<<8; - push(@pre, ord($buf)); + # third byte is low byte of record length + $cnt = read($fh, $buf, 1); + $err = 3 unless $cnt == 1; + $len = ord($buf); + push(@pre, ord($buf)); - # bytes five thru end-1 are data bytes - $cnt = read($fh, $buf, $len-4); - $err = 5 unless $cnt == $len-4 && $len >= 4; - @dat = unpack("C*", $buf); + # fourth byte is high byte of record length + $cnt = read($fh, $buf, 1); + $err = 4 unless $cnt == 1; + $len += ord($buf)<<8; + push(@pre, ord($buf)); - # last byte is checksum - $cnt = read($fh, $buf, 1); - $err = 6 unless $cnt == 1; - my $rcv = ord($buf); - push(@suf, ord($buf)); + # bytes five thru end-1 are data bytes + $cnt = read($fh, $buf, $len-4); + $err = 5 unless $cnt == $len-4 && $len >= 4; + @dat = unpack("C*", $buf); + + # last byte is checksum + $cnt = read($fh, $buf, 1); + $err = 6 unless $cnt == 1; + my $rcv = ord($buf); + push(@suf, ord($buf)); + + # compare rcv'ed checksum vs exp'ed checksum + my $exp = &chksum(0x01, $len>>0, $len>>8, @dat); + warn sprintf("Warning: Bad checksum exp=0x%02X rcv=0x%02X", $exp, $rcv) unless $exp == $rcv; + + } elsif ($objtype eq 'RSX11') { + + # RSX-11 object file format consists of blocks of data in the following format. + # Each block consists of: + # + # lo(length) + # hi(length) + # databyte1 --- + # : | + # : > 'length' bytes + # : | + # databyteN --- + # zeroFill present if length is ODD; else not present + # + + # first byte is low byte of record length + $cnt = read($fh, $buf, 1); + # but exit OK if hit EOF + return () if $cnt == 0; + $err = 10 unless $cnt == 1; + $len = ord($buf); + push(@pre, ord($buf)); + + # second byte is high byte of record length + $cnt = read($fh, $buf, 1); + $err = 11 unless $cnt == 1; + $len += ord($buf)<<8; + push(@pre, ord($buf)); + + # bytes three thru end are data bytes + $cnt = read($fh, $buf, $len); + $err = 12 unless $cnt == $len && $len >= 0; + @dat = unpack("C*", $buf); + + # optional pad byte if length is odd + $cnt = ($len & 1) ? read($fh, $buf, 1) : 2; + $err = 13 unless $cnt == 1 && ord($buf) == 0 || $cnt == 2; + + } # output the record if debugging if ($DEBUG >= 2) { @@ -691,11 +758,7 @@ sub read_rec ($) { } # check we have a well formatted record - warn sprintf("Warning: invalid object file record format (%d)", $err) if $err; - - # compare rcv'ed checksum vs exp'ed checksum - my $exp = &chksum(0x01, $len>>0, $len>>8, @dat); - warn sprintf("Warning: Bad checksum exp=0x%02X rcv=0x%02X", $exp, $rcv) unless $exp == $rcv; + warn sprintf("Warning: invalid %s object file record format (%d)", $objtype, $err) if $err; # all is well, return the record return @dat; @@ -820,7 +883,7 @@ sub parse_rec ($$$) { printf $LOG "..ENDGSD\n\n" if $DEBUG; $program{END}{ADDRESS} = 0; - foreach my $nam (sort({$psect{$a}{START} == $psect{$b}{START} ? $psect{$a}{LENGTH} <=> $psect{$b}{LENGTH} : $psect{$a}{START} <=> $psect{$b}{START}} keys(%psect))) { + foreach my $nam (sort({$psect{$a}{START} == $psect{$b}{START} ? $psect{$a}{NUMBER} <=> $psect{$b}{NUMBER} : $psect{$a}{START} <=> $psect{$b}{START}} keys(%psect))) { my $start = $psect{$nam}{START}; my $length = $psect{$nam}{LENGTH}; my $end = $length ? $start + $length - 1 : $start;