Subversion Repositories pentevo

Rev

Rev 885 | Details | Compare with Previous | 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
 
6
#include "util.h"
885 lvd 7
#include "wd93crc.h"
716 lvd 8
 
9
#pragma pack(push, 1)
10
struct TFdiSecHdr
11
{
12
    enum
13
    {
14
        FL_DELETED_DATA = 0x80,
15
        FL_NO_DATA = 0x40,
16
        FL_GOOD_CRC_4096 = 0x20,
17
        FL_GOOD_CRC_2048 = 0x10,
18
        FL_GOOD_CRC_1024 = 0x8,
19
        FL_GOOD_CRC_512 = 0x4,
20
        FL_GOOD_CRC_256 = 0x2,
21
        FL_GOOD_CRC_128 = 0x1
22
    };
23
 
24
    u8 c;
25
    u8 h;
26
    u8 r;
27
    u8 n;
28
    // flags:
29
    // bit 7 - 1 = deleted data (F8) / 0 = normal data (FB)
30
    // bit 6 - 1 - sector with no data
31
    // bits 0..5 - 1 = good crc for sector size (128, 256, 512, 1024, 2048, 4096)
32
    u8 fl;
33
    u16 DataOffset;
34
};
35
 
36
struct TFdiTrkHdr
37
{
38
    u32 TrkOffset;
39
    u16 Res1;
40
    u8  Spt;
41
    TFdiSecHdr Sec[];
42
};
43
 
44
struct TFdiHdr
45
{
46
    char Sig[3];
47
    u8 Rw;
48
    u16 c;
49
    u16 h;
50
    u16 TextOffset;
51
    u16 DataOffset;
52
    u16 AddLen;
53
    u8 AddData[]; // AddLen -> TFdiAddInfo
54
//   TFdiTrkHdr Trk[c*h];
55
};
56
 
57
struct TFdiAddInfo
58
{
59
    enum { BAD_BYTES = 1 };
60
    enum { FDI_2 = 2 };
61
    u16 Ver; // 2 - FDI 2
62
    u16 AddInfoType; // 1 - bad bytes info
63
    u32 TrkAddInfoOffset; // -> TFdiTrkAddInfo
64
    u32 DataOffset;
65
};
66
 
67
struct TFdiSecAddInfo
68
{
69
    u8 Flags; // 1 - Массив сбойных байтов присутствует
70
    // Смещение битового массива сбойных байтов внутри трэка
71
    // Число битов определяется размером сектора
72
    // Один бит соответствует одному сбойному байту
73
    u16 DataOffset;
74
};
75
 
76
struct TFdiTrkAddInfo
77
{
78
    u32 TrkOffset; // Смещение массива сбойных байтов для трэка относительно TFdiAddInfo->DataOffset,
79
                   // 0xFFFFFFFF - Массив описателей параметров секторов отсутствует
80
    TFdiSecAddInfo Sec[]; // Spt
81
};
82
#pragma pack(pop)
83
 
84
 
