Subversion Repositories pentevo

Rev

Rev 798 | 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"
7
 
8
enum TDiskType
9
{
10
    DS_80 = 0x16,
11
    DS_40 = 0x17,
12
    SS_80 = 0x18,
13
    SS_40 = 0x19
14
};
15
 
16
enum { TRD_SIG = 0x10 };
17
 
18
#pragma pack(push, 1)
19
struct TTrdDirEntryBase
20
{
21
    char Name[8];
22
    u8 Type;
23
    u16 Start;
24
    u16 Length;
25
    u8 SecCnt; // ����� ����� � ��������
26
};
27
 
28
struct TTrdDirEntry : public TTrdDirEntryBase
29
{
30
    u8 Sec; // ��������� ������
31
    u8 Trk; // ��������� �������
32
};
33
 
34
struct TTrdSec9
35
{
36
    u8 Zero;         // 00
37
    u8 Reserved[224];
38
    u8 FirstFreeSec; // E1
39
    u8 FirstFreeTrk; // E2
40
    u8 DiskType;     // E3
41
    u8 FileCnt;      // E4
42
    u16 FreeSecCnt;  // E5, E6
43
    u8 TrDosSig;     // E7
44
    u8 Res1[2];      // | 0
45
    u8 Res2[9];      // | 32
46
    u8 Res3;         // | 0
47
    u8 DelFileCnt;   // F4
48
    char Label[8];   // F5-FC
49
    u8 Res4[3];      // | 0
50
};
51
 
52
struct TSclHdr
53
{
54
    u8 Sig[8];  // SINCLAIR
55
    u8 FileCnt;
56
#pragma warning(push)
57
#pragma warning(disable: 4200)
58
    TTrdDirEntryBase Files[];
59
#pragma warning(pop)
60
};
61
#pragma pack(pop)
62
 
63
void FDD::format_trd(unsigned CylCnt)
64
{
65
   static const unsigned char lv[3][16] =
66
    { { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 },
67
      { 1,9,2,10,3,11,4,12,5,13,6,14,7,15,8,16 },
68
      { 1,12,7,2,13,8,3,14,9,4,15,10,5,16,11,6 } };
69
 
70
   newdisk(CylCnt, 2);
71
 
72
   for (unsigned c = 0; c < cyls; c++) {
73
      for (unsigned side = 0; side < 2; side++) {
74
         t.seek(this, c, side, JUST_SEEK); t.s = 16;
75
         for (unsigned sn = 0; sn < 16; sn++) {
76
            unsigned s = lv[conf.trdos_interleave][sn];
796 DimkaM 77
            t.hdr[sn].n = u8(s); t.hdr[sn].l = 1;
78
            t.hdr[sn].c = u8(c); t.hdr[sn].s = 0;
716 lvd 79
            t.hdr[sn].c1 = t.hdr[sn].c2 = 0;
80
            t.hdr[sn].data = (unsigned char*)1;
800 DimkaM 81
            t.hdr[sn].datlen = 0;
716 lvd 82
         }
83
         t.format();
84
      }
85
   }
86
}
87
 
88
void FDD::emptydisk(unsigned FreeSecCnt)
89
{
90
    unsigned SecCnt = FreeSecCnt + 16;
91
    unsigned CylCnt = SecCnt / (16 * 2) + ((SecCnt % (16 * 2)) ? 1 : 0);
92
    format_trd(CylCnt);
93
    t.seek(this, 0, 0, LOAD_SECTORS);
800 DimkaM 94
    const SECHDR *Sec9Hdr = t.get_sector(9, 1);
716 lvd 95
    if(!Sec9Hdr)
96
        return;
97
 
98
    TTrdSec9 *Sec9 = (TTrdSec9 *)Sec9Hdr->data;
99
    Sec9->FirstFreeTrk = 1;           // first free track
100
    Sec9->DiskType = DS_80;           // 80T,DS
796 DimkaM 101
    Sec9->FreeSecCnt = u16(FreeSecCnt);    // free sec
716 lvd 102
    Sec9->TrDosSig = TRD_SIG;         // trdos flag
103
    memset(Sec9->Label, ' ', 8);      // label
104
    memset(Sec9->Res2, ' ', 9);       // reserved
800 DimkaM 105
    t.write_sector(9, 1, Sec9Hdr->data); // update sector CRC
716 lvd 106
}
107
 
