Bladeren bron

gw read: Retry on unsuccessful read of AmigaDOS data

Keir Fraser 4 jaren geleden
bovenliggende
commit
cff9038b88
2 gewijzigde bestanden met toevoegingen van 75 en 39 verwijderingen
  1. 37 35
      scripts/greaseweazle/codec/amiga/amigados.py
  2. 38 4
      scripts/greaseweazle/tools/read.py

+ 37 - 35
scripts/greaseweazle/codec/amiga/amigados.py

@@ -62,6 +62,41 @@ class AmigaDOS:
         return self.raw_track().flux()
 
 
+    def decode_raw(self, track):
+        raw = RawTrack(clock = 2e-6, data = track)
+        bits, times = raw.bitarray, raw.timearray
+
+        sectors = bits.search(sync)
+        for offs in bits.itersearch(sync):
+
+            if self.nr_missing() == 0:
+                break
+
+            sec = bits[offs:offs+544*16].tobytes()
+            if len(sec) != 1088:
+                continue
+
+            header = decode(sec[4:12])
+            format, track, sec_id, togo = tuple(header)
+            if format != 0xff or track != self.tracknr \
+               or not(sec_id < self.nsec and 0 < togo <= self.nsec) \
+               or self.exists(sec_id, togo):
+                continue
+
+            label = decode(sec[12:44])
+            hsum, = struct.unpack('>I', decode(sec[44:52]))
+            if hsum != checksum(header + label):
+                continue
+
+            dsum, = struct.unpack('>I', decode(sec[52:60]))
+            data = decode(sec[60:1084])
+            gap = decode(sec[1084:1088])
+            if dsum != checksum(data):
+                continue;
+
+            self.add(sec_id, togo, label, data)
+
+
     def raw_track(self):
 
         # List of sector IDs missing from the sector map:
@@ -134,41 +169,8 @@ def checksum(dat):
 
 
 def decode_track(cyl, head, track):
-
-    raw = RawTrack(clock = 2e-6, data = track)
-    bits, times = raw.bitarray, raw.timearray
-    tracknr = cyl*2 + head
-    ados = AmigaDOS(tracknr)
-    
-    sectors = bits.search(sync)
-    for offs in bits.itersearch(sync):
-
-        sec = bits[offs:offs+544*16].tobytes()
-        if len(sec) != 1088:
-            continue
-
-        header = decode(sec[4:12])
-        format, track, sec_id, togo = tuple(header)
-        if format != 0xff or track != tracknr \
-           or not(sec_id < ados.nsec and 0 < togo <= ados.nsec) \
-           or ados.exists(sec_id, togo):
-            continue
-
-        label = decode(sec[12:44])
-        hsum, = struct.unpack('>I', decode(sec[44:52]))
-        if hsum != checksum(header + label):
-            continue
-
-        dsum, = struct.unpack('>I', decode(sec[52:60]))
-        data = decode(sec[60:1084])
-        gap = decode(sec[1084:1088])
-        if dsum != checksum(data):
-            continue;
-
-        ados.add(sec_id, togo, label, data)
-        if ados.nr_missing() == 0:
-            break
-
+    ados = AmigaDOS(cyl*2 + head)
+    ados.decode_raw(track)
     return ados
 
 

+ 38 - 4
scripts/greaseweazle/tools/read.py

@@ -60,6 +60,43 @@ def normalise_rpm(flux, rpm):
     return Flux([norm_to_index]*len(flux.index_list), norm_flux, freq)
 
 
+def read_and_normalise(usb, args):
+    flux = usb.read_track(args.revs)
+    if args.rpm is not None:
+        flux = normalise_rpm(flux, args.rpm)
+    return flux
+
+
+class Formatter:
+    def __init__(self):
+        self.length = 0
+    def print(self, s):
+        self.erase()
+        self.length = len(s)
+        print(s, end="", flush=True)
+    def erase(self):
+        l = self.length
+        print("\b"*l + " "*l + "\b"*l, end="", flush=True)
+        self.length = 0
+
+
+def read_with_retry(usb, args, cyl, side, decoder):
+    flux = read_and_normalise(usb, args)
+    if decoder is None:
+        return flux
+    dat = decoder(cyl, side, flux)
+    if dat.nr_missing() != 0:
+        formatter = Formatter()
+        for retry in range(3):
+            formatter.print(" Retry %d" % (retry+1))
+            flux = read_and_normalise(usb, args)
+            dat.decode_raw(flux)
+            if dat.nr_missing() == 0:
+                break
+        formatter.erase()
+    return dat
+
+
 def read_to_image(usb, args, image, decoder=None):
     """Reads a floppy disk and dumps it into a new image file.
     """
@@ -68,10 +105,7 @@ def read_to_image(usb, args, image, decoder=None):
         for side in range(0, args.nr_sides):
             print("\rReading Track %u.%u..." % (cyl, side), end="")
             usb.seek((cyl, cyl*2)[args.double_step], side)
-            flux = usb.read_track(args.revs)
-            if args.rpm is not None:
-                flux = normalise_rpm(flux, args.rpm)
-            dat = flux if decoder is None else decoder(cyl, side, flux)
+            dat = read_with_retry(usb, args, cyl, side, decoder)
             image.append_track(dat)
 
     print()