Top secrets sources NedoPC pentevo

Rev

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

#include "std.h"

#include "emul.h"
#include "vars.h"
#include "wd93crc.h"

#include "util.h"

int FDD::write_td0(FILE *ff)
{
   unsigned char zerosec[256] = { 0 };
   unsigned char td0hdr[12] = { 0 };

   *(unsigned short*)td0hdr = WORD2('T','D');
   td0hdr[4] = 21; td0hdr[6] = 2; td0hdr[9] = (unsigned char)sides;
   if (*dsc) td0hdr[7] = 0x80;
   *(unsigned short*)(td0hdr + 10) = crc16(td0hdr, 10);
   fwrite(td0hdr, 1, 12, ff);
   if (*dsc) {
      unsigned char inf[0x200] = { 0 };
      strcpy((char*)inf+10, dsc);
      unsigned len = unsigned(strlen(dsc)+1);
      *(unsigned*)(inf+2) = len;
      *(unsigned short*)inf = crc16(inf+2, len+8);
      fwrite(inf, 1, len+10, ff);
   }

   unsigned c; //Alone Coder 0.36.7
   for (/*unsigned*/ c = 0; c < cyls; c++)
      for (unsigned s = 0; s < sides; s++) {
         t.seek(this,c,s,LOAD_SECTORS);
         unsigned char bf[16];
         *bf = u8(t.s);
         bf[1] = u8(c); bf[2] = u8(s);
         bf[3] = (unsigned char)crc16(bf, 3);
         fwrite(bf, 1, 4, ff);
         for (unsigned sec = 0; sec < t.s; sec++) {
             if(!t.hdr[sec].data)
             {
                 t.hdr[sec].data = zerosec;
                 t.hdr[sec].datlen = 256;
                 t.hdr[sec].l = 1;
             }
            *(unsigned*)bf = *(unsigned*)&t.hdr[sec];
            bf[4] = 0; // flags
            bf[5] = (unsigned char)crc16(t.hdr[sec].data, t.hdr[sec].datlen);
            *(unsigned short*)(bf+6) = u16(t.hdr[sec].datlen + 1);
            bf[8] = 0; // compression type = none
            fwrite(bf, 1, 9, ff);
            if (fwrite(t.hdr[sec].data, 1, t.hdr[sec].datlen, ff) != t.hdr[sec].datlen) return 0;
         }
      }
   c = WORD4(0xFF,0,0,0);
   if (fwrite(&c, 1, 4, ff) != 4) return 0;
   return 1;
}


unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf);

// No ID address field was present for this sector,
// but there is a data field. The sector information in
// the header represents fabricated information.
const ULONG TD0_SEC_NO_ID = 0x40;

// This sector's data field is missing; no sector data follows this header.
const ULONG TD0_SEC_NO_DATA = 0x20;

// A DOS sector copy was requested; this sector was not allocated.
// In this case, no sector data follows this header.
const ULONG TD0_SEC_NO_DATA2 = 0x10;

#pragma pack(push, 1)
struct TTd0Sec
{
    u8 c;
    u8 h;
    u8 s;
    u8 n;
    u8 flags;
    u8 crc;
};
#pragma pack(pop)

