--- /dev/null
+MIT/X Consortium License
+
+© 2020 Aaron Taylor <ataylor at subgeniuskitty dot com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
--- /dev/null
+# © 2020 Aaron Taylor <ataylor at subgeniuskitty dot com>
+# See LICENSE.txt file for copyright and license details.
+
+PREFIX = $(HOME)
+BINPREFIX = $(PREFIX)/bin
+
+CC = cc
+CC_FLAGS = -std=c99
+
+all: bin2load
+
+bin2load:
+ @$(CC) $(CC_FLAGS) -o $@ bin2load.c
+
+install: bin2load
+ @mkdir -p $(BINPREFIX)
+ @cp ./bin2load $(BINPREFIX)/bin2load
+ @chmod +x $(BINPREFIX)/bin2load
+
+uninstall:
+ @rm $(BINPREFIX)/bin2load
+
+clean:
+ @rm -f bin2load bin2load.core
--- /dev/null
+# Overview #
+
+This is a simple program that converts raw binary data into a paper-tape image
+compatible with SIMH.
+
+For example, I commonly use it when transfering compiled PDP-11 code into SIMH
+with the output of:
+
+ pdp11-aout-objcopy --only-section=.text --output-target binary program.out program.bin
+
+It does not generate correct checksums, but this generates only a warning in
+SIMH, not an error.
+
+
+# Status #
+
+Tested and working on Linux and FreeBSD.
+
+
+# Instructions #
+
+The `Makefile` provides targets for `all`, `install`, `uninstall`, and `clean`.
+Edit the `Makefile` to set `$PREFIX` for alternate installation paths. By
+default it installs to `$HOME/bin`.
+
+Once compiled and added to your `$PATH`, simply provide a raw binary blob as
+`input` and receive a SIMH compatible paper tape image at `output`.
+
+If provided via the `-a` flag, the paper tape will load at the provided address
+in memory. If not provided, this defaults to `01000` (`1000` octal).
+
+ bin2load -i /path/to/input -o /path/to/output -a 01000
+
--- /dev/null
+/*
+ * © 2020 Aaron Taylor <ataylor at subgeniuskitty dot com>
+ * See LICENSE.txt file for copyright and license details.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+
+#define VERSION 1
+
+void
+print_usage( char ** argv )
+{
+ printf( "bin2load v%d (www.subgeniuskitty.com)\n"
+ "Usage: %s i <file> -o <file> [-a <address>]\n"
+ " -i <file> Binary file to be written to tape.\n"
+ " For example, binary executable from 'pdp11-aout-objdump'.\n"
+ " -o <file> New paper tape image for use with SIMH.\n"
+ " -a <address> Address on PDP-11 at which to load paper tape contents.\n"
+ , VERSION, argv[0]
+ );
+}
+
+
+int
+main( int argc, char ** argv)
+{
+ int c;
+ FILE * src = NULL;
+ FILE * dst = NULL;
+ uint16_t address = 01000; /* Default address to load tape contents. */
+
+ while ((c = getopt(argc, argv, "i:o:a:h")) != -1) {
+ switch (c) {
+ case 'i':
+ if ((src = fopen(optarg, "r")) == NULL ) {
+ fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
+ }
+ break;
+ case 'o':
+ if ((dst = fopen(optarg, "w+")) == NULL ) {
+ fprintf(stderr, "ERROR: %s: %s\n", optarg, strerror(errno));
+ }
+ break;
+ case 'a':
+ address = (uint16_t) strtol(optarg, NULL, 0);
+ break;
+ case 'h':
+ print_usage(argv);
+ exit(EXIT_FAILURE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (src == NULL || dst == NULL) {
+ print_usage(argv);
+ exit(EXIT_FAILURE);
+ }
+ printf("Paper tape will load at address 0%o.\n", address);
+
+ /*
+ * Paper tape format(bytes, not words):
+ * 01
+ * 00
+ * Low byte of packet length (binary length + 6 for header)
+ * High byte of packet length
+ * Low byte of address to load binary data at
+ * High byte of address
+ * DataBegin
+ * |
+ * |
+ * DataEnd
+ * Checksum
+ *
+ * I am unsure of the checksum format and need to check the SIMH source.
+ * In the meantime a zero checksum still functions, albeit with a warning.
+ */
+
+ uint16_t size = 6;
+
+ uint16_t header[] = {1,0,01000};
+ fwrite(header,6,1,dst);
+
+ uint8_t byte;
+ int read;
+ do {
+ read = fread(&byte,1,1,src);
+ if(read == 1) fwrite(&byte,1,1,dst);
+ size += read;
+ } while (read == 1);
+
+ uint16_t footer[] = {0,1,6,01000,0};
+ fwrite(footer,10,1,dst);
+
+ fseek(dst,2,SEEK_SET);
+ fwrite(&size,2,1,dst);
+
+ fclose(src);
+ fclose(dst);
+}