https://github.com/virtualagc/virtualagc
Raw File
Tip revision: 4e5d304eb7cd5589b924ffb8b423b6f15511b35d authored by Ron Burkey on 20 October 2018, 17:47:00 UTC
The sample Block I AGC program TRIVIUM, found at the very end of one of
Tip revision: 4e5d304
binsourcer.py
#
# Python program to aid entering AGC binsource.
#
# Jim Lawton 2009-10-09
#
# binsource files are in the form of blocks of 5-digit octal numbers,
# 8 per line, 4 lines per block, 8 blocks per page, 4 pages per bank.
# Example:
#
#     50026 30001 30027 02177 50026 30001 30027 02034
#     50026 30001 30027 02630 50026 30001 30027 02042
#     50026 30001 30027 02037 50026 30001 30027 02377
#     20017 32075 50015 07005 03007 01101 02266 32075
#
# Comments begin with a semicolon. The rest of the line is ignored.
# the BANK keyword specifies the bank number (e.g. "BANK=2").

# TODO: calculate and print address of row
# TODO: check checksum


import os
import sys
import glob
import datetime
import signal


_DEFAULT_HEADER = \
"""
; Copyright:    Public domain
; Filename:     Solarium055.binsource
; Purpose:      An ASCII file used to input an AGC executable in octal format.
;               The actual octal (usable by the yaAGC program) must be created
;               by processing with the oct2bin program (which may be found in
;               the Tools directory of the virtualagc project).
;               Refer to www.ibiblio.org/apollo for explanations.
; Contact:
; History:      YYYY-MM-DD XXX  Created.
;
;
; This data has been manually transcribed from a scanned listing of TBD
; build NNN.
;
; For convenience, the page numbers (as marked on the printed assembly listing)
; are given in the comments. The notations V or A (or both or neither) have
; been added after the page numbers to indicate the proofing method used
; (Visual or Audio). Regardless of the proofing method (if any), all code is
; believed to be correct, on the basis of automated checking of the "bugger
; words" (i.e., bank checksums), except, of course, where stated otherwise.
; (The parenthesized number, if any, following the V or A, is the number of
; errors corrected on that proofing pass.)
;
; The rule followed here is that each memory page has to be proofed at least
; once, and that the *final* proofing of any given memory page must have
; encountered 0 errors.
;
; Input-data format:
;   Each memory bank begins with a "BANK=" line. The remainder of the bank
;   consists of octal values. Note that banks should be zero-filled at the end
;   to make the lengths come out correct.

NUMBANKS=34
"""


def signal_handler(signal, frame):
    global pagedata, page, outfile, useCommas
    print "Ctrl+C"
    savePage(outfile, page, pagedata, useCommas, crash=True)
    sys.exit(1)


def prompt(promptString, default=""):
    response = raw_input(promptString)
    if len(response) == 0:
        if len(default) > 0:
            response = default
        else:
            response = None
    return response


def octPrompt(promptString="5 digit octal: "):
    while True:
        response = raw_input(promptString)
        if len(response) == 0 or len(response) > 5:
            response = None
            break
        else:
            try:
                response = int(response, 8)
                break
            except:
                continue
    return response


def parse(infile):
    ifile = open(infile, 'r')
    lines = ifile.readlines()
    print "Parsing input file..."
    for line in lines:
        if line.startswith(';'):
            continue
        if line.startswith("BANK="):
            bank = int(line.split('=')[1])
            print "    Bank %d" % bank
    ifile.close()


def savePage(outfile, page, pagedata, useCommas=False, crash=False):
    print "Saving page..."
    if outfile is None:
        return
    ofile = open(outfile, 'a')
    lines = []
    if crash:
        if pagedata is None or pagedata == {}:
            lines = ["\n",
                "************************** CRASH *************************\n",
                "*                    No data to save!                    *\n",
                "**********************************************************\n"]
        else:
            lines = ["\n",
                "*********************** CRASH SAVE ***********************\n",
                "* Please check data below this point. It may be corrupt! *\n",
                "**********************************************************\n"]
    stop = False
    if pagedata:
        for row in range(32):
            line = ""
            for col in range(8):
                pos = row * 8 + col
                if pos not in pagedata.keys():
                    continue
                if useCommas:
                    line += "%05o, " % pagedata[pos]
                else:
                    line += "%05o " % pagedata[pos]
            line += "\n"
            if (row + 1) % 4 == 0:
                line += "\n"
            lines.append(line)
    if crash and not (pagedata is None or pagedata == {}):
        lines.extend(["\n",
            "*********************** CRASH SAVE ***********************\n",
            "\n"])
    ofile.write("; p. %d\n" % page)
    ofile.writelines(lines)
    ofile.write("\n")
    ofile.close()


