Conversion UnLZX (LZX decompress ) in C to PB Nativ

Windows specific forum
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Hello @ll :D

I'm doing a Conversion from the UnLZX c source. From Here

https://aminet.net/package/util/arc/PPCunlzx#contents

to Purebasic. As Plain Nativ Module without having to access external resources or the unLZX Executable CMD Windows
version
. Listing files with merged works. What I don't quite understand is the crc table. How do I implement that?

Can you take a look and see if that's ok?'

Also as far as the conversion of the operands like "&&" (logical and) or "^" (Xor) is concerned. I continue with "Trail and Error continue"

regards

Here is the C Source from PPC UnLZX

Code: Select all

/* $VER: unlzx.c 1.0 (22.2.98) */
/* Created: 11.2.98 */

/* LZX Extract in (supposedly) portable C.                                */

/* Compile with:                                                          */
/* gcc unlzx.c -ounlzx -O2                                                */

/* Thanks to Dan Fraser for decoding the coredumps and helping me track   */
/* down some HIDEOUSLY ANNOYING bugs.                                     */

/* Everything is accessed as unsigned char's to try and avoid problems    */
/* with byte order and alignment. Most of the decrunch functions          */
/* encourage overruns in the buffers to make things as fast as possible.  */
/* All the time is taken up in crc_calc() and decrunch() so they are      */
/* pretty damn optimized. Don't try to understand this program.           */

/* ---------------------------------------------------------------------- */

#include <stdlib.h>
#include <stdio.h>

/* ---------------------------------------------------------------------- */

static const unsigned char VERSION[]="$VER: unlzx 1.0 (22.2.98)";

/* ---------------------------------------------------------------------- */

int mode;

unsigned char info_header[10];
unsigned char archive_header[31];
unsigned char header_filename[256];
unsigned char header_comment[256];

unsigned int pack_size;
unsigned int unpack_size;

unsigned int crc;
unsigned int year, month, day;
unsigned int hour, minute, second;
unsigned char attributes;
unsigned char pack_mode;

/* ---------------------------------------------------------------------- */

struct filename_node
{
 struct filename_node *next;
 unsigned int length;
 unsigned int crc;
 char filename[256];
};

struct filename_node *filename_list;

/* ---------------------------------------------------------------------- */

unsigned char read_buffer[16384]; /* have a reasonable sized read buffer */
unsigned char decrunch_buffer[258+65536+258]; /* allow overrun for speed */

unsigned char *source;
unsigned char *destination;
unsigned char *source_end;
unsigned char *destination_end;

unsigned int decrunch_method;
unsigned int decrunch_length;
unsigned int last_offset;
unsigned int global_control;
int global_shift;

unsigned char offset_len[8];
unsigned short offset_table[128];
unsigned char huffman20_len[20];
unsigned short huffman20_table[96];
unsigned char literal_len[768];
unsigned short literal_table[5120];

/* ---------------------------------------------------------------------- */

static const char *month_str[16]=
{
 "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug",
 "sep", "oct", "nov", "dec", "?13", "?14", "?15", "?16"
};

/* ---------------------------------------------------------------------- */

unsigned int sum;

static const unsigned int crc_table[256]=
{
 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,
 0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,
 0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,
 0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,
 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,
 0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,
 0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,
 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,
 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,
 0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,
 0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,
 0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,
 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,
 0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,
 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,
 0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,
 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,
 0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,
 0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,
 0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,
 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,
 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,
 0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,
 0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,
 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,
 0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,
 0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,
 0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,
 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,
 0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,
 0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,
 0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,
 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,
 0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,
 0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,
 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,
 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,
 0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,
 0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,
 0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,
 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,
 0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,
 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D
};

/* ---------------------------------------------------------------------- */

static const unsigned char table_one[32]=
{
 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
};

static const unsigned int table_two[32]=
{
 0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
 1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152
};

static const unsigned int table_three[16]=
{
 0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767
};

static const unsigned char table_four[34]=
{
 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
};

/* ---------------------------------------------------------------------- */

/* Possible problems with 64 bit machines here. It kept giving warnings   */
/* for people so I changed back to ~.                                     */

void crc_calc(unsigned char *memory, unsigned int length)
{
 register unsigned int temp;

 if(length)
 {
  temp = ~sum; /* was (sum ^ 4294967295) */
  do
  {
   temp = crc_table[(*memory++ ^ temp) & 255] ^ (temp >> 8);
  } while(--length);
  sum = ~temp; /* was (temp ^ 4294967295) */
 }
}

/* ---------------------------------------------------------------------- */

/* Build a fast huffman decode table from the symbol bit lengths.         */
/* There is an alternate algorithm which is faster but also more complex. */

int make_decode_table(int number_symbols, int table_size,
                      unsigned char *length, unsigned short *table)
{
 register unsigned char bit_num = 0;
 register int symbol;
 unsigned int leaf; /* could be a register */
 unsigned int table_mask, bit_mask, pos, fill, next_symbol, reverse;
 int abort = 0;

 pos = 0; /* consistantly used as the current position in the decode table */

 bit_mask = table_mask = 1 << table_size;

 bit_mask >>= 1; /* don't do the first number */
 bit_num++;

 while((!abort) && (bit_num <= table_size))
 {
  for(symbol = 0; symbol < number_symbols; symbol++)
  {
   if(length[symbol] == bit_num)
   {
    reverse = pos; /* reverse the order of the position's bits */
    leaf = 0;
    fill = table_size;
    do /* reverse the position */
    {
     leaf = (leaf << 1) + (reverse & 1);
     reverse >>= 1;
    } while(--fill);
    if((pos += bit_mask) > table_mask)
    {
     abort = 1;
     break; /* we will overrun the table! abort! */
    }
    fill = bit_mask;
    next_symbol = 1 << bit_num;
    do
    {
     table[leaf] = symbol;
     leaf += next_symbol;
    } while(--fill);
   }
  }
  bit_mask >>= 1;
  bit_num++;
 }

 if((!abort) && (pos != table_mask))
 {
  for(symbol = pos; symbol < table_mask; symbol++) /* clear the rest of the table */
  {
   reverse = symbol; /* reverse the order of the position's bits */
   leaf = 0;
   fill = table_size;
   do /* reverse the position */
   {
    leaf = (leaf << 1) + (reverse & 1);
    reverse >>= 1;
   } while(--fill);
   table[leaf] = 0;
  }
  next_symbol = table_mask >> 1;
  pos <<= 16;
  table_mask <<= 16;
  bit_mask = 32768;

  while((!abort) && (bit_num <= 16))
  {
   for(symbol = 0; symbol < number_symbols; symbol++)
   {
    if(length[symbol] == bit_num)
    {
     reverse = pos >> 16; /* reverse the order of the position's bits */
     leaf = 0;
     fill = table_size;
     do /* reverse the position */
     {
      leaf = (leaf << 1) + (reverse & 1);
      reverse >>= 1;
     } while(--fill);
     for(fill = 0; fill < bit_num - table_size; fill++)
     {
      if(table[leaf] == 0)
      {
       table[(next_symbol << 1)] = 0;
       table[(next_symbol << 1) + 1] = 0;
       table[leaf] = next_symbol++;
      }
      leaf = table[leaf] << 1;
      leaf += (pos >> (15 - fill)) & 1;
     }
     table[leaf] = symbol;
     if((pos += bit_mask) > table_mask)
     {
      abort = 1;
      break; /* we will overrun the table! abort! */
     }
    }
   }
   bit_mask >>= 1;
   bit_num++;
  }
 }
 if(pos != table_mask) abort = 1; /* the table is incomplete! */

 return(abort);
}

/* ---------------------------------------------------------------------- */

/* Read and build the decrunch tables. There better be enough data in the */
/* source buffer or it's stuffed. */

int read_literal_table()
{
 register unsigned int control;
 register int shift;
 unsigned int temp; /* could be a register */
 unsigned int symbol, pos, count, fix, max_symbol;
 int abort = 0;

 control = global_control;
 shift = global_shift;

 if(shift < 0) /* fix the control word if necessary */
 {
  shift += 16;
  control += *source++ << (8 + shift);
  control += *source++ << shift;
 }

/* read the decrunch method */

 decrunch_method = control & 7;
 control >>= 3;
 if((shift -= 3) < 0)
 {
  shift += 16;
  control += *source++ << (8 + shift);
  control += *source++ << shift;
 }

/* Read and build the offset huffman table */

 if((!abort) && (decrunch_method == 3))
 {
  for(temp = 0; temp < 8; temp++)
  {
   offset_len[temp] = control & 7;
   control >>= 3;
   if((shift -= 3) < 0)
   {
    shift += 16;
    control += *source++ << (8 + shift);
    control += *source++ << shift;
   }
  }
  abort = make_decode_table(8, 7, offset_len, offset_table);
 }

/* read decrunch length */

 if(!abort)
 {
  decrunch_length = (control & 255) << 16;
  control >>= 8;
  if((shift -= 8) < 0)
  {
   shift += 16;
   control += *source++ << (8 + shift);
   control += *source++ << shift;
  }
  decrunch_length += (control & 255) << 8;
  control >>= 8;
  if((shift -= 8) < 0)
  {
   shift += 16;
   control += *source++ << (8 + shift);
   control += *source++ << shift;
  }
  decrunch_length += (control & 255);
  control >>= 8;
  if((shift -= 8) < 0)
  {
   shift += 16;
   control += *source++ << (8 + shift);
   control += *source++ << shift;
  }
 }

/* read and build the huffman literal table */

 if((!abort) && (decrunch_method != 1))
 {
  pos = 0;
  fix = 1;
  max_symbol = 256;

  do
  {
   for(temp = 0; temp < 20; temp++)
   {
    huffman20_len[temp] = control & 15;
    control >>= 4;
    if((shift -= 4) < 0)
    {
     shift += 16;
     control += *source++ << (8 + shift);
     control += *source++ << shift;
    }
   }
   abort = make_decode_table(20, 6, huffman20_len, huffman20_table);

   if(abort) break; /* argh! table is corrupt! */

   do
   {
    if((symbol = huffman20_table[control & 63]) >= 20)
    {
     do /* symbol is longer than 6 bits */
     {
      symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
      if(!shift--)
      {
       shift += 16;
       control += *source++ << 24;
       control += *source++ << 16;
      }
      control >>= 1;
     } while(symbol >= 20);
     temp = 6;
    }
    else
    {
     temp = huffman20_len[symbol];
    }
    control >>= temp;
    if((shift -= temp) < 0)
    {
     shift += 16;
     control += *source++ << (8 + shift);
     control += *source++ << shift;
    }
    switch(symbol)
    {
     case 17:
     case 18:
     {
      if(symbol == 17)
      {
       temp = 4;
       count = 3;
      }
      else /* symbol == 18 */
      {
       temp = 6 - fix;
       count = 19;
      }
      count += (control & table_three[temp]) + fix;
      control >>= temp;
      if((shift -= temp) < 0)
      {
       shift += 16;
       control += *source++ << (8 + shift);
       control += *source++ << shift;
      }
      while((pos < max_symbol) && (count--))
       literal_len[pos++] = 0;
      break;
     }
     case 19:
     {
      count = (control & 1) + 3 + fix;
      if(!shift--)
      {
       shift += 16;
       control += *source++ << 24;
       control += *source++ << 16;
      }
      control >>= 1;
      if((symbol = huffman20_table[control & 63]) >= 20)
      {
       do /* symbol is longer than 6 bits */
       {
        symbol = huffman20_table[((control >> 6) & 1) + (symbol << 1)];
        if(!shift--)
        {
         shift += 16;
         control += *source++ << 24;
         control += *source++ << 16;
        }
        control >>= 1;
       } while(symbol >= 20);
       temp = 6;
      }
      else
      {
       temp = huffman20_len[symbol];
      }
      control >>= temp;
      if((shift -= temp) < 0)
      {
       shift += 16;
       control += *source++ << (8 + shift);
       control += *source++ << shift;
      }
      symbol = table_four[literal_len[pos] + 17 - symbol];
      while((pos < max_symbol) && (count--))
       literal_len[pos++] = symbol;
      break;
     }
     default:
     {
      symbol = table_four[literal_len[pos] + 17 - symbol];
      literal_len[pos++] = symbol;
      break;
     }
    }
   } while(pos < max_symbol);
   fix--;
   max_symbol += 512;
  } while(max_symbol == 768);

  if(!abort)
   abort = make_decode_table(768, 12, literal_len, literal_table);
 }

 global_control = control;
 global_shift = shift;

 return(abort);
}

