diskstack 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. diskstack/__init__.py +5 -0
  2. diskstack/_vendor/__init__.py +0 -0
  3. diskstack/_vendor/greaseweazle/COPYING +24 -0
  4. diskstack/_vendor/greaseweazle/__init__.py +2 -0
  5. diskstack/_vendor/greaseweazle/codec/__init__.py +0 -0
  6. diskstack/_vendor/greaseweazle/codec/amiga/__init__.py +0 -0
  7. diskstack/_vendor/greaseweazle/codec/amiga/amigados.py +221 -0
  8. diskstack/_vendor/greaseweazle/codec/apple2/__init__.py +0 -0
  9. diskstack/_vendor/greaseweazle/codec/apple2/apple2_gcr.py +223 -0
  10. diskstack/_vendor/greaseweazle/codec/bitcell.py +117 -0
  11. diskstack/_vendor/greaseweazle/codec/codec.py +362 -0
  12. diskstack/_vendor/greaseweazle/codec/commodore/__init__.py +0 -0
  13. diskstack/_vendor/greaseweazle/codec/commodore/c64_gcr.py +229 -0
  14. diskstack/_vendor/greaseweazle/codec/datageneral/__init__.py +0 -0
  15. diskstack/_vendor/greaseweazle/codec/datageneral/datageneral.py +211 -0
  16. diskstack/_vendor/greaseweazle/codec/hp/__init__.py +0 -0
  17. diskstack/_vendor/greaseweazle/codec/hp/hp_mmfm.py +258 -0
  18. diskstack/_vendor/greaseweazle/codec/ibm/__init__.py +0 -0
  19. diskstack/_vendor/greaseweazle/codec/ibm/ibm.py +1005 -0
  20. diskstack/_vendor/greaseweazle/codec/macintosh/__init__.py +0 -0
  21. diskstack/_vendor/greaseweazle/codec/macintosh/mac_gcr.py +238 -0
  22. diskstack/_vendor/greaseweazle/codec/micropolis/__init__.py +0 -0
  23. diskstack/_vendor/greaseweazle/codec/micropolis/micropolis.py +233 -0
  24. diskstack/_vendor/greaseweazle/codec/northstar/__init__.py +0 -0
  25. diskstack/_vendor/greaseweazle/codec/northstar/northstar.py +210 -0
  26. diskstack/_vendor/greaseweazle/data/__init__.py +0 -0
  27. diskstack/_vendor/greaseweazle/data/diskdefs.cfg +81 -0
  28. diskstack/_vendor/greaseweazle/data/diskdefs_acorn.cfg +119 -0
  29. diskstack/_vendor/greaseweazle/data/diskdefs_akai.cfg +27 -0
  30. diskstack/_vendor/greaseweazle/data/diskdefs_amiga.cfg +17 -0
  31. diskstack/_vendor/greaseweazle/data/diskdefs_apple2.cfg +31 -0
  32. diskstack/_vendor/greaseweazle/data/diskdefs_apricot.cfg +25 -0
  33. diskstack/_vendor/greaseweazle/data/diskdefs_atari.cfg +33 -0
  34. diskstack/_vendor/greaseweazle/data/diskdefs_atarist.cfg +76 -0
  35. diskstack/_vendor/greaseweazle/data/diskdefs_coco.cfg +98 -0
  36. diskstack/_vendor/greaseweazle/data/diskdefs_commodore.cfg +127 -0
  37. diskstack/_vendor/greaseweazle/data/diskdefs_datageneral.cfg +8 -0
  38. diskstack/_vendor/greaseweazle/data/diskdefs_dec.cfg +37 -0
  39. diskstack/_vendor/greaseweazle/data/diskdefs_dragon.cfg +61 -0
  40. diskstack/_vendor/greaseweazle/data/diskdefs_eagle.cfg +25 -0
  41. diskstack/_vendor/greaseweazle/data/diskdefs_ensoniq.cfg +39 -0
  42. diskstack/_vendor/greaseweazle/data/diskdefs_epson.cfg +95 -0
  43. diskstack/_vendor/greaseweazle/data/diskdefs_gem.cfg +15 -0
  44. diskstack/_vendor/greaseweazle/data/diskdefs_hp.cfg +25 -0
  45. diskstack/_vendor/greaseweazle/data/diskdefs_ibm.cfg +140 -0
  46. diskstack/_vendor/greaseweazle/data/diskdefs_kaypro.cfg +58 -0
  47. diskstack/_vendor/greaseweazle/data/diskdefs_luxor.cfg +96 -0
  48. diskstack/_vendor/greaseweazle/data/diskdefs_mac.cfg +71 -0
  49. diskstack/_vendor/greaseweazle/data/diskdefs_micropolis.cfg +73 -0
  50. diskstack/_vendor/greaseweazle/data/diskdefs_mm1.cfg +69 -0
  51. diskstack/_vendor/greaseweazle/data/diskdefs_msx.cfg +45 -0
  52. diskstack/_vendor/greaseweazle/data/diskdefs_northstar.cfg +37 -0
  53. diskstack/_vendor/greaseweazle/data/diskdefs_occ1.cfg +23 -0
  54. diskstack/_vendor/greaseweazle/data/diskdefs_olivetti.cfg +18 -0
  55. diskstack/_vendor/greaseweazle/data/diskdefs_pc98.cfg +69 -0
  56. diskstack/_vendor/greaseweazle/data/diskdefs_raw.cfg +25 -0
  57. diskstack/_vendor/greaseweazle/data/diskdefs_rm.cfg +98 -0
  58. diskstack/_vendor/greaseweazle/data/diskdefs_sci.cfg +15 -0
  59. diskstack/_vendor/greaseweazle/data/diskdefs_sega.cfg +13 -0
  60. diskstack/_vendor/greaseweazle/data/diskdefs_sharp.cfg +13 -0
  61. diskstack/_vendor/greaseweazle/data/diskdefs_thomson.cfg +78 -0
  62. diskstack/_vendor/greaseweazle/data/diskdefs_tsc.cfg +81 -0
  63. diskstack/_vendor/greaseweazle/data/diskdefs_xerox.cfg +59 -0
  64. diskstack/_vendor/greaseweazle/data/diskdefs_zx.cfg +245 -0
  65. diskstack/_vendor/greaseweazle/error.py +19 -0
  66. diskstack/_vendor/greaseweazle/flux.py +315 -0
  67. diskstack/_vendor/greaseweazle/image/__init__.py +0 -0
  68. diskstack/_vendor/greaseweazle/image/a2r.py +133 -0
  69. diskstack/_vendor/greaseweazle/image/acorn.py +28 -0
  70. diskstack/_vendor/greaseweazle/image/adf.py +15 -0
  71. diskstack/_vendor/greaseweazle/image/apple2.py +18 -0
  72. diskstack/_vendor/greaseweazle/image/apridisk.py +107 -0
  73. diskstack/_vendor/greaseweazle/image/caps.py +464 -0
  74. diskstack/_vendor/greaseweazle/image/d64.py +51 -0
  75. diskstack/_vendor/greaseweazle/image/d81.py +28 -0
  76. diskstack/_vendor/greaseweazle/image/d88.py +211 -0
  77. diskstack/_vendor/greaseweazle/image/dcp.py +45 -0
  78. diskstack/_vendor/greaseweazle/image/dim.py +53 -0
  79. diskstack/_vendor/greaseweazle/image/dmk.py +166 -0
  80. diskstack/_vendor/greaseweazle/image/dsk.py +31 -0
  81. diskstack/_vendor/greaseweazle/image/edsk.py +591 -0
  82. diskstack/_vendor/greaseweazle/image/fd.py +23 -0
  83. diskstack/_vendor/greaseweazle/image/fdi.py +41 -0
  84. diskstack/_vendor/greaseweazle/image/hdm.py +15 -0
  85. diskstack/_vendor/greaseweazle/image/hfe.py +742 -0
  86. diskstack/_vendor/greaseweazle/image/image.py +130 -0
  87. diskstack/_vendor/greaseweazle/image/imd.py +201 -0
  88. diskstack/_vendor/greaseweazle/image/img.py +111 -0
  89. diskstack/_vendor/greaseweazle/image/kryoflux.py +304 -0
  90. diskstack/_vendor/greaseweazle/image/mgt.py +15 -0
  91. diskstack/_vendor/greaseweazle/image/msa.py +153 -0
  92. diskstack/_vendor/greaseweazle/image/nfd.py +113 -0
  93. diskstack/_vendor/greaseweazle/image/nsi.py +47 -0
  94. diskstack/_vendor/greaseweazle/image/scp.py +471 -0
  95. diskstack/_vendor/greaseweazle/image/sf7.py +15 -0
  96. diskstack/_vendor/greaseweazle/image/sharp2d.py +15 -0
  97. diskstack/_vendor/greaseweazle/image/td0.py +141 -0
  98. diskstack/_vendor/greaseweazle/image/xdf.py +15 -0
  99. diskstack/_vendor/greaseweazle/optimised/__init__.py +22 -0
  100. diskstack/_vendor/greaseweazle/tools/__init__.py +0 -0
  101. diskstack/_vendor/greaseweazle/tools/util.py +133 -0
  102. diskstack/_vendor/greaseweazle/track.py +494 -0
  103. diskstack/cache.py +210 -0
  104. diskstack/candidates.py +396 -0
  105. diskstack/cli.py +348 -0
  106. diskstack/errors.py +5 -0
  107. diskstack/filler.py +29 -0
  108. diskstack/formats.py +381 -0
  109. diskstack/parallel.py +73 -0
  110. diskstack/report.py +353 -0
  111. diskstack/stack.py +317 -0
  112. diskstack-1.0.0.dist-info/METADATA +329 -0
  113. diskstack-1.0.0.dist-info/RECORD +119 -0
  114. diskstack-1.0.0.dist-info/WHEEL +5 -0
  115. diskstack-1.0.0.dist-info/entry_points.txt +2 -0
  116. diskstack-1.0.0.dist-info/licenses/LICENSE +21 -0
  117. diskstack-1.0.0.dist-info/licenses/NOTICE +55 -0
  118. diskstack-1.0.0.dist-info/licenses/diskstack/_vendor/greaseweazle/COPYING +24 -0
  119. diskstack-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,211 @@
