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. #include "wd93crc.h"
  6.  
  7. #include "util.h"
  8.  
  9. static inline unsigned CalcSecSizeMask()
  10. {
  11.     // ╠рёър ъюфр ЁрчьхЁр ёхъЄюЁр (3 - фы  fd1793, 0xF - фы  uPD765)
  12.     return (conf.mem_model == MM_PLUS3) ? 0xFU : 3U;
  13. }
  14.  
  15. void TRKCACHE::seek(FDD *d, unsigned cyl, unsigned side, SEEK_MODE fs)
  16. {
  17.    if ((d == drive) && (sf == fs) && (cyl == TRKCACHE::cyl) && (side == TRKCACHE::side))
  18.        return;
  19.  
  20.    drive = d; sf = fs; s = 0;
  21.    TRKCACHE::cyl = cyl; TRKCACHE::side = side;
  22.    if (cyl >= MAX_CYLS || side >= d->sides || !d->rawdata)
  23.    {
  24.        trkd = nullptr;
  25.        return;
  26.    }
  27.  
  28.    assert(cyl < MAX_CYLS);
  29.  
  30.    if(cyl >= d->cyls) // ╤ыєўрщ єтхышўхэш  ЁрчьхЁр фшёър яЁш ЇюЁьрЄшЁютрэшш фюяюыэшЄхы№э√ї фюЁюцхъ фю MAX_CYLS
  31.    {
  32.        if(fs != JUST_SEEK)
  33.        {
  34.            trkd = nullptr;
  35.            return;
  36.        }
  37.  
  38.        d->cyls = cyl + 1;
  39.    }
  40.  
  41.    trkd = d->trkd[cyl][side];
  42.    trki = d->trki[cyl][side];
  43.    trkwp = d->trkwp[cyl][side];
  44.    trklen = d->trklen[cyl][side];
  45.    if (!trklen)
  46.    {
  47.        trkd = nullptr;
  48.        return;
  49.    }
  50.  
  51.    ts_byte = Z80FQ / (trklen * FDD_RPS);
  52.    if (fs == JUST_SEEK)
  53.        return; // else find sectors
  54.  
  55.    auto SecSizeMask{ CalcSecSizeMask() };
  56.  
  57.    for (unsigned i = 0; i < trklen - 8; i++)
  58.    {
  59.       if (trkd[i] != 0xA1 || trkd[i+1] != 0xFE || !test_i(i)) // ╧юшёъ idam
  60.           continue;
  61.  
  62.       if (s == MAX_SEC)
  63.           errexit("too many sectors");
  64.  
  65.       SECHDR *h = &hdr[s++]; // ╟ряюыэхэшх чруюыютър
  66.       h->id = trkd + i + 2; // ╙ърчрЄхы№ эр чруюыютюъ ёхъЄюЁр
  67.       h->c = h->id[0];
  68.       h->s = h->id[1];
  69.       h->n = h->id[2];
  70.       h->l = h->id[3];
  71.       h->crc = *(unsigned short*)(trkd+i+6);
  72.       h->c1 = (wd93_crc(trkd+i+1, 5) == h->crc);
  73.       h->data = nullptr;
  74.       h->datlen = 0;
  75.       h->wp_start = 0;
  76.       h->Flags = 0;
  77. //      if (h->l > 5) continue; [vv]
  78.  
  79.       unsigned end = min(trklen - 8, i + 8 + 43); // 43-DD, 30-SD
  80.  
  81.       // ╘юЁьшЁютрэшх єърчрЄхы  эр чюэє фрээ√ї ёхъЄюЁр
  82.       for (unsigned j = i + 8; j < end; j++)
  83.       {
  84.          if (trkd[j] != 0xA1 || !test_i(j) || test_i(j+1))
  85.              continue;
  86.  
  87.          if (trkd[j+1] == 0xF8 || trkd[j+1] == 0xFB) // ═рщфхэ data am (0xFB), deleted data am (0xF8)
  88.          {
  89.             if(trkd[j + 1] == 0xF8) // ddam
  90.             {
  91.                 h->Flags |= SECHDR::FL_DDAM;
  92.             }
  93.             h->datlen = min(128U << (h->l & SecSizeMask), MAX_SEC_DATA_LEN); // [vv] FD1793 use only 2 lsb of sector size code
  94.             h->data = trkd + j + 2;
  95.             // ─ы  сюы№°шї ёхъЄюЁют 8192 срщЄр (эх тыхчр■∙шї эр фюЁюцъє)
  96.             // фю яЁютхЁъш crc фхыю эх фюїюфшЄ, ъюьрэфр яЁхЁ√трхЄё  яю тЄюЁюьє яЁюїюцфхэш■ шэфхъёр
  97.             if((h->l & SecSizeMask) < 6 && wd93_crc(h->data - 1, h->datlen + 1) != *(unsigned short*)(h->data + h->datlen))
  98.             {
  99.                 h->c2 = 0;
  100.             }
  101.             else
  102.             {
  103.                 h->c2 = 1;
  104.             }
  105.  
  106.             if(trkwp)
  107.             {
  108.                 for(unsigned b = 0; b < h->datlen; b++)
  109.                 {
  110.                     if(test_wp(j + 2 + b))
  111.                     {
  112.                         h->wp_start = j + 2; // ┼ёЄ№ їюЄ с√ юфшэ ёсющэ√щ срщЄ
  113.                         break;
  114.                     }
  115.                 }
  116.             }
  117.          }
  118.          break;
  119.       }
  120.    }
  121. }
  122.  
  123. void TRKCACHE::format()
  124. {
  125.    if(!trkd) // ╥Ё¤ъ схч фрээ√ї (ЇюЁьрЄшЁютрэшх эх эєцэю)
  126.    {
  127.        return;
  128.    }
  129.  
  130.    auto SecSizeMask{ CalcSecSizeMask() };
  131.  
  132.    memset(trkd, 0, trklen);
  133.    memset(trki, 0, unsigned(trklen + 7U) >> 3);
  134.    memset(trkwp, 0, unsigned(trklen + 7U) >> 3);
  135.  
  136.    unsigned char *dst = trkd;
  137.  
  138.    unsigned i;
  139.  
  140.    //6250-6144=106
  141.    //gap4a(80)+sync0(12)+iam(3)+1+s*(gap1(50)+sync1(12)+idam(3)+1+4+2+gap2(22)+sync2(12)+data_am(3)+1+2)
  142.    unsigned gap4a = 80;
  143.    unsigned sync0 = 12;
  144.    unsigned i_am = 3;
  145.    unsigned gap1 = 40;
  146.    unsigned sync1 = 12;
  147.    unsigned id_am = 3;
  148.    unsigned gap2 = 22;
  149.    unsigned sync2 = 12;
  150.    unsigned data_am = 3;
  151.  
  152.    unsigned data_sz = 0;
  153.    for (unsigned is = 0; is < s; is++)
  154.    {
  155.       SECHDR *sechdr = hdr + is;
  156.       data_sz += sechdr->datlen != 0 ? sechdr->datlen : min(128U << (sechdr->l & SecSizeMask), MAX_SEC_DATA_LEN); // n
  157.    }
  158.  
  159.    if((gap4a+sync0+i_am+1+data_sz+s*(gap1+sync1+id_am+1+4+2+gap2+sync2+data_am+1+2)) >= MAX_TRACK_LEN)
  160.    { // ╧Ёхт√°хэшх ёЄрэфрЁЄэющ фышэ√ фюЁюцъш, ёюъЁр∙рхь ярЁрьхЄЁ√ фю ьшэшьры№э√ї
  161.        gap4a = 1;
  162.        sync0 = 1;
  163.        i_am = 1;
  164.        gap1 = 1;
  165.        sync1 = 1;
  166.        id_am = 1;
  167.        gap2 = 1;
  168.        sync2 = 1;
  169.        data_am = 1;
  170.    }
  171.  
  172.    memset(dst, 0x4E, gap4a); dst += gap4a; // gap4a
  173.    memset(dst, 0, sync0); dst += sync0; //sync
  174.  
  175.    for (i = 0; i < i_am; i++) // iam
  176.        write(unsigned(dst++ - trkd), 0xC2, 1);
  177.    *dst++ = 0xFC;
  178.  
  179.    for (unsigned is = 0; is < s; is++)
  180.    {
  181.       memset(dst, 0x4E, gap1); dst += gap1; // gap1 // 50 [vv] // fixme: recalculate gap1 only for non standard formats
  182.       memset(dst, 0, sync1); dst += sync1; //sync
  183.       for (i = 0; i < id_am; i++) // idam
  184.           write(unsigned(dst++ - trkd), 0xA1, 1);
  185.       *dst++ = 0xFE;
  186.  
  187.       SECHDR *sechdr = hdr + is;
  188.       *dst++ = sechdr->c; // c
  189.       *dst++ = sechdr->s; // h
  190.       *dst++ = sechdr->n; // s
  191.       *dst++ = sechdr->l; // n
  192.  
  193.       unsigned crc = wd93_crc(dst-5, 5); // crc
  194.       if (sechdr->c1 == 1)
  195.           crc = sechdr->crc;
  196.       if (sechdr->c1 == 2)
  197.           crc ^= 0xFFFF;
  198.       *(unsigned*)dst = crc;
  199.       dst += 2;
  200.  
  201.       if (sechdr->data)
  202.       {
  203.          memset(dst, 0x4E, gap2); dst += gap2; // gap2
  204.          memset(dst, 0, sync2); dst += sync2; //sync
  205.          for (i = 0; i < data_am; i++) // data am
  206.              write(unsigned(dst++ - trkd), 0xA1, 1);
  207.          *dst++ = (sechdr->Flags & SECHDR::FL_DDAM) ? 0xF8 : 0xFB;
  208.  
  209. //         if (sechdr->l > 5) errexit("strange sector"); // [vv]
  210.          unsigned len = sechdr->datlen != 0 ? sechdr->datlen : min(128U << (sechdr->l & SecSizeMask), MAX_SEC_DATA_LEN); // data
  211.          if (sechdr->data != (unsigned char*)1)
  212.          {
  213.              memcpy(dst, sechdr->data, len);
  214.              if(sechdr->wp) // ╩юяшЁютрэшх сшЄютющ ърЁЄ√ ёсющэ√ї срщЄют
  215.              {
  216.                  unsigned wp_start = unsigned(dst - trkd);
  217.                  sechdr->wp_start = wp_start;
  218.                  for(unsigned b = 0; b < len; b++)
  219.                  {
  220.                      if(test_bit(sechdr->wp, b))
  221.                      {
  222.                          set_wp(wp_start + b);
  223.                      }
  224.                  }
  225.              }
  226.          }
  227.          else
  228.              memset(dst, 0, len);
  229.  
  230.          crc = wd93_crc(dst-1, len+1); // crc
  231.          if (sechdr->c2 == 1)
  232.              crc = sechdr->crcd;
  233.          if (sechdr->c2 == 2)
  234.              crc ^= 0xFFFF;
  235.          *(unsigned*)(dst+len) = crc;
  236.              dst += len+2;
  237.       }
  238.    }
  239.    if (dst > trklen + trkd)
  240.    {
  241.        printf("cyl=%u, h=%u, additional len=%u\n", cyl, side, unsigned(dst - (trklen + trkd)));
  242.        errexit("track too long");
  243.    }
  244.    while (dst < trkd + trklen)
  245.        *dst++ = 0x4E;
  246. }
  247.  
  248. #if 1
  249. void TRKCACHE::dump()
  250. {
  251.    printf("\n%u/%u:", cyl, side);
  252.    if (!trkd) { printf("<e>"); return; }
  253.    if (!sf) { printf("<n>"); return; }
  254.    for (unsigned i = 0; i < s; i++)
  255.       printf("%c%02X-%02X-%02X-%02X,%c%c%c", i?' ':'<', hdr[i].c,hdr[i].s,hdr[i].n,hdr[i].l, hdr[i].c1?'+':'-', hdr[i].c2?'+':'-', hdr[i].data?'d':'h');
  256.    printf(">");
  257. }
  258. #endif
  259.  
  260. unsigned TRKCACHE::write_sector(unsigned sec, unsigned l, unsigned char *data)
  261. {
  262.    const SECHDR *h = get_sector(sec, l);
  263.    if (!h || !h->data)
  264.        return 0;
  265.    unsigned sz = h->datlen;
  266.    if(h->data != data)
  267.       memcpy(h->data, data, sz);
  268.    *(unsigned short*)(h->data+sz) = (unsigned short)wd93_crc(h->data-1, sz+1);
  269.    return sz;
  270. }
  271.  
  272. const SECHDR *TRKCACHE::get_sector(unsigned sec, unsigned l) const
  273. {
  274.    unsigned i;
  275.    for (i = 0; i < s; i++)
  276.    {
  277.       if (hdr[i].n == sec)
  278.           break;
  279.    }
  280.    if (i == s)
  281.        return nullptr;
  282.  
  283. //   dump();
  284.  
  285.    auto SecSizeMask{ CalcSecSizeMask() };
  286.  
  287.    // hdr[i].c != cyl - эх ЁрсюЄр■Є batman the movie, op. thunderbold ш яюфюсэ√х
  288.    // тючьюцэю эрфю т√ёЄрты Є№ Їыру эх ёютярфхэш  ЎшышэфЁр, ышсю эюьхЁ ЎшышэфЁр тююс∙х эх тыш хЄ эр яюшёъ ёхъЄюЁр
  289.    // Є.х. тыш хЄ Єюы№ъю эюьхЁ ёхъЄюЁр ш ъюф хую ЁрчьхЁр
  290.    if ((hdr[i].l & SecSizeMask) != (l & SecSizeMask) /*|| hdr[i].c != cyl*/)
  291.        return nullptr;
  292.  
  293.    return &hdr[i];
  294. }
  295.  
  296.