int FDD::read_td0()
{
   if (*(short*)snbuf == WORD2('t','d'))
   { // packed disk
      unsigned char *tmp = (unsigned char*)malloc(snapsize);
      memcpy(tmp, snbuf+12, snapsize-12);
      snapsize = 12+unpack_lzh(tmp, snapsize-12, snbuf+12);
      ::free(tmp);
      //*(short*)snbuf = WORD2('T','D');
   }

   char dscbuffer[sizeof(dsc)];
   *dscbuffer = 0;

   unsigned char *start = snbuf+12;
   if (snbuf[7] & 0x80) // coment record
   {
      start += 10;
      unsigned len = *(unsigned short*)(snbuf+14);
      start += len;
      if (len >= sizeof dsc)
          len = sizeof(dsc)-1;
      memcpy(dscbuffer, snbuf+12+10, len);
      dscbuffer[len] = 0;
   }
   unsigned char *td0_src = start;

   unsigned sides = (snbuf[9] == 1 ? 1 : 2);
   unsigned max_cyl = 0;

   for (;;)
   {
      unsigned char s = *td0_src; // Sectors
      if (s == 0xFF)
          break;
      max_cyl = max(max_cyl, unsigned(td0_src[1])); // PhysTrack
      td0_src += 4; // sizeof(track_rec)
      for (; s; s--)
      {
         unsigned char flags = td0_src[4];
         td0_src += 6; // sizeof(sec_rec)

         assert(td0_src <= snbuf + snapsize);

         if (td0_src > snbuf + snapsize)
             return 0;
         td0_src += *(unsigned short*)td0_src + 2; // data_len
      }
   }

   if(max_cyl+1 > MAX_CYLS)
   {
       err_printf("cylinders (%d) > MAX_CYLS(%d)", max_cyl, MAX_CYLS);
       return 0;
   }

   newdisk(max_cyl+1, sides);
   memcpy(dsc, dscbuffer, sizeof dsc);

   td0_src = start;
   for (;;)
   {
      unsigned char t0[16384];
      unsigned char *dst = t0;
      unsigned char *trkh = td0_src;
      td0_src += 4; // sizeof(track_rec)

      if(*trkh == 0xFF)
          break;

      t.seek(this, trkh[1], trkh[2], JUST_SEEK);

      unsigned s = 0;
      for (unsigned se = 0; se < trkh[0]; se++)
      {
         TTd0Sec *SecHdr = (TTd0Sec *)td0_src;
         unsigned sec_size = 128U << (SecHdr->n & 3); // [vv]
         unsigned char flags = SecHdr->flags;
//         printf("fl=%x\n", flags);
//         printf("c=%d, h=%d, s=%d, n=%d\n", SecHdr->c, SecHdr->h, SecHdr->s, SecHdr->n);
         if(flags & (TD0_SEC_NO_ID | TD0_SEC_NO_DATA | TD0_SEC_NO_DATA2)) // skip sectors with no data & sectors without headers
         {
             td0_src += sizeof(TTd0Sec); // sizeof(sec_rec)

             unsigned src_size = *(unsigned short*)td0_src;
//             printf("sz=%d\n", src_size);
             td0_src += 2; // data_len
             unsigned char *end_packed_data = td0_src + src_size;
/*
             u8 method = *td0_src++;
             printf("m=%d\n", method);
             switch(method)
             {
             case 0:
                 {
                     char name[MAX_PATH];
                     sprintf(name, "%02d-%d-%03d-%d.trk", SecHdr->c, SecHdr->h, SecHdr->s, SecHdr->n);
                     FILE *f = fopen(name, "wb");
                     fwrite(td0_src, 1, src_size - 1, f);
                     fclose(f);
                     break;
                 }
             case 1:
                 {
                     unsigned n = *(unsigned short*)td0_src;
                     td0_src += 2;
                     unsigned short data = *(unsigned short*)td0_src;
                     printf("len=%d, data=%04X\n", n, data);
                     break;
                 }
             }
*/

             td0_src = end_packed_data;
             continue;
         }

          // c, h, s, n
         t.hdr[s].c = SecHdr->c;
         t.hdr[s].s = SecHdr->h;
         t.hdr[s].n = SecHdr->s;
         t.hdr[s].l = SecHdr->n;
         t.hdr[s].c1 = t.hdr[s].c2 = 0;
         t.hdr[s].data = dst;
         t.hdr[s].datlen = 0;

         td0_src += sizeof(TTd0Sec); // sizeof(sec_rec)

         unsigned src_size = *(unsigned short*)td0_src;
         td0_src += 2; // data_len
         unsigned char *end_packed_data = td0_src + src_size;

         if(src_size == 0)
         {
             printf("sector data size is zero\n");
             goto shit;
         }

         if(src_size > sec_size + 1)
         {
             printf("sector overflow: src_size=%u > (sec_size+1)=%u\n", src_size, sec_size + 1);
             goto shit;
         }

         memset(dst, 0, sec_size);

         switch (*td0_src++) // Method
         {
            case 0:  // raw sector
               memcpy(dst, td0_src, src_size-1);
               break;
            case 1:  // repeated 2-byte pattern
            {
               unsigned n = *(unsigned short*)td0_src;
               td0_src += 2;
               unsigned short data = *(unsigned short*)td0_src;
               for (unsigned i = 0; i < n; i++)
                  *(unsigned short*)(dst+2*i) = data;
               break;
            }
            case 2: // RLE block
            {
               u8 n;
               unsigned char *d0 = dst;
               do
               {
                  u8 RleData[510];
                  u8 l = 2 * (*td0_src++);
                  if(l == 0) // Zero count means a literal data block
                  {
                      n = *td0_src++;
                      if(dst + n > d0 + sec_size)
                      {
                          printf("sector overflow: pos=0x%x, l=%u, n=%u, sec_size=%u, src_size=%u\n",
                              unsigned(td0_src - 2 - snbuf), unsigned(l), unsigned(n), sec_size, src_size);
                          goto shit;
                      }
                      memcpy(dst, td0_src, n);
                      td0_src += n;
                      dst += n;
                  }
                  else // repeated fragment
                  {
                      n = *td0_src++;
                      memcpy(RleData, td0_src, l);
                      td0_src += l;
                      for ( ; n; n--)
                      {
                          if(dst + l > d0 + sec_size)
                          {
                              printf("sector overflow: pos=0x%x, dpos=0x%x, l=%u, sec_size=%u, src_size=%u\n",
                                  unsigned(td0_src - 2 - snbuf), unsigned((dst + l) - d0), unsigned(l), sec_size, src_size);
                              goto shit;
                          }
                          memcpy(dst, RleData, l);
                          dst += l;
                      }
                  }
               } while (td0_src < end_packed_data);
               dst = d0;
               break;
            }
            default: // error!
            errmsg("unknown block type");

            shit:
               errmsg("bad TD0 file");
               return 0;
         }
         dst += sec_size;
         td0_src = end_packed_data;
         s++;
      }
      t.s = s;
      t.format();
   }
   return 1;
}

