#Oric .TAP Converter
#Builds Oric/Atmos .TAP file from DASM -F1 file

#DASM -F1 File two byte load address in LSB, MSB order
#followed by binary object coda

#Oric/Atmos .TAP file has the following structure:
# $16 $16 $16 $16   Tape Synchronization Bytes
# $24 $00 $00       Header Start Bytes
# $00/$80           Program Type (BASIC/Assembly)
# $00/$80/$C7       Autostart (None/BASIC/Assembly)
# $XX $XX           End Address (MSB, LSB)
# $XX $XX           Start Address (MSB, LSB)
# $00               Padding Byte
# 'XXX...'          File Name (up to 16 characters)
# $00               File Name Terminator
# ...               Program Data

import os
import sys

def getArgs():
    argCount = len(sys.argv)
    if argCount != 2:
        print("Usage:", sys.argv[0], "objfile")
        exit(2)
    return sys.argv[1]

def splitFileSpec(filePath):
    fileDir, fileSpec = os.path.split(filePath)
    fileName, fileExt = os.path.splitext(fileSpec)
    if fileExt == '': fileExt = '.obj'
    return fileDir, fileName, fileExt

def readPrgFile(fileSpec):
    with open(fileSpec, "rb") as prgFile:
        prgAddr = prgFile.read(2)
        prgData = prgFile.read()
    address = prgAddr[0] + prgAddr[1] * 256
    return address, prgData

def writeTapFile(dir, name, addr, data):
    tapName = os.path.join(dir, name + ".tap")
    size = len(data)+1              #Program Size includes trailing 0 byte
    type = b'\x00' if addr == 0x0501 else b'\x80'   #Program Type BASIC/Assembly
    auto = b'\x00'                  #Autostart (None)
    #auto = b'\x80' if type == b'\x00' else b'\xC7'  #Autostart Flag
    start = addr.to_bytes(2, byteorder='big')       #Program Start Address
    end = (addr+size).to_bytes(2, byteorder='big')  #Program End Address
    ascName = name.upper().encode('ASCII')          #Program Name as ASCII bytes object
    with open(tapName, "wb") as tapFile:
        tapFile.write(b'\x16\x16\x16\x16')  #Tape Synchronization Bytes
        tapFile.write(b'\x24\x00\x00')      #Header Start Byte
        tapFile.write(type)         #Program Type
        tapFile.write(auto)         #Autostart Flag
        tapFile.write(end)          #Program End Address
        tapFile.write(start)        #Program Start Address MSB
        tapFile.write(b'\x00')      #Padding Byte
        tapFile.write(ascName)      #File Name
        tapFile.write(b'\x00')      #String Terminator
        tapFile.write(data)         #Binary Program Code
        tapFile.write(b'\x00')      #Final Dummy Byte
    return tapName

objFile = getArgs()
fileDir, fileName, fileExt = splitFileSpec(objFile)
inName = os.path.join(fileDir, fileName + fileExt)
print("Reading file", inName)
inAddr, inData = readPrgFile(inName)
outName = writeTapFile(fileDir, fileName, inAddr, inData)
print ("Wrote file", outName)