108
int FDD::addfile(unsigned char *hdr, unsigned char *data)
109
{
110
    t.seek(this, 0, 0, LOAD_SECTORS);
800 DimkaM 111
    const SECHDR *Sec9Hdr = t.get_sector(9, 1);
716 lvd 112
    if (!Sec9Hdr)
113
        return 0;
114
 
115
    TTrdSec9 *Sec9 = (TTrdSec9 *)Sec9Hdr->data;
116
    if(!Sec9)
117
        return 0;
118
 
119
    if(Sec9->FileCnt >= 128) // ������� �������� ���������
120
        return 0;
121
 
122
    unsigned len = ((TTrdDirEntry *)hdr)->SecCnt;
123
    unsigned pos = Sec9->FileCnt * sizeof(TTrdDirEntry);
800 DimkaM 124
    const SECHDR *dir = t.get_sector(1 + pos / 0x100, 1);
716 lvd 125
 
126
    if (!dir)
127
        return 0;
128
 
129
    if (Sec9->FreeSecCnt < len)
130
        return 0; // �� ����� ��� �����
131
 
132
    TTrdDirEntry *TrdDirEntry = (TTrdDirEntry *)(dir->data + (pos & 0xFF));
133
    memcpy(TrdDirEntry, hdr, 14);
134
    TrdDirEntry->Sec = Sec9->FirstFreeSec;
135
    TrdDirEntry->Trk = Sec9->FirstFreeTrk;
800 DimkaM 136
    t.write_sector(1 + pos / 0x100, 1, dir->data);
716 lvd 137
 
138
    pos = Sec9->FirstFreeSec + 16*Sec9->FirstFreeTrk;
139
    Sec9->FirstFreeSec = (pos+len) & 0x0F;
796 DimkaM 140
    Sec9->FirstFreeTrk = u8((pos+len) >> 4);
716 lvd 141
    Sec9->FileCnt++;
142
    Sec9->FreeSecCnt -= len;
800 DimkaM 143
    t.write_sector(9, 1, Sec9Hdr->data);
716 lvd 144
 
145
    // goto next track. s8 become invalid
146
    for (unsigned i = 0; i < len; i++, pos++)
147
    {
148
       t.seek(this, pos/32, (pos/16) & 1, LOAD_SECTORS);
149
       if (!t.trkd)
150
           return 0;
800 DimkaM 151
       if (!t.write_sector((pos & 0x0F) + 1, 1, data + i * 0x100))
716 lvd 152
           return 0;
153
    }
154
    return 1;
155
}
156
 
157
static bool FillCheck(const void *buf, char fill, size_t size)
158
{
159
    const char *p = (const char *)buf;
160
    while(size--)
161
    {
162
        if(*p++ != fill)
163
            return false;
164
    }
165
    return true;
166
}
167
 
