mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-30 23:50:04 +00:00
72 lines
2.8 KiB
Python
72 lines
2.8 KiB
Python
|
#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)
|