Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1088 | alone | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "wd93crc.h" |
||
6 | |||
7 | #include "util.h" |
||
8 | |||
9 | static inline unsigned CalcSecSizeMask() |
||
10 | { |
||
11 | // ����� ���� ������� ������� (3 - ��� fd1793, 0xF - ��� uPD765) |
||
12 | return (conf.mem_model == MM_PLUS3) ? 0xFU : 3U; |
||
13 | } |
||
14 | |||
15 | void TRKCACHE::seek(FDD *d, unsigned cyl, unsigned side, SEEK_MODE fs) |
||
16 | { |
||
17 | if ((d == drive) && (sf == fs) && (cyl == TRKCACHE::cyl) && (side == TRKCACHE::side)) |
||
18 | return; |
||
19 | |||
20 | drive = d; sf = fs; s = 0; |
||
21 | TRKCACHE::cyl = cyl; TRKCACHE::side = side; |
||
22 | if (cyl >= MAX_CYLS || side >= d->sides || !d->rawdata) |
||
23 | { |
||
24 | trkd = nullptr; |
||
25 | return; |
||
26 | } |
||
27 | |||
28 | assert(cyl < MAX_CYLS); |
||
29 | |||
30 | if(cyl >= d->cyls) // ������ ���������� ������� ����� ��� �������������� �������������� ������� �� MAX_CYLS |
||
31 | { |
||
32 | if(fs != JUST_SEEK) |
||
33 | { |
||
34 | trkd = nullptr; |
||
35 | return; |
||
36 | } |
||
37 | |||
38 | d->cyls = cyl + 1; |
||
39 | } |
||
40 | |||
41 | trkd = d->trkd[cyl][side]; |
||
42 | trki = d->trki[cyl][side]; |
||
43 | trkwp = d->trkwp[cyl][side]; |
||
44 | trklen = d->trklen[cyl][side]; |
||
45 | if (!trklen) |
||
46 | { |
||
47 | trkd = nullptr; |
||
48 | return; |
||
49 | } |
||
50 | |||
51 | ts_byte = Z80FQ / (trklen * FDD_RPS); |
||
52 | if (fs == JUST_SEEK) |
||
53 | return; // else find sectors |
||
54 | |||
55 | auto SecSizeMask{ CalcSecSizeMask() }; |
||
56 | |||
57 | for (unsigned i = 0; i < trklen - 8; i++) |
||
58 | { |
||
59 | if (trkd[i] != 0xA1 || trkd[i+1] != 0xFE || !test_i(i)) // ����� idam |
||
60 | continue; |
||
61 | |||
62 | if (s == MAX_SEC) |
||
63 | errexit("too many sectors"); |
||
64 | |||
65 | SECHDR *h = &hdr[s++]; // ���������� ��������� |
||
66 | h->id = trkd + i + 2; // ��������� �� ��������� ������� |
||
67 | h->c = h->id[0]; |
||
68 | h->s = h->id[1]; |
||
69 | h->n = h->id[2]; |
||
70 | h->l = h->id[3]; |
||
71 | h->crc = *(unsigned short*)(trkd+i+6); |
||
72 | h->c1 = (wd93_crc(trkd+i+1, 5) == h->crc); |
||
73 | h->data = nullptr; |
||
74 | h->datlen = 0; |
||
75 | h->wp_start = 0; |
||
76 | h->Flags = 0; |
||
77 | // if (h->l > 5) continue; [vv] |
||
78 | |||
79 | unsigned end = min(trklen - 8, i + 8 + 43); // 43-DD, 30-SD |
||
80 | |||
81 | // ������������ ��������� �� ���� ������ ������� |
||
82 | for (unsigned j = i + 8; j < end; j++) |
||
83 | { |
||
84 | if (trkd[j] != 0xA1 || !test_i(j) || test_i(j+1)) |
||
85 | continue; |
||
86 | |||
87 | if (trkd[j+1] == 0xF8 || trkd[j+1] == 0xFB) // ������ data am (0xFB), deleted data am (0xF8) |
||
88 | { |
||
89 | if(trkd[j + 1] == 0xF8) // ddam |
||
90 | { |
||
91 | h->Flags |= SECHDR::FL_DDAM; |
||
92 | } |
||
93 | h->datlen = min(128U << (h->l & SecSizeMask), MAX_SEC_DATA_LEN); // [vv] FD1793 use only 2 lsb of sector size code |
||
94 | h->data = trkd + j + 2; |
||
95 | // ��� ������� �������� 8192 ����� (�� ��������� �� �������) |
||
96 | // �� �������� crc ���� �� �������, ������� ����������� �� ������� ����������� ������� |
||
97 | if((h->l & SecSizeMask) < 6 && wd93_crc(h->data - 1, h->datlen + 1) != *(unsigned short*)(h->data + h->datlen)) |
||
98 | { |
||
99 | h->c2 = 0; |
||
100 | } |
||
101 | else |
||
102 | { |
||
103 | h->c2 = 1; |
||
104 | } |
||
105 | |||
106 | if(trkwp) |
||
107 | { |
||
108 | for(unsigned b = 0; b < h->datlen; b++) |
||
109 | { |
||
110 | if(test_wp(j + 2 + b)) |
||
111 | { |
||
112 | h->wp_start = j + 2; // ���� ������ ���� ������� ���� |
||
113 | break; |
||
114 | } |
||
115 | } |
||
116 | } |
||
117 | } |
||
118 | break; |
||
119 | } |
||
120 | } |
||
121 | } |
||
122 | |||
123 | void TRKCACHE::format() |
||
124 | { |
||
125 | if(!trkd) // ���� ��� ������ (�������������� �� �����) |
||
126 | { |
||
127 | return; |
||
128 | } |
||
129 | |||
130 | auto SecSizeMask{ CalcSecSizeMask() }; |
||
131 | |||
132 | memset(trkd, 0, trklen); |
||
133 | memset(trki, 0, unsigned(trklen + 7U) >> 3); |
||
134 | memset(trkwp, 0, unsigned(trklen + 7U) >> 3); |
||
135 | |||
136 | unsigned char *dst = trkd; |
||
137 | |||
138 | unsigned i; |
||
139 | |||
140 | //6250-6144=106 |
||
141 | //gap4a(80)+sync0(12)+iam(3)+1+s*(gap1(50)+sync1(12)+idam(3)+1+4+2+gap2(22)+sync2(12)+data_am(3)+1+2) |
||
142 | unsigned gap4a = 80; |
||
143 | unsigned sync0 = 12; |
||
144 | unsigned i_am = 3; |
||
145 | unsigned gap1 = 40; |
||
146 | unsigned sync1 = 12; |
||
147 | unsigned id_am = 3; |
||
148 | unsigned gap2 = 22; |
||
149 | unsigned sync2 = 12; |
||
150 | unsigned data_am = 3; |
||
151 | |||
152 | unsigned data_sz = 0; |
||
153 | for (unsigned is = 0; is < s; is++) |
||
154 | { |
||
155 | SECHDR *sechdr = hdr + is; |
||
156 | data_sz += sechdr->datlen != 0 ? sechdr->datlen : min(128U << (sechdr->l & SecSizeMask), MAX_SEC_DATA_LEN); // n |
||
157 | } |
||
158 | |||
159 | if((gap4a+sync0+i_am+1+data_sz+s*(gap1+sync1+id_am+1+4+2+gap2+sync2+data_am+1+2)) >= MAX_TRACK_LEN) |
||
160 | { // ���������� ����������� ����� �������, ��������� ��������� �� ����������� |
||
161 | gap4a = 1; |
||
162 | sync0 = 1; |
||
163 | i_am = 1; |
||
164 | gap1 = 1; |
||
165 | sync1 = 1; |
||
166 | id_am = 1; |
||
167 | gap2 = 1; |
||
168 | sync2 = 1; |
||
169 | data_am = 1; |
||
170 | } |
||
171 | |||
172 | memset(dst, 0x4E, gap4a); dst += gap4a; // gap4a |
||
173 | memset(dst, 0, sync0); dst += sync0; //sync |
||
174 | |||
175 | for (i = 0; i < i_am; i++) // iam |
||
176 | write(unsigned(dst++ - trkd), 0xC2, 1); |
||
177 | *dst++ = 0xFC; |
||
178 | |||
179 | for (unsigned is = 0; is < s; is++) |
||
180 | { |
||
181 | memset(dst, 0x4E, gap1); dst += gap1; // gap1 // 50 [vv] // fixme: recalculate gap1 only for non standard formats |
||
182 | memset(dst, 0, sync1); dst += sync1; //sync |
||
183 | for (i = 0; i < id_am; i++) // idam |
||
184 | write(unsigned(dst++ - trkd), 0xA1, 1); |
||
185 | *dst++ = 0xFE; |
||
186 | |||
187 | SECHDR *sechdr = hdr + is; |
||
188 | *dst++ = sechdr->c; // c |
||
189 | *dst++ = sechdr->s; // h |
||
190 | *dst++ = sechdr->n; // s |
||
191 | *dst++ = sechdr->l; // n |
||
192 | |||
193 | unsigned crc = wd93_crc(dst-5, 5); // crc |
||
194 | if (sechdr->c1 == 1) |
||
195 | crc = sechdr->crc; |
||
196 | if (sechdr->c1 == 2) |
||
197 | crc ^= 0xFFFF; |
||
198 | *(unsigned*)dst = crc; |
||
199 | dst += 2; |
||
200 | |||
201 | if (sechdr->data) |
||
202 | { |
||
203 | memset(dst, 0x4E, gap2); dst += gap2; // gap2 |
||
204 | memset(dst, 0, sync2); dst += sync2; //sync |
||
205 | for (i = 0; i < data_am; i++) // data am |
||
206 | write(unsigned(dst++ - trkd), 0xA1, 1); |
||
207 | *dst++ = (sechdr->Flags & SECHDR::FL_DDAM) ? 0xF8 : 0xFB; |
||
208 | |||
209 | // if (sechdr->l > 5) errexit("strange sector"); // [vv] |
||
210 | unsigned len = sechdr->datlen != 0 ? sechdr->datlen : min(128U << (sechdr->l & SecSizeMask), MAX_SEC_DATA_LEN); // data |
||
211 | if (sechdr->data != (unsigned char*)1) |
||
212 | { |
||
213 | memcpy(dst, sechdr->data, len); |
||
214 | if(sechdr->wp) // ����������� ������� ����� ������� ������ |
||
215 | { |
||
216 | unsigned wp_start = unsigned(dst - trkd); |
||
217 | sechdr->wp_start = wp_start; |
||
218 | for(unsigned b = 0; b < len; b++) |
||
219 | { |
||
220 | if(test_bit(sechdr->wp, b)) |
||
221 | { |
||
222 | set_wp(wp_start + b); |
||
223 | } |
||
224 | } |
||
225 | } |
||
226 | } |
||
227 | else |
||
228 | memset(dst, 0, len); |
||
229 | |||
230 | crc = wd93_crc(dst-1, len+1); // crc |
||
231 | if (sechdr->c2 == 1) |
||
232 | crc = sechdr->crcd; |
||
233 | if (sechdr->c2 == 2) |
||
234 | crc ^= 0xFFFF; |
||
235 | *(unsigned*)(dst+len) = crc; |
||
236 | dst += len+2; |
||
237 | } |
||
238 | } |
||
239 | if (dst > trklen + trkd) |
||
240 | { |
||
241 | printf("cyl=%u, h=%u, additional len=%u\n", cyl, side, unsigned(dst - (trklen + trkd))); |
||
242 | errexit("track too long"); |
||
243 | } |
||
244 | while (dst < trkd + trklen) |
||
245 | *dst++ = 0x4E; |
||
246 | } |
||
247 | |||
248 | #if 1 |
||
249 | void TRKCACHE::dump() |
||
250 | { |
||
251 | printf("\n%u/%u:", cyl, side); |
||
252 | if (!trkd) { printf("<e>"); return; } |
||
253 | if (!sf) { printf("<n>"); return; } |
||
254 | for (unsigned i = 0; i < s; i++) |
||
255 | printf("%c%02X-%02X-%02X-%02X,%c%c%c", i?' ':'<', hdr[i].c,hdr[i].s,hdr[i].n,hdr[i].l, hdr[i].c1?'+':'-', hdr[i].c2?'+':'-', hdr[i].data?'d':'h'); |
||
256 | printf(">"); |
||
257 | } |
||
258 | #endif |
||
259 | |||
260 | unsigned TRKCACHE::write_sector(unsigned sec, unsigned l, unsigned char *data) |
||
261 | { |
||
262 | const SECHDR *h = get_sector(sec, l); |
||
263 | if (!h || !h->data) |
||
264 | return 0; |
||
265 | unsigned sz = h->datlen; |
||
266 | if(h->data != data) |
||
267 | memcpy(h->data, data, sz); |
||
268 | *(unsigned short*)(h->data+sz) = (unsigned short)wd93_crc(h->data-1, sz+1); |
||
269 | return sz; |
||
270 | } |
||
271 | |||
272 | const SECHDR *TRKCACHE::get_sector(unsigned sec, unsigned l) const |
||
273 | { |
||
274 | unsigned i; |
||
275 | for (i = 0; i < s; i++) |
||
276 | { |
||
277 | if (hdr[i].n == sec) |
||
278 | break; |
||
279 | } |
||
280 | if (i == s) |
||
281 | return nullptr; |
||
282 | |||
283 | // dump(); |
||
284 | |||
285 | auto SecSizeMask{ CalcSecSizeMask() }; |
||
286 | |||
287 | // hdr[i].c != cyl - �� �������� batman the movie, op. thunderbold � �������� |
||
288 | // �������� ���� ���������� ���� �� ���������� ��������, ���� ����� �������� ������ �� ������ �� ����� ������� |
||
289 | // �.�. ������ ������ ����� ������� � ��� ��� ������� |
||
290 | if ((hdr[i].l & SecSizeMask) != (l & SecSizeMask) /*|| hdr[i].c != cyl*/) |
||
291 | return nullptr; |
||
292 | |||
293 | return &hdr[i]; |
||
294 | } |
||
295 |