Subversion Repositories pentevo

Rev

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