Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
716 | lvd | 1 | #include "std.h" |
2 | |||
3 | #include "emul.h" |
||
4 | #include "vars.h" |
||
5 | #include "wd93crc.h" |
||
6 | |||
7 | #include "util.h" |
||
8 | |||
9 | void TRKCACHE::seek(FDD *d, unsigned cyl, unsigned side, SEEK_MODE fs) |
||
10 | { |
||
11 | if ((d == drive) && (sf == fs) && (cyl == TRKCACHE::cyl) && (side == TRKCACHE::side)) |
||
12 | return; |
||
13 | |||
14 | drive = d; sf = fs; s = 0; |
||
15 | TRKCACHE::cyl = cyl; TRKCACHE::side = side; |
||
16 | if (cyl >= d->cyls || !d->rawdata) |
||
17 | { |
||
18 | trkd = 0; |
||
19 | return; |
||
20 | } |
||
21 | |||
22 | assert(cyl < MAX_CYLS); |
||
23 | trkd = d->trkd[cyl][side]; |
||
24 | trki = d->trki[cyl][side]; |
||
25 | trkwp = d->trkwp[cyl][side]; |
||
26 | trklen = d->trklen[cyl][side]; |
||
27 | if (!trklen) |
||
28 | { |
||
29 | trkd = 0; |
||
30 | return; |
||
31 | } |
||
32 | |||
33 | ts_byte = Z80FQ / (trklen * FDD_RPS); |
||
34 | if (fs == JUST_SEEK) |
||
35 | return; // else find sectors |
||
36 | |||
37 | for (unsigned i = 0; i < trklen - 8; i++) |
||
38 | { |
||
39 | if (trkd[i] != 0xA1 || trkd[i+1] != 0xFE || !test_i(i)) // Поиск idam |
||
40 | continue; |
||
41 | |||
42 | if (s == MAX_SEC) |
||
43 | errexit("too many sectors"); |
||
44 | |||
45 | SECHDR *h = &hdr[s++]; // Заполнение заголовка |
||
46 | h->id = trkd + i + 2; // Указатель на заголовок сектора |
||
47 | h->c = h->id[0]; |
||
48 | h->s = h->id[1]; |
||
49 | h->n = h->id[2]; |
||
50 | h->l = h->id[3]; |
||
51 | h->crc = *(unsigned short*)(trkd+i+6); |
||
52 | h->c1 = (wd93_crc(trkd+i+1, 5) == h->crc); |
||
53 | h->data = 0; |
||
54 | h->datlen = 0; |
||
55 | h->wp_start = 0; |
||
56 | // if (h->l > 5) continue; [vv] |
||
57 | |||
58 | unsigned end = min(trklen - 8, i + 8 + 43); // 43-DD, 30-SD |
||
59 | |||
60 | // Формирование указателя на зону данных сектора |
||
61 | for (unsigned j = i + 8; j < end; j++) |
||
62 | { |
||
63 | if (trkd[j] != 0xA1 || !test_i(j) || test_i(j+1)) |
||
64 | continue; |
||
65 | |||
66 | if (trkd[j+1] == 0xF8 || trkd[j+1] == 0xFB) // Найден data am |
||
67 | { |
||
68 | h->datlen = 128 << (h->l & 3); // [vv] FD1793 use only 2 lsb of sector size code |
||
69 | h->data = trkd + j + 2; |
||
70 | h->c2 = (wd93_crc(h->data-1, h->datlen+1) == *(unsigned short*)(h->data+h->datlen)); |
||
71 | |||
72 | if(trkwp) |
||
73 | { |
||
74 | for(unsigned b = 0; b < h->datlen; b++) |
||
75 | { |
||
76 | if(test_wp(j + 2 + b)) |
||
77 | { |
||
78 | h->wp_start = j + 2; // Есть хотябы один сбойный байт |
||
79 | break; |
||
80 | } |
||
81 | } |
||
82 | } |
||
83 | } |
||
84 | break; |
||
85 | } |
||
86 | } |
||
87 | } |
||
88 | |||
89 | void TRKCACHE::format() |
||
90 | { |
||
91 | memset(trkd, 0, trklen); |
||
92 | memset(trki, 0, unsigned(trklen + 7U) >> 3); |
||
93 | memset(trkwp, 0, unsigned(trklen + 7U) >> 3); |
||
94 | |||
95 | unsigned char *dst = trkd; |
||
96 | |||
97 | unsigned i; |
||
98 | |||
99 | //6250-6144=106 |
||
100 | //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) |
||
101 | unsigned gap4a = 80; |
||
102 | unsigned sync0 = 12; |
||
103 | unsigned i_am = 3; |
||
104 | unsigned gap1 = 40; |
||
105 | unsigned sync1 = 12; |
||
106 | unsigned id_am = 3; |
||
107 | unsigned gap2 = 22; |
||
108 | unsigned sync2 = 12; |
||
109 | unsigned data_am = 3; |
||
110 | |||
111 | unsigned data_sz = 0; |
||
112 | for (unsigned is = 0; is < s; is++) |
||
113 | { |
||
114 | SECHDR *sechdr = hdr + is; |
||
115 | data_sz += (128 << (sechdr->l & 3)); // n |
||
116 | } |
||
117 | |||
118 | 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) |
||
119 | { // Превышение стандартной длины дорожки, сокращаем параметры до минимальных |
||
120 | gap4a = 1; |
||
121 | sync0 = 1; |
||
122 | i_am = 1; |
||
123 | gap1 = 1; |
||
124 | sync1 = 1; |
||
125 | id_am = 1; |
||
126 | gap2 = 1; |
||
127 | sync2 = 1; |
||
128 | data_am = 1; |
||
129 | } |
||
130 | |||
131 | memset(dst, 0x4E, gap4a); dst += gap4a; // gap4a |
||
132 | memset(dst, 0, sync0); dst += sync0; //sync |
||
133 | |||
134 | for (i = 0; i < i_am; i++) // iam |
||
135 | write(dst++ - trkd, 0xC2, 1); |
||
136 | *dst++ = 0xFC; |
||
137 | |||
138 | for (unsigned is = 0; is < s; is++) |
||
139 | { |
||
140 | memset(dst, 0x4E, gap1); dst += gap1; // gap1 // 50 [vv] // fixme: recalculate gap1 only for non standard formats |
||
141 | memset(dst, 0, sync1); dst += sync1; //sync |
||
142 | for (i = 0; i < id_am; i++) // idam |
||
143 | write(dst++ - trkd, 0xA1, 1); |
||
144 | *dst++ = 0xFE; |
||
145 | |||
146 | SECHDR *sechdr = hdr + is; |
||
147 | *dst++ = sechdr->c; // c |
||
148 | *dst++ = sechdr->s; // h |
||
149 | *dst++ = sechdr->n; // s |
||
150 | *dst++ = sechdr->l; // n |
||
151 | |||
152 | unsigned crc = wd93_crc(dst-5, 5); // crc |
||
153 | if (sechdr->c1 == 1) |
||
154 | crc = sechdr->crc; |
||
155 | if (sechdr->c1 == 2) |
||
156 | crc ^= 0xFFFF; |
||
157 | *(unsigned*)dst = crc; |
||
158 | dst += 2; |
||
159 | |||
160 | if (sechdr->data) |
||
161 | { |
||
162 | memset(dst, 0x4E, gap2); dst += gap2; // gap2 |
||
163 | memset(dst, 0, sync2); dst += sync2; //sync |
||
164 | for (i = 0; i < data_am; i++) // data am |
||
165 | write(dst++ - trkd, 0xA1, 1); |
||
166 | *dst++ = 0xFB; |
||
167 | |||
168 | // if (sechdr->l > 5) errexit("strange sector"); // [vv] |
||
169 | unsigned len = 128 << (sechdr->l & 3); // data |
||
170 | if (sechdr->data != (unsigned char*)1) |
||
171 | { |
||
172 | memcpy(dst, sechdr->data, len); |
||
173 | if(sechdr->wp) // Копирование битовой карты сбойных байтов |
||
174 | { |
||
175 | unsigned wp_start = dst - trkd; |
||
176 | sechdr->wp_start = wp_start; |
||
177 | for(unsigned b = 0; b < len; b++) |
||
178 | { |
||
179 | if(test_bit(sechdr->wp, b)) |
||
180 | { |
||
181 | set_wp(wp_start + b); |
||
182 | } |
||
183 | } |
||
184 | } |
||
185 | } |
||
186 | else |
||
187 | memset(dst, 0, len); |
||
188 | |||
189 | crc = wd93_crc(dst-1, len+1); // crc |
||
190 | if (sechdr->c2 == 1) |
||
191 | crc = sechdr->crcd; |
||
192 | if (sechdr->c2 == 2) |
||
193 | crc ^= 0xFFFF; |
||
194 | *(unsigned*)(dst+len) = crc; |
||
195 | dst += len+2; |
||
196 | } |
||
197 | } |
||
198 | if (dst > trklen + trkd) |
||
199 | { |
||
200 | printf("cyl=%u, h=%u, additional len=%u\n", cyl, side, dst - (trklen + trkd)); |
||
201 | errexit("track too long"); |
||
202 | } |
||
203 | while (dst < trkd + trklen) |
||
204 | *dst++ = 0x4E; |
||
205 | } |
||
206 | |||
207 | #if 1 |
||
208 | void TRKCACHE::dump() |
||
209 | { |
||
210 | printf("\n%d/%d:", cyl, side); |
||
211 | if (!trkd) { printf("<e>"); return; } |
||
212 | if (!sf) { printf("<n>"); return; } |
||
213 | for (unsigned i = 0; i < s; i++) |
||
214 | 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'); |
||
215 | printf(">"); |
||
216 | } |
||
217 | #endif |
||
218 | |||
219 | int TRKCACHE::write_sector(unsigned sec, unsigned char *data) |
||
220 | { |
||
221 | const SECHDR *h = get_sector(sec); |
||
222 | if (!h || !h->data) |
||
223 | return 0; |
||
224 | unsigned sz = h->datlen; |
||
225 | if(h->data != data) |
||
226 | memcpy(h->data, data, sz); |
||
227 | *(unsigned short*)(h->data+sz) = (unsigned short)wd93_crc(h->data-1, sz+1); |
||
228 | return sz; |
||
229 | } |
||
230 | |||
231 | const SECHDR *TRKCACHE::get_sector(unsigned sec) const |
||
232 | { |
||
233 | unsigned i; |
||
234 | for (i = 0; i < s; i++) |
||
235 | { |
||
236 | if (hdr[i].n == sec) |
||
237 | break; |
||
238 | } |
||
239 | if (i == s) |
||
240 | return 0; |
||
241 | |||
242 | // dump(); |
||
243 | |||
244 | if (/*(hdr[i].l & 3) != 1 ||*/ hdr[i].c != cyl) // [vv] |
||
245 | return 0; |
||
246 | return &hdr[i]; |
||
247 | } |
||
248 |