Subversion Repositories pentevo

Rev

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