// ------------------------------------------------------ LZH unpacker


static unsigned char *packed_ptr, *packed_end;

static unsigned readChar()
{
    if(packed_ptr < packed_end)
    {
        return *packed_ptr++;
    }
    else
    {
        return -1U;
    }
}

static unsigned char d_code[256] =
{
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
        0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
        0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
        0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
        0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
        0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
        0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
        0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
        0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
        0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
        0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
        0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
        0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
        0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
        0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
        0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
};

static unsigned char d_len[256] =
{
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};


const int N = 4096;     // buffer size
const int F = 60;       // lookahead buffer size
const int THRESHOLD =   2;
const int NIL = N;      // leaf of tree

static unsigned char text_buf[N + F - 1];

const int N_CHAR = (256 - THRESHOLD + F);       // kinds of characters (character code = 0..N_CHAR-1)
const int T =   (N_CHAR * 2 - 1);       // size of table
const int R = (T - 1);                  // position of root
const int MAX_FREQ = 0x8000;            // updates tree when the
                                    // root frequency comes to this value.

static unsigned short freq[T + 1];        // frequency table

static short prnt[T + N_CHAR]; // pointers to parent nodes, except for the
                        // elements [T..T + N_CHAR - 1] which are used to get
                        // the positions of leaves corresponding to the codes.
static short son[T];           // pointers to child nodes (son[], son[] + 1)


static int r;

static unsigned getbuf;
static unsigned char getlen;

static int GetBit()      /* get one bit */
{
  unsigned i;

  while (getlen <= 8)
  {
      if((i = readChar()) == -1U)
      {
          i = 0;
      }
      getbuf |= unsigned(i << (8 - getlen));
      getlen += 8;
  }
  i = getbuf;
  getbuf <<= 1;
  getlen--;
  return ((i>>15) & 1);
}

static int GetByte()     /* get one byte */
{
  unsigned i;

  while (getlen <= 8)
  {
      if((i = readChar()) == -1U)
      {
          i = 0;
      }
      getbuf |= unsigned(i << (8 - getlen));
      getlen += 8;
  }
  i = getbuf;
  getbuf <<= 8;
  getlen -= 8;
  return (i >> 8) & 0xFF;
}

