#!/bin/perl
#
# This script is a non-optimized tool to strip the loader record headers
# from NEWDOS/80 /CMD and /SYS files. Optionally the binary data can be 
# written to a file. The file name is SSSS-EEEE.BIN, where SSSS is the 
# start address of the record, EEEE the end address. This can be fed to 
# a generic disassembler using the start address as code start location.
#
# copyright fjkraan@xs4all.nl, 2011-07-15
#
use strict;

my ($fileName) = @ARGV;

my ($readCount, $bytes, $name);
my ($recordType, $address, $dataSize, $data);
my $moreData = 1;
my ($totalCount, $oldTotalCount) = 0;

open (BFH, "<$fileName") or die ("$0: error opening binary file \'$fileName\'");
binmode BFH;

while ($moreData) {
        $recordType = "";
        $readCount = read(BFH, $recordType, 1);
        $recordType = unpack ( 'C', $recordType);
        $totalCount++;
        unless ($readCount == 1) {
            $moreData = 0;
            print("out of data while record type read at : " . sprintf("%04X", $totalCount) . "\n");
            last;
        }
        if ($recordType != 1 && $recordType != 2) {
            print("Record type not 01 or 02 but " . sprintf("%02X", $recordType) . " at " . sprintf("%04X", $totalCount) . "\n");
            next;
        }

        $readCount = read(BFH, $dataSize, 1);
        $dataSize = unpack ( 'C', $dataSize);
        $totalCount++;
        unless ($readCount == 1) {
            $moreData = 0;
            print("out of data while dataSize read at : " . sprintf("%04X", $totalCount) . "\n");
            last;
        }
        if ($dataSize < 3 && $recordType == 1) { $dataSize += 254; } else { $dataSize -= 2; }

        $readCount = read(BFH, $address, 2);
        $address = unpack ( 'S', $address);
        $totalCount += 2;
        unless ($readCount == 2) {
            $moreData = 0;
            print("out of data while address read at : " . sprintf("%04X", $totalCount) . "\n");
            last;
        }
   
        $data = "";
        if ($recordType != 2) {
	    $readCount = read(BFH, $data, $dataSize);
	    $totalCount += $readCount;
	    unless ($readCount == $dataSize) {
		$moreData = 0;
		print("out of data while data read. Expected: " . $dataSize . "; Got: " . $readCount . ") at : " . sprintf("%04X", $totalCount) . "\n");
		last;
	    }
            $name = "SYS0_" . sprintf("%04X", $address) . "-" . sprintf("%04X", $address + $dataSize - 1) . ".BIN";
#            &saveBin($name, $data);
        }

	print(sprintf("Locations: %04X - %04X; RecordType: %02X; DataSize: %02X; Address: %04X; Data: ",
			    $oldTotalCount, $totalCount-1, $recordType, $dataSize, $address)); 
	print uc(unpack("H*", $data));
	print "\n";
	$oldTotalCount = $totalCount;
}

print("End of data at: " . $totalCount . "/" . sprintf("%04X", $totalCount) ."\n");
close BFH;

sub saveBin() {
    my ($name, $data) = @_;

    open(DFH, ">$name") or die ("$0: error opening binary file \'$name\'");
    binmode DFH;
    print(DFH $data);
    close DFH;
}
