#!/usr/bin/env python

# Written by Will Senn. Create a bootable SimH tap file to install the system.
# Originally Based on Hellwig Geisse’s mktape.c and inspired by various Perl scripts
# Argument handling borrowed from Allen Garvin's mk-dist-tape.py
#
# created 20171012.1924
# coverted to python 20220120.1019 in prep for a better generalized version
# generalized by adding argument handling

# ./mktape.py -o v7.tap f0:512 f1:512 f2:512 f3:512 f4:512 f5 f6
# equivalent to ./mktape.py -7
# shasum v7.tap
# e6188335c0c9a3e3fbdc9c29615f940233722432  v7.tap
# ./mktape.py -o bsd42.tap stand:512 miniroot rootdump srcsys.tar usr.tar vfont.tar src.tar new.tar ingres.tar
# shasum bsd42.tap
# 8810274832cadf01083eeb228368896048b35a5a  bsd42.tap

import sys
import struct
import argparse

EOF = b"\x00\x00\x00\x00"
EOM = b"\xFF\xFF\xFF\xFF"
files = []
blkszs = []

# add arguments for default v7 tape creation, and 4.2bsd
parser = argparse.ArgumentParser(description="Create distribution tapes for simh")
parser.add_argument("--v7", "-7", action='store_true',
	help="build v7 tape (requires tape files in dir)")
parser.add_argument("--bsd42", action='store_true',
	help="build bsd42 tape (requires tape files in dir)")
parser.add_argument("--bsd43", action='store_true',
	help="build bsd43 tape (requires tape files in dir)")
parser.add_argument("--blocksize", "-b", type=int,
	help="set default block size (default 10240)", default=10240)
parser.add_argument("-output", "-o", metavar="FILE",
	help="output to file (if omitted, sends to stdout)")
parser.add_argument("file", nargs="*",
	help="files to add in order (append with :bs where bs is block size)")
args = parser.parse_args()

if args.v7:
	filelist = ["f0:512", "f1:512", "f2:512", "f3:512", "f4:512", "f5", "f6"]
	blocksize = 10240
	outfile = "v7.tap"
elif args.bsd42:
	filelist = ["stand:512", "miniroot", "rootdump", "srcsys.tar",
				"usr.tar", "vfont.tar", "src.tar", "new.tar", "ingres.tar"]
	blocksize = 10240
	outfile = "bsd42.tap"
elif args.bsd43:
	filelist = ["stand:512", "miniroot", "rootdump", "usr.tar",
				"srcsys.tar", "src.tar", "vfont.tar", "new.tar", "ingres.tar",
				"install.tar"]
	blocksize = 10240
	outfile = "bsd43.tap"
else:
	blocksize = args.blocksize
	if args.output:
		outfile = args.output
	else:
		outfile = "out.tap"
	filelist = args.file

for f in filelist:
	if ":" in f:
		fn = f.split(":")[0]
		bs = f.split(":")[1]
		if not bs.isdigit():
			parser.print_help()
			print(f"\nERROR: blocksize {bs} in {f} is not a positive integer")
			sys.exit(1)
		bs = int(bs)
	else:
		fn = f
		bs = blocksize
	files.append(fn)
	blkszs.append(bs)
try:
	fdout = open(outfile, "wb")
except IOError as e:
	print(f"{outfile}: errno {e.errno}: {e.strerror}")
	sys.exit(1)

for f in range(0, len(files)):
	file = files[f]
	blocksize = blkszs[f]
	packedlen = struct.pack("<I", blocksize)
	try:
		fdin = open(file, "rb")
	except IOError as e:
		print(f"{file}: errno {e.errno}: {e.strerror}")
		sys.exit(1)
	blockswritten = 0
	bytes = fdin.read(blocksize)
	while(bytes):
		buffer = bytes
		if len(bytes) < blocksize:
			buffer += b"\x00" * (blocksize - len(bytes))
		fdout.write(packedlen)
		fdout.write(buffer)
		fdout.write(packedlen)
		blockswritten += 1
		bytes = fdin.read(blocksize)
	fdin.close()
	fdout.write(EOF)

	print(f"file {f}: block size {blocksize}: {blockswritten} records")
	print(f"file {f}: eof after {blockswritten} records: {blocksize * blockswritten} bytes")
fdout.write(EOF)
fdout.write(EOM)
