Subversion Repositories pentevo

Rev

Rev 796 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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];
  77.             t.hdr[sn].n = u8(s); t.hdr[sn].l = 1;
  78.             t.hdr[sn].c = u8(c); t.hdr[sn].s = 0;
  79.             t.hdr[sn].c1 = t.hdr[sn].c2 = 0;
  80.             t.hdr[sn].data = (unsigned char*)1;
  81.          }
  82.          t.format();
  83.       }
  84.    }
  85. }
  86.  
  87. void FDD::emptydisk(unsigned FreeSecCnt)
  88. {
  89.     unsigned SecCnt = FreeSecCnt + 16;
  90.     unsigned CylCnt = SecCnt / (16 * 2) + ((SecCnt % (16 * 2)) ? 1 : 0);
  91.     format_trd(CylCnt);
  92.     t.seek(this, 0, 0, LOAD_SECTORS);
  93.     const SECHDR *Sec9Hdr = t.get_sector(9);
  94.     if(!Sec9Hdr)
  95.         return;
  96.  
  97.     TTrdSec9 *Sec9 = (TTrdSec9 *)Sec9Hdr->data;
  98.     Sec9->FirstFreeTrk = 1;           // first free track
  99.     Sec9->DiskType = DS_80;           // 80T,DS
  100.     Sec9->FreeSecCnt = u16(FreeSecCnt);    // free sec
  101.     Sec9->TrDosSig = TRD_SIG;         // trdos flag
  102.     memset(Sec9->Label, ' ', 8);      // label
  103.     memset(Sec9->Res2, ' ', 9);       // reserved
  104.     t.write_sector(9, Sec9Hdr->data); // update sector CRC
  105. }
  106.  
  107. int FDD::addfile(unsigned char *hdr, unsigned char *data)
  108. {
  109.     t.seek(this, 0, 0, LOAD_SECTORS);
  110.     const SECHDR *Sec9Hdr = t.get_sector(9);
  111.     if (!Sec9Hdr)
  112.         return 0;
  113.  
  114.     TTrdSec9 *Sec9 = (TTrdSec9 *)Sec9Hdr->data;
  115.     if(!Sec9)
  116.         return 0;
  117.  
  118.     if(Sec9->FileCnt >= 128) // ╩рЄрыюу чряюыэхэ яюыэюёЄ№■
  119.         return 0;
  120.  
  121.     unsigned len = ((TTrdDirEntry *)hdr)->SecCnt;
  122.     unsigned pos = Sec9->FileCnt * sizeof(TTrdDirEntry);
  123.     const SECHDR *dir = t.get_sector(1 + pos / 0x100);
  124.  
  125.     if (!dir)
  126.         return 0;
  127.  
  128.     if (Sec9->FreeSecCnt < len)
  129.         return 0; // ═р фшёъх эхЄ ьхёЄр
  130.  
  131.     TTrdDirEntry *TrdDirEntry = (TTrdDirEntry *)(dir->data + (pos & 0xFF));
  132.     memcpy(TrdDirEntry, hdr, 14);
  133.     TrdDirEntry->Sec = Sec9->FirstFreeSec;
  134.     TrdDirEntry->Trk = Sec9->FirstFreeTrk;
  135.     t.write_sector(1 + pos / 0x100, dir->data);
  136.  
  137.     pos = Sec9->FirstFreeSec + 16*Sec9->FirstFreeTrk;
  138.     Sec9->FirstFreeSec = (pos+len) & 0x0F;
  139.     Sec9->FirstFreeTrk = u8((pos+len) >> 4);
  140.     Sec9->FileCnt++;
  141.     Sec9->FreeSecCnt -= len;
  142.     t.write_sector(9, Sec9Hdr->data);
  143.  
  144.     // goto next track. s8 become invalid
  145.     for (unsigned i = 0; i < len; i++, pos++)
  146.     {
  147.        t.seek(this, pos/32, (pos/16) & 1, LOAD_SECTORS);
  148.        if (!t.trkd)
  149.            return 0;
  150.        if (!t.write_sector((pos & 0x0F) + 1, data + i * 0x100))
  151.            return 0;
  152.     }
  153.     return 1;
  154. }
  155.  
  156. static bool FillCheck(const void *buf, char fill, size_t size)
  157. {
  158.     const char *p = (const char *)buf;
  159.     while(size--)
  160.     {
  161.         if(*p++ != fill)
  162.             return false;
  163.     }
  164.     return true;
  165. }
  166.  
  167. // destroys snbuf - use after loading all files
  168. void FDD::addboot()
  169. {
  170.    t.seek(this, 0, 0, LOAD_SECTORS);
  171.  
  172.    // ╧ЁютхЁър эр Єю ўЄю фшёъ шьххЄ tr-dos ЇюЁьрЄ
  173.    const SECHDR *Hdr = t.get_sector(9);
  174.    if(!Hdr)
  175.        return;
  176.  
  177.    if((Hdr->l & 3) != 1) // ╧ЁютхЁър ъюфр ЁрчьхЁр ёхъЄюЁр (1 - 256 срщЄ)
  178.        return;
  179.  
  180.    const TTrdSec9 *Sec9 = (const TTrdSec9 *)Hdr->data;
  181.    if(!Sec9)
  182.        return;
  183.  
  184.    if(Sec9->Zero != 0)
  185.        return;
  186.  
  187.    if(Sec9->TrDosSig != TRD_SIG)
  188.        return;
  189.  
  190.    if(!(FillCheck(Sec9->Res2, ' ', 9) || FillCheck(Sec9->Res2, 0, 9)))
  191.        return;
  192.  
  193.    if(!(Sec9->DiskType == DS_80 || Sec9->DiskType == DS_40 ||
  194.        Sec9->DiskType == SS_80 || Sec9->DiskType == SS_40))
  195.        return;
  196.  
  197.    for (unsigned s = 0; s < 8; s++)
  198.    {
  199.       const SECHDR *sc = t.get_sector(1 + s);
  200.       if (!sc)
  201.           return;
  202.       TTrdDirEntry *TrdDirEntry = (TTrdDirEntry *)sc->data;
  203.       for (unsigned i = 0; i < 16; i++)
  204.       {
  205.          if (memcmp(TrdDirEntry[i].Name, "boot    B", 9) == 0)
  206.              return;
  207.       }
  208.    }
  209.  
  210.    FILE *f = fopen(conf.appendboot, "rb");
  211.    if (!f)
  212.        return;
  213.    fread(snbuf, 1, sizeof snbuf, f);
  214.    fclose(f);
  215.    snbuf[13] = snbuf[14]; // copy length
  216.    addfile(snbuf, snbuf+0x11);
  217. }
  218.  
  219. int FDD::read_scl()
  220. {
  221.    unsigned size = 0, i;
  222.    TSclHdr *SclHdr = (TSclHdr *)snbuf;
  223.    for (i = 0; i < SclHdr->FileCnt; i++)
  224.        size += SclHdr->Files[i].SecCnt;
  225.  
  226.    emptydisk(max(size, 2544U));
  227.  
  228.    unsigned char *data = snbuf + sizeof(TSclHdr) + SclHdr->FileCnt * sizeof(TTrdDirEntryBase);
  229.    for (i = 0; i < SclHdr->FileCnt; i++)
  230.    {
  231.       if (!addfile((u8 *)&SclHdr->Files[i], data))
  232.           return 0;
  233.       data += SclHdr->Files[i].SecCnt * 0x100;
  234.    }
  235.  
  236.    return 1;
  237. }
  238.  
  239. int FDD::read_hob()
  240. {
  241.    if(!rawdata)
  242.    {
  243.        emptydisk(2544);
  244.    }
  245.    snbuf[13] = snbuf[14];
  246.    int r = addfile(snbuf, snbuf+0x11);
  247.    return r;
  248. }
  249.  
  250. int FDD::read_trd()
  251. {
  252.    unsigned CylCnt = snapsize / (256 * 16 * 2) + ((snapsize % (256 * 16 * 2)) ? 1 : 0);
  253.  
  254.    if(CylCnt > MAX_CYLS)
  255.    {
  256.        err_printf("cylinders (%u) > MAX_CYLS(%d)", CylCnt, MAX_CYLS);
  257.        return 0;
  258.    }
  259.  
  260.    format_trd(CylCnt);
  261.  
  262.    for (unsigned i = 0; i < snapsize; i += 0x100)
  263.    {
  264.       t.seek(this, i>>13, (i>>12) & 1, LOAD_SECTORS);
  265.       t.write_sector(((i>>8) & 0x0F)+1, snbuf+i);
  266.    }
  267.    return 1;
  268. }
  269.  
  270. int FDD::write_trd(FILE *ff)
  271. {
  272.    static unsigned char zerosec[256] = { 0 };
  273.  
  274.    for (unsigned i = 0; i < cyls * sides * 16; i++)
  275.    {
  276.       t.seek(this, i>>5, (i>>4) & 1, LOAD_SECTORS);
  277.       const SECHDR *hdr = t.get_sector((i & 0x0F)+1);
  278.       unsigned char *ptr = zerosec;
  279.       if (hdr && hdr->data)
  280.           ptr = hdr->data;
  281.       if (fwrite(ptr, 1, 256, ff) != 256)
  282.           return 0;
  283.    }
  284.    return 1;
  285. }
  286.