/* ---------------------------------------------------------------------- */

/* Fill up the decrunch buffer. Needs lots of overrun for both destination */
/* and source buffers. Most of the time is spent in this routine so it's  */
/* pretty damn optimized. */

void decrunch()
{
 register unsigned int control;
 register int shift;
 unsigned int temp; /* could be a register */
 unsigned int symbol, count;
 unsigned char *string;

 control = global_control;
 shift = global_shift;

 do
 {
  if((symbol = literal_table[control & 4095]) >= 768)
  {
   control >>= 12;
   if((shift -= 12) < 0)
   {
    shift += 16;
    control += *source++ << (8 + shift);
    control += *source++ << shift;
   }
   do /* literal is longer than 12 bits */
   {
    symbol = literal_table[(control & 1) + (symbol << 1)];
    if(!shift--)
    {
     shift += 16;
     control += *source++ << 24;
     control += *source++ << 16;
    }
    control >>= 1;
   } while(symbol >= 768);
  }
  else
  {
   temp = literal_len[symbol];
   control >>= temp;
   if((shift -= temp) < 0)
   {
    shift += 16;
    control += *source++ << (8 + shift);
    control += *source++ << shift;
   }
  }
  if(symbol < 256)
  {
   *destination++ = symbol;
  }
  else
  {
   symbol -= 256;
   count = table_two[temp = symbol & 31];
   temp = table_one[temp];
   if((temp >= 3) && (decrunch_method == 3))
   {
    temp -= 3;
    count += ((control & table_three[temp]) << 3);
    control >>= temp;
    if((shift -= temp) < 0)
    {
     shift += 16;
     control += *source++ << (8 + shift);
     control += *source++ << shift;
    }
    count += (temp = offset_table[control & 127]);
    temp = offset_len[temp];
   }
   else
   {
    count += control & table_three[temp];
    if(!count) count = last_offset;
   }
   control >>= temp;
   if((shift -= temp) < 0)
   {
    shift += 16;
    control += *source++ << (8 + shift);
    control += *source++ << shift;
   }
   last_offset = count;

   count = table_two[temp = (symbol >> 5) & 15] + 3;
   temp = table_one[temp];
   count += (control & table_three[temp]);
   control >>= temp;
   if((shift -= temp) < 0)
   {
    shift += 16;
    control += *source++ << (8 + shift);
    control += *source++ << shift;
   }
   string = (decrunch_buffer + last_offset < destination) ?
            destination - last_offset : destination + 65536 - last_offset;
   do
   {
    *destination++ = *string++;
   } while(--count);
  }
 } while((destination < destination_end) && (source < source_end));

 global_control = control;
 global_shift = shift;
}

/* ---------------------------------------------------------------------- */

/* Opens a file for writing & creates the full path if required. */

FILE *open_output(char *filename)
{
 unsigned int temp;
 FILE *file;

 if(!(file = fopen(filename, "wb")))
 {
/* couldn't open the file. try and create directories */
  for(temp = 0; filename[temp]; temp++)
  {
   if(filename[temp] == '/')
   {
    filename[temp] = 0;
    mkdir(filename, 511); /* I don't care if it works or not */
    filename[temp] = '/';
   }
  }
  if(!(file = fopen(filename, "wb")))
  {
   perror("FOpen");
  }
 }
 return(file);
}

/* ---------------------------------------------------------------------- */

/* Trying to understand this function is hazardous. */

int extract_normal(FILE *in_file)
{
 struct filename_node *node;
 FILE *out_file = 0;
 unsigned char *pos;
 unsigned char *temp;
 unsigned int count;
 int abort = 0;

 global_control = 0; /* initial control word */
 global_shift = -16;
 last_offset = 1;
 unpack_size = 0;
 decrunch_length = 0;

 for(count = 0; count < 8; count++)
  offset_len[count] = 0;
 for(count = 0; count < 768; count ++)
  literal_len[count] = 0;

 source_end = (source = read_buffer + 16384) - 1024;
 pos = destination_end = destination = decrunch_buffer + 258 + 65536;

 for(node = filename_list; (!abort) && node; node = node->next)
 {
  printf("Extracting \"%s\"...", node->filename);
  fflush(stdout);

  out_file = open_output(node->filename);

  sum = 0; /* reset CRC */

  unpack_size = node->length;

  while(unpack_size > 0)
  {

   if(pos == destination) /* time to fill the buffer? */
   {
/* check if we have enough data and read some if not */
    if(source >= source_end) /* have we exhausted the current read buffer? */
    {
     temp = read_buffer;
     if(count = temp - source + 16384)
     {
      do /* copy the remaining overrun to the start of the buffer */
      {
       *temp++ = *source++;
      } while(--count);
     }
     source = read_buffer;
     count = source - temp + 16384;

     if(pack_size < count) count = pack_size; /* make sure we don't read too much */

     if(fread(temp, 1, count, in_file) != count)
     {
      printf("\n");
      if(ferror(in_file))
       perror("FRead(Data)");
      else
       fprintf(stderr, "EOF: Data\n");
      abort = 1;
      break; /* fatal error */
     }
     pack_size -= count;

     temp += count;
     if(source >= temp) break; /* argh! no more data! */
    } /* if(source >= source_end) */

/* check if we need to read the tables */
    if(decrunch_length <= 0)
    {
     if(read_literal_table()) break; /* argh! can't make huffman tables! */
    }

/* unpack some data */
    if(destination >= decrunch_buffer + 258 + 65536)
    {
     if(count = destination - decrunch_buffer - 65536)
     {
      temp = (destination = decrunch_buffer) + 65536;
      do /* copy the overrun to the start of the buffer */
      {
       *destination++ = *temp++;
      } while(--count);
     }
     pos = destination;
    }
    destination_end = destination + decrunch_length;
    if(destination_end > decrunch_buffer + 258 + 65536)
     destination_end = decrunch_buffer + 258 + 65536;
    temp = destination;

    decrunch();

    decrunch_length -= (destination - temp);
   }

/* calculate amount of data we can use before we need to fill the buffer again */
   count = destination - pos;
   if(count > unpack_size) count = unpack_size; /* take only what we need */

   crc_calc(pos, count);

   if(out_file) /* Write the data to the file */
   {
    if(fwrite(pos, 1, count, out_file) != count)
    {
     perror("FWrite"); /* argh! write error */
     fclose(out_file);
     out_file = 0;
    }
   }
   unpack_size -= count;
   pos += count;
  }

  if(out_file)
  {
   fclose(out_file);
   if(!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  }
 } /* for */

 return(abort);
}

/* ---------------------------------------------------------------------- */

/* This is less complex than extract_normal. Almost decipherable. */

int extract_store(FILE *in_file)
{
 struct filename_node *node;
 FILE *out_file;
 unsigned int count;
 int abort = 0;

 for(node = filename_list; (!abort) && node; node = node->next)
 {
  printf("Storing \"%s\"...", node->filename);
  fflush(stdout);

  out_file = open_output(node->filename);

  sum = 0; /* reset CRC */

  unpack_size = node->length;
  if(unpack_size > pack_size) unpack_size = pack_size;

  while(unpack_size > 0)
  {
   count = (unpack_size > 16384) ? 16384 : unpack_size;

   if(fread(read_buffer, 1, count, in_file) != count)
   {
    printf("\n");
    if(ferror(in_file))
     perror("FRead(Data)");
    else
     fprintf(stderr, "EOF: Data\n");
    abort = 1;
    break; /* fatal error */
   }
   pack_size -= count;

   crc_calc(read_buffer, count);

   if(out_file) /* Write the data to the file */
   {
    if(fwrite(read_buffer, 1, count, out_file) != count)
    {
     perror("FWrite"); /* argh! write error */
     fclose(out_file);
     out_file = 0;
    }
   }
   unpack_size -= count;
  }

  if(out_file)
  {
   fclose(out_file);
   if(!abort) printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
  }
 } /* for */

 return(abort);
}

/* ---------------------------------------------------------------------- */

/* Easiest of the three. Just print the file(s) we didn't understand. */

int extract_unknown(FILE *in_file)
{
 struct filename_node *node;
 int abort = 0;

 for(node = filename_list; node; node = node->next)
 {
  printf("Unknown \"%s\"\n", node->filename);
 }

 return(abort);
}

/* ---------------------------------------------------------------------- */

/* Read the archive and build a linked list of names. Merged files is     */
/* always assumed. Will fail if there is no memory for a node. Sigh.      */

int extract_archive(FILE *in_file)
{
 unsigned int temp;
 struct filename_node **filename_next;
 struct filename_node *node;
 struct filename_node *temp_node;
 int actual;
 int abort;
 int result = 1; /* assume an error */

 filename_list = 0; /* clear the list */
 filename_next = &filename_list;

 do
 {
  abort = 1; /* assume an error */
  actual = fread(archive_header, 1, 31, in_file);
  if(!ferror(in_file))
  {
   if(actual) /* 0 is normal and means EOF */
   {
    if(actual == 31)
    {
     sum = 0; /* reset CRC */
     crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26]; /* header crc */
     archive_header[29] = 0; /* Must set the field to 0 before calculating the crc */
     archive_header[28] = 0;
     archive_header[27] = 0;
     archive_header[26] = 0;
     crc_calc(archive_header, 31);
     temp = archive_header[30]; /* filename length */
     actual = fread(header_filename, 1, temp, in_file);
     if(!ferror(in_file))
     {
      if(actual == temp)
      {
       header_filename[temp] = 0;
       crc_calc(header_filename, temp);
	   
       temp = archive_header[14]; /* comment length */
       actual = fread(header_comment, 1, temp, in_file);
       if(!ferror(in_file))
       {
        if(actual == temp)
        {
         header_comment[temp] = 0;
         crc_calc(header_comment, temp);
         if(sum == crc)
         {
          unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2]; /* unpack size */
          pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6]; /* packed size */
          pack_mode = archive_header[11]; /* pack mode */
          crc = (archive_header[25] << 24) + (archive_header[24] << 16) + (archive_header[23] << 8) + archive_header[22]; /* data crc */

          if(node = (struct filename_node *)malloc(sizeof(struct filename_node))) /* allocate a filename node */
          {
           *filename_next = node; /* add this node to the list */
           filename_next = &(node->next);
           node->next = 0;
           node->length = unpack_size;
           node->crc = crc;
           for(temp = 0; node->filename[temp] = header_filename[temp]; temp++);

           if(pack_size)
           {
            switch(pack_mode)
            {
             case 0: /* store */
             {
              abort = extract_store(in_file);
              break;
             }
             case 2: /* normal */
             {
              abort = extract_normal(in_file);
              break;
             }
             default: /* unknown */
             {
              abort = extract_unknown(in_file);
              break;
             }
            }
            if(abort) break; /* a read error occured */

            temp_node = filename_list; /* free the list now */
            while(node = temp_node)
            {
             temp_node = node->next;
             free(node);
            }
            filename_list = 0; /* clear the list */
            filename_next = &filename_list;

            if(fseek(in_file, pack_size, SEEK_CUR))
            {
             perror("FSeek(Data)");
             break;
            }
           }
           else
            abort = 0; /* continue */
          }
          else
           fprintf(stderr, "MAlloc(Filename_node)\n");
         }
         else
          fprintf(stderr, "CRC: Archive_Header\n");
        }
        else
         fprintf(stderr, "EOF: Header_Comment\n");
       }
       else
        perror("FRead(Header_Comment)");
      }
      else
       fprintf(stderr, "EOF: Header_Filename\n");
     }
     else
      perror("FRead(Header_Filename)");
    }
    else
     fprintf(stderr, "EOF: Archive_Header\n");
   }
   else
   {
    result = 0; /* normal termination */
   }
  }
  else
   perror("FRead(Archive_Header)");
 } while(!abort);

