Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b0500ec
Skip first 128 bytes if -t/--tifiles is an argument. Allows listing …
Apr 4, 2016
fac201d
Convert from IV254 to PROGRAM to handle TIFILES formatted files. Thi…
christopherkobayashi Apr 5, 2016
d4ab1bf
Only do IV254 conversion if program actually is IV254.
christopherkobayashi Apr 5, 2016
ce99b70
Fix off-by-one and remove debug print statement.
christopherkobayashi Apr 5, 2016
300eac4
Revert "Fix off-by-one and remove debug print statement."
Apr 6, 2016
aec042b
Revert "Only do IV254 conversion if program actually is IV254."
Apr 6, 2016
e8c3ee4
Revert "Convert from IV254 to PROGRAM to handle TIFILES formatted fil…
Apr 6, 2016
47fa4d6
Attempt to autodetect IV254 (at image read time), and stub in IV254 w…
Apr 6, 2016
4a655d3
Git will be the death of me.
Apr 7, 2016
bec6231
Revert "Revert "Fix off-by-one and remove debug print statement."" be…
Apr 7, 2016
9247088
Zap typo that shows that I'm a C programmer at heart.
Apr 7, 2016
5ab281b
Properly set long_ for propagation through program, and switch from _…
Apr 7, 2016
820db7e
Revert this properly.
Apr 7, 2016
162a9d3
Fix missing end parenthesis.
Apr 7, 2016
fc09932
Refactor my long-format code into the original code; turns out the is…
christopherkobayashi Apr 7, 2016
a97b491
Autodetect TIFILES.
christopherkobayashi Apr 7, 2016
405ed70
Perform identification/sanity checks on programs set as TIFILES, and …
christopherkobayashi Apr 13, 2016
8decd3a
First attempt at supporting 2S2D80T. Myarc changed the sector alloca…
christopherkobayashi Apr 17, 2016
bbb1de5
Fix sector allocation check for DSDD80T. DSDD80T works now.
Apr 19, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 50 additions & 8 deletions xbas99.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import sys
import re
import os.path
import traceback


VERSION = "1.5.0"
Expand Down Expand Up @@ -169,15 +170,16 @@ class BasicProgram:
# maximum number of bytes/tokens per BASIC line
maxTokensPerLine = 254

def __init__(self, data=None, source=None, long_=False):
def __init__(self, data=None, source=None, long_=False, tifiles_=False):
self.lines = {}
self.textlits = []
self.warnings = []
if data:
try:
self.load(data, long_)
self.load(data, long_, tifiles_)
except IndexError:
self.warn("Program file is corrupted")
# print traceback.format_exc()
elif source:
self.parse(source)

Expand All @@ -188,16 +190,23 @@ def warn(self, text):

# program -> source