def main():
    global pagedata, page, outfile, useCommas
    outfile = None
    page = None
    pagedata = {}
    useCommas = False

    startpage = prompt("Starting page: ")
    if startpage == None:
        print >>sys.stderr, "Error, must specify a starting page."
        sys.exit(1)
    else:
        startpage = int(startpage)
    bsFiles = glob.glob('*.binsource')
    if len(bsFiles) == 1:
        defInfile = bsFiles[0]
        promptStr = "Input file (default=%s): " % defInfile
    else:
        defInfile = None
        promptStr = "Input file: "
    infile = prompt(promptStr)
    if infile == None:
        infile = defInfile

    defOutfile = "%s-%d.binsource" % (datetime.datetime.now().strftime("%Y%m%d_%H%M%S"), startpage)
    promptStr = "Output file (default=%s): " % defOutfile

    outfile = prompt(promptStr)
    if outfile == None:
        outfile = defOutfile

    if os.path.exists(outfile):
        print "File %s already exists!" % outfile
        overwrite = prompt("Overwrite? (Y/N) [N]: ")
        if overwrite == None or overwrite == "N":
            print >>sys.stderr, "Exiting."
            sys.exit(1)

    direction = prompt("Processing direction (0=column order, 1=row order, 2=column/block order) [0]: ")
    if direction == None:
        direction = 0
    else:
        direction = int(direction)

    useCommas = prompt("Use comma delimiters? (Y/N) [N]: ")
    if useCommas == None or useCommas == "N":
        useCommas = False
    else:
        useCommas = True

#    startaddr = prompt("Starting address [02000]: ")
#    if startaddr == None:
#        startbank = 0
#        startaddr = 02000
#    else:
#        if ',' in startaddr:
#            startbank = int(startaddr.split(',')[0], 8)
#            startaddr = int(startaddr.split(',')[1], 8)
#        else:
#            startbank = 0
#            startaddr = int(startaddr, 8)

    print "Input file: %s" % infile
    print "Output file: %s" % outfile
    print "Direction: %s" % direction
    print "Starting page: %s" % startpage
#    print "Starting bank: %s" % oct(startbank)
#    print "Starting address: %s" % oct(startaddr)
    print "Comma delimiters: %s" % useCommas
    print

    if infile:
        parse(infile)
    else:
        # Put default header text in the output file.
        ofile = open(outfile, 'w')
        ofile.write(_DEFAULT_HEADER)
        ofile.write("\n")
        ofile.close()

    stop = False
    page = startpage

    while not stop:
        print "Page: %d" % page

        col = 0
        row = 0
        block = 0
        blockrow = 0

        zeroRest = False
        zeroCol = False

        # Can process input in different directions.
        # Output always stored in row order.
        if direction == 0:
            # Column order, i.e. top to bottom of page for each column, left to right.
            while col < 8:
                print "Column: %02d" % col
                row = 0
                while row < 32:
                    word = octPrompt("Row %02d: " % row)
                    if word == None:
                        response = prompt("Back (b), Retry (r), finish (f), zero rest of column (z) [r]: ", default='r')
                        if response == 'f':
                            stop = True
                            break
                        elif response == 'b':
                            row -= 1
                            if row < 0:
                                row = 0
                            continue
                        elif response == 'z':
                            zeroCol = True
                            break
                        else:
                            continue
                    pagedata[row * 8 + col] = word
                    if (row + 1) % 4 == 0:
                        print
                    row += 1
                if stop:
                    break
                if zeroCol:
                    for zrow in range(row, 32):
                        pagedata[zrow * 8 + col] = 0
                col += 1

        elif direction == 1:
            # Row order, i.e. left to right for each row of page, top to bottom.
            while row < 32:
                print "Row: %02d" % row
                col = 0
                while col < 8:
                    word = octPrompt("Col %02d: " % col)
                    if word == None:
                        response = prompt("Back (b), Retry (r), finish (f), zero rest of page (z) [r]: ", default='r')
                        if response == 'f':
                            stop = True
                            break
                        elif response == 'z':
                            zeroRest = True
                            break
                        elif response == 'b':
                            col -= 1
                            if col < 0:
                                col = 0
                            continue
                        else:
                            continue
                    pagedata[row * 8 + col] = word
                    col += 1
                if stop:
                    break
                if zeroRest:
                    break
            if zeroRest:
                for pos in range(row * 8 + col, 256):
                    pagedata[pos] = 0
            row += 1

        else:
            # Column block order in a page, i.e. top to botton of page for each block of 4 rows,
            # column order within each block.
            while block < 8:
                print "Block: %02d" % block
                col = 0
                while col < 8:
                    print "Column: %02d" % col
                    blockrow = 0
                    while blockrow < 4:
                        row = block * 4 + blockrow
                        word = octPrompt("Row %02d: " % blockrow)
                        if word == None:
                            response = prompt("Back (b), Retry (r), finish (f) [r]: ", default='r')
                            if response == 'f':
                                stop = True
                                break
                            elif response == 'b':
                                blockrow -= 1
                                if blockrow < 0:
                                    blockrow = 0
                                    continue
                            else:
                                continue
                        pagedata[row * 8 + col] = word
                        blockrow += 1
                    if stop:
                        break
                    col += 1
                if stop:
                    break
                print
                block += 1

        savePage(outfile, page, pagedata, useCommas)

        response = prompt("Next page (y/n) [n]: ")
        if response == 'y':
            page += 1
            continue
        else:
            break

    print "Done"


if __name__ == "__main__":
    global pagedata, page, outfile
    signal.signal(signal.SIGINT, signal_handler)
    main()
back to top