168
// destroys snbuf - use after loading all files
169
void FDD::addboot()
170
{
171
   t.seek(this, 0, 0, LOAD_SECTORS);
172
 
173
   // �������� �� �� ��� ���� ����� tr-dos ������
800 DimkaM 174
   const SECHDR *Hdr = t.get_sector(9, 1);
716 lvd 175
   if(!Hdr)
176
       return;
177
 
178
   if((Hdr->l & 3) != 1) // �������� ���� ������� ������� (1 - 256 ����)
179
       return;
180
 
181
   const TTrdSec9 *Sec9 = (const TTrdSec9 *)Hdr->data;
182
   if(!Sec9)
183
       return;
184
 
185
   if(Sec9->Zero != 0)
186
       return;
187
 
188
   if(Sec9->TrDosSig != TRD_SIG)
189
       return;
190
 
191
   if(!(FillCheck(Sec9->Res2, ' ', 9) || FillCheck(Sec9->Res2, 0, 9)))
192
       return;
193
 
194
   if(!(Sec9->DiskType == DS_80 || Sec9->DiskType == DS_40 ||
195
       Sec9->DiskType == SS_80 || Sec9->DiskType == SS_40))
196
       return;
197
 
198
   for (unsigned s = 0; s < 8; s++)
199
   {
800 DimkaM 200
      const SECHDR *sc = t.get_sector(1 + s, 1);
716 lvd 201
      if (!sc)
202
          return;
203
      TTrdDirEntry *TrdDirEntry = (TTrdDirEntry *)sc->data;
204
      for (unsigned i = 0; i < 16; i++)
205
      {
206
         if (memcmp(TrdDirEntry[i].Name, "boot    B", 9) == 0)
207
             return;
208
      }
209
   }
210
 
211
   FILE *f = fopen(conf.appendboot, "rb");
212
   if (!f)
213
       return;
214
   fread(snbuf, 1, sizeof snbuf, f);
215
   fclose(f);
216
   snbuf[13] = snbuf[14]; // copy length
217
   addfile(snbuf, snbuf+0x11);
218
}
219
 
220
int FDD::read_scl()
221
{
222
   unsigned size = 0, i;
223
   TSclHdr *SclHdr = (TSclHdr *)snbuf;
224
   for (i = 0; i < SclHdr->FileCnt; i++)
225
       size += SclHdr->Files[i].SecCnt;
226
 
227
   emptydisk(max(size, 2544U));
228
 
229
   unsigned char *data = snbuf + sizeof(TSclHdr) + SclHdr->FileCnt * sizeof(TTrdDirEntryBase);
230
   for (i = 0; i < SclHdr->FileCnt; i++)
231
   {
232
      if (!addfile((u8 *)&SclHdr->Files[i], data))
233
          return 0;
234
      data += SclHdr->Files[i].SecCnt * 0x100;
235
   }
236
 
237
   return 1;
238
}
239
 
240
int FDD::read_hob()
241
{
242
   if(!rawdata)
243
   {
244
       emptydisk(2544);
245
   }
246
   snbuf[13] = snbuf[14];
247
   int r = addfile(snbuf, snbuf+0x11);
248
   return r;
249
}
250
 
251
int FDD::read_trd()
252
{
253
   unsigned CylCnt = snapsize / (256 * 16 * 2) + ((snapsize % (256 * 16 * 2)) ? 1 : 0);
254
 
255
   if(CylCnt > MAX_CYLS)
256
   {
257
       err_printf("cylinders (%u) > MAX_CYLS(%d)", CylCnt, MAX_CYLS);
258
       return 0;
259
   }
260
 
261
   format_trd(CylCnt);
262
 
263
   for (unsigned i = 0; i < snapsize; i += 0x100)
264
   {
265
      t.seek(this, i>>13, (i>>12) & 1, LOAD_SECTORS);
800 DimkaM 266
      t.write_sector(((i>>8) & 0x0F)+1, 1, snbuf+i);
716 lvd 267
   }
268
   return 1;
269
}
270
 
271
int FDD::write_trd(FILE *ff)
272
{
273
   static unsigned char zerosec[256] = { 0 };
274
 
275
   for (unsigned i = 0; i < cyls * sides * 16; i++)
276
   {
277
      t.seek(this, i>>5, (i>>4) & 1, LOAD_SECTORS);
800 DimkaM 278
      const SECHDR *hdr = t.get_sector((i & 0x0F)+1, 1);
716 lvd 279
      unsigned char *ptr = zerosec;
280
      if (hdr && hdr->data)
281
          ptr = hdr->data;
282
      if (fwrite(ptr, 1, 256, ff) != 256)
283
          return 0;
284
   }
285
   return 1;
286
}