/* free the filename list in case an error occured */
 temp_node = filename_list;
 while(node = temp_node)
 {
  temp_node = node->next;
  free(node);
 }

 return(result);
}

/* ---------------------------------------------------------------------- */

/* List the contents of an archive in a nice formatted kinda way.         */

int view_archive(FILE *in_file)
{
 unsigned int temp;
 unsigned int total_pack = 0;
 unsigned int total_unpack = 0;
 unsigned int total_files = 0;
 unsigned int merge_size = 0;
 int actual;
 int abort;
 int result = 1; /* assume an error */

 printf("Unpacked   Packed Time     Date        Attrib   Name\n");
 printf("-------- -------- -------- ----------- -------- ----\n");

 do
 {
  abort = 1; /* assume an error */
  actual = fread(archive_header, 1, 31, in_file);
  if(!ferror(in_file))
  {
   if(actual) /* 0 is normal and means EOF */
   {
    if(actual == 31)
    {
     sum = 0; /* reset CRC */
     crc = (archive_header[29] << 24) + (archive_header[28] << 16) + (archive_header[27] << 8) + archive_header[26];
     archive_header[29] = 0; /* Must set the field to 0 before calculating the crc */
     archive_header[28] = 0;
     archive_header[27] = 0;
     archive_header[26] = 0;
     crc_calc(archive_header, 31);
     temp = archive_header[30]; /* filename length */
	 
     actual = fread(header_filename, 1, temp, in_file);
	 
     if(!ferror(in_file))
     {
		 
      if(actual == temp)
      {
       header_filename[temp] = 0;
       crc_calc(header_filename, temp);
       temp = archive_header[14]; /* comment length */
	   
       actual = fread(header_comment, 1, temp, in_file);
       if(!ferror(in_file))
       {
		   
        if(actual == temp)
        {
			
         header_comment[temp] = 0;
         crc_calc(header_comment, temp);
         if(sum == crc)
         {
			 
          attributes = archive_header[0]; /* file protection modes */
          unpack_size = (archive_header[5] << 24) + (archive_header[4] << 16) + (archive_header[3] << 8) + archive_header[2]; /* unpack size */
          pack_size = (archive_header[9] << 24) + (archive_header[8] << 16) + (archive_header[7] << 8) + archive_header[6]; /* packed size */
          temp = (archive_header[18] << 24) + (archive_header[19] << 16) + (archive_header[20] << 8) + archive_header[21]; /* date */
          year = ((temp >> 17) & 63) + 1970;
          month = (temp >> 23) & 15;
          day = (temp >> 27) & 31;
          hour = (temp >> 12) & 31;
          minute = (temp >> 6) & 63;
          second = temp & 63;

          total_pack += pack_size;
          total_unpack += unpack_size;
          total_files++;
          merge_size += unpack_size;

          printf("%8ld ", unpack_size);
          if(archive_header[12] & 1)
           printf("     n/a ");
          else
          
			printf("%8ld ", pack_size);
			printf("%02ld:%02ld:%02ld ", hour, minute, second);
			printf("%2ld-%s-%4ld ", day, month_str[month], year);
          
			printf("%c%c%c%c%c%c%c%c ",
                 (attributes & 32) ? 'h' : '-',
                 (attributes & 64) ? 's' : '-',
                 (attributes & 128) ? 'p' : '-',
                 (attributes & 16) ? 'a' : '-',
                 (attributes & 1) ? 'r' : '-',
                 (attributes & 2) ? 'w' : '-',
                 (attributes & 8) ? 'e' : '-',
                 (attributes & 4) ? 'd' : '-');
				 
			printf("\"%s\"\n", header_filename);
		  
			if(header_comment[0])
			printf(": \"%s\"\n", header_comment);
		
          if((archive_header[12] & 1) && pack_size)
          {
           printf("%8ld %8ld Merged\n", merge_size, pack_size);
          }

          if(pack_size) /* seek past the packed data */
          {
           merge_size = 0;
		   
           if(!fseek(in_file, pack_size, SEEK_CUR))
           {
            abort = 0; /* continue */
			
           }
		   
           else
            perror("FSeek()");
		
          }		  
          else
           abort = 0; /* continue */
         }
         else
          fprintf(stderr, "CRC: Archive_Header\n");
        }
        else
         fprintf(stderr, "EOF: Header_Comment\n");
       }
       else
        perror("FRead(Header_Comment)");
      }
      else
       fprintf(stderr, "EOF: Header_Filename\n");
     }
     else
      perror("FRead(Header_Filename)");
    }
    else
     fprintf(stderr, "EOF: Archive_Header\n");
   }
   else
   {
    printf("-------- -------- -------- ----------- -------- ----\n");
    printf("%8ld %8ld ", total_unpack, total_pack);
    printf("%ld file%s\n", total_files, ((total_files == 1) ? "" : "s"));

    result = 0; /* normal termination */
   }
  }
  else
   perror("FRead(Archive_Header)");
 } while(!abort);

 return(result);
}

/* ---------------------------------------------------------------------- */

/* Process a single archive. */

int process_archive(char *filename)
{
 int result = 1; /* assume an error */
 FILE *in_file;
 int actual;

 if(in_file = fopen(filename,"rb"))
 {
  actual = fread(info_header, 1, 10, in_file);
  if(!ferror(in_file))
  {
   if(actual == 10)
   {
    if((info_header[0] == 76) && (info_header[1] == 90) && (info_header[2] == 88)) /* LZX */
    {
     switch(mode)
     {
      case 1: /* extract archive */
      {
       result = extract_archive(in_file);
       break;
      }
      case 2: /* view archive */
      {
       result = view_archive(in_file);
       break;
      }
     }
    }
    else
     fprintf(stderr, "Info_Header: Bad ID\n");
   }
   else
    fprintf(stderr, "EOF: Info_Header\n");
  }
  else
   perror("FRead(Info_Header)");
  fclose(in_file);
 }
 else
  perror("FOpen(Archive)");
 return(result);
}

/* ---------------------------------------------------------------------- */

/* Handle options & multiple filenames. */

int main(int argc, char **argv)
{
 int result = 0;
 int option;
 extern int optind;

 mode = 1; /* default mode is extract */
 while ((option = getopt(argc, argv, "vx")) != EOF)
 {
  switch(option)
  {
   case 'v': /* (v)iew archive */
   {
    mode = 2;
    break;
   }
   case 'x': /* e(x)tract archive */
   {
    mode = 1;
    break;
   }
   case '?': /* unknown option */
   {
    result = 1;
    break;
   }
  }
 }
 if(optind >= argc) result = 1; /* gotta have a filename */

 if(!result)
 {
  if((argc - optind) > 1)
  {
   for(; optind < argc; optind++)
   {
    printf("\nArchive \"%s\"...\n\n", argv[optind]);
    process_archive(argv[optind]);
   }
   result = 0; /* Can't give a reliable result for multiple archives */
  }
  else
  {
   result = process_archive(argv[optind]); /* do a single archive */
  }
 }
 else
 {
  fprintf(stderr, "Usage: unlzx [-v][-x] archive(s)\n");
  fprintf(stderr, "\t-v : list archive(s)\n");
  fprintf(stderr, "\t-x : extract (default)\n");
  result = 2;
 }

 return(result);
}

