ipf_align.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. # ipf_align.py
  2. #
  3. # Align all tracks in an IPF image to the same offset from index mark.
  4. #
  5. # Written & released by Keir Fraser <keir.xen@gmail.com>
  6. #
  7. # This is free and unencumbered software released into the public domain.
  8. # See the file COPYING for more details, or visit <http://unlicense.org>.
  9. import struct, sys, crcmod.predefined
  10. def main(argv):
  11. crc32 = crcmod.predefined.Crc('crc-32')
  12. offset = 1024
  13. if len(argv) == 4:
  14. offset = int(argv[3])
  15. elif len(argv) != 3:
  16. print("%s <input_file> <output_file> [<offset>]" % argv[0])
  17. return
  18. with open(argv[1], "rb") as f:
  19. in_dat = bytearray(f.read())
  20. out_dat = bytearray()
  21. while in_dat:
  22. # Decode the common record header
  23. id, length, crc = struct.unpack(">4s2I", in_dat[:12])
  24. # Consume the record from the input array
  25. record = in_dat[:length]
  26. in_dat = in_dat[length:]
  27. # Check the CRC
  28. record[8:12] = bytes(4)
  29. assert crc == crc32.new(record).crcValue, "CRC mismatch"
  30. # Modify the record as necessary
  31. if id == b'IMGE':
  32. trkbits, = struct.unpack(">I", record[48:52])
  33. if trkbits > offset:
  34. record[32:40] = struct.pack(">2I", offset//8, offset)
  35. # Re-calculate the CRC
  36. record[8:12] = struct.pack(">I", crc32.new(record).crcValue)
  37. # DATA chunk has extra data to copy
  38. if id == b'DATA':
  39. size, bsize, dcrc, datchunk = struct.unpack(">4I", record[12:28])
  40. record += in_dat[:size]
  41. in_dat = in_dat[size:]
  42. # Write the full modified record into the output array
  43. out_dat += record
  44. with open(argv[2], "wb") as f:
  45. f.write(out_dat)
  46. if __name__ == "__main__":
  47. main(sys.argv)