85
int FDD::read_fdi()
86
{
87
   const TFdiHdr *FdiHdr = (const TFdiHdr *)snbuf;
88
   unsigned cyls = FdiHdr->c;
89
   unsigned sides = FdiHdr->h;
90
   unsigned AddLen = FdiHdr->AddLen;
91
 
92
   if(cyls > MAX_CYLS)
93
   {
94
       err_printf("cylinders (%u) > MAX_CYLS(%d)", cyls, MAX_CYLS);
95
       return 0;
96
   }
97
 
98
   if(sides > 2)
99
   {
100
       err_printf("sides (%u) > 2", sides);
101
       return 0;
102
   }
103
 
104
   newdisk(cyls, sides);
105
 
784 DimkaM 106
   const TFdiAddInfo *FdiAddInfo = nullptr;
107
   const TFdiTrkAddInfo *FdiTrkAddInfo = nullptr;
716 lvd 108
   if(AddLen >= sizeof(TFdiAddInfo))
109
   {
110
       // Проверить параметры FdiAddInfo (версию, тип и т.д.)
111
       FdiAddInfo = (const TFdiAddInfo *)FdiHdr->AddData;
112
       if(FdiAddInfo->Ver >= TFdiAddInfo::FDI_2 && FdiAddInfo->AddInfoType == TFdiAddInfo::BAD_BYTES)
113
       {
114
           FdiTrkAddInfo = (const TFdiTrkAddInfo *)(snbuf + FdiAddInfo->TrkAddInfoOffset);
115
       }
116
   }
117
 
118
   strncpy(dsc, (const char *)&snbuf[FdiHdr->TextOffset], sizeof(dsc));
119
   dsc[sizeof(dsc) - 1] = 0;
120
 
121
   int res = 1;
122
   const TFdiTrkHdr *FdiTrkHdr = (const TFdiTrkHdr *)&snbuf[sizeof(TFdiHdr) + FdiHdr->AddLen];
123
   u8 *dat = snbuf + FdiHdr->DataOffset;
124
 
125
   for (unsigned c = 0; c < cyls; c++)
126
   {
127
      for (unsigned s = 0; s < sides; s++)
128
      {
129
         t.seek(this, c,s, JUST_SEEK);
130
 
131
         u8 *t0 = dat + FdiTrkHdr->TrkOffset;
132
         unsigned ns = FdiTrkHdr->Spt;
784 DimkaM 133
         u8 *wp0 = nullptr;
716 lvd 134
         if(FdiTrkAddInfo && FdiTrkAddInfo->TrkOffset != UINT_MAX)
135
         {
136
             wp0 = snbuf + FdiAddInfo->DataOffset + FdiTrkAddInfo->TrkOffset;
137
             if(wp0 >  snbuf + snapsize)
138
             {
139
                 err_printf("bad bytes data is beyond disk image end");
140
                 return 0;
141
             }
142
         }
143
 
144
         for (unsigned sec = 0; sec < ns; sec++)
145
         {
146
            t.hdr[sec].c = FdiTrkHdr->Sec[sec].c;
147
            t.hdr[sec].s = FdiTrkHdr->Sec[sec].h;
148
            t.hdr[sec].n = FdiTrkHdr->Sec[sec].r;
149
            t.hdr[sec].l = FdiTrkHdr->Sec[sec].n;
150
            t.hdr[sec].c1 = 0;
784 DimkaM 151
            t.hdr[sec].wp = nullptr;
800 DimkaM 152
            t.hdr[sec].datlen = 0;
716 lvd 153
 
154
            if (FdiTrkHdr->Sec[sec].fl & TFdiSecHdr::FL_NO_DATA)
800 DimkaM 155
            {
784 DimkaM 156
                t.hdr[sec].data = nullptr;
800 DimkaM 157
            }
716 lvd 158
            else
159
            {
160
               if (t0 + FdiTrkHdr->Sec[sec].DataOffset > snbuf + snapsize)
161
               {
162
                   err_printf("sector data is beyond disk image end");
163
                   return 0;
164
               }
165
               t.hdr[sec].data = t0 + FdiTrkHdr->Sec[sec].DataOffset;
166
 
167
               if(FdiTrkAddInfo && FdiTrkAddInfo->TrkOffset != UINT_MAX)
168
               {
784 DimkaM 169
                   t.hdr[sec].wp = ((FdiTrkAddInfo->Sec[sec].Flags & 1) ? (wp0 + FdiTrkAddInfo->Sec[sec].DataOffset) : nullptr);
716 lvd 170
               }
171
#if 0
172
               if(FdiTrkHdr->Sec[sec].n > 3)
173
               {
174
                   u8 buf[1+1024];
175
                   buf[0] = (FdiTrkHdr->Sec[sec].fl & TFdiSecHdr::FL_DELETED_DATA) ? 0xF8 : 0xFB;
176
                   memcpy(buf+1, t.hdr[sec].data, 128U << (FdiTrkHdr->Sec[sec].n & 3));
177
 
178
                   u16 crc_calc = wd93_crc(buf, (128U << (FdiTrkHdr->Sec[sec].n & 3)) + 1);
179
                   u16 crc_from_hdr = *(u16*)(t.hdr[sec].data+(128U << (FdiTrkHdr->Sec[sec].n & 3)));
180
                   printf("phys: c=%-2u, h=%u, s=%u | hdr: c=0x%02X, h=0x%02X, r=0x%02X, n=%02X(%u) | crc1=0x%04X, crc2=0x%04X\n",
181
                       c, s, sec,
182
                       FdiTrkHdr->Sec[sec].c, FdiTrkHdr->Sec[sec].h, FdiTrkHdr->Sec[sec].r, FdiTrkHdr->Sec[sec].n, (FdiTrkHdr->Sec[sec].n & 3),
183
                       crc_calc, crc_from_hdr);
184
 
185
                   if(crc_calc == crc_from_hdr)
186
                   {
187
                       TFdiTrkHdr *FdiTrkHdrRW = const_cast<TFdiTrkHdr *>(FdiTrkHdr);
188
                       FdiTrkHdrRW->Sec[sec].fl |= (1<<(FdiTrkHdr->Sec[sec].n & 3));
189
 
190
                   }
191
               }
192
#endif
193
               t.hdr[sec].c2 = (FdiTrkHdr->Sec[sec].fl & (1<<(FdiTrkHdr->Sec[sec].n & 3))) ? 0:2; // [vv]
194
            }
195
/* [vv]
196
            if (t.hdr[sec].l>5)
197
            {
198
                t.hdr[sec].data = 0;
199
                if (!(trk[4] & 0x40))
200
                    res = 0;
201
            }
202
*/
203
         } // sec
204
         t.s = ns;
205
         t.format();
206
 
207
         if(FdiTrkAddInfo)
208
         {
209
             FdiTrkAddInfo = (const TFdiTrkAddInfo *)(((const u8 *)FdiTrkAddInfo) + sizeof(TFdiTrkAddInfo) +
210
              ((FdiTrkAddInfo->TrkOffset != UINT_MAX) ? FdiTrkHdr->Spt * sizeof(TFdiSecAddInfo) : 0));
211
         }
212
 
213
         FdiTrkHdr = (const TFdiTrkHdr *)(((const u8 *)FdiTrkHdr) + sizeof(TFdiTrkHdr) + FdiTrkHdr->Spt * sizeof(TFdiSecHdr));
214
      } // s
215
   }
216
   return res;
217
}
218
 