/* ---------------------------------------------------------------------- */

/* Some info for the reader only. This is unused by the program and can   */
/* safely be deleted.                                                     */

#define INFO_DAMAGE_PROTECT 1
#define INFO_FLAG_LOCKED 2

/* STRUCTURE Info_Header
{
  UBYTE ID[3]; 0 - "LZX"
  UBYTE flags; 3 - INFO_FLAG_#?
  UBYTE[6]; 4
} */ /* SIZE = 10 */

#define HDR_FLAG_MERGED 1

#define HDR_PROT_READ    1
#define HDR_PROT_WRITE   2
#define HDR_PROT_DELETE  4
#define HDR_PROT_EXECUTE 8
#define HDR_PROT_ARCHIVE 16
#define HDR_PROT_HOLD    32
#define HDR_PROT_SCRIPT  64
#define HDR_PROT_PURE    128

#define HDR_TYPE_MSDOS   0
#define HDR_TYPE_WINDOWS 1
#define HDR_TYPE_OS2     2
#define HDR_TYPE_AMIGA   10
#define HDR_TYPE_UNIX    20

#define HDR_PACK_STORE    0
#define HDR_PACK_NORMAL   2
#define HDR_PACK_EOF      32

/* STRUCTURE Archive_Header
{
  UBYTE attributes; 0 - HDR_PROT_#?
  UBYTE; 1
  ULONG unpacked_length; 2 - FUCKED UP LITTLE ENDIAN SHIT
  ULONG packed_length; 6 - FUCKED UP LITTLE ENDIAN SHIT
  UBYTE machine_type; 10 - HDR_TYPE_#?
  UBYTE pack_mode; 11 - HDR_PACK_#?
  UBYTE flags; 12 - HDR_FLAG_#?
  UBYTE; 13
  UBYTE len_comment; 14 - comment length [0,79]
  UBYTE extract_ver; 15 - version needed to extract
  UBYTE; 16
  UBYTE; 17
  ULONG date; 18 - Packed_Date
  ULONG data_crc; 22 - FUCKED UP LITTLE ENDIAN SHIT
  ULONG header_crc; 26 - FUCKED UP LITTLE ENDIAN SHIT
  UBYTE filename_len; 30 - filename length
} */ /* SIZE = 31 */

#define DATE_SHIFT_YEAR   17
#define DATE_SHIFT_MONTH  23
#define DATE_SHIFT_DAY    27
#define DATE_SHIFT_HOUR   12
#define DATE_SHIFT_MINUTE 6
#define DATE_SHIFT_SECOND 0
#define DATE_MASK_YEAR    0x007E0000
#define DATE_MASK_MONTH   0x07800000
#define DATE_MASK_DAY     0xF8000000
#define DATE_MASK_HOUR    0x0001F000
#define DATE_MASK_MINUTE  0x00000FC0
#define DATE_MASK_SECOND  0x0000003F

/* STRUCTURE DATE_Unpacked
{
  UBYTE year; 80 - Year 0=1970 1=1971 63=2033
  UBYTE month; 81 - 0=january 1=february .. 11=december
  UBYTE day; 82
  UBYTE hour; 83
  UBYTE minute; 84
  UBYTE second; 85
} */ /* SIZE = 6 */

/* STRUCTURE DATE_Packed
{
  UBYTE packed[4]; bit 0 is MSB, 31 is LSB
; bit # 0-4=Day 5-8=Month 9-14=Year 15-19=Hour 20-25=Minute 26-31=Second
} */ /* SIZE = 4 */


And here is my Conversion

Code: Select all

DeclareModule PackLZX
    
    Declare.i   Process_Archive(File.s)
EndDeclareModule


Module PackLZX
    
    Structure ArchiveFormat
        dateiname.s
        dateipath.s
        size.i     
        *image
    EndStructure     
    
    Structure Info_Header
        c.c[10]
    EndStructure
    
    Structure Archive_Header
        c.c[31]
    EndStructure
    
    Structure Header_Filename
        c.c[256]
    EndStructure
    
    Structure Header_Comment
        c.c[256]
    EndStructure     
    
    Structure Longs
    l.l[256]
    EndStructure    
    
   Global sum
   Global pack_size;
   Global unpack_size;    
   Global crc;
   Global year, month, day;
   Global hour, minute, second;
   Global attributes.c;
   Global pack_mode.c;
    
    DataSection
    CRC_TABLE:
    Data.l $00000000,$77073096,$EE0E612C,$990951BA,$076DC419,$706AF48F
    Data.l $E963A535,$9E6495A3,$0EDB8832,$79DCB8A4,$E0D5E91E,$97D2D988
    Data.l $09B64C2B,$7EB17CBD,$E7B82D07,$90BF1D91,$1DB71064,$6AB020F2
    Data.l $F3B97148,$84BE41DE,$1ADAD47D,$6DDDE4EB,$F4D4B551,$83D385C7
    Data.l $136C9856,$646BA8C0,$FD62F97A,$8A65C9EC,$14015C4F,$63066CD9
    Data.l $FA0F3D63,$8D080DF5,$3B6E20C8,$4C69105E,$D56041E4,$A2677172
    Data.l $3C03E4D1,$4B04D447,$D20D85FD,$A50AB56B,$35B5A8FA,$42B2986C
    Data.l $DBBBC9D6,$ACBCF940,$32D86CE3,$45DF5C75,$DCD60DCF,$ABD13D59
    Data.l $26D930AC,$51DE003A,$C8D75180,$BFD06116,$21B4F4B5,$56B3C423
    Data.l $CFBA9599,$B8BDA50F,$2802B89E,$5F058808,$C60CD9B2,$B10BE924
    Data.l $2F6F7C87,$58684C11,$C1611DAB,$B6662D3D,$76DC4190,$01DB7106
    Data.l $98D220BC,$EFD5102A,$71B18589,$06B6B51F,$9FBFE4A5,$E8B8D433
    Data.l $7807C9A2,$0F00F934,$9609A88E,$E10E9818,$7F6A0DBB,$086D3D2D
    Data.l $91646C97,$E6635C01,$6B6B51F4,$1C6C6162,$856530D8,$F262004E
    Data.l $6C0695ED,$1B01A57B,$8208F4C1,$F50FC457,$65B0D9C6,$12B7E950
    Data.l $8BBEB8EA,$FCB9887C,$62DD1DDF,$15DA2D49,$8CD37CF3,$FBD44C65
    Data.l $4DB26158,$3AB551CE,$A3BC0074,$D4BB30E2,$4ADFA541,$3DD895D7
    Data.l $A4D1C46D,$D3D6F4FB,$4369E96A,$346ED9FC,$AD678846,$DA60B8D0
    Data.l $44042D73,$33031DE5,$AA0A4C5F,$DD0D7CC9,$5005713C,$270241AA
    Data.l $BE0B1010,$C90C2086,$5768B525,$206F85B3,$B966D409,$CE61E49F
    Data.l $5EDEF90E,$29D9C998,$B0D09822,$C7D7A8B4,$59B33D17,$2EB40D81
    Data.l $B7BD5C3B,$C0BA6CAD,$EDB88320,$9ABFB3B6,$03B6E20C,$74B1D29A
    Data.l $EAD54739,$9DD277AF,$04DB2615,$73DC1683,$E3630B12,$94643B84
    Data.l $0D6D6A3E,$7A6A5AA8,$E40ECF0B,$9309FF9D,$0A00AE27,$7D079EB1
    Data.l $F00F9344,$8708A3D2,$1E01F268,$6906C2FE,$F762575D,$806567CB
    Data.l $196C3671,$6E6B06E7,$FED41B76,$89D32BE0,$10DA7A5A,$67DD4ACC
    Data.l $F9B9DF6F,$8EBEEFF9,$17B7BE43,$60B08ED5,$D6D6A3E8,$A1D1937E
    Data.l $38D8C2C4,$4FDFF252,$D1BB67F1,$A6BC5767,$3FB506DD,$48B2364B
    Data.l $D80D2BDA,$AF0A1B4C,$36034AF6,$41047A60,$DF60EFC3,$A867DF55
    Data.l $316E8EEF,$4669BE79,$CB61B38C,$BC66831A,$256FD2A0,$5268E236
    Data.l $CC0C7795,$BB0B4703,$220216B9,$5505262F,$C5BA3BBE,$B2BD0B28
    Data.l $2BB45A92,$5CB36A04,$C2D7FFA7,$B5D0CF31,$2CD99E8B,$5BDEAE1D
    Data.l $9B64C2B0,$EC63F226,$756AA39C,$026D930A,$9C0906A9,$EB0E363F
    Data.l $72076785,$05005713,$95BF4A82,$E2B87A14,$7BB12BAE,$0CB61B38
    Data.l $92D28E9B,$E5D5BE0D,$7CDCEFB7,$0BDBDF21,$86D3D2D4,$F1D4E242
    Data.l $68DDB3F8,$1FDA836E,$81BE16CD,$F6B9265B,$6FB077E1,$18B74777
    Data.l $88085AE6,$FF0F6A70,$66063BCA,$11010B5C,$8F659EFF,$F862AE69
    Data.l $616BFFD3,$166CCF45,$A00AE278,$D70DD2EE,$4E048354,$3903B3C2
    Data.l $A7672661,$D06016F7,$4969474D,$3E6E77DB,$AED16A4A,$D9D65ADC
    Data.l $40DF0B66,$37D83BF0,$A9BCAE53,$DEBB9EC5,$47B2CF7F,$30B5FFE9
    Data.l $BDBDF21C,$CABAC28A,$53B39330,$24B4A3A6,$BAD03605,$CDD70693
    Data.l $54DE5729,$23D967BF,$B3667A2E,$C4614AB8,$5D681B02,$2A6F2B94
    Data.l $B40BBE37,$C30C8EA1,$5A05DF1B,$2D02EF8D