def load(self, data, long_):
def load(self, data, long_, tifiles_):
"""load tokenized BASIC program"""
if long_ or data[1:3] == "\xab\xcd":
# convert long format INT/VAR 254 to PROGRAM
program, p = "", 11
if tifiles_:
p = 128
else:
p = 11
program = ""
while p < len(data):
l = ord(data[p]) + 1
program += data[p + 1:p + l]
p += l
p += l + 1
data = "XX" + data[5:7] + data[3:5] + "XX" + program
# f = open("data", "wb")
# f.write(data)
# f.close()
# extract line number table and token table
ptrTokens = ordw(data[2:4]) + 1
ptrLineNumbers = ordw(data[4:6])
Expand Down Expand Up @@ -257,6 +266,9 @@ def getSource(self):
softspace = True
else:
lit, typ, n = Tokens.literal(tokens[p:])
if not lit:
sys.stderr.write("Illegal token\n")
sys.exit(1)
istext = (lit[0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
Tokens.STMTSEP) and typ is None
if (((istext or lit == "#" or
Expand Down Expand Up @@ -412,8 +424,8 @@ def getImage(self, long_=False, protected=False):
chrw(checksum) + chrw(lastAddr - 1))
chunks = [(linoTable + tokenTable)[i:i + 254]
for i in xrange(0, len(linoTable + tokenTable), 254)]
return (chr(len(header)) + header +
"".join([chr(len(c)) + c for c in chunks]))
return (chr(len(header)) + header + (chr(0x00)*(255-len(header))) +
"".join([chr(len(c)) + c + chr(0xff) for c in chunks]))
else:
header = (chrw(checksum) + chrw(tokenTabAddr - 1) +
chrw(linoTabAddr) + chrw(lastAddr - 1))
Expand Down Expand Up @@ -468,6 +480,7 @@ def join(lines, minLinoDelta=1, maxLinoDelta=3):

def main():
import argparse
tifiles = False

args = argparse.ArgumentParser(
version=VERSION,
Expand All @@ -493,6 +506,8 @@ def main():
help="join split source lines (for -e)")
args.add_argument("-o", "--output", dest="output", metavar="<file>",
help="set output filename")
args.add_argument("-t", "--tifiles", action="store_true", dest="astifiles",
help="assume TIFILES format program to list or decode")
opts = args.parse_args()

#setup
Expand All @@ -507,11 +522,24 @@ def main():
else:
with open(opts.source, "rb") as fin:
image = fin.read()
if image[1:8] == "TIFILES":
opts.astifiles = True
if opts.astifiles:
flags = ord(image[0x0a])
reclen = ord(image[0x0d])
if (flags & 0x01) or ( (flags & 0x82) and reclen == 0xfe):
image = image[128:]
tifiles = True
else:
print "File is not in TIFILES PROGRAM or IV254 format."
sys.exit(1)
if image[1:3] == "\xab\xcd":
opts.long_ = True
if opts.merge:
program = BasicProgram()
program.merge(image)
else:
program = BasicProgram(data=image, long_=opts.long_)
program = BasicProgram(data=image, long_=opts.long_, tifiles_=tifiles)
data = program.getSource()
output = "-" if opts.list_ else opts.output or barename + ".b99"
elif opts.dump:
Expand All @@ -535,6 +563,20 @@ def main():
raise BasicError("Invalid line delta for join")
program = BasicProgram(source=lines)
data = program.getImage(long_=opts.long_, protected=opts.protect)
if opts.astifiles:
tifiles_header = chr(0x07) + "TIFILES" + chr(0x00)
print hex(len(data)), len(data), (len(data) // 256)
data += chr(0x00)*( (((len(data) // 256) + 1) * 256) - len(data))
tifiles_header += chr( (len(data) / 256) + 1)
if opts.long_:
tifiles_header += chr(0x82) + chr(0x01)
tifiles_header += chr(0xba) # wrong, placeholder
else:
tifiles_header += chr(0x01) + chr(0x00)
tifiles_header += chr(0xba) # wrong, placeholder
tifiles_header += chr(0x00)*(128-len(tifiles_header))

data = tifiles_header + data
output = opts.output or barename + ".prg"

if program and program.warnings:
Expand Down
31 changes: 23 additions & 8 deletions xdm99.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ class Disk:
bytesPerSector = 256
defaultSectorsPerTrack = 9
defaultTracks = 40
maxSectors = 1600
maxSectors = 2880
blankByte = "\xe5"
clusterSize = 1

def __init__(self, image):
if len(image) < 2 * Disk.bytesPerSector:
Expand All @@ -125,10 +126,13 @@ def __init__(self, image):
if len(self.image) < self.totalSectors * Disk.bytesPerSector:
self.warn("Disk image truncated", "image")
self.checkGeometry()
if self.totalSectors == 2880:
Disk.clusterSize = 2
self.usedSectors = 0
try:
for i in xrange(used(self.totalSectors, 8)):
self.usedSectors += bin(ord(self.allocBitmap[i])).count("1")
for i in xrange(used(self.totalSectors / self.clusterSize, 8)):
self.usedSectors += bin(ord(self.allocBitmap[i])).count("1") * self.clusterSize

except IndexError:
self.warn("Allocation map corrupted", "alloc")
self.catalog = {}
Expand Down Expand Up @@ -163,7 +167,11 @@ def initCatalog(self):
if error:
fd.error = True
self.catalog[fd.name] = File(fd=fd, data=data)
scount += fd.totalSectors + 1
# Myarc DSDD80T always uses multiple of 512 bytes, including dir
# entries
if ((fd.totalSectors % 2) != 0) and Disk.clusterSize == 2:
fd.totalSectors += 1
scount += fd.totalSectors + Disk.clusterSize
# consistency check
if scount != self.usedSectors - 2:
self.warn(
Expand All @@ -187,7 +195,13 @@ def readFile(self, name, sectors, clusters):
self.warn("%s: File contents corrupted" % name)
error = True
continue
if len(data) != sectors * Disk.bytesPerSector:
if Disk.clusterSize is 2 and ((Disk.bytesPerSector * sectors) % 512):
# pad to multiple of 2 sectors for DSDD80T
expectedLength = Disk.bytesPerSector * (sectors+1)
else:
expectedLength = Disk.bytesPerSector * sectors

if len(data) != expectedLength:
self.warn("%s: File size mismatch: found %d bytes, expected %d" % (
name, len(data), sectors * Disk.bytesPerSector))
error = True
Expand Down Expand Up @@ -321,10 +335,11 @@ def checkAllocation(self):
"""check sector allocation for consistency"""
reads = {n: [] for n in xrange(self.totalSectors)}
allocated = []
for i in xrange(used(self.totalSectors, 8)):
for i in xrange(used(self.totalSectors / self.clusterSize, 8)):
byte = ord(self.allocBitmap[i])
for j in xrange(8):
allocated.append(byte & 1 << j != 0)
for j in xrange(8):
for k in xrange(self.clusterSize):
allocated.append(byte & 1 << j != 0)
# unallocated sectors
for n, context in self.readSectors:
reads[n].append(context)
Expand Down