Subversion Repositories pentevo

Rev

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

  1. #include <stdio.h>
  2.  
  3. #include "mhmt-types.h"
  4. #include "mhmt-globals.h"
  5. #include "mhmt-emit.h"
  6. #include "mhmt-lz.h"
  7. #include "mhmt-optimal.h"
  8.  
  9.  
  10.  
  11. // actually generate output file from optimal chain - MegaLZ version
  12. ULONG emit_megalz(struct optchain * optch, ULONG actual_len)
  13. {
  14.         ULONG position;
  15.         LONG length;
  16.         LONG disp;
  17.  
  18.         LONG max_disp; // maximum encountered displacement
  19.  
  20.  
  21.         ULONG varbits,varlen;
  22.  
  23.         ULONG success = 1;
  24.  
  25.         max_disp = 0;
  26.  
  27.  
  28.         // some checks
  29.         if( !optch )
  30.         {
  31.                 printf("mhmt-emit.c:emit_megalz() - NULL passed!\n");
  32.                 return 0;
  33.         }
  34.  
  35.         // initialize
  36.         success = success && emit_file(NULL, EMIT_FILE_INIT);
  37.  
  38.         success = success && emit_byte(0, EMIT_BYTE_INIT);
  39.  
  40.         success = success && emit_bits(0, EMIT_BITS_INIT);
  41.  
  42.  
  43.         // copy first byte as-is
  44.         success = success && emit_file( wrk.indata, 1);
  45.  
  46.         // go emitting codes
  47.         position = 1;
  48.  
  49.         while( (position<actual_len) && success )
  50.         {
  51.                 length = optch[position].code.length;
  52.                 disp   = optch[position].code.disp;
  53.  
  54.                 if( length==0 )
  55.                 {
  56.                         printf("mhmt-emit.c:emit_megalz() - encountered stop-code in optimal chain before emitting all data!\n");
  57.                         return 0;
  58.                 }
  59.                 else if( length==1 ) // either copy-byte or len=1 code
  60.                 {
  61.                         if( disp==0 ) // copy-byte (%1<byte>)
  62.                         {
  63.                                 success = success && emit_bits( 0x80000000, 1 );
  64.                                 success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
  65.                         }
  66.                         else if( (-8)<=disp && disp<=(-1) ) // len=1, disp=-1..-8 (%000abc)
  67.                         {
  68.                                 success = success && emit_bits( 0x00000000,   3 );
  69.                                 success = success && emit_bits( disp<<(32-3), 3 );
  70.  
  71.                                 if( max_disp > disp ) max_disp = disp;
  72.                         }
  73.                         else
  74.                                 goto INVALID_CODE_MEGALZ;
  75.                 }
  76.                 else if( length==2 )
  77.                 {
  78.                         if( (-256)<=disp && disp<=(-1) ) // %001<byte>
  79.                         {
  80.                                 success = success && emit_bits( 0x20000000, 3 );
  81.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  82.  
  83.                                 if( max_disp > disp ) max_disp = disp;
  84.                         }
  85.                         else
  86.                                 goto INVALID_CODE_MEGALZ;
  87.                 }
  88.                 else if( 3<=length && length<=255 )
  89.                 {
  90.                         // length coding
  91.                         if( length==3 ) // %010
  92.                         {
  93.                                 success = success && emit_bits( 0x40000000, 3 );
  94.                         }
  95.                         else // length==4..255, %011
  96.                         {
  97.                                 success = success && emit_bits( 0x60000000, 3 );
  98.  
  99.                                 // calculate size of variable bits
  100.                                 varlen = 0;
  101.                                 varbits = (length-2)>>1;
  102.                                 while( varbits )
  103.                                 {
  104.                                         varbits >>= 1;
  105.                                         varlen++;
  106.                                 }
  107.  
  108.                                 varbits = length-2-(1<<varlen); // prepare length coding
  109.  
  110.                                 success = success && emit_bits(       1<<(32-varlen), varlen );
  111.                                 success = success && emit_bits( varbits<<(32-varlen), varlen );
  112.                         }
  113.  
  114.                         // displacement coding
  115.                         if( (-256)<=disp && disp<=(-1) )
  116.                         {
  117.                                 success = success && emit_bits( 0, 1 );
  118.                                 success = success && emit_byte( (UBYTE)(0x00ff & disp), EMIT_BYTE_ADD );
  119.  
  120.                                 if( max_disp > disp ) max_disp = disp;
  121.                         }
  122.                         else if( (-4352)<=disp && disp<(-256) )
  123.                         {
  124.                                 success = success && emit_bits( 0x80000000, 1 );
  125.  
  126.                                 success = success && emit_bits( (0x0F00&(disp+0x0100))<<20, 4 );
  127.  
  128.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  129.  
  130.                                 if( max_disp > disp ) max_disp = disp;
  131.                         }
  132.                         else
  133.                                 goto INVALID_CODE_MEGALZ;
  134.                 }
  135.                 else
  136.                 {
  137. INVALID_CODE_MEGALZ:
  138.                         printf("mhmt-emit.c:emit_megalz() - invalid code: length=%d, displacement=%d\n",length,disp);
  139.                         return 0;
  140.                 }
  141.  
  142.                 position += length;
  143.         }
  144.  
  145.         // stop-code
  146.         success = success && emit_bits( 0x60100000, 12 );
  147.         success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
  148.  
  149.         success = success && emit_file( NULL, EMIT_FILE_FINISH );
  150.  
  151.         if( success )
  152.                 printf("Maximum displacement actually used is %d.\n",-max_disp);
  153.  
  154.         return success;
  155. }
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. // actually generate output file from optimal chain - hrum version
  173. ULONG emit_hrum(struct optchain * optch, ULONG actual_len)
  174. {
  175.         ULONG position;
  176.         LONG length;
  177.         LONG disp;
  178.  
  179.         LONG max_disp; // maximum encountered displacement
  180.  
  181.  
  182.         ULONG varbits,varlen;
  183.  
  184.         ULONG success = 1;
  185.  
  186.         max_disp = 0;
  187.  
  188.  
  189.         // some checks
  190.         if( !optch )
  191.         {
  192.                 printf("mhmt-emit.c:emit_hrum() - NULL passed!\n");
  193.                 return 0;
  194.         }
  195.  
  196.         // initialize
  197.         success = success && emit_file(NULL, EMIT_FILE_INIT);
  198.  
  199.         success = success && emit_byte(0, EMIT_BYTE_INIT);
  200.  
  201.         success = success && emit_bits(0, EMIT_BITS_INIT);
  202.  
  203.  
  204.         // manage zx header info
  205.         if( wrk.zxheader )
  206.         {
  207.         success = success && emit_file( &wrk.indata[wrk.inlen-5], 5);
  208.                 success = success && emit_file( (UBYTE*)"\020\020", 2); // 0x10, 0x10
  209.         }
  210.  
  211.         // schedule first byte to be placed just after first bitstream word
  212.         success = success && emit_byte( wrk.indata[0], EMIT_BYTE_ADD);
  213.  
  214.         // go emitting codes
  215.         position = 1;
  216.  
  217.         while( (position<actual_len) && success )
  218.         {
  219.                 length = optch[position].code.length;
  220.                 disp   = optch[position].code.disp;
  221.  
  222.                 if( length==0 )
  223.                 {
  224.                         printf("mhmt-emit.c:emit_hrum() - encountered stop-code in optimal chain before emitting all data!\n");
  225.                         return 0;
  226.                 }
  227.                 else if( length==1 ) // either copy-byte or len=1 code
  228.                 {
  229.                         if( disp==0 ) // copy-byte (%1<byte>)
  230.                         {
  231.                                 success = success && emit_bits( 0x80000000, 1 );
  232.                                 success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
  233.                         }
  234.                         else if( (-8)<=disp && disp<=(-1) ) // len=1, disp=-1..-8 (%000abc)
  235.                         {
  236.                                 success = success && emit_bits( 0x00000000,   3 );
  237.                                 success = success && emit_bits( disp<<(32-3), 3 );
  238.  
  239.                                 if( max_disp > disp ) max_disp = disp;
  240.                         }
  241.                         else
  242.                                 goto INVALID_CODE_HRUM;
  243.                 }
  244.                 else if( length==2 )
  245.                 {
  246.                         if( (-256)<=disp && disp<=(-1) ) // %001<byte>
  247.                         {
  248.                                 success = success && emit_bits( 0x20000000, 3 );
  249.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  250.  
  251.                                 if( max_disp > disp ) max_disp = disp;
  252.                         }
  253.                         else
  254.                                 goto INVALID_CODE_HRUM;
  255.                 }
  256.                 else if( 3<=length && length<=255 )
  257.                 {
  258.                         // length coding
  259.                         if( length==3 )
  260.                         {
  261.                                 success = success && emit_bits( 0x40000000, 3 );
  262.                         }
  263.                         else if( length<=15 )
  264.                         {
  265.                                 varlen=2;
  266.  
  267.                                 varbits = (length % 3)<<30; // low 2 bits (except for length==15)
  268.                                 if( length==15 ) varbits = 0xC0000000;
  269.  
  270.                                 if( length>=6 ) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
  271.                                 if( length>=9 ) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
  272.                                 if( length>=12) { varbits = 0xC0000000 | (varbits>>2); varlen += 2; }
  273.  
  274.                                 success = success && emit_bits( 0x60000000, 3 );
  275.                                 success = success && emit_bits( varbits, varlen );
  276.                         }
  277.                         else // 15<length<=255: %01100<len>
  278.                         {
  279.                                 success = success && emit_bits( 0x60000000, 5 );
  280.                                 success = success && emit_byte( (UBYTE)(length&0x00FF), EMIT_BYTE_ADD );
  281.                         }
  282.  
  283.                         // displacement coding
  284.                         if( (-256)<=disp && disp<=(-1) ) // %0<disp>
  285.                         {
  286.                                 success = success && emit_bits( 0x00000000, 1 );
  287.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  288.  
  289.                                 if( max_disp > disp ) max_disp = disp;
  290.                         }
  291.                         else if( (-4096)<=disp && disp<(-256) ) //%1abcd<disp>
  292.                         {
  293.                                 success = success && emit_bits( 0x80000000, 1 );
  294.                                 success = success && emit_bits( (0x0F00&disp)<<20, 4 );
  295.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  296.  
  297.                                 if( max_disp > disp ) max_disp = disp;
  298.                         }
  299.                         else
  300.                                 goto INVALID_CODE_HRUM;
  301.                 }
  302.                 else
  303.                 {
  304. INVALID_CODE_HRUM:
  305.                         printf("mhmt-emit.c:emit_hrum() - invalid code: length=%d, displacement=%d\n",length,disp);
  306.                         return 0;
  307.                 }
  308.  
  309.                 position += length;
  310.         }
  311.  
  312.         // stop-code: %01100<0>
  313.         success = success && emit_bits( 0x60000000, 5 );
  314.         success = success && emit_byte( 0x00, EMIT_BYTE_ADD );
  315.  
  316.         success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
  317.         success = success && emit_file( NULL, EMIT_FILE_FINISH );
  318.  
  319.         if( success )
  320.                 printf("Maximum displacement actually used is %d.\n",-max_disp);
  321.  
  322.         return success;
  323. }
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340. ULONG emit_hrust(struct optchain * optch, ULONG actual_len)
  341. {
  342.         ULONG position;
  343.         LONG length;
  344.         LONG disp;
  345.  
  346.         LONG max_disp; // maximum encountered displacement
  347.  
  348.         ULONG varbits,varlen;
  349.         ULONG success = 1;
  350.  
  351.         UBYTE wrlen[2];
  352.  
  353.         ULONG expbitlen = 2; // expandable match: bitlength of displacement
  354.  
  355.         ULONG flen;
  356.        
  357.  
  358.         max_disp = 0;
  359.  
  360.  
  361.         // some checks
  362.         if( !optch )
  363.         {
  364.                 printf("mhmt-emit.c:emit_hrust() - NULL passed!\n");
  365.                 return 0;
  366.         }
  367.  
  368.         // initialize
  369.         success = success && emit_file(NULL, EMIT_FILE_INIT);
  370.  
  371.         success = success && emit_byte(0, EMIT_BYTE_INIT);
  372.  
  373.         success = success && emit_bits(0, EMIT_BITS_INIT);
  374.  
  375.  
  376.         // manage zx header info
  377.         if( wrk.zxheader )
  378.         {
  379.                 success = success && emit_file( (UBYTE*)"HR", 2);
  380.  
  381.                 wrlen[0] = wrk.inlen&0x00FF;
  382.                 wrlen[1] = (wrk.inlen>>8)&0x00FF;
  383.                 success = success && emit_file( wrlen, 2); // unpacked length mod 65536
  384.  
  385.                 success = success && emit_file( wrlen, 2); // packed length - !to be filled later!
  386.  
  387.         success = success && emit_file( &wrk.indata[wrk.inlen-6], 6); // last bytes
  388.         }
  389.  
  390.         // schedule first byte to be placed just after first bitstream word
  391.         success = success && emit_byte( wrk.indata[0], EMIT_BYTE_ADD);
  392.  
  393.         // go emitting codes
  394.         position = 1;
  395.  
  396.         while( (position<actual_len) && success )
  397.         {
  398.                 #ifdef DBG
  399.                         printf("%04x:",position);
  400.                 #endif
  401.  
  402.                 length = optch[position].code.length;
  403.                 disp   = optch[position].code.disp;
  404.  
  405.                 if( length==0 )
  406.                 {
  407.                         printf("mhmt-emit.c:emit_hrust() - encountered stop-code in optimal chain before emitting all data!\n");
  408.                         return 0;
  409.                 }
  410.                 else if( disp==0 ) // copy-bytes
  411.                 {
  412.                         if( length==1 ) // 1 byte: %1<byte>
  413.                         {
  414.                                 success = success && emit_bits( 0x80000000, 1 );
  415.                                 success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
  416.                         }
  417.                         else if( (12<=length) && (length<=42) && ( !(length&1) ) ) // %0110001abcd<byte,byte,...>
  418.                         {
  419.                                 varbits = (length-12)<<27;
  420.                                 success = success && emit_bits( 0x62000000, 7 );
  421.  
  422.                                 success = success && emit_bits( varbits, 4 );
  423.  
  424.                                 varlen = 0;
  425.                                 while( success && (varlen<(ULONG)length) )
  426.                                 {
  427.                                         success = success && emit_byte( wrk.indata[position+varlen], EMIT_BYTE_ADD );
  428.                                         varlen++;
  429.                                 }
  430.                         }
  431.                         else
  432.                                 goto INVALID_CODE_HRUST;
  433.                 }
  434.                 else if( length==(-3) ) // insertion code
  435.                 {
  436.                         if( (-16)<=disp && disp<=(-1) ) // %011001abcd<byte>
  437.                         {
  438.                                 success = success && emit_bits( 0x64000000, 6 );
  439.                                 success = success && emit_bits( disp<<(32-4), 4 );
  440.                         }
  441.                         else if( (-79)<=disp && disp<(-16) )
  442.                         {
  443.                                 if( disp&1 ) // ffb1..ffef: %01001<byte><byte>
  444.                                 {
  445.                                         success = success && emit_bits( 0x48000000, 5 );
  446.  
  447.                                         varbits = disp&0x00FF;
  448.                                         varbits += 15;
  449.                                         varbits ^= 3;
  450.                                         varbits = ( (varbits>>1)&0x007F ) | ( (varbits<<7)&0x0080 );
  451.  
  452.                                         success = success && emit_byte( (UBYTE)(varbits&0x00FF), EMIT_BYTE_ADD );
  453.                                 }
  454.                                 else // ffb2..ffee: %00110<byte><byte>
  455.                                 {
  456.                                         success = success && emit_bits( 0x30000000, 5 );
  457.  
  458.                                         varbits = disp&0x00FF;
  459.                                         varbits += 15;
  460.                                         varbits ^= 2;
  461.                                         varbits = ( (varbits>>1)&0x007F ) | ( (varbits<<7)&0x0080 );
  462.  
  463.                                         success = success && emit_byte( (UBYTE)(varbits&0x00FF), EMIT_BYTE_ADD );
  464.                                 }
  465.                         }
  466.                         else
  467.                                 goto INVALID_CODE_HRUST;
  468.  
  469.                         success = success && emit_byte( wrk.indata[position+1], EMIT_BYTE_ADD );
  470.                 }
  471.                 else if( length==1 ) // %000abc
  472.                 {
  473.                         if( (-8)<=disp && disp<=(-1) )
  474.                         {
  475.                                 success = success && emit_bits( 0x00000000, 3 );
  476.                                 success = success && emit_bits( disp<<(32-3), 3 );
  477.                         }
  478.                         else
  479.                                 goto INVALID_CODE_HRUST;
  480.                 }
  481.                 else if( length==2 )
  482.                 {
  483.                         if( (-32)<=disp && disp<=(-1) ) // %00111abcde
  484.                         {
  485.                                 success = success && emit_bits( 0x38000000, 5 );
  486.                                 success = success && emit_bits( disp<<(32-5), 5 );
  487.                         }
  488.                         else if( (-256)<=disp && disp<(-32) ) // %00110<byte>
  489.                         {
  490.                                 success = success && emit_bits( 0x30000000, 5 );
  491.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  492.                         }
  493.                         else if( (-512)<=disp && disp<(-256) ) // %00101<byte>
  494.                         {
  495.                                 success = success && emit_bits( 0x28000000, 5 );
  496.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  497.                         }
  498.                         else if( (-768)<=disp && disp<(-512) ) // %00100<byte>
  499.                         {
  500.                                 success = success && emit_bits( 0x20000000, 5 );
  501.                                 success = success && emit_byte( (UBYTE)(0x00FF & disp), EMIT_BYTE_ADD );
  502.                         }
  503.                         else
  504.                                 goto INVALID_CODE_HRUST;
  505.                 }
  506.                 else if (3<=length && length<=3839 && (-65536)<=disp && disp<=(-1) )
  507.                 {
  508.                         // first see if we need emitting expansion codes
  509.  
  510.                                 //  -513.. -1024  (FDFF..FC00) - 2 bits
  511.                                 //  -1025..-2048  (FBFF..F800) - 3
  512.                                 //  -2049..-4096  (F7FF..F000) - 4
  513.                                 //  -4097..-8192  (EFFF..E000) - 5
  514.                                 //  -8193..-16384 (DFFF..C000) - 6
  515.                                 // -16385..-32768 (BFFF..8000) - 7
  516.                                 // -32769..-65536 (7FFF..0000) - 8
  517.                         if( disp<(-512) )
  518.                         {
  519.                                 varbits = 1024;
  520.                                 varlen  = 2;
  521.                                 while( (ULONG)(-disp) > varbits )
  522.                                 {
  523.                                         varbits <<= 1;
  524.                                         varlen++;
  525.                                 }
  526.  
  527.                                 // emit expansion codes, if necessary: %00110<FE>
  528.                                 while( varlen>expbitlen )
  529.                                 {
  530.                                         success = success && emit_bits( 0x30000000, 5 );
  531.                                         success = success && emit_byte( 0x00FE, EMIT_BYTE_ADD );
  532.                                         #ifdef DBG
  533.                                                 printf("expansion\n");
  534.                                         #endif
  535.  
  536.                                         expbitlen++;
  537.                                 }
  538.                         }
  539.  
  540.  
  541.  
  542.  
  543.  
  544.                         // emit length
  545.  
  546.                         if( length<=15 ) // 3..15
  547.                         {
  548.                                 success = success && emit_bits( 0, 1 );
  549.  
  550.                                 if( length==3 )
  551.                                 {
  552.                                         success = success && emit_bits( 0x80000000, 2 ); // %010
  553.                                 }
  554.                                 else
  555.                                 {
  556.                                         varlen  = length/3;
  557.                                         varbits = length%3;
  558.  
  559.                                         success = success && emit_bits( 0xFFFFFFFF, varlen<<1 );
  560.  
  561.                                         if( length!=15 )
  562.                                                 success = success && emit_bits( varbits<<(32-2), 2 );
  563.                                 }
  564.                         }
  565.                         else if( length<=127 ) // 16..127: %0110000abcdefg
  566.                         {
  567.                                 success = success && emit_bits( 0x60000000, 7 );
  568.                                 success = success && emit_bits( length<<(32-7), 7 );
  569.                         }
  570.                         else // 128..3839
  571.                         {
  572.                                 success = success && emit_bits( 0x60000000, 7 );
  573.                                 success = success && emit_bits( length<<(32-15), 7 );
  574.                                 success = success && emit_byte( (UBYTE)(length&0x00FF), EMIT_BYTE_ADD );
  575.                         }
  576.  
  577.  
  578.                         // emit displacement
  579.                         if( (-32)<=disp ) // ffe0..ffff: %10abcde
  580.                         {
  581.                                 success = success && emit_bits( 0x80000000, 2 );
  582.                                 success = success && emit_bits( disp<<(32-5), 5 );
  583.                         }
  584.                         else if( (-256)<=disp ) // ff00..ffdf: %01<byte>
  585.                         {
  586.                                 success = success && emit_bits( 0x40000000, 2 );
  587.                                 success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
  588.                         }
  589.                         else if( (-512)<=disp ) // fe00..feff: %00<byte>
  590.                         {
  591.                                 success = success && emit_bits( 0x00000000, 2 );
  592.                                 success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
  593.                         }
  594.                         else // variable code length: [-65536..-512)
  595.                         {
  596.  
  597.                                 // displacement itself: %11ab[cdefgh]<byte>
  598.                                 success = success && emit_bits( 0xC0000000, 2 );
  599.                                 success = success && emit_bits( disp<<(24-expbitlen), expbitlen );
  600.                                 success = success && emit_byte( (UBYTE)(disp&0x00FF), EMIT_BYTE_ADD );
  601.                         }
  602.                 }
  603.                 else
  604.                 {
  605. INVALID_CODE_HRUST:
  606.                         printf("mhmt-emit.c:emit_hrust() - invalid code: length=%d, displacement=%d\n",length,disp);
  607.                         return 0;
  608.                 }
  609.  
  610.                 #ifdef DBG
  611.                         if( length==(-3) )
  612.                         {
  613.                                 printf("insert-match.len=%d,disp=%d\n",(-length),disp);
  614.                         }
  615.                         else if( disp==0 )
  616.                         {
  617.                                 printf("copy.len=%d\n",length);
  618.                         }
  619.                         else
  620.                         {
  621.                                 printf("match.len=%d,disp=%d\n",length,disp);
  622.                         }
  623.                 #endif
  624.  
  625.  
  626.                 if( max_disp > disp ) max_disp = disp;
  627.  
  628.                 if( length>0 ) // account for negative length
  629.                         position += length;
  630.                 else
  631.                         position -= length;
  632.         }
  633.  
  634.         // stop-code: %0110_0000_0011_11
  635.         success = success && emit_bits( 0x603C0000, 14 );
  636.  
  637.         success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
  638.         success = success && emit_file( NULL, EMIT_FILE_FINISH );
  639.  
  640.         // complete the header
  641.         if( success && wrk.zxheader )
  642.         {
  643.                 success = success && ( (0xFFFFFFFF) != (flen = ftell(wrk.file_out)) ); //filesize
  644.                
  645.                 success = success && !fseek(wrk.file_out, 4, SEEK_SET); // pos to 4th byte
  646.                
  647.                 wrlen[0] = flen&255;
  648.                 wrlen[1] = (flen>>8)&255;
  649.                 // write len
  650.                 success = success && ( 2==fwrite(wrlen, 1, 2, wrk.file_out) );
  651.                
  652.                 if( !success )
  653.                 {
  654.                         printf("emit_hrust(): failed to write packed length to header!\n");
  655.                         return 0;
  656.                 }
  657.         }
  658.        
  659.        
  660.         if( success )
  661.         {
  662.                 printf("Maximum displacement actually used is %d.\n",-max_disp);
  663.  
  664.                 // TODO: patch packed length in file, if zx header
  665.         }
  666.  
  667.  
  668.         return success;
  669. }
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.        
  693. // actually generate output file from optimal chain - zx7 version
  694. ULONG emit_zx7(struct optchain * optch, ULONG actual_len)
  695. {
  696.         ULONG position;
  697.         LONG length;
  698.         LONG disp;
  699.  
  700.         LONG max_disp; // maximum encountered displacement
  701.  
  702.  
  703.         ULONG varbits,varlen;
  704.  
  705.         ULONG success = 1;
  706.  
  707.         max_disp = 0;
  708.  
  709.  
  710.         // some checks
  711.         if( !optch )
  712.         {
  713.                 printf("mhmt-emit.c:emit_zx7() - NULL passed!\n");
  714.                 return 0;
  715.         }
  716.  
  717.         // initialize
  718.         success = success && emit_file(NULL, EMIT_FILE_INIT);
  719.  
  720.         success = success && emit_byte(0, EMIT_BYTE_INIT);
  721.  
  722.         success = success && emit_bits(0, EMIT_BITS_INIT);
  723.  
  724.  
  725.         // copy first byte as-is
  726.         success = success && emit_file( wrk.indata, 1);
  727. //printf("FIRST: #%02x\n\n",*wrk.indata);
  728.  
  729.         // go emitting codes
  730.         position = 1;
  731.  
  732.         while( (position<actual_len) && success )
  733.         {
  734.                 length = optch[position].code.length;
  735.                 disp   = optch[position].code.disp;
  736.  
  737.                 if( length==0 )
  738.                 {
  739.                         printf("mhmt-emit.c:emit_zx7() - encountered stop-code in optimal chain before emitting all data!\n");
  740.                         return 0;
  741.                 }
  742.                 else if( length==1 ) // copy-byte
  743.                 {
  744.                         if( disp==0 ) // copy-byte (%0<byte>)
  745.                         {
  746. //printf("BITS: %%");
  747.                                 success = success && emit_bits( 0x00000000, 1 );
  748.                                 success = success && emit_byte( wrk.indata[position], EMIT_BYTE_ADD );
  749. //printf("\nBYTE: #%02x\n\n",wrk.indata[position]);
  750.                         }
  751.                         else
  752.                                 goto INVALID_CODE_ZX7;
  753.                 }
  754.                 else if( 2<=length && length<=65536 )
  755.                 {
  756.                         // length coding
  757.                         varbits = length-1;
  758.                         varlen=0;
  759.                         while( varbits )
  760.                         {
  761.                                 varbits>>=1;
  762.                                 varlen+=1;
  763.                         }
  764.                         // varlen=1 for len=2,
  765.                         //       =2 for len=3,4
  766.                         //       =3         5,6,7,8
  767.  
  768. //printf("BITS: %%");
  769.                         success = success && emit_bits( 0x80000000, varlen );
  770.                         success = success && emit_bits( (length-1)<<(32-varlen), varlen );
  771.  
  772.                         // displacement coding
  773.                         if( (-128)<=disp && disp<=(-1) )
  774.                         {
  775.                                 success = success && emit_byte( ((UBYTE)(-disp-1))&127, EMIT_BYTE_ADD );
  776. //printf("\nBYTE: #%02x\n\n",((UBYTE)(-disp-1))&127);
  777.                                 if( max_disp > disp ) max_disp = disp;
  778.                         }
  779.                         else if( (-2176)<=disp && disp<(-128) )
  780.                         {
  781.                                 success = success && emit_byte( (((UBYTE)(-disp-129))&127)|128, EMIT_BYTE_ADD );
  782. //printf("\nBYTE: #%02x\n",(((UBYTE)(-disp-129))&127)|128);
  783. //printf("BITS: %%");
  784.                                 success = success && emit_bits( ((-disp-129)&0x780)<<21, 4 );
  785. //printf("\n\n");
  786.                                 if( max_disp > disp ) max_disp = disp;
  787.                         }
  788.                         else
  789.                                 goto INVALID_CODE_ZX7;
  790.                 }
  791.                 else
  792.                 {
  793. INVALID_CODE_ZX7:
  794.                         printf("mhmt-emit.c:emit_zx7() - invalid code: length=%d, displacement=%d\n",length,disp);
  795.                         return 0;
  796.                 }
  797.  
  798.                 position += length;
  799.         }
  800.  
  801.         // stop-code
  802. //printf("BITS: %%");
  803.         success = success && emit_bits( 0x80004000, 18 );
  804.         success = success && emit_bits( 0, EMIT_BITS_FINISH ); // this also flushes emit_byte()
  805. //printf("\n");
  806.         success = success && emit_file( NULL, EMIT_FILE_FINISH );
  807.  
  808.         if( success )
  809.                 printf("Maximum displacement actually used is %d.\n",-max_disp);
  810.  
  811.         return success;
  812. }
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855. // emit bytes to the output buffer and flush to file when needed
  856. // 'operation' defines what to do as described in *.h
  857. // 'byte' is emitted only when length >=1,
  858. // When length=EMIT_FILE_FINISH (0), flushes tail to file
  859. // When length=EMIT_FILE_INIT (-1), initializes.
  860. //
  861. // returns zero in case of any problems (fails to write buffer to file), otherwise non-zero
  862. ULONG emit_file(UBYTE * bytes, LONG length)
  863. {
  864.         static UBYTE buffer[EMIT_FILEBUF_SIZE];
  865.  
  866.         static ULONG position;
  867.  
  868.  
  869.         if( length==EMIT_FILE_INIT )
  870.         {
  871.                 position = 0;
  872.  
  873.                 return 1;
  874.         }
  875.         else if( length>0 )
  876.         {
  877.                 while( (position+length) >= EMIT_FILEBUF_SIZE ) // if we have to flush buffer
  878.                 {
  879.                         length -= (EMIT_FILEBUF_SIZE-position);
  880.  
  881.                         while( position < EMIT_FILEBUF_SIZE ) // fill buffer to the end, if possible
  882.                         {
  883.                                 buffer[position++] = *(bytes++);
  884.                         }
  885.  
  886.                         if( EMIT_FILEBUF_SIZE!=fwrite(buffer, 1, EMIT_FILEBUF_SIZE, wrk.file_out) )
  887.                         {
  888.                                 printf("mhmt-emit.c:emit_file() can't write to file!\n");
  889.                                 return 0;
  890.                         }
  891.  
  892.                         position=0;
  893.                 }
  894.  
  895.                 while( length-- ) // if something left that does not need flushing
  896.                 {
  897.                         buffer[position++] = *(bytes++);
  898.                 }
  899.  
  900.                 return 1;
  901.         }
  902.         else if( length==EMIT_FILE_FINISH )
  903.         {
  904.                 if( position>0 ) // do we have anything to flush?
  905.                 {
  906.                         if( position!=fwrite(buffer, 1, position, wrk.file_out) )
  907.                         {
  908.                                 printf("mhmt-emit.c:emit_file() can't write to file!\n");
  909.                                 return 0;
  910.                         }
  911.                 }
  912.  
  913.                 return 1;
  914.         }
  915.         else
  916.         {
  917.                 printf("mhmt-emit.c:emit_file() encountered invalid arguments!\n");
  918.                 return 0;
  919.         }
  920. }
  921.  
  922.  
  923.  
  924. // store emitted bytes in special buffer, because emitted bits go earlier than corresponding bytes.
  925. // then, when bits are flushed to the file, bytes are flushed just after.
  926. // returns zero if any problems. "operation" dictates what to do (see *.h)
  927. ULONG emit_byte(UBYTE byte, ULONG operation)
  928. {
  929.         static UBYTE buffer[EMIT_BYTEBUF_SIZE];
  930.  
  931.         static ULONG in_pos, out_pos;
  932.  
  933.         ULONG success;
  934.  
  935.  
  936.         switch( operation )
  937.         {
  938.         case EMIT_BYTE_INIT:
  939.  
  940.                 in_pos  = 0;
  941.                 out_pos = 0;
  942.  
  943.                 return 1;
  944.  
  945.  
  946.         case EMIT_BYTE_ADD:
  947.  
  948.                 #ifdef DBG
  949.                         printf("<%02x>",byte&0x00FF);
  950.                 #endif
  951.  
  952.                 buffer[in_pos] = byte;
  953.  
  954.                 in_pos = (in_pos+1) & (EMIT_BYTEBUF_SIZE-1);
  955.  
  956.  
  957.                 if( in_pos==out_pos ) // overflow!
  958.                 {
  959.                         printf("mhmt-emit.c:emit_byte() buffer overflow!\n");
  960.                         return 0;
  961.                 }
  962.  
  963.                 return 1;
  964.  
  965.  
  966.         case EMIT_BYTE_FLUSH:
  967.  
  968.                 if( in_pos==out_pos ) // nothing to do?
  969.                         return 1;
  970.                 else if( in_pos>out_pos ) // no index wraparound
  971.                 {
  972.                         success = emit_file( &buffer[out_pos], in_pos-out_pos );
  973.                 }
  974.                 else // in_pos<out_pos - wraparound
  975.                 {
  976.                         success = emit_file( &buffer[out_pos], EMIT_BYTEBUF_SIZE-out_pos );
  977.  
  978.                         if( in_pos )
  979.                                 success = success && emit_file( &buffer[0], in_pos );
  980.                 }
  981.  
  982.                 out_pos=in_pos;
  983.                 return success;
  984.  
  985.         default:
  986.                 printf("mhmt-emit.c:emit_byte() encountered invalid arguments!\n");
  987.                 return 0;
  988.         }
  989. }
  990.  
  991.  
  992. // collects bits, emit to output stream when needed. accounts for word or byte mode, little-big endian, empty or full bits
  993. // length is either positive number of bits or one of two special cases (see *.h)
  994. //
  995. ULONG emit_bits(ULONG msb_aligned_bits, LONG length)
  996. {
  997.         static ULONG bit_store;
  998.         static ULONG bit_count;
  999.  
  1000.         ULONG max_bits;
  1001.  
  1002.         ULONG success = 1;
  1003.  
  1004.  
  1005.         max_bits = wrk.wordbit ? 16 : 8;
  1006.  
  1007.         if( length==EMIT_BITS_INIT )
  1008.         {
  1009.                 bit_store = 0;
  1010.                 bit_count = 0;
  1011.                 return 1;
  1012.         }
  1013.         else if( length==EMIT_BITS_FINISH )
  1014.         {
  1015.                 if( bit_count ) // some bits to flush
  1016.                 {
  1017.                         while( (bit_count++)<max_bits )
  1018.                                 bit_store <<= 1;
  1019.  
  1020.                         success = success && emit_bits_flush(bit_store);
  1021.                 }
  1022.  
  1023.                 success = success && emit_byte(0, EMIT_BYTE_FLUSH);
  1024.  
  1025.                 return success;
  1026.         }
  1027.         else if( length>0 ) // add bits
  1028.         {
  1029.                 do
  1030.                 {
  1031.                         if( !wrk.fullbits ) // empty bits - check for flushing before shiftin
  1032.                         {
  1033.                                 if( bit_count==max_bits )
  1034.                                 {
  1035.                                         success = success && emit_bits_flush(bit_store);
  1036.                                         success = success && emit_byte(0, EMIT_BYTE_FLUSH);
  1037.  
  1038.                                         bit_count = 0;
  1039.                                 }
  1040.                         }
  1041.  
  1042.  
  1043. //printf("%d",1&(msb_aligned_bits>>31));
  1044.  
  1045.                         bit_store = (bit_store<<1) | ( 1 & (msb_aligned_bits>>31) );
  1046.                         msb_aligned_bits <<= 1;
  1047.                         bit_count++;
  1048.  
  1049.                         if( wrk.fullbits ) // full bits - check for flushing after bit shiftin
  1050.                         {
  1051.                                 if( bit_count==max_bits )
  1052.                                 {
  1053.                                         success = success && emit_bits_flush(bit_store);
  1054.                                         success = success && emit_byte(0, EMIT_BYTE_FLUSH);
  1055.  
  1056.                                         bit_count = 0;
  1057.                                 }
  1058.                         }
  1059.  
  1060.                 } while( --length );
  1061.  
  1062.                 return success;
  1063.         }
  1064.         else
  1065.         {
  1066.                 printf("mhmt-emit.c:emit_bits() encountered invalid arguments!\n");
  1067.                 return 0;
  1068.         }
  1069. }
  1070.  
  1071. // flushes either word or byte from given bits
  1072. //
  1073. ULONG emit_bits_flush(ULONG bits)
  1074. {
  1075.         UBYTE store_byte;
  1076.  
  1077.         ULONG success = 1;
  1078.  
  1079.         if( wrk.wordbit ) // 16bits
  1080.         {
  1081.                 if( wrk.bigend ) // big endian
  1082.                 {
  1083.                         store_byte = 0x00FF & (bits >> 8);
  1084.                         success = success && emit_file( &store_byte, 1);
  1085.  
  1086.                         store_byte = 0x00FF & bits;
  1087.                         success = success && emit_file( &store_byte, 1);
  1088.                 }
  1089.                 else // little endian
  1090.                 {
  1091.                         store_byte = 0x00FF & bits;
  1092.                         success = success && emit_file( &store_byte, 1);
  1093.  
  1094.                         store_byte = 0x00FF & (bits >> 8);
  1095.                         success = success && emit_file( &store_byte, 1);
  1096.                 }
  1097.         }
  1098.         else // 8bits
  1099.         {
  1100.                 store_byte = 0x00FF & bits;
  1101.                 success = success && emit_file( &store_byte, 1);
  1102.         }
  1103.  
  1104.         return success;
  1105. }
  1106.  
  1107.