adf.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. import struct
  8. from greaseweazle import error
  9. from greaseweazle.track import MasterTrack
  10. from greaseweazle.bitcell import Bitcell
  11. import greaseweazle.codec.amiga.amigados as amigados
  12. from bitarray import bitarray
  13. class ADF:
  14. default_format = 'amiga.amigados'
  15. def __init__(self, start_cyl, nr_sides):
  16. error.check(nr_sides == 2, "ADF: Must be double-sided")
  17. self.bitrate = 253
  18. self.sec_per_track = 11
  19. self.track_list = [None] * start_cyl
  20. @classmethod
  21. def to_file(cls, start_cyl, nr_sides):
  22. adf = cls(start_cyl, nr_sides)
  23. return adf
  24. @classmethod
  25. def from_file(cls, dat):
  26. adf = cls(0, 2)
  27. nsec = adf.sec_per_track
  28. error.check((len(dat) % (2*nsec*512)) == 0, "Bad ADF image")
  29. ncyl = len(dat) // (2*nsec*512)
  30. if ncyl > 90:
  31. ncyl //= 2
  32. nsec *= 2
  33. adf.bitrate *= 2
  34. adf.sec_per_track = nsec
  35. for i in range(ncyl*2):
  36. ados = amigados.AmigaDOS(tracknr=i, nsec=nsec)
  37. ados.set_adf_track(dat[i*nsec*512:(i+1)*nsec*512])
  38. adf.track_list.append(ados)
  39. return adf
  40. def get_track(self, cyl, side, writeout=False):
  41. off = cyl * 2 + side
  42. if off >= len(self.track_list):
  43. return None
  44. rawbytes = self.track_list[off].bits()
  45. tdat = bitarray(endian='big')
  46. tdat.frombytes(rawbytes)
  47. track = MasterTrack(
  48. bits = tdat,
  49. time_per_rev = 0.2)
  50. track.verify = self.track_list[off]
  51. return track
  52. def append_track(self, track):
  53. self.track_list.append(track)
  54. def get_image(self):
  55. tlen = self.sec_per_track * 512
  56. tdat = bytearray()
  57. for tracknr in range(len(self.track_list)):
  58. t = self.track_list[tracknr]
  59. if t is not None and hasattr(t, 'get_adf_track'):
  60. tdat += t.get_adf_track()
  61. elif tracknr < 160:
  62. # Pad empty/damaged tracks.
  63. tdat += bytes(tlen)
  64. else:
  65. # Do not extend past 160 tracks unless there is data.
  66. break
  67. if len(self.track_list) < 160:
  68. tdat += bytes(tlen * (160 - len(self.track_list)))
  69. return tdat
  70. # Local variables:
  71. # python-indent: 4
  72. # End: