#include <avr/io.h>
#include <avr/pgmspace.h>
#include "mytypes.h"
#include "main.h"
#include "depacker_dirty.h"
UWORD dbpos; // current position in buffer (wrappable)
UBYTE bitstream;
UBYTE bitcount;
void depacker_dirty(void)
{
UBYTE j;
UBYTE bits;
WORD disp;
dbpos=0;
// get first byte of packed file and write to output
put_byte(NEXT_BYTE);
// second byte goes to bitstream
bitstream=NEXT_BYTE;
bitcount=8;
// actual depacking loop!
do
{
j=0;
// get 1st bit - either OUTBYTE or beginning of LZ code
if( get_bits_dirty(1) )
{ // OUTBYTE
put_byte(NEXT_BYTE);
}
else
{ // LZ code
switch( get_bits_dirty(2) )
{
case 0: // 000
repeat( 0xFFF8|get_bits_dirty(3) ,1);
break;
case 1: // 001
repeat( 0xFF00|NEXT_BYTE ,2);
break;
case 2: // 010
repeat(get_bigdisp_dirty(),3);
break;
case 3: // 011
// extract num of length bits
do j++; while( !get_bits_dirty(1) );
if( j<8 ) // check for exit code
{
// get length bits itself
bits=get_bits_dirty(j);
disp=get_bigdisp_dirty();
repeat(disp,2+(1<<j)+bits);
}
break;
}
}
} while( j<8 );
if( (DBMASK&dbpos) )
{
put_buffer(DBMASK&dbpos);
}
}
void repeat(WORD disp,UBYTE len)
{ // repeat len bytes with disp displacement (negative)
// uses dbpos & dbuf
UBYTE i; // since length is no more than 255
for(i=0;i<len;i++)
{
put_byte(dbuf[DBMASK&(dbpos+disp)]);
}
}
void put_byte(UBYTE byte)
{
dbuf[dbpos]=byte;
dbpos = DBMASK & (dbpos+1);
if( !dbpos )
{
put_buffer(DBSIZE);
}
}
UBYTE get_bits_dirty(UBYTE numbits)
{ // gets bits in a byte-wise style, no checks
// numbits must be >0
UBYTE bits;
bits=0;
do
{
if( !(bitcount--) )
{
bitcount=7;
bitstream=NEXT_BYTE;
}
bits = (bits<<1)|(bitstream>>7); // all shifts byte-wise
bitstream<<=1;
} while (--numbits);
return bits;
}
WORD get_bigdisp_dirty(void)
{ // fetches 'big' displacement (-1..-4352)
// returns negative displacement
UBYTE bits;
if( get_bits_dirty(1) )
{ // longer displacement
bits=get_bits_dirty(4);
return (((0xF0|bits)-1)<<8)|NEXT_BYTE;
}
else
{ // shorter displacement
return 0xFF00|NEXT_BYTE;
}
}