#!/bin/python
# 
# Experimental converter from TMS7000 format to Hex-Intel. The sumcheck
# for the input format isn't correct yet.
# version 0.9
# fjkraan@electrickery.nl 2016-01-27

import sys

if len(sys.argv) == 1:
   print("Usage: python t7kDump2hexIntel2.py <t7kHexFile>")
   exit()
if len(sys.argv) > 1:
    hexFile = sys.argv[1]

address = 0
byteCount = 0
sumChk = 0
checkCheckSum = False
t7kLineSum = ''
hexIntelLine = ''
hexIntelDataRecType = '00'

file = open(hexFile, 'r')
lines = file.readlines()
file.close()

def processK(lineStrip):    # process header
    return lineStrip[13:]
    
def process9(lineStrip):    # process start address
    global sumChk
    global address
    global hexIntelLine
    address = int(lineStrip[1:5], 16)
#    print("Start address: " + hex(address))
    sumChk += int(lineStrip[1:3], 16)
    sumChk += int(lineStrip[3:5], 16)
    return lineStrip[5:]
    
def processB(lineStrip):    # process two data bytes (four digits)
    global byteCount
    global sumChk
    global hexIntelLine
    byteCount = byteCount + 2
    hexIntelLine += lineStrip[1:3] + lineStrip[3:5]
    sumChk += int(lineStrip[1:3], 16)
    sumChk += int(lineStrip[3:5], 16)
    return lineStrip[5:]
    
def process7(lineStrip):    # process checksum
    global checkCheckSum
    global t7kLineSum
    checkCheckSum = True
    t7kLineSum = lineStrip[1:5]
    return lineStrip[5:]
    
def process8(lineStrip):    # ignore checksum
    global checkChecksum
    checkChecksum = False
    return lineStrip[5:]
    
def processAst(lineStrip):  # process one data byte (two digits)
    global byteCount
    global sumChk
    global hexIntelLine
    byteCount = byteCount + 1
    hexIntelLine += lineStrip[1:3]
    sumChk += int(lineStrip[1:3], 16)
    return lineStrip[3:]
    
def format2Hex(value):
    return "{:02X}".format(value)
        
def format4Hex(value):
    return "{:04X}".format(value)

def asciiSum(line):
    sum = 0
    for char in line:
        if char >= ' ' and char <= '~':
#            print(char, end='')
            sum += ord(char)
#        else:
#            print("'"+char+"'")
#    print()
    return sum % 0x10000
    
def hexIntelSum(hexIntelLine):
    calcLine = hexIntelLine[0:]
#    print(">" + calcLine)
    sum = 0
    while calcLine:
        value = calcLine[0:2]
        calcLine = calcLine[2:]
#        print("> (" + value + ") " + calcLine + " (" + hex(sum) + ")")
        sum += int(value, 16)
    return sum % 0x100

for line in lines:
    lineStrip = line.strip()
    t7kCheckSum = asciiSum(lineStrip[0:-5]) # all chars excluding actual checksum and 'F' postfix
    if (lineStrip):
#        print("<" + lineStrip + ">")
        while len(lineStrip) > 0:
            blockType = lineStrip[0]
            if blockType == 'K':
                lineStrip = processK(lineStrip)
            elif blockType == '9':
                lineStrip = process9(lineStrip)
            elif blockType == 'B':
                lineStrip = processB(lineStrip)
            elif blockType == '7':
                lineStrip = process7(lineStrip)
            elif blockType == '8':
                lineStrip = process8(lineStrip)            
            elif blockType == '*':
                lineStrip = processAst(lineStrip)
            elif blockType == 'F':
                break
    if checkCheckSum:   # this is the T7k format checksum check
#        print(" LineSum: " + t7kLineSum + ", calcSum: " + format4Hex(0x10000 - t7kCheckSum) + " " + format4Hex(t7kCheckSum))
        t7kCalcSum = 0x10000 - t7kCheckSum % 0x10000
        if t7kLineSum != format4Hex(t7kCalcSum):
            print("Checksum error, expected: " + format4Hex(t7kCalcSum) + ", actual: " + t7kLineSum)
    hexIntelLineSum = hexIntelSum(format2Hex(byteCount) + format4Hex(address) + hexIntelDataRecType + hexIntelLine)

#    hexIntelLine = ":" + format2Hex(byteCount) + " " + format4Hex(address) + " " + hexIntelDataRecType + hexIntelLine + " " + format2Hex((0x100 - hexIntelLineSum) % 0x100) + " / " + hex(0x100 - hexIntelLineSum)
    hexIntelLine = ":" + format2Hex(byteCount) + format4Hex(address) + hexIntelDataRecType + hexIntelLine + format2Hex((0x100 - hexIntelLineSum) % 0x100)
    print(hexIntelLine)
    sumChk = 0
    address += byteCount
    byteCount = 0
    hexIntelLine = ''
    t7kLinesum = ''
    
print(":00000001FF")

# testing
#dummyLine = ':10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
#print(dummyLine + format2Hex(0x100 - hexIntelSum(dummyLine)))
#dummyLine = ':10F09600FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF'
#print(dummyLine + format2Hex(0x100 - hexIntelSum(dummyLine)))

# hex-intel
# :ccaaaatthhhhhhhh....hhhhss
# ss = binary two's complement of cc, tt, aaaa, hh..hh
# tt = 00 for data, 01 for end record

# The 7000 checksum is the 2’s complement of the 16-bit sum of the ASCII 
# values of all characters on the line between carriage returns, excluding 
# all control characters such as <CR>, <LF>, and <FF>.
