Blame |
Last modification |
View Log
| Download
| RSS feed
#include <stdio.h>
#include "mhmt-types.h"
#include "mhmt-globals.h"
#include "mhmt-emit.h"
#include "mhmt-lz.h"
#include "mhmt-optimal.h"
// actually generate output file from optimal chain - MegaLZ version
ULONG emit_megalz
(struct optchain
* optch
, ULONG actual_len
)
{
ULONG position
;
LONG length
;
LONG disp
;
LONG max_disp
; // maximum encountered displacement
ULONG varbits
,varlen
;
ULONG success
= 1;
max_disp
= 0;
// some checks
if( !optch
)
{
printf("mhmt-emit.c:emit_megalz() - NULL passed!\n");
return 0;
}
// initialize
success
= success
&& emit_file
(NULL
, EMIT_FILE_INIT
);
success
= success
&& emit_byte
(0, EMIT_BYTE_INIT
);
success
= success
&& emit_bits
(0, EMIT_BITS_INIT
);
// copy first byte as-is
success
= success
&& emit_file
( wrk.
indata, 1);
// go emitting codes
position
= 1;
while( (position
<actual_len
) && success
)
{
length
= optch
[position
].
code.
length;
disp
= optch
[position
].
code.
disp;
if( length
==0 )
{
printf("mhmt-emit.c:emit_megalz() - encountered stop-code in optimal chain before emitting all data!\n");
return 0;
}
else if( length
==1 ) // either copy-byte or len=1 code
{
if( disp
==0 ) // copy-byte (%1<byte>)
{
success
= success
&& emit_bits
( 0x80000000, 1 );
success
= success
&& emit_byte
( wrk.
indata[position
], EMIT_BYTE_ADD
);
}
else if( (-8)<=disp
&& disp
<=(-1) ) // len=1, disp=-1..-8 (%000abc)
{
success
= success
&& emit_bits
( 0x00000000, 3 );
success
= success
&& emit_bits
( disp
<<(32-3), 3 );
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_MEGALZ
;
}
else if( length
==2 )
{
if( (-256)<=disp
&& disp
<=(-1) ) // %001<byte>
{
success
= success
&& emit_bits
( 0x20000000, 3 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_MEGALZ
;
}
else if( 3<=length
&& length
<=255 )
{
// length coding
if( length
==3 ) // %010
{
success
= success
&& emit_bits
( 0x40000000, 3 );
}
else // length==4..255, %011
{
success
= success
&& emit_bits
( 0x60000000, 3 );
// calculate size of variable bits
varlen
= 0;
varbits
= (length
-2)>>1;
while( varbits
)
{
varbits
>>= 1;
varlen
++;
}
varbits
= length
-2-(1<<varlen
); // prepare length coding
success
= success
&& emit_bits
( 1<<(32-varlen
), varlen
);
success
= success
&& emit_bits
( varbits
<<(32-varlen
), varlen
);
}
// displacement coding
if( (-256)<=disp
&& disp
<=(-1) )
{
success
= success
&& emit_bits
( 0, 1 );
success
= success
&& emit_byte
( (UBYTE
)(0x00ff & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else if( (-4352)<=disp
&& disp
<(-256) )
{
success
= success
&& emit_bits
( 0x80000000, 1 );
success
= success
&& emit_bits
( (0x0F00&(disp
+0x0100))<<20, 4 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_MEGALZ
;
}
else
{
INVALID_CODE_MEGALZ
:
printf("mhmt-emit.c:emit_megalz() - invalid code: length=%d, displacement=%d\n",length
,disp
);
return 0;
}
position
+= length
;
}
// stop-code
success
= success
&& emit_bits
( 0x60100000, 12 );
success
= success
&& emit_bits
( 0, EMIT_BITS_FINISH
); // this also flushes emit_byte()
success
= success
&& emit_file
( NULL
, EMIT_FILE_FINISH
);
if( success
)
printf("Maximum displacement actually used is %d.\n",-max_disp
);
return success
;
}
// actually generate output file from optimal chain - hrum version
ULONG emit_hrum
(struct optchain
* optch
, ULONG actual_len
)
{
ULONG position
;
LONG length
;
LONG disp
;
LONG max_disp
; // maximum encountered displacement
ULONG varbits
,varlen
;
ULONG success
= 1;
max_disp
= 0;
// some checks
if( !optch
)
{
printf("mhmt-emit.c:emit_hrum() - NULL passed!\n");
return 0;
}
// initialize
success
= success
&& emit_file
(NULL
, EMIT_FILE_INIT
);
success
= success
&& emit_byte
(0, EMIT_BYTE_INIT
);
success
= success
&& emit_bits
(0, EMIT_BITS_INIT
);
// manage zx header info
if( wrk.
zxheader )
{
success
= success
&& emit_file
( &wrk.
indata[wrk.
inlen-5], 5);
success
= success
&& emit_file
( (UBYTE
*)"\020\020", 2); // 0x10, 0x10
}
// schedule first byte to be placed just after first bitstream word
success
= success
&& emit_byte
( wrk.
indata[0], EMIT_BYTE_ADD
);
// go emitting codes
position
= 1;
while( (position
<actual_len
) && success
)
{
length
= optch
[position
].
code.
length;
disp
= optch
[position
].
code.
disp;
if( length
==0 )
{
printf("mhmt-emit.c:emit_hrum() - encountered stop-code in optimal chain before emitting all data!\n");
return 0;
}
else if( length
==1 ) // either copy-byte or len=1 code
{
if( disp
==0 ) // copy-byte (%1<byte>)
{
success
= success
&& emit_bits
( 0x80000000, 1 );
success
= success
&& emit_byte
( wrk.
indata[position
], EMIT_BYTE_ADD
);
}
else if( (-8)<=disp
&& disp
<=(-1) ) // len=1, disp=-1..-8 (%000abc)
{
success
= success
&& emit_bits
( 0x00000000, 3 );
success
= success
&& emit_bits
( disp
<<(32-3), 3 );
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_HRUM
;
}
else if( length
==2 )
{
if( (-256)<=disp
&& disp
<=(-1) ) // %001<byte>
{
success
= success
&& emit_bits
( 0x20000000, 3 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_HRUM
;
}
else if( 3<=length
&& length
<=255 )
{
// length coding
if( length
==3 )
{
success
= success
&& emit_bits
( 0x40000000, 3 );
}
else if( length
<=15 )
{
varlen
=2;
varbits
= (length
% 3)<<30; // low 2 bits (except for length==15)
if( length
==15 ) varbits
= 0xC0000000;
if( length
>=6 ) { varbits
= 0xC0000000 | (varbits
>>2); varlen
+= 2; }
if( length
>=9 ) { varbits
= 0xC0000000 | (varbits
>>2); varlen
+= 2; }
if( length
>=12) { varbits
= 0xC0000000 | (varbits
>>2); varlen
+= 2; }
success
= success
&& emit_bits
( 0x60000000, 3 );
success
= success
&& emit_bits
( varbits
, varlen
);
}
else // 15<length<=255: %01100<len>
{
success
= success
&& emit_bits
( 0x60000000, 5 );
success
= success
&& emit_byte
( (UBYTE
)(length
&0x00FF), EMIT_BYTE_ADD
);
}
// displacement coding
if( (-256)<=disp
&& disp
<=(-1) ) // %0<disp>
{
success
= success
&& emit_bits
( 0x00000000, 1 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else if( (-4096)<=disp
&& disp
<(-256) ) //%1abcd<disp>
{
success
= success
&& emit_bits
( 0x80000000, 1 );
success
= success
&& emit_bits
( (0x0F00&disp
)<<20, 4 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_HRUM
;
}
else
{
INVALID_CODE_HRUM
:
printf("mhmt-emit.c:emit_hrum() - invalid code: length=%d, displacement=%d\n",length
,disp
);
return 0;
}
position
+= length
;
}
// stop-code: %01100<0>
success
= success
&& emit_bits
( 0x60000000, 5 );
success
= success
&& emit_byte
( 0x00, EMIT_BYTE_ADD
);
success
= success
&& emit_bits
( 0, EMIT_BITS_FINISH
); // this also flushes emit_byte()
success
= success
&& emit_file
( NULL
, EMIT_FILE_FINISH
);
if( success
)
printf("Maximum displacement actually used is %d.\n",-max_disp
);
return success
;
}
ULONG emit_hrust
(struct optchain
* optch
, ULONG actual_len
)
{
ULONG position
;
LONG length
;
LONG disp
;
LONG max_disp
; // maximum encountered displacement
ULONG varbits
,varlen
;
ULONG success
= 1;
UBYTE wrlen
[2];
ULONG expbitlen
= 2; // expandable match: bitlength of displacement
ULONG flen
;
max_disp
= 0;
// some checks
if( !optch
)
{
printf("mhmt-emit.c:emit_hrust() - NULL passed!\n");
return 0;
}
// initialize
success
= success
&& emit_file
(NULL
, EMIT_FILE_INIT
);
success
= success
&& emit_byte
(0, EMIT_BYTE_INIT
);
success
= success
&& emit_bits
(0, EMIT_BITS_INIT
);
// manage zx header info
if( wrk.
zxheader )
{
success
= success
&& emit_file
( (UBYTE
*)"HR", 2);
wrlen
[0] = wrk.
inlen&0x00FF;
wrlen
[1] = (wrk.
inlen>>8)&0x00FF;
success
= success
&& emit_file
( wrlen
, 2); // unpacked length mod 65536
success
= success
&& emit_file
( wrlen
, 2); // packed length - !to be filled later!
success
= success
&& emit_file
( &wrk.
indata[wrk.
inlen-6], 6); // last bytes
}
// schedule first byte to be placed just after first bitstream word
success
= success
&& emit_byte
( wrk.
indata[0], EMIT_BYTE_ADD
);
// go emitting codes
position
= 1;
while( (position
<actual_len
) && success
)
{
#ifdef DBG
printf("%04x:",position
);
#endif
length
= optch
[position
].
code.
length;
disp
= optch
[position
].
code.
disp;
if( length
==0 )
{
printf("mhmt-emit.c:emit_hrust() - encountered stop-code in optimal chain before emitting all data!\n");
return 0;
}
else if( disp
==0 ) // copy-bytes
{
if( length
==1 ) // 1 byte: %1<byte>
{
success
= success
&& emit_bits
( 0x80000000, 1 );
success
= success
&& emit_byte
( wrk.
indata[position
], EMIT_BYTE_ADD
);
}
else if( (12<=length
) && (length
<=42) && ( !(length
&1) ) ) // %0110001abcd<byte,byte,...>
{
varbits
= (length
-12)<<27;
success
= success
&& emit_bits
( 0x62000000, 7 );
success
= success
&& emit_bits
( varbits
, 4 );
varlen
= 0;
while( success
&& (varlen
<(ULONG
)length
) )
{
success
= success
&& emit_byte
( wrk.
indata[position
+varlen
], EMIT_BYTE_ADD
);
varlen
++;
}
}
else
goto INVALID_CODE_HRUST
;
}
else if( length
==(-3) ) // insertion code
{
if( (-16)<=disp
&& disp
<=(-1) ) // %011001abcd<byte>
{
success
= success
&& emit_bits
( 0x64000000, 6 );
success
= success
&& emit_bits
( disp
<<(32-4), 4 );
}
else if( (-79)<=disp
&& disp
<(-16) )
{
if( disp
&1 ) // ffb1..ffef: %01001<byte><byte>
{
success
= success
&& emit_bits
( 0x48000000, 5 );
varbits
= disp
&0x00FF;
varbits
+= 15;
varbits
^= 3;
varbits
= ( (varbits
>>1)&0x007F ) | ( (varbits
<<7)&0x0080 );
success
= success
&& emit_byte
( (UBYTE
)(varbits
&0x00FF), EMIT_BYTE_ADD
);
}
else // ffb2..ffee: %00110<byte><byte>
{
success
= success
&& emit_bits
( 0x30000000, 5 );
varbits
= disp
&0x00FF;
varbits
+= 15;
varbits
^= 2;
varbits
= ( (varbits
>>1)&0x007F ) | ( (varbits
<<7)&0x0080 );
success
= success
&& emit_byte
( (UBYTE
)(varbits
&0x00FF), EMIT_BYTE_ADD
);
}
}
else
goto INVALID_CODE_HRUST
;
success
= success
&& emit_byte
( wrk.
indata[position
+1], EMIT_BYTE_ADD
);
}
else if( length
==1 ) // %000abc
{
if( (-8)<=disp
&& disp
<=(-1) )
{
success
= success
&& emit_bits
( 0x00000000, 3 );
success
= success
&& emit_bits
( disp
<<(32-3), 3 );
}
else
goto INVALID_CODE_HRUST
;
}
else if( length
==2 )
{
if( (-32)<=disp
&& disp
<=(-1) ) // %00111abcde
{
success
= success
&& emit_bits
( 0x38000000, 5 );
success
= success
&& emit_bits
( disp
<<(32-5), 5 );
}
else if( (-256)<=disp
&& disp
<(-32) ) // %00110<byte>
{
success
= success
&& emit_bits
( 0x30000000, 5 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
}
else if( (-512)<=disp
&& disp
<(-256) ) // %00101<byte>
{
success
= success
&& emit_bits
( 0x28000000, 5 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
}
else if( (-768)<=disp
&& disp
<(-512) ) // %00100<byte>
{
success
= success
&& emit_bits
( 0x20000000, 5 );
success
= success
&& emit_byte
( (UBYTE
)(0x00FF & disp
), EMIT_BYTE_ADD
);
}
else
goto INVALID_CODE_HRUST
;
}
else if (3<=length
&& length
<=3839 && (-65536)<=disp
&& disp
<=(-1) )
{
// first see if we need emitting expansion codes
// -513.. -1024 (FDFF..FC00) - 2 bits
// -1025..-2048 (FBFF..F800) - 3
// -2049..-4096 (F7FF..F000) - 4
// -4097..-8192 (EFFF..E000) - 5
// -8193..-16384 (DFFF..C000) - 6
// -16385..-32768 (BFFF..8000) - 7
// -32769..-65536 (7FFF..0000) - 8
if( disp
<(-512) )
{
varbits
= 1024;
varlen
= 2;
while( (ULONG
)(-disp
) > varbits
)
{
varbits
<<= 1;
varlen
++;
}
// emit expansion codes, if necessary: %00110<FE>
while( varlen
>expbitlen
)
{
success
= success
&& emit_bits
( 0x30000000, 5 );
success
= success
&& emit_byte
( 0x00FE, EMIT_BYTE_ADD
);
#ifdef DBG
printf("expansion\n");
#endif
expbitlen
++;
}
}
// emit length
if( length
<=15 ) // 3..15
{
success
= success
&& emit_bits
( 0, 1 );
if( length
==3 )
{
success
= success
&& emit_bits
( 0x80000000, 2 ); // %010
}
else
{
varlen
= length
/3;
varbits
= length
%3;
success
= success
&& emit_bits
( 0xFFFFFFFF, varlen
<<1 );
if( length
!=15 )
success
= success
&& emit_bits
( varbits
<<(32-2), 2 );
}
}
else if( length
<=127 ) // 16..127: %0110000abcdefg
{
success
= success
&& emit_bits
( 0x60000000, 7 );
success
= success
&& emit_bits
( length
<<(32-7), 7 );
}
else // 128..3839
{
success
= success
&& emit_bits
( 0x60000000, 7 );
success
= success
&& emit_bits
( length
<<(32-15), 7 );
success
= success
&& emit_byte
( (UBYTE
)(length
&0x00FF), EMIT_BYTE_ADD
);
}
// emit displacement
if( (-32)<=disp
) // ffe0..ffff: %10abcde
{
success
= success
&& emit_bits
( 0x80000000, 2 );
success
= success
&& emit_bits
( disp
<<(32-5), 5 );
}
else if( (-256)<=disp
) // ff00..ffdf: %01<byte>
{
success
= success
&& emit_bits
( 0x40000000, 2 );
success
= success
&& emit_byte
( (UBYTE
)(disp
&0x00FF), EMIT_BYTE_ADD
);
}
else if( (-512)<=disp
) // fe00..feff: %00<byte>
{
success
= success
&& emit_bits
( 0x00000000, 2 );
success
= success
&& emit_byte
( (UBYTE
)(disp
&0x00FF), EMIT_BYTE_ADD
);
}
else // variable code length: [-65536..-512)
{
// displacement itself: %11ab[cdefgh]<byte>
success
= success
&& emit_bits
( 0xC0000000, 2 );
success
= success
&& emit_bits
( disp
<<(24-expbitlen
), expbitlen
);
success
= success
&& emit_byte
( (UBYTE
)(disp
&0x00FF), EMIT_BYTE_ADD
);
}
}
else
{
INVALID_CODE_HRUST
:
printf("mhmt-emit.c:emit_hrust() - invalid code: length=%d, displacement=%d\n",length
,disp
);
return 0;
}
#ifdef DBG
if( length
==(-3) )
{
printf("insert-match.len=%d,disp=%d\n",(-length
),disp
);
}
else if( disp
==0 )
{
printf("copy.len=%d\n",length
);
}
else
{
printf("match.len=%d,disp=%d\n",length
,disp
);
}
#endif
if( max_disp
> disp
) max_disp
= disp
;
if( length
>0 ) // account for negative length
position
+= length
;
else
position
-= length
;
}
// stop-code: %0110_0000_0011_11
success
= success
&& emit_bits
( 0x603C0000, 14 );
success
= success
&& emit_bits
( 0, EMIT_BITS_FINISH
); // this also flushes emit_byte()
success
= success
&& emit_file
( NULL
, EMIT_FILE_FINISH
);
// complete the header
if( success
&& wrk.
zxheader )
{
success
= success
&& ( (0xFFFFFFFF) != (flen
= ftell(wrk.
file_out)) ); //filesize
success
= success
&& !fseek(wrk.
file_out, 4, SEEK_SET
); // pos to 4th byte
wrlen
[0] = flen
&255;
wrlen
[1] = (flen
>>8)&255;
// write len
success
= success
&& ( 2==fwrite(wrlen
, 1, 2, wrk.
file_out) );
if( !success
)
{
printf("emit_hrust(): failed to write packed length to header!\n");
return 0;
}
}
if( success
)
{
printf("Maximum displacement actually used is %d.\n",-max_disp
);
// TODO: patch packed length in file, if zx header
}
return success
;
}
// actually generate output file from optimal chain - zx7 version
ULONG emit_zx7
(struct optchain
* optch
, ULONG actual_len
)
{
ULONG position
;
LONG length
;
LONG disp
;
LONG max_disp
; // maximum encountered displacement
ULONG varbits
,varlen
;
ULONG success
= 1;
max_disp
= 0;
// some checks
if( !optch
)
{
printf("mhmt-emit.c:emit_zx7() - NULL passed!\n");
return 0;
}
// initialize
success
= success
&& emit_file
(NULL
, EMIT_FILE_INIT
);
success
= success
&& emit_byte
(0, EMIT_BYTE_INIT
);
success
= success
&& emit_bits
(0, EMIT_BITS_INIT
);
// copy first byte as-is
success
= success
&& emit_file
( wrk.
indata, 1);
//printf("FIRST: #%02x\n\n",*wrk.indata);
// go emitting codes
position
= 1;
while( (position
<actual_len
) && success
)
{
length
= optch
[position
].
code.
length;
disp
= optch
[position
].
code.
disp;
if( length
==0 )
{
printf("mhmt-emit.c:emit_zx7() - encountered stop-code in optimal chain before emitting all data!\n");
return 0;
}
else if( length
==1 ) // copy-byte
{
if( disp
==0 ) // copy-byte (%0<byte>)
{
//printf("BITS: %%");
success
= success
&& emit_bits
( 0x00000000, 1 );
success
= success
&& emit_byte
( wrk.
indata[position
], EMIT_BYTE_ADD
);
//printf("\nBYTE: #%02x\n\n",wrk.indata[position]);
}
else
goto INVALID_CODE_ZX7
;
}
else if( 2<=length
&& length
<=65536 )
{
// length coding
varbits
= length
-1;
varlen
=0;
while( varbits
)
{
varbits
>>=1;
varlen
+=1;
}
// varlen=1 for len=2,
// =2 for len=3,4
// =3 5,6,7,8
//printf("BITS: %%");
success
= success
&& emit_bits
( 0x80000000, varlen
);
success
= success
&& emit_bits
( (length
-1)<<(32-varlen
), varlen
);
// displacement coding
if( (-128)<=disp
&& disp
<=(-1) )
{
success
= success
&& emit_byte
( ((UBYTE
)(-disp
-1))&127, EMIT_BYTE_ADD
);
//printf("\nBYTE: #%02x\n\n",((UBYTE)(-disp-1))&127);
if( max_disp
> disp
) max_disp
= disp
;
}
else if( (-2176)<=disp
&& disp
<(-128) )
{
success
= success
&& emit_byte
( (((UBYTE
)(-disp
-129))&127)|128, EMIT_BYTE_ADD
);
//printf("\nBYTE: #%02x\n",(((UBYTE)(-disp-129))&127)|128);
//printf("BITS: %%");
success
= success
&& emit_bits
( ((-disp
-129)&0x780)<<21, 4 );
//printf("\n\n");
if( max_disp
> disp
) max_disp
= disp
;
}
else
goto INVALID_CODE_ZX7
;
}
else
{
INVALID_CODE_ZX7
:
printf("mhmt-emit.c:emit_zx7() - invalid code: length=%d, displacement=%d\n",length
,disp
);
return 0;
}
position
+= length
;
}
// stop-code
//printf("BITS: %%");
success
= success
&& emit_bits
( 0x80004000, 18 );
success
= success
&& emit_bits
( 0, EMIT_BITS_FINISH
); // this also flushes emit_byte()
//printf("\n");
success
= success
&& emit_file
( NULL
, EMIT_FILE_FINISH
);
if( success
)
printf("Maximum displacement actually used is %d.\n",-max_disp
);
return success
;
}
// emit bytes to the output buffer and flush to file when needed
// 'operation' defines what to do as described in *.h
// 'byte' is emitted only when length >=1,
// When length=EMIT_FILE_FINISH (0), flushes tail to file
// When length=EMIT_FILE_INIT (-1), initializes.
//
// returns zero in case of any problems (fails to write buffer to file), otherwise non-zero
ULONG emit_file
(UBYTE
* bytes
, LONG length
)
{
static UBYTE buffer
[EMIT_FILEBUF_SIZE
];
static ULONG position
;
if( length
==EMIT_FILE_INIT
)
{
position
= 0;
return 1;
}
else if( length
>0 )
{
while( (position
+length
) >= EMIT_FILEBUF_SIZE
) // if we have to flush buffer
{
length
-= (EMIT_FILEBUF_SIZE
-position
);
while( position
< EMIT_FILEBUF_SIZE
) // fill buffer to the end, if possible
{
buffer
[position
++] = *(bytes
++);
}
if( EMIT_FILEBUF_SIZE
!=fwrite(buffer
, 1, EMIT_FILEBUF_SIZE
, wrk.
file_out) )
{
printf("mhmt-emit.c:emit_file() can't write to file!\n");
return 0;
}
position
=0;
}
while( length
-- ) // if something left that does not need flushing
{
buffer
[position
++] = *(bytes
++);
}
return 1;
}
else if( length
==EMIT_FILE_FINISH
)
{
if( position
>0 ) // do we have anything to flush?
{
if( position
!=fwrite(buffer
, 1, position
, wrk.
file_out) )
{
printf("mhmt-emit.c:emit_file() can't write to file!\n");
return 0;
}
}
return 1;
}
else
{
printf("mhmt-emit.c:emit_file() encountered invalid arguments!\n");
return 0;
}
}
// store emitted bytes in special buffer, because emitted bits go earlier than corresponding bytes.
// then, when bits are flushed to the file, bytes are flushed just after.
// returns zero if any problems. "operation" dictates what to do (see *.h)
ULONG emit_byte
(UBYTE byte
, ULONG operation
)
{
static UBYTE buffer
[EMIT_BYTEBUF_SIZE
];
static ULONG in_pos
, out_pos
;
ULONG success
;
switch( operation
)
{
case EMIT_BYTE_INIT
:
in_pos
= 0;
out_pos
= 0;
return 1;
case EMIT_BYTE_ADD
:
#ifdef DBG
printf("<%02x>",byte
&0x00FF);
#endif
buffer
[in_pos
] = byte
;
in_pos
= (in_pos
+1) & (EMIT_BYTEBUF_SIZE
-1);
if( in_pos
==out_pos
) // overflow!
{
printf("mhmt-emit.c:emit_byte() buffer overflow!\n");
return 0;
}
return 1;
case EMIT_BYTE_FLUSH
:
if( in_pos
==out_pos
) // nothing to do?
return 1;
else if( in_pos
>out_pos
) // no index wraparound
{
success
= emit_file
( &buffer
[out_pos
], in_pos
-out_pos
);
}
else // in_pos<out_pos - wraparound
{
success
= emit_file
( &buffer
[out_pos
], EMIT_BYTEBUF_SIZE
-out_pos
);
if( in_pos
)
success
= success
&& emit_file
( &buffer
[0], in_pos
);
}
out_pos
=in_pos
;
return success
;
default:
printf("mhmt-emit.c:emit_byte() encountered invalid arguments!\n");
return 0;
}
}
// collects bits, emit to output stream when needed. accounts for word or byte mode, little-big endian, empty or full bits
// length is either positive number of bits or one of two special cases (see *.h)
//
ULONG emit_bits
(ULONG msb_aligned_bits
, LONG length
)
{
static ULONG bit_store
;
static ULONG bit_count
;
ULONG max_bits
;
ULONG success
= 1;
max_bits
= wrk.
wordbit ? 16 : 8;
if( length
==EMIT_BITS_INIT
)
{
bit_store
= 0;
bit_count
= 0;
return 1;
}
else if( length
==EMIT_BITS_FINISH
)
{
if( bit_count
) // some bits to flush
{
while( (bit_count
++)<max_bits
)
bit_store
<<= 1;
success
= success
&& emit_bits_flush
(bit_store
);
}
success
= success
&& emit_byte
(0, EMIT_BYTE_FLUSH
);
return success
;
}
else if( length
>0 ) // add bits
{
do
{
if( !wrk.
fullbits ) // empty bits - check for flushing before shiftin
{
if( bit_count
==max_bits
)
{
success
= success
&& emit_bits_flush
(bit_store
);
success
= success
&& emit_byte
(0, EMIT_BYTE_FLUSH
);
bit_count
= 0;
}
}
//printf("%d",1&(msb_aligned_bits>>31));
bit_store
= (bit_store
<<1) | ( 1 & (msb_aligned_bits
>>31) );
msb_aligned_bits
<<= 1;
bit_count
++;
if( wrk.
fullbits ) // full bits - check for flushing after bit shiftin
{
if( bit_count
==max_bits
)
{
success
= success
&& emit_bits_flush
(bit_store
);
success
= success
&& emit_byte
(0, EMIT_BYTE_FLUSH
);
bit_count
= 0;
}
}
} while( --length
);
return success
;
}
else
{
printf("mhmt-emit.c:emit_bits() encountered invalid arguments!\n");
return 0;
}
}
// flushes either word or byte from given bits
//
ULONG emit_bits_flush
(ULONG bits
)
{
UBYTE store_byte
;
ULONG success
= 1;
if( wrk.
wordbit ) // 16bits
{
if( wrk.
bigend ) // big endian
{
store_byte
= 0x00FF & (bits
>> 8);
success
= success
&& emit_file
( &store_byte
, 1);
store_byte
= 0x00FF & bits
;
success
= success
&& emit_file
( &store_byte
, 1);
}
else // little endian
{
store_byte
= 0x00FF & bits
;
success
= success
&& emit_file
( &store_byte
, 1);
store_byte
= 0x00FF & (bits
>> 8);
success
= success
&& emit_file
( &store_byte
, 1);
}
}
else // 8bits
{
store_byte
= 0x00FF & bits
;
success
= success
&& emit_file
( &store_byte
, 1);
}
return success
;
}