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


In reply to Why Is Writing to a Binary File so Hard?[SOLVED] by jmlynesjr

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.