EndDataSection

    Procedure LogicalAnd(a,b)           ; Conversion from &&
                                        ; Ob das richtig bezweifle ich. Aber das Auflisten der Dateiene deckt sich mit 'unlzx für Windows 95'
                                        ;    
        If (a = 1 And b = 0)
            ProcedureReturn  0
         EndIf   
     EndProcedure        
    ;
    ;
    ;    
    Procedure crc_calc(*memory, length.i)
        
        ;
        ; Die CRC Summe berechnen
        Protected temp.i, *Table.Longs
        
        *Table = ?CRC_TABLE
        
        If( length > 0)
            
            ;
            ; sum : globale Var. Erstmal
            temp = ~sum; /* was (sum ^ 4294967295) */
            
            ;For i = 0 To length-1
            ;    Debug *table\l[i]
            ;Next    
            
            While 0 < length 
                ;temp = *Table\[(*memory++ ^ temp) & 255] ^ (temp >> 8);                              
                
                Debug temp
                length - 1
            Wend
            
            sum = ~temp; /* was (temp ^ 4294967295) */
        EndIf    

    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Unpack(size.i)
                
        If ( size = 0 )
            ProcedureReturn "n/a"
        EndIf    
        ProcedureReturn Str(size)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .s    Get_Packed(size.i,c.b)
                
        If (c & 1)
            ProcedureReturn "n/a"
        EndIf    
        
        ProcedureReturn Str(size)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .s    Get_Clock(hour.i,minute.i,second.i)
        
        ;
        ; TODO 
        szClock.s = RSet(Str(hour),2,Chr(48)) + ":" + RSet(Str(minute),2,Chr(48)) + ":" + RSet( Str(second),2,Chr(48))
        ProcedureReturn szClock
        
    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Date(day.i,month.i,year.i)

        szDate.s =  RSet(Str(day),2,Chr(48)) + "-" + RSet(Str(month),2,Chr(48)) + "-" + Str(year)
        ProcedureReturn szDate
        
    EndProcedure 
    ;
    ;
    ;
    Procedure .s    Get_Attrib(attrib.i)
        
        szAttrib.s ="--------"
        ;
        ;
        ; 0 = Kein Attribut gesetzt
        
        If ( (attributes & 32) > 0 )
            ;
            ; Attributes 'h'
            szAttrib = ReplaceString( szAttrib, "-", "h", 0,1,1)
        EndIf    
        
        If ( (attributes & 64) > 0 )
            ;
            ; Attributes 's'
            szAttrib = ReplaceString( szAttrib, "-", "s", 0,2,1)
        EndIf
        
        If ( (attributes & 128) > 0 )
            ;
            ; Attributes 'p'
            szAttrib = ReplaceString( szAttrib, "-", "p", 0,3,1)
        EndIf  
        
        If ( (attributes & 16) > 0 )
            ;
            ; Attributes 'a'
            szAttrib = ReplaceString( szAttrib, "-", "a", 0,4,1)
        EndIf
        
        If ( (attributes & 1) > 0 )
            ;
            ; Attributes 'r': Read
            szAttrib = ReplaceString( szAttrib, "-", "r", 0,5,1)
        EndIf         
        
        If ( (attributes & 2) > 0 )
            ;
            ; Attributes 'w': Write
            szAttrib = ReplaceString( szAttrib, "-", "w", 0,6,1)            
        EndIf 
        
        If ( (attributes & 8) > 0 )
            ;
            ; Attributes 'e': 
            szAttrib = ReplaceString( szAttrib, "-", "e", 0,7,1)            
        EndIf         
        
        If ( (attributes & 4) > 0 )
            ;
            ; Attributes 'd': 
            szAttrib = ReplaceString( szAttrib, "-", "d", 0,8,1)            
        EndIf                    
                    
        ProcedureReturn szAttrib
        
    EndProcedure     
    ;
    ;
    ;
    Procedure .s    Get_File(*Header_Filename.Header_Filename)
                
        Protected  szFile.s = ""
        
        szFile = PeekS(*Header_Filename)
        
        ProcedureReturn szFile
        
    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Comment(*Header_Comment.Header_Comment)
                
        Protected  szComment.s = ""
        
        If ( *Header_Comment\c[0] > 0 )        
            szComment = PeekS(*Header_Comment)
        EndIf    
        
        ProcedureReturn szComment
        
    EndProcedure     
    ;
    ;
    ;    
    Procedure .i    View_Archive(lzxData)
        
        Protected *Archive_Header.Archive_Header
        Protected *Header_Filename.Header_Filename
        Protected *Header_Comment.Header_Comment
        Protected temp.i
        Protected total_pack    = 0;
        Protected total_unpack  = 0;
        Protected total_files   = 0;
        Protected merge_size    = 0;    
        Protected actual
        Protected abort;
        Protected result        = 1; /* assume an error */
        
        Protected dbFilename.s, dbFileSize.s, dbComment.s
        
        Debug ("Unpacked" + Chr(9) +"  Packed" + Chr(9) +"   Time " + Chr(9) + "   Date " + Chr(9) + " Attrib " + Chr(9) + "Dir/File");
        Debug ("--------" + Chr(9) +"--------" + Chr(9) +"--------" + Chr(9) + "--------" + Chr(9) + "--------" + Chr(9) + "--------");;        
        
        *Archive_Header = AllocateMemory( 31 )
        *Header_Filename=AllocateMemory( 256 )
        *Header_Comment =AllocateMemory( 256 )
        
        Repeat
            
            ;abort = 0; /* assume an error */            
            ;
            ;
            For x = 0 To 30
                *Archive_Header\c[x] = ReadAsciiCharacter(lzxData)   
                actual = x
            Next  
            
            If (actual > 0) ;/* 0 is normal And means EOF */
                
                If (actual = 30 )
                    sum = 0 ; /* reset CRC */  
                    crc = (*Archive_Header\c[29] << 24) + (*Archive_Header\c[28] << 16) + (*Archive_Header\c[27] << 8) + *Archive_Header\c[26] ; /* header crc */  
                    
                    *Archive_Header\c[29] = 0; /* Must set the field to 0 before calculating the crc */
                    *Archive_Header\c[28] = 0;
                    *Archive_Header\c[27] = 0;
                    *Archive_Header\c[26] = 0;                    
                    
                    ;crc_calc(*Archive_Header, 31);                    
                    ;Debug Str(crc) + " :: " + Str(sum)
                    temp = *Archive_Header\c[30] ;          /* filename length */
                    actual = temp
                    ;
                    ;                    
                    For x = 0 To temp-1
                        ; 
                        ; Dateinamen Sichern
                        *Header_Filename\c[x] = ReadAsciiCharacter(lzxData) 
                    Next                  
                    
                    
                    *Header_Filename\c[temp] = 0;
                    ;crc_calc(*Header_Filename, temp);
                    temp = *Archive_Header\c[14];            /* comment length */
                    actual = temp
                    
                    For x = 0 To temp-1
                        ; 
                        ; Kommentar Sichern                        
                        *Header_Comment\c[x] = ReadByte(lzxData) 
                    Next                                        
                    
                    *Header_Comment\c[temp] = 0;
                    ;crc_calc(*Header_Comment, temp);
                    ;Debug Str(crc) + " :: " + Str(sum)
                    ;If ( sum = crc )
                    attributes  = *Archive_Header\c[0]   ; /* file protection modes */
                    
                    unpack_size = (*Archive_Header\c[5]  << 24) + (*Archive_Header\c[4]  << 16) + (*Archive_Header\c[3]  << 8) + *Archive_Header\c[2]   ; /* unpack size */
                    pack_size   = (*Archive_Header\c[9]  << 24) + (*Archive_Header\c[8]  << 16) + (*Archive_Header\c[7]  << 8) + *Archive_Header\c[6]   ; /* packed size */
                    temp        = (*Archive_Header\c[18] << 24) + (*Archive_Header\c[19] << 16) + (*Archive_Header\c[20] << 8) + *Archive_Header\c[21]  ; /* date */
                    
                    year        = ((temp >> 17) & 63) + 1970                                                                                          ;
                    month       = ((temp >> 23) & 15) + 1;
                    day         =  (temp >> 27) & 31;
                    hour        =  (temp >> 12) & 31;
                    minute      =  (temp >> 6) & 63;
                    second      =   temp & 63       
                    
                    ;
                    ; Aus dem Loop nach dem Listing Springen ... erstmal so umgesetzt
                    If (unpack_size = 0) And (pack_size = 0) And (Get_Clock (hour,minute,second) = "00:00:00") And ( Get_Attrib(attributes) = "--------") And ( Len(Get_File (*Header_Filename)) = 0 )
                        ;n/a	0	0:0:0	0-1-1970	--------
                        Break
                    EndIf  
                    
                    total_pack  + pack_size;
                    total_unpack+ unpack_size;
                    total_files +1             
                    merge_size  + unpack_size;                                                            
                    
  
                    ;
                    ; Situtation über die ausgelsenen Dateien
                    Debug RSet(Get_Unpack(unpack_size),8,Chr(32))                       + Chr(9) + 
                          RSet(Get_Packed(pack_size,*Archive_Header\c[12]),8,Chr(32))   + Chr(9) +
                          Get_Clock (hour,minute,second)    + Chr(9) +
                          Get_Date  (day,month,year)        + Chr(9) +
                          Get_Attrib(attributes)            + Chr(9) +
                          Get_File  (*Header_Filename)
                          Get_Comment(*Header_Comment)
                          
                    ;
                    ; Dateien ''merged
                    If   (*archive_header\c[12] & 1) And ( pack_size > 0)                        
                        Debug RSet(Str(merge_size),8,Chr(32)) + Chr(9) + RSet(Get_Packed(pack_size,LogicalAnd( (*archive_header\c[12] & 1) , pack_size)),8,Chr(32))  + Chr(9) + "Merged"
                    EndIf

                   If ( pack_size > 0); /* seek past the packed Data */ 
                       merge_size = 0;
                       
                       FileSeek(lzxData, pack_size, #PB_Relative)
                   EndIf                   
                    
                    ;
                Else    
                    Debug("EOF: Archive_Header\n");                    
                EndIf    
            Else
                ;result = 0; /* normal termination */
            EndIf
                    
            
            
        Until (abort = 1)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .i    Process_Archive(File.s)
        
        Protected  *Info_Header.Info_Header
        
        *Info_Header = AllocateMemory( 10 )
                
        lzxData = ReadFile( #PB_Any,  File) 
        If ( lzxData > 0 )
            
            ;
            ;
            For x = 0 To 9
                   *Info_Header\c[x] = ReadByte(lzxData)                             
            Next
                         
        EndIf
        
        If( (*Info_Header\c[0] = 76) And (*Info_Header\c[1] = 90) And (*Info_Header\c[2] = 88) )   ; /* LZX */
            Debug "LZX Header gefunden"
            View_Archive(lzxData)
        EndIf    
            
       CloseFile(lzxData)  
                 
        
        
    EndProcedure
    
    
EndModule

CompilerIf #PB_Compiler_IsMainFile
    EnableExplicit
    
    Define File.s, Pattern.s
    
    Pattern = "LZX (*.lzx)|*.lzx|Alle Dateien (*.*)|*.*"
        
    File = OpenFileRequester("LZX Tester","",Pattern,0)
    If ( File )        
        ;File = "B:\AmbermoonHD.lzx"
        ;File = "B:\REQHACK.lzx"    
        PackLZX::Process_Archive(File)
    EndIf
    
    
CompilerEndIf    

Image
Image

Code: Select all

temp = crc_table[(*memory++ ^ temp) & 255] ^ (temp >> 8);
How to Convert this line to PB? I'm not quite sure if I implemented the crc table correctly in my code.

^ = xor but i can not write xor on PB and && too. Can not write "And" in the functions only !,<<,<,>,>>,+,- etc.. are allowed.

greetings

Edit Here is always the Updated Code
https://github.com/MartyShepard/LHvSyst ... hiveLZX.pb


PS: If that works we all have an open source LZX extractor that you can do whatever you want with. :D
Last edited by Marty2PB on Thu Feb 09, 2023 1:01 am, edited 1 time in total.
juergenkulow
Enthusiast
Enthusiast
Posts: 544
Joined: Wed Sep 25, 2019 10:18 am

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by juergenkulow »

Code: Select all

;Bitwise XOR, AND
Debug "a b a xor b a and b"
For a=0 To 1
  For b=0 To 1
    Debug Str(a)+" "+Str(b)+"    "+ Str( a ! b )+ "       "+Str( a & b)
  Next
Next 
; a b a xor b a and b
; 0 0    0       0
; 0 1    1       0
; 1 0    1       0
; 1 1    0       1
PB Documentation Variables and Types Operator & and !
Please ask your questions, because switch on the cognition apparatus decides on the only known life in the universe.Wersten :DDüsseldorf NRW Germany Europe Earth Solar System Flake Bubble Orionarm
Milky Way Local_Group Virgo Supercluster Laniakea Universe
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Mijikai »

Maybe:

Code: Select all

EnableExplicit

Structure CRC
  crc.l[256]
EndStructure

Global *crc.CRC = ?CRC_TABLE
Global *memory
Global temp.i

*memory + 1

temp = *crc\crc[(*memory ! temp) & 255] ! (temp >> 8)

Debug temp
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Thanks for the Feedback :)

CRC Check works *wuhuhu*

Code: Select all

Macro UNINT(a)
    (a)&$ffffffff
EndMacro  
    ;
    ;
    ;    
    Procedure.i crc_calc(*memory.CRC_Memory, length.i)
        
        ;
        ; Die CRC Summe berechnen
        Protected CRC.i, *Table.CRC
        
        *Table = ?CRC_TABLE
                
        If( length > 0)
            
            CRC = UNINT(~sum) ; /* was (sum ^ 4294967295) */  
            
            While i < Length             
                
                CRC = UNINT(*Table\crc[*memory\c[i] ! CRC & 255] ! (CRC >> 8));
                Debug "CRC Table: " + Str(CRC) + " - Char: " + Str( *memory\c[i] )                
                
                i + 1                
            Wend            

            sum = UNINT(~CRC); /* was (temp ^ 4294967295) */
            ProcedureReturn temp
        EndIf    

Image
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Update, Progress

- Listing and CRC calculate works

Code: Select all

DeclareModule PackLZX
    
    Declare.i   Process_Archive(File.s)
EndDeclareModule


Module PackLZX
    
    Structure ArchiveFormat
        dateiname.s
        dateipath.s
        size.i     
        *image
    EndStructure     
    
    Structure CRC_Memory
        c.c[256]
    EndStructure
    
    Structure Info_Header
        c.c[10]
    EndStructure
    
    Structure Archive_Header
        c.c[31]
    EndStructure
    
    Structure Header_Filename
        c.c[256]
    EndStructure
    
    Structure Header_Comment
        c.c[256]
    EndStructure     
    
    Structure FileBuffer
        c.c[256]
        size.i
    EndStructure
    
    Structure CRC
    crc.i[256]
    EndStructure    
    
    
    Structure LZX_ARCHIVE
        Path.s
        File.s
        Full.s
        pbData.l
        sum.i                ; ist die Globale Varibale sum und nutzt "variable temp" in crc_calc      
        crc.i                ; Abgleich und Vergleich
        *Header.Info_Header
        *Archiv.Archive_Header
        *Filename.Header_Filename
        *Comment.Header_Comment 
    EndStructure    
    
   Global sum.i
   Global pack_size;
   Global unpack_size;    
   Global crc;
   Global year, month, day;
   Global hour, minute, second;
   Global attributes.c;
   Global pack_mode.c;
    
    DataSection
    CRC_TABLE:
    Data.i $00000000,$77073096,$EE0E612C,$990951BA,$076DC419,$706AF48F
    Data.i $E963A535,$9E6495A3,$0EDB8832,$79DCB8A4,$E0D5E91E,$97D2D988
    Data.i $09B64C2B,$7EB17CBD,$E7B82D07,$90BF1D91,$1DB71064,$6AB020F2
    Data.i $F3B97148,$84BE41DE,$1ADAD47D,$6DDDE4EB,$F4D4B551,$83D385C7
    Data.i $136C9856,$646BA8C0,$FD62F97A,$8A65C9EC,$14015C4F,$63066CD9
    Data.i $FA0F3D63,$8D080DF5,$3B6E20C8,$4C69105E,$D56041E4,$A2677172
    Data.i $3C03E4D1,$4B04D447,$D20D85FD,$A50AB56B,$35B5A8FA,$42B2986C
    Data.i $DBBBC9D6,$ACBCF940,$32D86CE3,$45DF5C75,$DCD60DCF,$ABD13D59
    Data.i $26D930AC,$51DE003A,$C8D75180,$BFD06116,$21B4F4B5,$56B3C423
    Data.i $CFBA9599,$B8BDA50F,$2802B89E,$5F058808,$C60CD9B2,$B10BE924
    Data.i $2F6F7C87,$58684C11,$C1611DAB,$B6662D3D,$76DC4190,$01DB7106
    Data.i $98D220BC,$EFD5102A,$71B18589,$06B6B51F,$9FBFE4A5,$E8B8D433
    Data.i $7807C9A2,$0F00F934,$9609A88E,$E10E9818,$7F6A0DBB,$086D3D2D
    Data.i $91646C97,$E6635C01,$6B6B51F4,$1C6C6162,$856530D8,$F262004E
    Data.i $6C0695ED,$1B01A57B,$8208F4C1,$F50FC457,$65B0D9C6,$12B7E950
    Data.i $8BBEB8EA,$FCB9887C,$62DD1DDF,$15DA2D49,$8CD37CF3,$FBD44C65
    Data.i $4DB26158,$3AB551CE,$A3BC0074,$D4BB30E2,$4ADFA541,$3DD895D7
    Data.i $A4D1C46D,$D3D6F4FB,$4369E96A,$346ED9FC,$AD678846,$DA60B8D0
    Data.i $44042D73,$33031DE5,$AA0A4C5F,$DD0D7CC9,$5005713C,$270241AA
    Data.i $BE0B1010,$C90C2086,$5768B525,$206F85B3,$B966D409,$CE61E49F
    Data.i $5EDEF90E,$29D9C998,$B0D09822,$C7D7A8B4,$59B33D17,$2EB40D81
    Data.i $B7BD5C3B,$C0BA6CAD,$EDB88320,$9ABFB3B6,$03B6E20C,$74B1D29A
    Data.i $EAD54739,$9DD277AF,$04DB2615,$73DC1683,$E3630B12,$94643B84
    Data.i $0D6D6A3E,$7A6A5AA8,$E40ECF0B,$9309FF9D,$0A00AE27,$7D079EB1
    Data.i $F00F9344,$8708A3D2,$1E01F268,$6906C2FE,$F762575D,$806567CB
    Data.i $196C3671,$6E6B06E7,$FED41B76,$89D32BE0,$10DA7A5A,$67DD4ACC
    Data.i $F9B9DF6F,$8EBEEFF9,$17B7BE43,$60B08ED5,$D6D6A3E8,$A1D1937E
    Data.i $38D8C2C4,$4FDFF252,$D1BB67F1,$A6BC5767,$3FB506DD,$48B2364B
    Data.i $D80D2BDA,$AF0A1B4C,$36034AF6,$41047A60,$DF60EFC3,$A867DF55
    Data.i $316E8EEF,$4669BE79,$CB61B38C,$BC66831A,$256FD2A0,$5268E236
    Data.i $CC0C7795,$BB0B4703,$220216B9,$5505262F,$C5BA3BBE,$B2BD0B28
    Data.i $2BB45A92,$5CB36A04,$C2D7FFA7,$B5D0CF31,$2CD99E8B,$5BDEAE1D
    Data.i $9B64C2B0,$EC63F226,$756AA39C,$026D930A,$9C0906A9,$EB0E363F
    Data.i $72076785,$05005713,$95BF4A82,$E2B87A14,$7BB12BAE,$0CB61B38
    Data.i $92D28E9B,$E5D5BE0D,$7CDCEFB7,$0BDBDF21,$86D3D2D4,$F1D4E242
    Data.i $68DDB3F8,$1FDA836E,$81BE16CD,$F6B9265B,$6FB077E1,$18B74777
    Data.i $88085AE6,$FF0F6A70,$66063BCA,$11010B5C,$8F659EFF,$F862AE69
    Data.i $616BFFD3,$166CCF45,$A00AE278,$D70DD2EE,$4E048354,$3903B3C2
    Data.i $A7672661,$D06016F7,$4969474D,$3E6E77DB,$AED16A4A,$D9D65ADC
    Data.i $40DF0B66,$37D83BF0,$A9BCAE53,$DEBB9EC5,$47B2CF7F,$30B5FFE9
    Data.i $BDBDF21C,$CABAC28A,$53B39330,$24B4A3A6,$BAD03605,$CDD70693
    Data.i $54DE5729,$23D967BF,$B3667A2E,$C4614AB8,$5D681B02,$2A6F2B94
    Data.i $B40BBE37,$C30C8EA1,$5A05DF1B,$2D02EF8D
EndDataSection

Procedure LogicalAND(a,b)           ; Conversion from &&
                                    ; Ob das richtig bezweifle ich. Aber das Auflisten der Dateiene deckt sich mit 'unlzx für Windows 95'                                        ;    
    If (a = 0 And b = 0)
        ProcedureReturn  0
    ElseIf  (a = 0 And b = 1)  
        ProcedureReturn  0
    ElseIf  (a = 1 And b = 0)  
        ProcedureReturn  0  
    ElseIf  (a = 1 And b = 1)  
        ProcedureReturn  1
    EndIf   
    
EndProcedure    
        
Macro UNINT(a)
    (a)&$ffffffff
EndMacro  
    ;
    ;
    ;    
    Procedure.i crc_calc(*Memory.CRC_Memory,*UnLZX.LZX_ARCHIVE, length.i)
        
        ;
        ; Die CRC Summe berechnen
        
        Protected CRC.i, *Table.CRC
        
        *Table = ?CRC_TABLE
                
        If( length > 0)
            
            CRC = UNINT(~*UnLZX\sum) ; /* was (sum ^ 4294967295) */  
            
            While i < Length             
                
                CRC = UNINT(*Table\crc[*Memory\c[i] ! CRC & 255] ! (CRC >> 8));
                ;Debug "CRC Table: " + Str(CRC) + " - Char: " + Str( *Memory\c[i] )                
                
                i + 1                
            Wend            

            *UnLZX\sum = UNINT(~CRC); /* was (temp ^ 4294967295) */
        EndIf    

    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Unpack(size.i)
                
        If ( size = 0 )
            ProcedureReturn "n/a"
        EndIf    
        ProcedureReturn Str(size)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .s    Get_Packed(size.i,c.b)
                
        If (c & 1)
            ProcedureReturn "n/a"
        EndIf    
        
        ProcedureReturn Str(size)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .s    Get_Clock(hour.i,minute.i,second.i)
        
        ;
        ; TODO 
        szClock.s = RSet(Str(hour),2,Chr(48)) + ":" + RSet(Str(minute),2,Chr(48)) + ":" + RSet( Str(second),2,Chr(48))
        ProcedureReturn szClock
        
    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Date(day.i,month.i,year.i)

        szDate.s =  RSet(Str(day),2,Chr(48)) + "-" + RSet(Str(month),2,Chr(48)) + "-" + Str(year)
        ProcedureReturn szDate
        
    EndProcedure 
    ;
    ;
    ;
    Procedure .s    Get_Attrib(attrib.i)
        
        szAttrib.s ="--------"
        ;
        ;
        ; 0 = Kein Attribut gesetzt
        
        If ( (attributes & 32) > 0 )
            ;
            ; Attributes 'h'
            szAttrib = ReplaceString( szAttrib, "-", "h", 0,1,1)
        EndIf    
        
        If ( (attributes & 64) > 0 )
            ;
            ; Attributes 's'
            szAttrib = ReplaceString( szAttrib, "-", "s", 0,2,1)
        EndIf
        
        If ( (attributes & 128) > 0 )
            ;
            ; Attributes 'p'
            szAttrib = ReplaceString( szAttrib, "-", "p", 0,3,1)
        EndIf  
        
        If ( (attributes & 16) > 0 )
            ;
            ; Attributes 'a'
            szAttrib = ReplaceString( szAttrib, "-", "a", 0,4,1)
        EndIf
        
        If ( (attributes & 1) > 0 )
            ;
            ; Attributes 'r': Read
            szAttrib = ReplaceString( szAttrib, "-", "r", 0,5,1)
        EndIf         
        
        If ( (attributes & 2) > 0 )
            ;
            ; Attributes 'w': Write
            szAttrib = ReplaceString( szAttrib, "-", "w", 0,6,1)            
        EndIf 
        
        If ( (attributes & 8) > 0 )
            ;
            ; Attributes 'e': 
            szAttrib = ReplaceString( szAttrib, "-", "e", 0,7,1)            
        EndIf         
        
        If ( (attributes & 4) > 0 )
            ;
            ; Attributes 'd': 
            szAttrib = ReplaceString( szAttrib, "-", "d", 0,8,1)            
        EndIf                    
                    
        ProcedureReturn szAttrib
        
    EndProcedure     
    ;
    ;
    ;
    Procedure .s    Get_File(*UnLZX.LZX_ARCHIVE)
                
        Protected  szFile.s = ""
        
        szFile = PeekS(*UnLZX\Filename)
        
        ProcedureReturn szFile
        
    EndProcedure
    ;
    ;
    ;
    Procedure .s    Get_Comment(*UnLZX.LZX_ARCHIVE)
                
        Protected  szComment.s = ""
        
        
      
            szComment = PeekS(*UnLZX\Comment)
        
        
        ProcedureReturn szComment
        
    EndProcedure     
    ;
    ;
    ;
    Procedure .i    FileRead( *Buffer.FileBuffer, Size.i, Count.i ,*UnLZX.LZX_ARCHIVE)
                                
        ;For x = Size To Count
        ; 
        ; Dateinamen Sichern
        ;*Buffer\c[x] = ReadAsciiCharacter(*UnLZX\pbData) 
        ; Debug "File Read: (" +RSet( Str( x ),2,"0") + ") :" + Str( *Buffer\c[x] )
        ;Size +1
        ;Next
        
        ;*Buffer\size = x
        
        ;ProcedureReturn *Buffer
    EndProcedure    
    ;
    ;
    ;
    Procedure .i    View_Archive(*UnLZX.LZX_ARCHIVE)
        
        Protected TempPosition  = 0
        Protected total_pack    = 0;
        Protected total_unpack  = 0;
        Protected total_files   = 0;
        Protected merge_size    = 0;    
        Protected CurrentPosition  = 0;   ist die "actual" variable
        Protected abort;
        Protected result        = 1; /* assume an error */
        
        Protected dbFilename.s, dbFileSize.s, dbComment.s ;4046869439
        
        Debug ("Unpacked" + Chr(9) +"  Packed" + Chr(9) + " CRC Calc " + Chr(9) + " CRC Summe " + Chr(9) +"   Time " + Chr(9) + "   Date " + Chr(9) + " Attrib " + Chr(9) + "Dir/File"  )
        Debug ("--------" + Chr(9) +"--------" + Chr(9) + "-----------"+ Chr(9) + "-----------" + Chr(9) +"--------" + Chr(9) + "--------" + Chr(9) + "--------" + Chr(9) + "--------"  )      
                
        Repeat
            
            ;abort = 0; /* assume an error */            
            ;
            ;
            
            For x = 0 To 30
                *UnLZX\Archiv\c[x] = ReadAsciiCharacter(*UnLZX\pbData)   
                CurrentPosition = x+1
            Next            
            
            If (CurrentPosition > 0)                                ; /* 0 is normal And means EOF */
                
                If (CurrentPosition = 31 )
                    
                    *UnLZX\sum = 0 ;                                /* reset CRC */  
                    
                    *UnLZX\crc = (*UnLZX\Archiv\c[29] << 24) + (*UnLZX\Archiv\c[28] << 16) + (*UnLZX\Archiv\c[27] << 8) + *UnLZX\Archiv\c[26] ; /* header crc */  
                    
                    *UnLZX\Archiv\c[29] = 0;                        /* Must set the field to 0 before calculating the crc */
                    *UnLZX\Archiv\c[28] = 0;
                    *UnLZX\Archiv\c[27] = 0;
                    *UnLZX\Archiv\c[26] = 0;                    
                    
                    crc_calc( *UnLZX\Archiv, *UnLZX, 31 )                                       
                    
                    ;--------------------------------------------------------------------------------------------------------------------------------------------
                    ;                    
                    TempPosition= *UnLZX\Archiv\c[30] ;             /* filename length */
                    
                    
                    For x = 0 To TempPosition-1
                        *UnLZX\Filename\c[x] = ReadAsciiCharacter(*UnLZX\pbData)   
                        CurrentPosition = x+1
                    Next                   
                    ; 
                    ; Dateinamen Sichern                                                 
                    
                    If ( CurrentPosition = TempPosition )
                       
                        *UnLZX\Filename\c[TempPosition] = 0;
                        
                        crc_calc(*UnLZX\Filename,  *UnLZX, TempPosition);         
                        
                        ;--------------------------------------------------------------------------------------------------------------------------------------------
                        ;
                        TempPosition     = *UnLZX\Archiv\c[14];            /* comment length */
                        CurrentPosition  = *UnLZX\Archiv\c[14]                     
                        For x = 0 To TempPosition-1
                            *UnLZX\Comment\c[x] = ReadAsciiCharacter(*UnLZX\pbData)   
                        Next                                                                                
                                                    
                        If ( CurrentPosition = TempPosition )

                            crc_calc(*UnLZX\Comment,  *UnLZX, TempPosition);
                                                           
                            If ( *UnLZX\sum = *UnLZX\crc )
                                
                                attributes  = *UnLZX\Archiv\c[0]   ; /* file protection modes */
                                
                                unpack_size = (*UnLZX\Archiv\c[5]  << 24) + (*UnLZX\Archiv\c[4]  << 16) + (*UnLZX\Archiv\c[3]  << 8) + *UnLZX\Archiv\c[2]   ; /* unpack size */
                                pack_size   = (*UnLZX\Archiv\c[9]  << 24) + (*UnLZX\Archiv\c[8]  << 16) + (*UnLZX\Archiv\c[7]  << 8) + *UnLZX\Archiv\c[6]   ; /* packed size */
                                DatePosition= (*UnLZX\Archiv\c[18] << 24) + (*UnLZX\Archiv\c[19] << 16) + (*UnLZX\Archiv\c[20] << 8) + *UnLZX\Archiv\c[21]  ; /* date */
                                
                                year        = ((DatePosition >> 17) & 63) + 1970                                                                                          ;
                                month       = ((DatePosition >> 23) & 15) + 1                                                                                             ;
                                day         =  (DatePosition >> 27) & 31                                                                                                  ;
                                hour        =  (DatePosition >> 12) & 31                                                                                                  ;
                                minute      =  (DatePosition >> 6) & 63                                                                                                   ;
                                second      =   DatePosition & 63       
                                
                                ;
                                ; Aus dem Loop nach dem Listing Springen ... erstmal so umgesetzt
                               ; If (unpack_size = 0) And (pack_size = 0) And (Get_Clock (hour,minute,second) = "00:00:00") And ( Get_Attrib(attributes) = "--------") And ( Len(Get_File (*UnLZX\Filename)) = 0 )
                               ;     ;n/a	0	0:0:0	0-1-1970	--------
                               ;     Break
                               ; EndIf  
                                
                                total_pack  + pack_size;
                                total_unpack+ unpack_size;
                                total_files +1             
                                merge_size  + unpack_size;                                                            
                                
                                
                                ;
                                ; Situtation über die ausgelsenen Dateien
                                Debug RSet(Get_Unpack(unpack_size),8,Chr(32))                     + Chr(9) + 
                                      RSet(Get_Packed(pack_size,*UnLZX\Archiv\c[12]),8,Chr(32))   + Chr(9) +
                                      RSet( Str(*UnLZX\sum),10," ")                               + Chr(9) +
                                      RSet( Str(*UnLZX\crc),10," ")                               + Chr(9) +                                      
                                      Get_Clock  (hour,minute,second)                             + Chr(9) +
                                      Get_Date   (day,month,year)                                 + Chr(9) +
                                      Get_Attrib (attributes)                                     + Chr(9) +
                                      Get_File   (*UnLZX)                                         + Chr(9) + Chr(9) + Get_Comment(*UnLZX)
                                
                                ;
                                ; Dateien ''merged
                                If   (*UnLZX\Archiv\c[12] & 1) And ( pack_size > 0)                        
                                    Debug RSet(Str(merge_size),8,Chr(32)) + Chr(9) + RSet(Get_Packed(pack_size,LogicalAnd( (*UnLZX\Archiv\c[12] & 1) , pack_size)),8,Chr(32))  + Chr(9) + "Merged"
                                EndIf
                                
                                If ( pack_size > 0); /* seek past the packed Data */ 
                                    merge_size = 0 ;
                                    
                                    FileSeek(*UnLZX\pbData, pack_size, #PB_Relative)
                                EndIf                   
                            Else
                                Debug "CRC: Archive_Header ... CRC Mismatch"
                                Debug "CRC Table: " + Str(*UnLZX\sum) + ":: CRC *UnLZX\Archiv: "+ Str(*UnLZX\crc)                                   
                            EndIf
                            
                        Else
                            Debug "End Of File: Header_Comment"
                        EndIf
                    Else
                        Debug "End Of File: Header_Filename"
                        Break
                    EndIf 
                Else    
                    Debug "End Of File: Archive_Header"
                EndIf
            Else
                Debug"-------- -------- -------- ----------- -------- ----"
                ;Debug "%8ld %8ld ", total_unpack, total_pack                  ;
                ;Debug "%ld file%s\n", total_files, ((total_files == 1) ? "" : "s"));
            EndIf
            ;result = 0; /* normal termination */                
            
            
        Until (abort = 1)
        
    EndProcedure    
    ;
    ;
    ;
    Procedure  .i   Process_Header(*UnLZX.LZX_ARCHIVE)
        
        Protected FilePosition.i
        
        For FilePosition = 0 To 9
            *UnLZX\Header\c[FilePosition] = ReadByte(*UnLZX\pbData)                             
        Next                         
        
        
       If ( (*UnLZX\Header\c[0] = 76) And (*UnLZX\Header\c[1] = 90) And (*UnLZX\Header\c[2] = 88) )   ; /* LZX */           
           
           Debug "Process_Header() : LZX gefunden"
           ProcedureReturn #True
       EndIf        
       
       ProcedureReturn #False
        
    EndProcedure    
    ;
    ;
    ;
    Procedure .i    Process_Archive(File.s)
                
        If ( FileSize( File ) > 0 )
                        
            *UnLZX.LZX_ARCHIVE  = AllocateMemory(SizeOf(LZX_ARCHIVE))
            InitializeStructure(*UnLZX, LZX_ARCHIVE)
            
            *UnLZX\Full         = File
            *UnLZX\Path         = GetPathPart( *UnLZX\Path  )
            *UnLZX\File         = GetFilePart( *UnLZX\File , #PB_FileSystem_NoExtension)
            
            *UnLZX\Header       = AllocateMemory(  10 )
            *UnLZX\Archiv       = AllocateMemory(  31 )
            *UnLZX\Filename     = AllocateMemory( 256 )
            *UnLZX\Comment      = AllocateMemory( 256 )
            
            *UnLZX\pbData       = ReadFile( #PB_Any,  *UnLZX\Full )
            
            If ( Process_Header(*UnLZX.LZX_ARCHIVE) = #True )
                
                View_Archive(*UnLZX.LZX_ARCHIVE) 
                
            EndIf
            
            CloseFile(*UnLZX\pbData)  
            
            FreeMemory(*UnLZX)
        EndIf          
                
    EndProcedure
    
    
EndModule

CompilerIf #PB_Compiler_IsMainFile
    EnableExplicit
    
    Define File.s, Pattern.s
    
    Pattern = "LZX (*.lzx)|*.lzx|Alle Dateien (*.*)|*.*"
        
    File = OpenFileRequester("LZX Tester","",Pattern,0)
    If ( File )        
        ;File = "B:\AmbermoonHD.lzx"
        ;File = "B:\REQHACK.lzx"    
        PackLZX::Process_Archive(File)
    EndIf
    
    
CompilerEndIf    
Image
Fred
Administrator
Administrator
Posts: 16619
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Fred »

That brings back some memories :). Good work !
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Hm. i got in troubles with this code

Code: Select all

          unsigned char *source;
          register unsigned int control;
          register int shift;

          shift += 16;
          control += *source++ << (8 + shift);
          control += *source++ << shift;
My approach for the translation from c to pb would be:

The Full C Code is in the First post in routine: read_literal_table().
Dieser Codeblock wird in "Read Literal" öfter abgefragt und Ich bekomme bei dieser Routine immer falsche werte.
This block of code is queried more often in "Read Literal" and I always get wrong values with this routine.

Code: Select all

        Structure source
         c.c[1]
        EndStructure 
    
        protected shift.i
        protected control.i
                  
        shift = shift + 16;
          
        *source\c[0] + 1
        control = control + *source\c[0] << (8 + shift);
        *source\c[0] + 1
        control = control + *source\c[0] << shift;
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by infratec »

You are increasing the value, but not the pointer.

Code: Select all

Protected shift.i
Protected control.i
Protected *source.Ascii

shift + 16

*source + 1
control + (*source\a << (8 + shift))
*source + 1
control + (*source\a << shift)
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Hello infratec :D
thanks for hint. Yes now ist works.

PS:
Thanks again for the help with the C64 disk and tape module. :wink:

Fred: Thank you :)
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

I'm well on my way :)

However, there are 2 functions with operands that I am unsure about converting to pb correctly.

First in the routine "Extract Normal" in C

Code: Select all

do /* copy the overrun to the start of the buffer */
{
 *destination++ = *temp++;
} while(--count);

i think in Purebasic

Code: Select all

*p\destination\a + *p\temp\a
*p\destination  + 1
*p\temp + 1
The same is in the Decrunch Routine in C

Code: Select all

               do
               {
                    *destination++ = *string++;
               } while(--count);

The second is a Conditional ternary operator ( ? ) in the Decrunch Routine in C

Code: Select all

*string = (decrunch_buffer + last_offset < destination) ?  destination - last_offset : destination + 65536 - last_offset;
i think in Purebasic

Code: Select all

                  If ( ( *DecrBuffer + *p\last_offset) < *p\destination )                      
                     *string\c[0] = PeekB(*p\destination - *p\last_offset)
                  Else
                     *string\c[0] = *p\destination + 65536 - *p\last_offset
                  EndIf
My Output
Image

This is the Original Output
Image

Some characters are shifted in my file. I think it's because of the routine that I didn't convert it properly. Otherwise the positions are correct so far.

greetings
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by infratec »

Code: Select all

                  If ( ( *DecrBuffer + *p\last_offset) < *p\destination )                      
                     *string\c[0] = PeekB(*p\destination - *p\last_offset)
                  Else
                     *string\c[0] = *p\destination + 65536 - *p\last_offset
                  EndIf
You are inconsequent :wink:

Code: Select all

                  If ( ( *DecrBuffer + *p\last_offset) < *p\destination )                      
                     *string\c[0] = PeekA(*p\destination - *p\last_offset)
                  Else
                     *string\c[0] = PeekA(*p\destination + 65536 - *p\last_offset)
                  EndIf
PeekA is better then PeekB, because the result is unsigned.


And your structure is wrong:

Code: Select all

Structure source
         c.c[1]
EndStructure
.c in PB is unicode, which is more or less a word and not a byte
Switch to *String.ASCII
or, if you want to stay with your structure, use

Code: Select all

Structure source
         c.a[1]
EndStructure
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

Yes. You right. But the Signs are always shiftet. I somehow have a conversion error in there.


I upload the the Source to my Github Account. Too much Code. :D
https://github.com/MartyShepard/LHvSyst ... hiveLZX.pb
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

infratec wrote: Wed Feb 08, 2023 11:53 pm
.c in PB is unicode, which is more or less a word and not a byte
Ah, ok. I got confused with that. :?
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by infratec »

Can you provide a lzx file which works with your code?

Because I downloaded a few lzx files an I get CRC errors.

Example:
https://files.scene.org/view/demos/grou ... s-flve.lzx
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Conversion UnLZX (LZX decompress ) in C to PB Nativ

Post by Marty2PB »

infratec wrote: Thu Feb 09, 2023 5:38 pm Can you provide a lzx file which works with your code?

Because I downloaded a few lzx files an I get CRC errors.

Example:
https://files.scene.org/view/demos/grou ... s-flve.lzx

do you mean CRCs bi Downloading or CRC from the PB Convertet Source
The Listings and CRC works but not Exctracting (I downloade the Scene Demo file from your Post)

Image

here is another file
https://filehorst.de/d/eghfJzv
Post Reply