flashfloppy/scripts/edsk_fix_gaps.py

108 lines
4.1 KiB
Python

# edsk_fix_gaps.py
#
# Some images with GAPS protection incorrectly have the next sector's pre-sync
# bytes (12x00) included. This script detects such images and strips the
# extra bytes.
#
# Written & released by Keir Fraser <keir.xen@gmail.com>
#
# This is free and unencumbered software released into the public domain.
# See the file COPYING for more details, or visit <http://unlicense.org>.
import struct, sys
def main(argv):
if len(argv) != 3:
print("%s <input_file> <output_file>" % argv[0])
return
in_f = open(argv[1], "rb")
in_dat = in_f.read()
out_dat = bytearray(in_dat[:256])
in_dat = in_dat[256:]
fixed = 0
nr_idam_gaps = 0
trk = 0
while True:
if not in_dat:
break
x = struct.unpack("<10s", in_dat[:10])
if x[0] != b'Track-Info':
out_dat += in_dat[:256]
in_dat = in_dat[256:]
continue
(track, side) = struct.unpack("BB", in_dat[16:18])
(n, nr, gap, filler) = struct.unpack("BBBB", in_dat[20:24])
out_dat += in_dat[:24]
sinfo = bytearray(in_dat[24:256])
in_dat = in_dat[256:]
sec_dat = [None] * nr
idam_gaps = [False] * nr
in_dlen = 0
for i in range(nr):
(c,h,r,n,s1,s2,alen) = struct.unpack("<BBBBBBH", sinfo[:8])
sec_dat[i] = in_dat[:alen]
in_dat = in_dat[alen:]
in_dlen += alen
if alen % 0x80 != 0 and alen >= 13:
remainder = bytearray(sec_dat[i][-13:])
# Check for exactly 12x00 at end of data area
if remainder[0] != 0 and all([v == 0 for v in remainder[1:]]):
# Strip the 12x00 bytes
alen -= 12
sec_dat[i] = sec_dat[i][:-12]
sinfo[6] = alen & 0xff
sinfo[7] = (alen >> 8) & 0xff
# Check if the next sector's IDAM is included
idam = bytearray(12+4)
idam[12] = idam[13] = idam[14] = 0xa1
idam[15] = 0xfe
if sec_dat[i][-100:].find(idam) != -1 and i < nr-1:
# IDAM is included. Mark this sector for later fixup
idam_gaps[i] = True
nr_idam_gaps += 1
fixed += 1
out_dat += sinfo[:8]
sinfo = sinfo[8:]
if sinfo:
out_dat += sinfo
# Check for required late fixups
for i in reversed(range(nr)):
if idam_gaps[i]:
# This sector includes next sector's IDAM, presumably because
# of a post-IDAM gapo signature. We fix this by completely
# de-interleaving the sector. We work back to front as
# may need to concatenate multiple later sectors.
sec_dat[i] += bytearray(12) # Pre-sync
sec_dat[i] += bytearray([0xa1]) * 3 # Sync
sec_dat[i] += bytearray([0xfb]) # DAM
sec_dat[i] += sec_dat[i+1] # Data
alen = len(sec_dat[i])
out_dat[24+i*8+6-256] = alen & 0xff
out_dat[24+i*8+7-256] = (alen >> 8) & 0xff
# Emit sector data areas
out_dlen = 256
for x in sec_dat:
out_dat += x
out_dlen += len(x)
# Fix up input alignment
if in_dlen % 256 != 0:
in_dat = in_dat[256-in_dlen%256:]
# Fix up output alignment
if out_dlen % 256 != 0:
out_dat += bytearray(256-out_dlen%256)
out_dlen += 256 - out_dlen%256
# Find track in track-sizes header and adjust track size
while out_dat[52+trk] == 0:
trk += 1
out_dat[52+trk] = out_dlen >> 8
trk += 1
# All done! Create the output file and print a user summary
out_f = open(argv[2], "wb")
out_f.write(out_dat)
if fixed != 0:
print("Fixed %u sectors (%u de-interleaved)" % (fixed, nr_idam_gaps))
else:
print("No fixups")
if __name__ == "__main__":
main(sys.argv)