Subversion Repositories pentevo

Rev

Blame | 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. #include "wd93crc.h"
  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.  
  106.    const TFdiAddInfo *FdiAddInfo = nullptr;
  107.    const TFdiTrkAddInfo *FdiTrkAddInfo = nullptr;
  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;
  133.          u8 *wp0 = nullptr;
  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;
  151.             t.hdr[sec].wp = nullptr;
  152.             t.hdr[sec].datlen = 0;
  153.  
  154.             if (FdiTrkHdr->Sec[sec].fl & TFdiSecHdr::FL_NO_DATA)
  155.             {
  156.                 t.hdr[sec].data = nullptr;
  157.             }
  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.                {
  169.                    t.hdr[sec].wp = ((FdiTrkAddInfo->Sec[sec].Flags & 1) ? (wp0 + FdiTrkAddInfo->Sec[sec].DataOffset) : nullptr);
  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;
  248.    unsigned tlen = unsigned(strlen(dsc)+1);
  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;
  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);
  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;
  286.          FdiTrkHdr.Spt = u8(t.s);
  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.  
  315.            FdiSecHdr.DataOffset = u16(secoffs);
  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;
  388.                        FdiSecAddInfo.DataOffset = u16(secoffs);
  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. }
  431.