jmlynesjr has asked for the wisdom of the Perl Monks concerning the following question:
SOLVED: Trial and error with pack options.
my $c = pack('W*', @binbytes); print $out $c;
Been away for awhile...
Background: I recently discovered the Simh/Open-Simh open source project. This project provides a framework for building simulators for vintage computers(many minis are currently supported - DG, DEC, HP, Honeywell, XDS, etc.). As a Data General(DG) Nova/Eclipse programmer from the 70s, I decided to download the Nova simulator and give it a try. It's a very slick piece of software. It runs the original Data General binary software distributions at about 40x speed on my Dell laptop. I compiled and ran a FORTRAN IV code from the 70s. The simulator represents peripheral devices as unstructured linux files(Ubuntu 22.04 LTS in my case). I want to be able to move text files from the DG RDOS filesystem to/from the linux file system mostly to have access to an editor that I remember how to use.
I'm trying to do this via the DG papertape reader and papertape punch devices. Going from RDOS to linux was easy. Going from linux back to RDOS not so easy. HELP! I can't get the script to write out the binary file. It needs to be actual binary data not a text representation of binary data
The fix has to be simple. I just don't see it.
Notes: RDOS - Data General's Realtime Disk Operating System
RDOS -> linux convert CRs to LFs
linux -> RDOS convert LFs to CRs
Original RDOS Macro file output by the RDOS BPUNCH(binary punch) command.
Output to a simulated papertape punch. The papertape punch is simulated as an unstructured linux file.
MESSAGE INIT WORKING DIRECTORIES-SETUP.MC MESSAGE INIT MACROS INIT UTIL INIT FORT DIR PETE GDIR
Hexdump of the above macro file as a linux binary file, one byte for each character punched. Note the CR(0d) RDOS line endings.
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |......... +.......| * 00000190 4d 45 53 53 41 47 45 20 49 4e 49 54 20 57 4f 52 |MESSAGE I +NIT WOR| 000001a0 4b 49 4e 47 20 44 49 52 45 43 54 4f 52 49 45 53 |KING DIRE +CTORIES| 000001b0 2d 53 45 54 55 50 2e 4d 43 0d 4d 45 53 53 41 47 |-SETUP.MC +.MESSAG| 000001c0 45 0d 49 4e 49 54 20 4d 41 43 52 4f 53 0d 49 4e |E.INIT MA +CROS.IN| 000001d0 49 54 20 55 54 49 4c 0d 49 4e 49 54 20 46 4f 52 |IT UTIL.I +NIT FOR| 000001e0 54 0d 44 49 52 20 50 45 54 45 0d 47 44 49 52 0d |T.DIR PET +E.GDIR.| 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |......... +.......| * 00000380
ptreader.pl takes the above binary file, replaces the RDOS CR(od) line endings with linux LF(0a) line endings, strips off all of the nulls(00), and outputs a linux text file. Read() works fine to read the BPUNCH binary file.
#! /usr/bin/perl # ptreader.pl - Papertape decoder for the Simh Data General Nova/Eclip +se Simulator # The linux file PTP.OUT is produced by the RDOS BPU +NCH command # PTP.OUT is a binary file that has a lot of leading + and trailing nulls # The nulls are stripped off and the remainder is co +pied to the output # file PTP.TXT. Line endings are converted. # # ptreader provides a way to copy text files from # the simulated RDOS filesystem to the linux filesys +tem # # RDOS -> PTP.OUT -> ptreader.pl -> PTP.TXT # # Created by: James M. Lynes jr. # Created on: January 29,2024 # Last Modified: 01/29/2024 - Initial version # 01/30/2024 - Additional comments, fix line ending(0x0 +A) # # Usage: On RDOS: BPUNCH filename # Creates the (binary formatted) linux file: PTP.OU +T # # On linux: ./ptreader.pl # Reads PTP.OUT and creates the reformated linux te +xt file PTP.TXT # # Note: Use ptwriter.pl to format a linux text file to be rea +d by RDOS use strict; use warnings; open(my $in, '<:raw', "PTP.OUT") or die; open(my $out, '>', "PTP.TXT") or die; my $content; my $length; my $maxlength = 4000; my @inbytes; my @outbytes; $length = read($in, $content, $maxlength); # Read the binary fil +e print "Length: $length\n"; # Show total bytes re +ad @inbytes = unpack("C*", $content); # Unpack bytes into a +n array foreach(@inbytes) { # Delete null bytes next if($_ == 0); push(@outbytes, $_); } foreach(@outbytes){printf ("0x%02X ", $_)}; # Show a hex dump of +array print "\n"; foreach(@outbytes) { # Show the text read + my $code = chr($_); if($_ == 0x0D) { $code = chr(0x0A); # Fix linux line end +ing } print "$code"; print $out $code; # Copy text to output + file } close $in; close $out;
ptwriter is supposed to take a linux text file, change LFs back to CRs, and write out the result into a binary file. This code fails miserably! Actually getting it to write out the binary file is the problem.
#! /usr/bin/perl # ptwriter.pl - Papertape encoder for the Simh Data General Nova/Eclip +se Simulator # The linux file PTR.IN is a binary formatted file w +hich can # be read from the RDOS $PTR1 device. # # The user is prompted for the linux text file to conver +t # # ptwriter provides a way to copy text files from # the linux filesystem to the simulated RDOS filesys +tem # # linux file -> ptwriter.pl -> PTR.IN -> RDOS # # Created by: James M. Lynes jr. # Created on: January 30,2024 # Last Modified: 01/30/2024 - Initial version # # # Usage: On linux: ./ptwriter.pl # Creates the (binary formatted) linux file: PTR.IN # User is prompted for the linux text file name # # On RDOS: XFER/A $PTR1 filename # Copies linux file PTP.IN to RDOS file filename # # # Note: Use ptreader.pl to format a RDOS binary file into a l +inux text file use strict; use warnings; print "\n\n"; print "ptwriter - convert linux text file to RDOS papertape input file +\n"; print "=============================================================== +\n"; print "Input linux text file name: "; my $lfile = <STDIN>; chomp($lfile); open(my $in, '<', $lfile) or die; open(my $out, '>', "PTR.IN") or die; my @inbytes; my @bytes; my @outbytes; my $outbytes; my @binbytes; while(my $line = <$in>) { # Read text file con +vert to binary @bytes = unpack('C*', $line); push(@outbytes, @bytes); } my $len = $#outbytes + 1; print "Characters Read: $len\n\n"; #foreach(@outbytes){printf ("0x%02X ", $_)}; # Show a hex dump o +f array #print "\n\n"; foreach(@outbytes) { my $code = $_; if($code == 0x0A) { # Convert linux line +end to RDOS line end $code = 0x0C; } # printf("0x%02X ", $code); # Show the converted + text push(@binbytes, $code); } #print "\n\n"; #foreach(@binbytes) {printf ("0x%02X ", $_)}; # *** Output data lo +oks good at this point *** #print "\n\n"; my $ctr = 0; foreach(@binbytes) { # *** This code not +producing correct my $c = $binbytes[$ctr]; # binary fil +e *** print "$c"; print $out $c; $ctr = $ctr + 1; } close $in; close $out;
James
There's never enough time to do it right, but always enough time to do it over...
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Why Is Writing to a Binary File so Hard?
by hv (Prior) on Jan 31, 2024 at 23:22 UTC | |
by NetWallah (Canon) on Feb 01, 2024 at 00:21 UTC | |
by afoken (Chancellor) on Feb 01, 2024 at 09:29 UTC | |
by jmlynesjr (Deacon) on Feb 01, 2024 at 01:07 UTC | |
Re: Why Is Writing to a Binary File so Hard?
by NetWallah (Canon) on Jan 31, 2024 at 21:50 UTC | |
by jmlynesjr (Deacon) on Feb 01, 2024 at 01:02 UTC | |
by hossman (Prior) on Feb 01, 2024 at 23:54 UTC |