219
int FDD::write_fdi(FILE *ff)
220
{
221
   unsigned b, c, s, se, total_s = 0;
222
   unsigned sectors_wp = 0; // Общее число секторов для которых пишутся заголовки с дополнительной информацией
223
   unsigned total_size = 0; // Общий размер данных занимаемый секторами
224
 
225
   // Подсчет общего числа секторов на диске
226
   for (c = 0; c < cyls; c++)
227
   {
228
      for (s = 0; s < sides; s++)
229
      {
230
         t.seek(this, c, s, LOAD_SECTORS);
231
         for(se = 0; se < t.s; se++)
232
         {
233
             total_size += (t.hdr[se].data ? t.hdr[se].datlen : 0);
234
         }
235
         for(se = 0; se < t.s; se++)
236
         {
237
             if(t.hdr[se].wp_start)
238
             {
239
                 sectors_wp += t.s;
240
                 break;
241
             }
242
         }
243
         total_s += t.s;
244
      }
245
   }
246
 
247
   unsigned AddLen = sectors_wp ? sizeof(TFdiAddInfo) : 0;
784 DimkaM 248
   unsigned tlen = unsigned(strlen(dsc)+1);
716 lvd 249
   unsigned hsize = sizeof(TFdiHdr) + AddLen + cyls * sides * sizeof(TFdiTrkHdr) + total_s * sizeof(TFdiSecHdr);
250
   unsigned AddHdrsSize = cyls * sides * sizeof(TFdiTrkAddInfo) + sectors_wp * sizeof(TFdiSecAddInfo);
251
 
252
   // Формирование FDI заголовка
253
   TFdiHdr *FdiHdr = (TFdiHdr *)snbuf;
254
   memcpy(FdiHdr->Sig, "FDI", 3);
255
   FdiHdr->Rw = 0;
784 DimkaM 256
   FdiHdr->c = u16(cyls);
257
   FdiHdr->h = u16(sides);
258
   FdiHdr->TextOffset = u16(hsize);
259
   FdiHdr->DataOffset = u16(FdiHdr->TextOffset + tlen);
260
   FdiHdr->AddLen = u16(AddLen);
716 lvd 261
 
262
   TFdiAddInfo *FdiAddInfo = (TFdiAddInfo *)FdiHdr->AddData;
263
   if(AddLen)
264
   {
265
       FdiAddInfo->Ver = TFdiAddInfo::FDI_2; // FDI ver 2
266
       FdiAddInfo->AddInfoType = TFdiAddInfo::BAD_BYTES; // Информация о сбойных байтах
267
       FdiAddInfo->TrkAddInfoOffset = FdiHdr->DataOffset + total_size;
268
       FdiAddInfo->DataOffset = FdiAddInfo->TrkAddInfoOffset + AddHdrsSize;
269
   }
270
 
271
   // Запись FDI заголовка с дополнительными данными
272
   if(fwrite(FdiHdr, sizeof(TFdiHdr) + AddLen, 1, ff) != 1)
273
       return 0;
274
 
275
   unsigned trkoffs = 0;
276
   for (c = 0; c < cyls; c++)
277
   {
278
      for (s = 0; s < sides; s++)
279
      {
280
         t.seek(this, c, s, LOAD_SECTORS);
281
 
282
         // Формирование заголовка трэка
283
         TFdiTrkHdr FdiTrkHdr;
284
         FdiTrkHdr.TrkOffset = trkoffs;
285
         FdiTrkHdr.Res1 = 0;
784 DimkaM 286
         FdiTrkHdr.Spt = u8(t.s);
716 lvd 287
 
288
         // Запись заголовка трэка
289
         if(fwrite(&FdiTrkHdr, sizeof(FdiTrkHdr), 1, ff) != 1)
290
             return 0;
291
 
292
         unsigned secoffs = 0;
293
         for (se = 0; se < t.s; se++)
294
         {
295
           // Формирование заголовка сектора
296
           TFdiSecHdr FdiSecHdr;
297
           FdiSecHdr.c = t.hdr[se].c;
298
           FdiSecHdr.h = t.hdr[se].s;
299
           FdiSecHdr.r = t.hdr[se].n;
300
           FdiSecHdr.n = t.hdr[se].l;
301
           FdiSecHdr.fl = 0;
302
 
303
           if(t.hdr[se].data)
304
           {
305
               if(t.hdr[se].data[-1] == 0xF8)
306
                  FdiSecHdr.fl |= TFdiSecHdr::FL_DELETED_DATA;
307
               else
308
                  FdiSecHdr.fl |= (t.hdr[se].c2 ? (1<<(t.hdr[se].l & 3)) : 0); // [vv]
309
           }
310
           else
311
           {
312
               FdiSecHdr.fl |= TFdiSecHdr::FL_NO_DATA;
313
           }
314
 
784 DimkaM 315
           FdiSecHdr.DataOffset = u16(secoffs);
716 lvd 316
 
317
 
318
            // Запись заголовка сектора
319
            if(fwrite(&FdiSecHdr, sizeof(FdiSecHdr), 1, ff) != 1)
320
                return 0;
321
            secoffs += t.hdr[se].datlen;
322
         }
323
         trkoffs += secoffs;
324
      }
325
   }
326
 
327
   // Запись комментария
328
   fseek(ff, FdiHdr->TextOffset, SEEK_SET);
329
   if(fwrite(dsc, tlen, 1, ff) != 1)
330
       return 0;
331
 
332
   // Запись зон данных трэков
333
   for (c = 0; c < cyls; c++)
334
   {
335
      for (s = 0; s < sides; s++)
336
      {
337
         t.seek(this, c, s, LOAD_SECTORS);
338
         for (unsigned se = 0; se < t.s; se++)
339
         {
340
            if (t.hdr[se].data)
341
            {
342
               if (fwrite(t.hdr[se].data, t.hdr[se].datlen, 1, ff) != 1)
343
                   return 0;
344
            }
345
         }
346
      }
347
   }
348
 
349
   // Запись дополниетльной информации (информации о сбойных байтах)
350
   if(AddLen)
351
   {
352
       trkoffs = 0;
353
       for (c = 0; c < cyls; c++)
354
       {
355
          for (s = 0; s < sides; s++)
356
          {
357
             t.seek(this, c, s, LOAD_SECTORS);
358
 
359
             // Формирование заголовка трэка
360
             TFdiTrkAddInfo FdiTrkAddInfo;
361
             FdiTrkAddInfo.TrkOffset = UINT_MAX;
362
             for(b = 0; b < t.trklen; b++)
363
             {
364
                 if(t.test_wp(b))
365
                 {
366
                     FdiTrkAddInfo.TrkOffset = trkoffs;
367
                     break;
368
                 }
369
             }
370
 
371
             // Запись заголовка трэка
372
             if(fwrite(&FdiTrkAddInfo, sizeof(FdiTrkAddInfo), 1, ff) != 1)
373
                 return 0;
374
 
375
             unsigned secoffs = 0;
376
             if(FdiTrkAddInfo.TrkOffset != UINT_MAX)
377
             {
378
                 for (se = 0; se < t.s; se++)
379
                 {
380
                   // Формирование заголовка сектора
381
                   TFdiSecAddInfo FdiSecAddInfo;
382
                   FdiSecAddInfo.Flags = 0;
383
                   FdiSecAddInfo.DataOffset = 0;
384
 
385
                   if(t.hdr[se].wp_start)
386
                   {
387
                       FdiSecAddInfo.Flags |= 1;
784 DimkaM 388
                       FdiSecAddInfo.DataOffset = u16(secoffs);
716 lvd 389
                   }
390
 
391
                    // Запись заголовка сектора
392
                    if(fwrite(&FdiSecAddInfo, sizeof(FdiSecAddInfo), 1, ff) != 1)
393
                        return 0;
394
                    secoffs += (t.hdr[se].wp_start ? ((t.hdr[se].datlen + 7) >> 3) : 0);
395
                 }
396
             }
397
             trkoffs += secoffs;
398
          }
399
       }
400
 
401
       // Запись зон сбойных байтов
402
       for (c = 0; c < cyls; c++)
403
       {
404
          for (s = 0; s < sides; s++)
405
          {
406
             t.seek(this, c, s, LOAD_SECTORS);
407
             for (unsigned se = 0; se < t.s; se++)
408
             {
409
                if (t.hdr[se].wp_start)
410
                {
411
                   unsigned nbits = t.hdr[se].datlen;
412
 
413
                   u8 wp_bits[1024U >> 3U] = { 0 };
414
                   for(b = 0; b < nbits; b++)
415
                   {
416
                       if(t.test_wp(t.hdr[se].wp_start + b))
417
                       {
418
                           set_bit(wp_bits, b);
419
                       }
420
                   }
421
                   if (fwrite(wp_bits, (nbits + 7) >> 3, 1, ff) != 1)
422
                       return 0;
423
                }
424
             }
425
          }
426
       }
427
   }
428
 
429
   return 1;
430
}