Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include "mhmt-types.h"
  5. #include "mhmt-globals.h"
  6. #include "mhmt-pack.h"
  7. #include "mhmt-hash.h"
  8. #include "mhmt-tb.h"
  9. #include "mhmt-lz.h"
  10. #include "mhmt-optimal.h"
  11. #include "mhmt-emit.h"
  12.  
  13.  
  14. // entry function to pack data
  15. // returns zero if any error
  16. ULONG pack(void)
  17. {
  18.  
  19.  
  20.         ULONG (*get_lz_price)(OFFSET position, struct lzcode * lzcode) = NULL; // generates correct bitlen (price) of code
  21.  
  22.         ULONG (*emit)(struct optchain * optch, ULONG actual_len) = NULL; // emits lzcode to the output bit/byte stream
  23.  
  24.  
  25.         ULONG success=1;
  26.  
  27.  
  28.         ULONG actual_len; // actual length of packing (to account for ZX headers containing last unpacked bytes)
  29.  
  30.         UBYTE * hash;
  31.  
  32.         struct optchain * optch=NULL;
  33.  
  34.         static struct lzcode codes[MAX_CODES_SIZE]; // generate codes here; static to ensure it's not on the stack
  35.  
  36.  
  37.         UBYTE curr_byte, last_byte;
  38.         UWORD index;
  39.         OFFSET position;
  40.  
  41.  
  42.         // some preparations
  43.         //
  44.         if( wrk.packtype==PK_MLZ )
  45.         {
  46.                 get_lz_price  = &get_lz_price_megalz;
  47.                 emit          = &emit_megalz;
  48.         }
  49.         else if( wrk.packtype==PK_HRM )
  50.         {
  51.                 get_lz_price  = &get_lz_price_hrum;
  52.                 emit          = &emit_hrum;
  53.         }
  54.         else if( wrk.packtype==PK_HST )
  55.         {
  56.                 get_lz_price  = &get_lz_price_hrust;
  57.                 emit          = &emit_hrust;
  58.         }
  59.         else if( wrk.packtype==PK_ZX7 )
  60.         {
  61.                 get_lz_price  = &get_lz_price_zx7;
  62.                 emit          = &emit_zx7;
  63.         }
  64.         else
  65.         {
  66.                 printf("mhmt-pack.c:pack() - format unsupported!\n");
  67.                 return 0;
  68.         }
  69.  
  70.  
  71.         actual_len = wrk.inlen;
  72.         if( wrk.zxheader )
  73.         {
  74.                 if( wrk.packtype==PK_HRM )
  75.                 {
  76.                         actual_len -= 5;
  77.                 }
  78.                 else if( wrk.packtype==PK_HST )
  79.                 {
  80.                         actual_len -= 6;
  81.                 }
  82.                 else
  83.                 {
  84.                         printf("mhmt-pack.c:pack() - there must be no zxheader for anything except hrust or hrum!\n");
  85.                         return 0;
  86.                 }
  87.         }
  88.  
  89.  
  90.         // initializations and preparations
  91.         init_tb();
  92.  
  93.         hash = build_hash(wrk.indata, actual_len, wrk.prelen);
  94.         if( !hash )
  95.         {
  96.                 printf("mhmt-pack.c:pack() - build_hash() failed!\n");
  97.                 success = 0;
  98.         }
  99.  
  100.         if( success )
  101.         {
  102.                 optch = make_optch(actual_len);
  103.                 if( !optch )
  104.                 {
  105.                         printf("mhmt-pack.c:pack() - can't make optchain array!\n");
  106.                         success = 0;
  107.                 }
  108.         }
  109.  
  110.  
  111.         // go packing!
  112.         if( success )
  113.         {
  114.                 // fill TBs with prebinary date
  115.                 if( wrk.prebin )
  116.                 {
  117.                         curr_byte=wrk.indata[0LL-wrk.prelen];
  118.                         //
  119.                         for(position=(1LL-wrk.prelen);position<=0;position++)
  120.                         {
  121.                                 last_byte = curr_byte;
  122.                                 curr_byte = wrk.indata[position];
  123.  
  124.                                 index = (last_byte<<8) + curr_byte;
  125.                                
  126.                                 if( !add_tb(index,position) )
  127.                                 {
  128.                                         printf("mhmt-pack.c:pack() - add_tb() failed!\n");
  129.                                         success = 0;
  130.                                         goto ERROR;
  131.                                 }
  132.                         }
  133.                 }
  134.  
  135.                 if( !wrk.greedy ) // default optimal coding
  136.                 {
  137.                         // go generating lzcodes byte-by-byte
  138.                         //
  139.                         curr_byte = wrk.indata[0];
  140.                         //
  141.                         for(position=1;position<(OFFSET)actual_len;position++)
  142.                         {
  143.                                 last_byte = curr_byte;
  144.                                 curr_byte = wrk.indata[position];
  145.  
  146.                                 // add current two-byter to the chains
  147.                                 index = (last_byte<<8) + curr_byte;
  148.                                 if( !add_tb(index,position) )
  149.                                 {
  150.                                         printf("mhmt-pack.c:pack() - add_tb() failed!\n");
  151.                                         success = 0;
  152.                                         goto ERROR;
  153.                                 }
  154.  
  155.                                 // search lzcodes for given position
  156.                                 make_lz_codes(position, actual_len, hash, codes);
  157.  
  158.                                 // update optimal chain with lzcodes
  159.                                 update_optch(position, codes, get_lz_price, optch);
  160.                         }
  161.  
  162.  
  163.                         // all input bytes scanned, chain built, so now reverse it (prepare for scanning in output generation part)
  164.                         reverse_optch(optch, actual_len);
  165.                 }
  166.                 else // greedy coding
  167.                 {
  168.                         printf("mhmt-pack.c:pack() - greedy coding not supported!\n");
  169.                         success = 0;
  170.                 }
  171.  
  172.                 // data built, now emit packed file
  173.                 success = success && (*emit)(optch, actual_len);
  174.         }
  175.  
  176.  
  177.  
  178.  
  179.  
  180. ERROR:
  181.         free_optch(optch);
  182.  
  183.         destroy_hash(hash, wrk.prelen);
  184.  
  185.         return success;
  186. }
  187.