static void StartHuff()
{
  int i, j;

  getbuf = 0; getlen = 0;
  for (i = 0; i < N_CHAR; i++) {
    freq[i] = 1;
    son[i] = i16(i + T);
    prnt[i + T] = i16(i);
  }
  i = 0; j = N_CHAR;
  while (j <= R) {
    freq[j] = freq[i] + freq[i + 1];
    son[j] = i16(i);
    prnt[i] = prnt[i + 1] = i16(j);
    i += 2; j++;
  }
  freq[T] = 0xffff;
  prnt[R] = 0;

  for (i = 0; i < N - F; i++) text_buf[i] = ' ';
  r = N - F;
}

/* reconstruction of tree */
static void reconst()
{
  int i, j, k;
  int f;

  /* collect leaf nodes in the first half of the table */
  /* and replace the freq by (freq + 1) / 2. */
  j = 0;
  for(i = 0; i < T; i++)
  {
    if(son[i] >= T)
    {
      freq[j] = (freq[i] + 1) / 2;
      son[j] = son[i];
      j++;
    }
  }
  /* begin constructing tree by connecting sons */
  for(i = 0, j = N_CHAR; j < T; i += 2, j++)
  {
    k = i + 1;
    f = freq[j] = freq[i] + freq[k];
    for(k = j - 1; f < freq[k]; k--);
    k++;
    size_t l = unsigned(j - k) * sizeof(*freq);
    MoveMemory(&freq[k + 1], &freq[k], l);
    freq[k] = u16(f);
    MoveMemory(&son[k + 1], &son[k], l);
    son[k] = i16(i);
  }
  /* connect prnt */
  for (i = 0; i < T; i++)
    if ((k = son[i]) >= T) prnt[k] = i16(i);
    else prnt[k] = prnt[k + 1] = i16(i);
}


/* increment frequency of given code by one, and update tree */

static void update(int c)
{
  int i, j, k, l;

  if(freq[R] == MAX_FREQ) reconst();

  c = prnt[c + T];
  do {
    k = ++freq[c];

    /* if the order is disturbed, exchange nodes */
    if (k > freq[l = c + 1])
    {
      while (k > freq[++l]);
      l--;
      freq[c] = freq[l];
      freq[l] = u16(k);

      i = son[c];
      prnt[i] = i16(l);
      if (i < T) prnt[i + 1] = i16(l);

      j = son[l];
      son[l] = i16(i);

      prnt[j] = i16(c);
      if (j < T) prnt[j + 1] = i16(c);
      son[c] = i16(j);

      c = l;
    }
  } while ((c = prnt[c]) != 0);  /* repeat up to root */
}

static int DecodeChar()
{
  int c;

  c = son[R];

  /* travel from root to leaf, */
  /* choosing the smaller child node (son[]) if the read bit is 0, */
  /* the bigger (son[]+1} if 1 */
  while(c < T) c = son[c + GetBit()];
  c -= T;
  update(c);
  return c;
}

static int DecodePosition()
{
  int i, j, c;

  /* recover upper 6 bits from table */
  i = GetByte();
  c = (int)d_code[i] << 6;
  j = d_len[i];
  /* read lower 6 bits verbatim */
  j -= 2;
  while (j--) i = (i << 1) + GetBit();
  return c | (i & 0x3f);
}

unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf)
{
  packed_ptr = src; packed_end = src+size;
  int  i, j, k, c;
  unsigned count = 0;
  StartHuff();

//  while (count < textsize)  // textsize - sizeof unpacked data
  while (packed_ptr < packed_end)
  {
    c = DecodeChar();
    if(c < 256)
    {
      *buf++ = u8(c);
      text_buf[r++] = u8(c);
      r &= (N - 1);
      count++;
    } else {
      i = (r - DecodePosition() - 1) & (N - 1);
      j = c - 255 + THRESHOLD;
      for (k = 0; k < j; k++)
      {
        c = text_buf[(i + k) & (N - 1)];
        *buf++ = u8(c);
        text_buf[r++] = u8(c);
        r &= (N - 1);
        count++;
      }
    }
  }
  return count;
}