/ a2woz / __init__.py
__init__.py
 1  # SPDX-FileCopyrightText: 2019 4am
 2  #
 3  # SPDX-License-Identifier: MIT
 4  
 5  from .loggers import *
 6  from .strings import *
 7  from .util import *
 8  from . import wozardry
 9  import bitarray
10  import io
11  import json
12  import os.path
13  import time
14  
15  class PassportGlobals:
16      def __init__(self):
17          # things about the disk
18          self.track = 0 # display purposes only
19          self.sector = 0 # display purposes only
20          self.last_track = 0
21          self.filename = None
22  
23  class BasePassportProcessor: # base class
24      def __init__(self, filename, disk_image, logger_class=DefaultLogger, output_filename=None):
25          self.g = PassportGlobals()
26          self.g.filename = filename
27          self.g.output_filename = output_filename
28          self.g.disk_image = disk_image
29          self.g.logger = logger_class(self.g)
30          self.rwts = None
31          self.output_tracks = {}
32          self.burn = 0
33          if self.preprocess():
34              if self.run():
35                  self.postprocess()
36  
37      def preprocess(self):
38          return True
39  
40      def run(self):
41          return True
42  
43      def postprocess(self):
44          pass
45  
46  class RawConvert(BasePassportProcessor):
47      def run(self):
48          self.g.logger.PrintByID("reading", {"filename":self.g.filename})
49  
50          self.tracks = {}
51  
52          # main loop - loop through disk from track $22 down to track $00
53          for logical_track_num in range(0x22, -1, -1):
54              self.g.track = logical_track_num # for display purposes only
55              self.g.logger.debug("Seeking to track %s" % hex(self.g.track))
56  
57              for fractional_track in (0, .25, .5, .75):
58  
59                  physical_track_num = logical_track_num + fractional_track
60                  track = self.g.disk_image.seek(physical_track_num)
61                  if track and track.bits:
62                      track.fix()
63                      self.g.logger.debug("Writing to track %s + %.2f for %d bits" % (hex(self.g.track), fractional_track, len(track.bits)))
64                      self.output_tracks[physical_track_num] = wozardry.Track(track.bits, len(track.bits))
65  
66          return True
67  
68      def postprocess(self):
69          output_filename = self.g.output_filename
70          if output_filename is None:
71              source_base, source_ext = os.path.splitext(self.g.filename)
72              output_filename = source_base + '.woz'
73          self.g.logger.PrintByID("writing", {"filename":output_filename})
74  
75          woz_image = wozardry.WozDiskImage()
76          json_string = self.g.disk_image.to_json()
77          woz_image.from_json(json_string)
78          j = json.loads(json_string)
79          root = [x for x in j.keys()].pop()
80          woz_image.info["creator"] = STRINGS["header"].strip()[:32]
81          woz_image.info["synchronized"] = j[root]["info"]["synchronized"]
82          woz_image.info["cleaned"] = True #self.g.found_and_cleaned_weakbits
83          woz_image.info["write_protected"] = j[root]["info"]["write_protected"]
84          woz_image.meta["image_date"] = time.strftime("%Y-%m-%dT%H:%M:%S.000Z", time.gmtime())
85          for q in range(1 + (0x23 * 4)):
86              physical_track_num = q / 4
87              if physical_track_num in self.output_tracks:
88                  woz_image.add_track(physical_track_num, self.output_tracks[physical_track_num])
89          try:
90              wozardry.WozDiskImage(io.BytesIO(bytes(woz_image)))
91          except Exception as e:
92              raise Exception from e
93          with open(output_filename, 'wb') as f:
94              f.write(bytes(woz_image))