Subversion Repositories pentevo

Rev

Rev 798 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  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.             t.hdr[sn].datlen = 0;
  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);
  94.     const SECHDR *Sec9Hdr = t.get_sector(9, 1);
  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
  101.     Sec9->FreeSecCnt = u16(FreeSecCnt);    // free sec
  102.     Sec9->TrDosSig = TRD_SIG;         // trdos flag
  103.     memset(Sec9->Label, ' ', 8);      // label
  104.     memset(Sec9->Res2, ' ', 9);       // reserved
  105.     t.write_sector(9, 1, Sec9Hdr->data); // update sector CRC
  106. }
  107.  
  108. int FDD::addfile(unsigned char *hdr, unsigned char *data)
  109. {
  110.     t.seek(this, 0, 0, LOAD_SECTORS);
  111.     const SECHDR *Sec9Hdr = t.get_sector(9, 1);
  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);
  124.     const SECHDR *dir = t.get_sector(1 + pos / 0x100, 1);
  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;
  136.     t.write_sector(1 + pos / 0x100, 1, dir->data);
  137.  
  138.     pos = Sec9->FirstFreeSec + 16*Sec9->FirstFreeTrk;
  139.     Sec9->FirstFreeSec = (pos+len) & 0x0F;
  140.     Sec9->FirstFreeTrk = u8((pos+len) >> 4);
  141.     Sec9->FileCnt++;
  142.     Sec9->FreeSecCnt -= len;
  143.     t.write_sector(9, 1, Sec9Hdr->data);
  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;
  151.        if (!t.write_sector((pos & 0x0F) + 1, 1, data + i * 0x100))
  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 ЇюЁьрЄ
  174.    const SECHDR *Hdr = t.get_sector(9, 1);
  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.    {
  200.       const SECHDR *sc = t.get_sector(1 + s, 1);
  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);
  266.       t.write_sector(((i>>8) & 0x0F)+1, 1, snbuf+i);
  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);
  278.       const SECHDR *hdr = t.get_sector((i & 0x0F)+1, 1);
  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. }
  287.