Эх сурвалжийг харах

amigados: Fix raw track output when sectors are missing

Keir Fraser 4 жил өмнө
parent
commit
98d0c450bb

+ 30 - 13
scripts/greaseweazle/codec/amiga/amigados.py

@@ -25,65 +25,78 @@ class AmigaDOS:
         self.sector = [None] * nsec
         self.map = [None] * nsec
 
+
     def exists(self, sec_id, togo):
         return ((self.sector[sec_id] is not None)
                 or (self.map[self.nsec-togo] is not None))
 
+
     def nr_missing(self):
         return len([sec for sec in self.sector if sec is None])
 
+
     def add(self, sec_id, togo, label, data):
         assert not self.exists(sec_id, togo)
         self.sector[sec_id] = label, data
         self.map[self.nsec-togo] = sec_id
 
+
     def get_adf_track(self):
         tdat = bytearray()
         for sec in self.sector:
             tdat += sec[1] if sec is not None else bytes(512)
         return tdat
 
+
     def set_adf_track(self, tdat):
         self.map = list(range(self.nsec))
         for sec in self.map:
             self.sector[sec] = bytes(16), tdat[sec*512:(sec+1)*512]
 
+
     def flux_for_writeout(self):
         return self.flux()
 
+
     def flux(self):
         return self
 
+
     def bits(self):
-        next_bad_sec_id = 0
-        t = encode(bytes(128))
-        for nr in range(self.nsec):
-            sec_id = self.map[nr]
-            if sec_id is None:
-                while self.sector[next_bad_sec_id] is not None:
-                    next_bad_sec_id += 1
-                sec_id = next_bad_sec_id
-                label, data = bytes(16), bytes(512)
-            else:
-                label, data = self.sector[sec_id]
-            t += sync_bytes
+
+        # List of sector IDs missing from the sector map:
+        missing = iter([x for x in range(self.nsec) if not x in self.map])
+        # Sector map with the missing entries filled in:
+        full_map = [next(missing) if x is None else x for x in self.map]
+
+        # Post-index track gap.
+        t = encode(bytes(128 * (self.nsec//11)))
+
+        for nr, sec_id in zip(range(self.nsec), full_map):
+            sector = self.sector[sec_id]
+            label, data = (bytes(16), bytes(512)) if sector is None else sector
             header = bytes([0xff, self.tracknr, sec_id, self.nsec-nr])
+            t += sync_bytes
             t += encode(header)
             t += encode(label)
             t += encode(struct.pack('>I', checksum(header + label)))
             t += encode(struct.pack('>I', checksum(data)))
             t += encode(data)
             t += encode(bytes(2))
-        tlen = 101376 if self.nsec == 11 else 202752
+
+        # Add the pre-index gap, and encode to MFM.
+        tlen = 101376 * (self.nsec//11)
         t += bytes(tlen//8-len(t))
         return mfm_encode(t)
 
+
     def verify_track(self, flux):
         cyl = self.tracknr // 2
         head = self.tracknr & 1
         readback_track = decode_track(cyl, head, flux)
         return readback_track.nr_missing() == 0
 
+
 def mfm_encode(dat):
     y = 0
     out = bytearray()
@@ -95,22 +108,26 @@ def mfm_encode(dat):
         out.append(y)
     return bytes(out)
     
+
 def encode(dat):
     return bytes(it.chain(map(lambda x: (x >> 1) & 0x55, dat),
                           map(lambda x: x & 0x55, dat)))
 
+
 def decode(dat):
     length = len(dat)//2
     return bytes(map(lambda x, y: (x << 1 & 0xaa) | (y & 0x55),
                      it.islice(dat, 0, length),
                      it.islice(dat, length, None)))
 
+
 def checksum(dat):
     csum = 0
     for i in range(0, len(dat), 4):
         csum ^= struct.unpack('>I', dat[i:i+4])[0]
     return (csum ^ (csum>>1)) & 0x55555555
 
+
 def decode_track(cyl, head, flux):
 
     bc = Bitcell(clock = 2e-6, flux = flux)