1
+ # greaseweazle/codec/datageneral/datageneral.py
2
+ #
3
+ # Data General 8" floppy disk format, from DG document 015-000088-00
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
+
9
+ from typing import List, Optional
10
+
11
+ import struct, binascii # XXX
12
+ from bitarray import bitarray
13
+ import crcmod.predefined
14
+ import itertools as it
15
+ from enum import Enum
16
+
17
+ from diskstack._vendor.greaseweazle import error
18
+ from diskstack._vendor.greaseweazle.codec import codec
19
+ from diskstack._vendor.greaseweazle.codec.ibm.ibm import decode, encode, fm_encode
20
+ from diskstack._vendor.greaseweazle.track import MasterTrack, PLL, PLLTrack
21
+ from diskstack._vendor.greaseweazle.flux import HasFlux
22
+
23
+ default_revs = 1
24
+
25
+ bad_sector = b'-=[BAD SECTOR]=-'
26
+
27
+ sync_word = b'\x00\x01'
28
+ sync = bitarray(endian='big')
29
+ sync.frombytes(fm_encode(encode(sync_word)))
30
+
31
+ # CRC with poly x^16 + x^8 + 1
32
+ def csum(dat):
33
+ y = 0
34
+ # Need to "clock in" 8 extra bits to get the correct result
35
+ for x in dat + b'\x00':
36
+ y = ((y & 0xFF) ^ (y >> 8)) | (((y & 0xFF) ^ x) << 8)
37
+ return y
38
+
39
+ class DataGeneral(codec.Codec):
40
+
41
+ nsec = 8
42
+ time_per_rev = 60 / 360
43
+
44
+ verify_revs: float = default_revs
45
+
46
+ def __init__(self, cyl: int, head: int, config):
47
+ self.clock = 2e-6
48
+ self.bps = 512
49
+ self.cyl, self.head = cyl, head
50
+ self.config = config
51
+ self.sector: List[Optional[bytes]]
52
+ self.sector = [None] * self.nsec
53
+
54
+ def summary_string(self) -> str:
55
+ nsec, nbad = self.nsec, self.nr_missing()
56
+ s = "Data General 2F (%d/%d sectors)" % (nsec - nbad, nsec)
57
+ return s
58
+
59
+ # private
60
+ def add(self, sec_id, data) -> None:
61
+ assert not self.has_sec(sec_id)
62
+ self.sector[sec_id] = data
63
+
64
+ def has_sec(self, sec_id: int) -> bool:
65
+ return self.sector[sec_id] is not None
66
+
67
+ def nr_missing(self) -> int:
68
+ return len([sec for sec in self.sector if sec is None])
69
+
70
+ def get_img_track(self) -> bytearray:
71
+ tdat = bytearray()
72
+ for sec in self.sector:
73
+ tdat += sec if sec is not None else bad_sector * (self.bps//16)
74
+ return tdat
75
+
76
+ def set_img_track(self, tdat: bytes) -> int:
77
+ totsize = self.nsec * self.bps
78
+ if len(tdat) < totsize:
79
+ tdat += bytes(totsize - len(tdat))
80
+ for sec in range(self.nsec):
81
+ self.sector[sec] = tdat[sec*self.bps:(sec+1)*self.bps]
82
+ return totsize
83
+
84
+ def decode_flux(self, track: HasFlux, pll: Optional[PLL]=None) -> None:
85
+
86
+ flux = track.flux()
87
+ if flux.time_per_rev < self.time_per_rev / 2:
88
+ flux.identify_hard_sectors()
89
+ flux.cue_at_index()
90
+ raw = PLLTrack(time_per_rev = self.time_per_rev,
91
+ clock = self.clock, data = flux, pll = pll)
92
+
93
+ for rev in range(len(raw.revolutions)):
94
+
95
+ if self.nr_missing() == 0:
96
+ break
97
+
98
+ bits, _ = raw.get_revolution(rev)
99
+
100
+ hardsector_bits = raw.revolutions[rev].hardsector_bits
101
+ if hardsector_bits is not None:
102
+ hardsector_bits = list(it.accumulate(hardsector_bits))
103
+ # DG hard-sectored media has 4 holes per sector; 8 sectors
104
+ if len(hardsector_bits) == 32:
105
+ hardsector_bits = hardsector_bits[3::4]
106
+ else:
107
+ hardsector_bits = [len(bits)*(i+1)//self.nsec
108
+ for i in range(self.nsec)]
109
+ error.check(len(hardsector_bits) == self.nsec,
110
+ f'Data General: Unexpected number of sectors: '
111
+ f'{len(hardsector_bits)}')
112
+ hardsector_bits = [0] + hardsector_bits
113
+
114
+ for hsec_id in range(self.nsec):
115
+
116
+ s, e = hardsector_bits[hsec_id], hardsector_bits[hsec_id+1]
117
+ # Skip first 352 cells (704us), see Figure G-1
118
+ s += 352
119
+
120
+ offs = bits[s:e].search(sync)
121
+ if (off := next(offs, None)) is None:
122
+ continue
123
+ off += 2*16
124
+ h_off = off
125
+
126
+ # Read and check the preamble
127
+ preamble = decode(bits[s+off:s+off+2*16].tobytes())
128
+ if len(preamble) != 2:
129
+ continue
130
+ cyl = preamble[0] & 0x7F
131
+ sec_id = preamble[1] >> 2
132
+ if cyl != self.cyl or sec_id > self.nsec:
133
+ print('T%d.%d: Ignoring unexpected sector C:%d R:%d'
134
+ % (self.cyl, self.head, cyl, sec_id))
135
+ continue
136
+ if self.has_sec(sec_id):
137
+ break
138
+
139
+ # Skip 40 cells (80us) past the preamble word
140
+ d_off = off + 2*16 + 40
141
+ offs = bits[s+d_off:e].search(sync)
142
+ if (off := next(offs, None)) is None:
143
+ continue
144
+ off += d_off + 2*16
145
+
146
+ # Read and checksum the data
147
+ data = decode(bits[s+off:s+off+514*16].tobytes())
148
+ if len(data) != 514:
149
+ continue
150
+ read_csum = int.from_bytes(data[512:], 'big')
151
+ if csum(data[:512]) == read_csum:
152
+ self.add(sec_id, data[:512])
153
+
154
+
155
+ def master_track(self) -> MasterTrack:
156
+ t = bytes()
157
+ slen = int((self.time_per_rev / self.clock / self.nsec / 16))
158
+
159
+ for sec_id in range(self.nsec):
160
+ # Format track layout, Figures F-4 & H-9
161
+ s = encode(bytes(22*2))
162
+ s += encode(sync_word)
163
+
164
+ s += encode(struct.pack('>BB', self.cyl & 0x7f, sec_id << 2))
165
+
166
+ # Delay 20us + 160us (Figure G-5) ~= 6 bytes
167
+ s += encode(bytes(4))
168
+ s += encode(sync_word)
169
+
170
+ sector = self.sector[sec_id]
171
+ data = bad_sector*(self.bps//16) if sector is None else sector
172
+
173
+ s += encode(data + csum(data).to_bytes(2, 'big'))
174
+ s += encode(bytes(slen - len(s)//2))
175
+ t += s
176
+
177
+ t = fm_encode(t)
178
+
179
+ track = MasterTrack(bits = t, time_per_rev = self.time_per_rev,
180
+ hardsector_bits = [slen*16] * self.nsec)
181
+ track.verify = self
182
+ return track
183
+
184
+
185
+ def verify_track(self, flux):
186
+ readback_track = self.__class__(self.cyl, self.head, self.config)
187
+ readback_track.decode_flux(flux)
188
+ return (readback_track.nr_missing() == 0
189
+ and self.sector == readback_track.sector)
190
+
191
+
192
+ class DataGeneralDef(codec.TrackDef):
193
+
194
+ default_revs = default_revs
195
+
196
+ def __init__(self, format_name: str):
197
+ return
198
+
199
+ def add_param(self, key: str, val) -> None:
200
+ raise error.Fatal('unrecognised track option %s' % key)
201
+
202
+ def finalise(self) -> None:
203
+ return
204
+
205
+ def mk_track(self, cyl: int, head: int) -> DataGeneral:
206
+ return DataGeneral(cyl, head, self)
207
+
208
+
209
+ # Local variables:
210
+ # python-indent: 4
211
+ # End:
File without changes
@@ -0,0 +1,258 @@
1
+ # greaseweazle/codec/hp/hp_mmfm.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
+
7
+ # From github:brouhaha/fluxtoimd/modulation.py:
8
+ #
9
+ # See the file COPYING for more details, or visit <http://unlicense.org>.
10
+ # An HP-proprietary M2FM floppy format, used by the HP 7902, 9885,
11
+ # and 9895 Flexible Disc Drives.
12
+ # Documentation:
13
+ # 9885 Flexible Disk Drive Service Manual
14
+ # Hewlett-Packard, September 1976, part number 09885-90030
15
+ # 7902A Disc Drive Preliminary Service Manual
16
+ # Hwelett Packard, May 1979, part number 07902-90060
17
+ # 7902A & C/9895K Flexible Disc Drive Service Documentation
18
+ # Hewlett-Packard, January 1981, part number 07902-90030
19
+ # 9895A Flexible Disc Memory Service Manual,
20
+ # Hewlett-Packard, February 1981, part number 09895-90030
21
+ # 9885: single-sided, 67 track, M2FM format only
22
+ # 7902: double-sided, 77 track, M2FM or IBM 3740 FM formats
23
+ # 9895: double-sided, 77 track, M2FM or IBM 3740 FM formats
24
+
25
+ from typing import List, Optional
26
+
27
+ import struct
28
+ from bitarray import bitarray
29
+ import crcmod.predefined
30
+
31
+ from diskstack._vendor.greaseweazle import error
32
+ from diskstack._vendor.greaseweazle.codec import codec
33
+ from diskstack._vendor.greaseweazle.codec.ibm.ibm import decode, encode, sec_map
34
+ from diskstack._vendor.greaseweazle.track import MasterTrack, PLL, PLLTrack
35
+ from diskstack._vendor.greaseweazle.flux import HasFlux
36
+
37
+ default_revs = 1.1
38
+
39
+ bad_sector = b'-=[BAD SECTOR]=-' * 16
40
+
41
+ # Syncs have an extra clock bit:
42
+ # ff 0e -> 55 55 22 54 -> 55 55 2a 54
43
+ sector_sync_bytes = b'\x55\x55\x2a\x54'
44
+ # ff 0a -> 55 55 22 44 -> 55 55 2a 44
45
+ data_sync_bytes = b'\x55\x55\x2a\x44'
46
+
47
+ sector_sync = bitarray(endian='big')
48
+ sector_sync.frombytes(sector_sync_bytes)
49
+
50
+ data_sync = bitarray(endian='big')
51
+ data_sync.frombytes(data_sync_bytes)
52
+
53
+ crc16 = crcmod.predefined.Crc('crc-ccitt-false')
54
+
55
+ rev_list = bytearray()
56
+ for x in range(256):
57
+ y = 0
58
+ for i in range(8):
59
+ y <<= 1
60
+ y |= x & 1
61
+ x >>= 1
62
+ rev_list.append(y)
63
+
64
+ def bitrev(x):
65
+ return rev_list[x]
66
+
67
+ # MMFM:
68
+ # Write clock bit iff
69
+ # 1. No preceding clock or data
70
+ # 2. No following data
71
+ mmfm_list = bytearray()
72
+ for x in range(512):
73
+ for i in [7,5,3,1]:
74
+ if x & (0xf << (i-1)) == 0:
75
+ x |= 1<<i
76
+ mmfm_list.append(x & 255)
77
+
78
+ def mmfm_encode(dat):
79
+ y, out = 0, bytearray()
80
+ for x in dat:
81
+ if (x & 0xaa) == 0:
82
+ x = mmfm_list[(y<<8) | x]
83
+ out.append(x)
84
+ y = 0 if (x & 3) == 0 else 1
85
+ return bytes(out)
86
+
87
+ class HPMMFM(codec.Codec):
88
+
89
+ time_per_rev = 60 / 360
90
+ clock = 1e-6
91
+
92
+ verify_revs = default_revs
93
+
94
+ def __init__(self, cyl: int, head: int, config):
95
+ self.cyl, self.head = cyl, head
96
+ self.config = config
97
+ self.sector: List[Optional[bytes]]
98
+ self.sector = [None] * self.nsec
99
+
100
+ @property
101
+ def nsec(self) -> int:
102
+ return self.config.secs
103
+
104
+ def summary_string(self) -> str:
105
+ nsec, nbad = self.nsec, self.nr_missing()
106
+ s = "HP MMFM (%d/%d sectors)" % (nsec - nbad, nsec)
107
+ return s
108
+
109
+ # private
110
+ def add(self, sec_id, data) -> None:
111
+ assert not self.has_sec(sec_id)
112
+ self.sector[sec_id] = data
113
+
114
+ def has_sec(self, sec_id: int) -> bool:
115
+ return self.sector[sec_id] is not None
116
+
117
+ def nr_missing(self) -> int:
118
+ return len([sec for sec in self.sector if sec is None])
119
+
120
+ def get_img_track(self) -> bytearray:
121
+ tdat = bytearray()
122
+ for sec in self.sector:
123
+ tdat += sec if sec is not None else bad_sector
124
+ return tdat
125
+
126
+ def set_img_track(self, tdat: bytes) -> int:
127
+ totsize = self.nsec * 256
128
+ if len(tdat) < totsize:
129
+ tdat += bytes(totsize - len(tdat))
130
+ for sec in range(self.nsec):
131
+ self.sector[sec] = tdat[sec*256:(sec+1)*256]
132
+ return totsize
133
+
134
+ def decode_flux(self, track: HasFlux, pll: Optional[PLL]=None) -> None:
135
+ raw = PLLTrack(time_per_rev = self.time_per_rev,
136
+ clock = self.clock, data = track, pll = pll)
137
+ bits, _ = raw.get_all_data()
138
+
139
+ for offs in bits.search(sector_sync):
140
+
141
+ if self.nr_missing() == 0:
142
+ break
143
+
144
+ offs += 2*16
145
+ idam = decode(bits[offs:offs+4*16].tobytes())
146
+ if len(idam) != 4:
147
+ continue
148
+ if crc16.new(idam).crcValue != 0:
149
+ continue
150
+ cyl = bitrev(idam[0])
151
+ sec_id = bitrev(idam[1])
152
+ head = (sec_id & 128) == 128
153
+ sec_id &= 127
154
+ if cyl != self.cyl or head != self.head or sec_id > self.nsec:
155
+ print('T%d.%d: Ignoring unexpected sector C:%d H:%d R:%d'
156
+ % (self.cyl, self.head, cyl, head, sec_id))
157
+ continue
158
+ if self.has_sec(sec_id):
159
+ continue
160
+
161
+ # Find data
162
+ offs += 8*16
163
+ dat_offs = list(bits[offs:offs+50*16].search(data_sync))
164
+ if len(dat_offs) != 1:
165
+ continue
166
+ offs += dat_offs[0] + 2*16
167
+
168
+ sec = decode(bits[offs:offs+258*16].tobytes())
169
+ if len(sec) != 258:
170
+ continue
171
+ if crc16.new(sec).crcValue != 0:
172
+ continue
173
+
174
+ # bit swap, and byte swap
175
+ sec = bytes(map(lambda x: bitrev(x), sec[:256]))
176
+ sec = struct.pack('<128H', *struct.unpack('>128H', sec))
177
+
178
+ self.add(sec_id, sec)
179
+
180
+
181
+ def master_track(self) -> MasterTrack:
182
+
183
+ # Post-index track gap.
184
+ t = encode(bytes(100))
185
+
186
+ for sec_id in sec_map(self.nsec, self.config.interleave,
187
+ self.config.cskew, self.config.hskew,
188
+ self.cyl, self.head):
189
+ sector = self.sector[sec_id]
190
+ data = bad_sector if sector is None else sector
191
+ # Header
192
+ t += encode(bytes([0xff]*3)) + sector_sync_bytes
193
+ idam = bytes(map(lambda x: bitrev(x),
194
+ [self.cyl, sec_id | (self.head << 7)]))
195
+ idam += struct.pack('>H', crc16.new(idam).crcValue)
196
+ t += encode(idam)
197
+ t += encode(bytes(1 + 16 + 4))
198
+ # Data
199
+ t += encode(bytes([0xff]*3)) + data_sync_bytes
200
+ data = struct.pack('<128H', *struct.unpack('>128H', data))
201
+ data = bytes(map(lambda x: bitrev(x), data))
202
+ data += struct.pack('>H', crc16.new(data).crcValue)
203
+ t += encode(data)
204
+ t += encode(bytes(1 + 34 + 4))
205
+
206
+ # Add the pre-index gap.
207
+ tlen = int((self.time_per_rev / self.clock)) & ~31
208
+ t += encode(bytes((tlen//8-len(t))//2))
209
+
210
+ t = mmfm_encode(t)
211
+
212
+ track = MasterTrack(bits = t, time_per_rev = self.time_per_rev)
213
+ track.verify = self
214
+ return track
215
+
216
+
217
+ def verify_track(self, flux):
218
+ readback_track = self.__class__(self.cyl, self.head, self.config)
219
+ readback_track.decode_flux(flux)
220
+ return (readback_track.nr_missing() == 0
221
+ and self.sector == readback_track.sector)
222
+
223
+
224
+ class HPMMFMDef(codec.TrackDef):
225
+
226
+ default_revs = default_revs
227
+
228
+ def __init__(self, format_name: str):
229
+ self.interleave = 1
230
+ self.cskew, self.hskew = 0, 0
231
+ self.secs: Optional[int] = None
232
+ self.finalised = False
233
+
234
+ def add_param(self, key: str, val) -> None:
235
+ if key == 'secs':
236
+ val = int(val)
237
+ self.secs = val
238
+ elif key in ['interleave', 'cskew', 'hskew']:
239
+ n = int(val)
240
+ error.check(0 <= n <= 255, '%s out of range' % key)
241
+ setattr(self, key, n)
242
+ else:
243
+ raise error.Fatal('unrecognised track option %s' % key)
244
+
245
+ def finalise(self) -> None:
246
+ if self.finalised:
247
+ return
248
+ error.check(self.secs is not None,
249
+ 'number of sectors not specified')
250
+ self.finalised = True
251
+
252
+ def mk_track(self, cyl: int, head: int) -> HPMMFM:
253
+ return HPMMFM(cyl, head, self)
254
+
255
+
256
+ # Local variables:
257
+ # python-indent: 4
258
+ # End:
File without changes