adf.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. # greaseweazle/image/adf.py
  2. #
  3. # Written & released by Keir Fraser <keir.xen@gmail.com>
  4. #
  5. # This is free and unencumbered software released into the public domain.
  6. # See the file COPYING for more details, or visit <http://unlicense.org>.
  7. from greaseweazle import error
  8. import greaseweazle.codec.amiga.amigados as amigados
  9. from .image import Image
  10. class ADF(Image):
  11. default_format = 'amiga.amigados'
  12. def __init__(self):
  13. self.sec_per_track = 11
  14. self.to_track = dict()
  15. @classmethod
  16. def from_file(cls, name):
  17. with open(name, "rb") as f:
  18. dat = f.read()
  19. adf = cls()
  20. nsec = adf.sec_per_track
  21. error.check((len(dat) % (2*nsec*512)) == 0, "Bad ADF image")
  22. ncyl = len(dat) // (2*nsec*512)
  23. if ncyl > 90:
  24. ncyl //= 2
  25. nsec *= 2
  26. adf.sec_per_track = nsec
  27. for tnr in range(ncyl*2):
  28. ados = amigados.AmigaDOS(tracknr=tnr, nsec=nsec)
  29. ados.set_adf_track(dat[tnr*nsec*512:(tnr+1)*nsec*512])
  30. adf.to_track[tnr] = ados
  31. return adf
  32. def get_track(self, cyl, side):
  33. tnr = cyl * 2 + side
  34. if not tnr in self.to_track:
  35. return None
  36. return self.to_track[tnr].raw_track()
  37. def emit_track(self, cyl, side, track):
  38. tnr = cyl * 2 + side
  39. self.to_track[tnr] = track
  40. def get_image(self):
  41. tdat = bytearray()
  42. ntracks = max(self.to_track, default=0) + 1
  43. for tnr in range(ntracks):
  44. t = self.to_track[tnr] if tnr in self.to_track else None
  45. if t is not None and hasattr(t, 'get_adf_track'):
  46. tdat += t.get_adf_track()
  47. elif tnr < 160:
  48. # Pad empty/damaged tracks.
  49. tdat += amigados.bad_sector * self.sec_per_track
  50. else:
  51. # Do not extend past 160 tracks unless there is data.
  52. break
  53. if ntracks < 160:
  54. tdat += amigados.bad_sector * self.sec_per_track * (160 - ntracks)
  55. return tdat
  56. # Local variables:
  57. # python-indent: 4
  58. # End: