update to latest wozardry, copy as much metadata as possible when creating woz files

This commit is contained in:
4am 2019-03-03 19:13:21 -05:00
parent ae59d0d586
commit 5255a1a990
6 changed files with 669 additions and 316 deletions

View File

@ -31,7 +31,7 @@ class BaseCommand:
base, ext = os.path.splitext(args.file)
ext = ext.lower()
if ext == ".woz":
self.reader = wozardry.WozReader
self.reader = wozardry.WozDiskImage
elif ext == ".edd":
self.reader = eddimage.EDDReader
elif ext == ".a2r":
@ -40,7 +40,8 @@ class BaseCommand:
print("unrecognized file type")
if not self.logger:
self.logger = args.debug and DebugLogger or DefaultLogger
self.processor(self.reader(args.file), self.logger)
with open(args.file, "rb") as f:
self.processor(args.file, self.reader(f), self.logger)
class CommandVerify(BaseCommand):
def __init__(self):

View File

@ -6,6 +6,8 @@ from passport.constants import *
from passport.util import *
from passport import wozardry
import bitarray
import io
import json
import os.path
import time
@ -48,10 +50,12 @@ class PassportGlobals:
self.track = 0 # display purposes only
self.sector = 0 # display purposes only
self.last_track = 0
self.filename = None
class BasePassportProcessor: # base class
def __init__(self, disk_image, logger_class=DefaultLogger):
def __init__(self, filename, disk_image, logger_class=DefaultLogger):
self.g = PassportGlobals()
self.g.filename = filename
self.g.disk_image = disk_image
self.g.logger = logger_class(self.g)
self.rwts = None
@ -571,7 +575,7 @@ class BasePassportProcessor: # base class
def run(self):
self.g.logger.PrintByID("header")
self.g.logger.PrintByID("reading", {"filename":self.g.disk_image.filename})
self.g.logger.PrintByID("reading", {"filename":self.g.filename})
supports_reseek = ("reseek" in dir(self.g.disk_image))
# get raw track $00 data from the source disk
@ -621,7 +625,7 @@ class BasePassportProcessor: # base class
if self.g.tried_univ:
if logical_track_num == 0x22 and (0x0F not in physical_sectors):
self.g.logger.PrintByID("fail")
self.g.logger.PrintByID("fail", {"sector":0x0F})
self.g.logger.PrintByID("fatal220f")
return False
else:
@ -699,7 +703,7 @@ class Crack(Verify):
logical_sectors[patch.sector_num].decoded = b
def postprocess(self):
source_base, source_ext = os.path.splitext(self.g.disk_image.filename)
source_base, source_ext = os.path.splitext(self.g.filename)
output_filename = source_base + '.dsk'
self.g.logger.PrintByID("writing", {"filename":output_filename})
with open(output_filename, "wb") as f:
@ -732,21 +736,26 @@ class Convert(BasePassportProcessor):
self.output_tracks[physical_track_num] = wozardry.Track(b, len(b))
def postprocess(self):
source_base, source_ext = os.path.splitext(self.g.disk_image.filename)
source_base, source_ext = os.path.splitext(self.g.filename)
output_filename = source_base + '.woz'
self.g.logger.PrintByID("writing", {"filename":output_filename})
woz_image = wozardry.WozWriter(STRINGS["header"].strip())
woz_image.info["cleaned"] = self.g.found_and_cleaned_weakbits
woz_image.info["write_protected"] = self.g.protection_enforces_write_protected
woz_image = wozardry.WozDiskImage()
json_string = self.g.disk_image.to_json()
woz_image.from_json(json_string)
j = json.loads(json_string)
root = [x for x in j.keys()].pop()
woz_image.info["creator"] = STRINGS["header"].strip()[:32]
woz_image.info["synchronized"] = j[root]["info"]["synchronized"]
woz_image.info["cleaned"] = True #self.g.found_and_cleaned_weakbits
woz_image.info["write_protected"] = self.g.protection_enforces_write_protected or j[root]["info"]["write_protected"]
woz_image.meta["image_date"] = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())
for q in range(1 + (0x23 * 4)):
physical_track_num = q / 4
if physical_track_num in self.output_tracks:
woz_image.add_track(physical_track_num, self.output_tracks[physical_track_num])
with open(output_filename, 'wb') as f:
woz_image.write(f)
try:
wozardry.WozReader(output_filename)
wozardry.WozDiskImage(io.BytesIO(bytes(woz_image)))
except Exception as e:
os.remove(output_filename)
raise Exception from e
with open(output_filename, 'wb') as f:
f.write(bytes(woz_image))

View File

@ -6,12 +6,14 @@ import collections
class A2RSeekError(a2rchery.A2RError): pass
class A2RImage:
def __init__(self, filename=None, stream=None):
self.filename = filename
def __init__(self, iostream):
self.tracks = collections.OrderedDict()
self.a2r_image = a2rchery.A2RReader(filename, stream)
self.a2r_image = a2rchery.A2RReader(stream=iostream)
self.speed = 32
def to_json(self):
return self.a2r_image.to_json()
def to_bits(self, flux_record):
"""|flux_record| is a dictionary of 'capture_type', 'data_length', 'tick_count', and 'data'"""
bits = bitarray.bitarray()

View File

@ -1,20 +1,19 @@
from passport.wozardry import Track, raise_if
import bitarray
import json
class EDDError(Exception): pass # base class
class EDDLengthError(EDDError): pass
class EDDSeekError(EDDError): pass
class EDDReader:
def __init__(self, filename=None, stream=None):
DiskImage.__init__(self, filename, stream)
with stream or open(filename, 'rb') as f:
for i in range(137):
raw_bytes = f.read(16384)
raise_if(len(raw_bytes) != 16384, EDDLengthError, "Bad EDD file (did you image by quarter tracks?)")
bits = bitarray.bitarray(endian="big")
bits.frombytes(raw_bytes)
self.tracks.append(Track(bits, 131072))
def __init__(self, iostream):
for i in range(137):
raw_bytes = iostream.read(16384)
raise_if(len(raw_bytes) != 16384, EDDLengthError, "Bad EDD file (did you image by quarter tracks?)")
bits = bitarray.bitarray(endian="big")
bits.frombytes(raw_bytes)
self.tracks.append(Track(bits, 131072))
def seek(self, track_num):
if type(track_num) != float:
@ -25,3 +24,15 @@ class EDDReader:
raise EDDSeekError("Invalid track %s" % track_num)
trk_id = int(track_num * 4)
return self.tracks[trk_id]
def to_json(self):
j = {"edd":
{"info":
{"synchronized":False,
"write_protected":False,
"cleaned":False
},
"meta":{}
}
}
return json.dumps(j, indent=2)

View File

@ -1,4 +1,4 @@
__date__ = "2019-02-17"
__date__ = "2019-03-03"
STRINGS = {
"header": "Passport.py by 4am (" + __date__ + ")\n", # max 32 characters

File diff suppressed because it is too large Load Diff