Top secrets sources NedoPC pentevo

Rev

Rev 129 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

#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;
        }
}