Login

Subversion Repositories NedoOS

Rev

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

// this is not a code to be separately compiled!
// instead, it is included in mhmt-depack.c several times and depends on existing at include moment #define's to generate some compiling code
//
//                   // example defines:
//#define DPK_CHECK  // check input stream for consistency
//#define DPK_DEPACK // do depacking
//#define DPK_REPERR // report errors via printf
{
        ULONG check;
        ULONG byte,bits,bitlen;
        LONG disp;
        ULONG length;

        ULONG stop;


        ULONG success = 1;





        // rewind input stream
        //
        check = depack_getbyte(DEPACK_GETBYTE_REWIND);
#ifdef DPK_CHECK
        if( 0xFFFFFFFF == check )
        {
 #ifdef DPK_REPERR
                printf("mhmt-depack-megalz.c:{} - Can't rewind input stream!\n");
 #endif
                return 0;
        }
#endif


        // first byte of input stream goes to the output unchanged
        //
        byte = depack_getbyte(DEPACK_GETBYTE_NEXT);
#ifdef DPK_CHECK
        if( 0xFFFFFFFF == byte )
        {
NO_BYTE:
 #ifdef DPK_REPERR
                printf("mhmt-depack-megalz.c:{} - Can't get byte from input stream!\n");
 #endif
                return 0;
        }
#endif

#ifdef DPK_DEPACK
        success = success && depack_outbyte( (UBYTE)(0x00FF&byte), DEPACK_OUTBYTE_ADD );
#endif


#ifdef DPK_CHECK
 #ifdef DPK_REPERR
 #endif
#endif
        // next is byte to the bitstream
        //
        check = depack_getbits(8,DEPACK_GETBITS_FORCE);
#ifdef DPK_CHECK
        if( 0xFFFFFFFF == check )
        {
NO_BITS:
 #ifdef DPK_REPERR
                printf("mhmt-depack-megalz.c:{} - Can't get bits from input stream!\n");
 #endif
                return 0;
        }
#endif



        // now normal depacking loop
        //
        stop = 0;
        while( (!stop) && success )
        {
                bits = depack_getbits(1,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif

                if( 1&bits ) // %1<byte>
                {
                        byte = depack_getbyte(DEPACK_GETBYTE_NEXT);
#ifdef DPK_CHECK
                        if( 0xFFFFFFFF == byte ) goto NO_BYTE;
#endif

#ifdef DPK_DEPACK
                        success = success && depack_outbyte( (UBYTE)(0x00FF&byte), DEPACK_OUTBYTE_ADD );
#endif
                }
                else // %0xx
                {
                        bits = depack_getbits(2,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                        if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif

                        switch( 0x03 & bits )
                        {
                        case 0x00: // %000xxx

                                bits = depack_getbits(3,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                                if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif

                                disp = (-8) | (bits&0x07); // FFFFFFF8..FFFFFFFF (-8..-1)
#ifdef DPK_CHECK
                                if( (ULONG)(-disp) > wrk.maxwin )
                                {
WRONG_DISP:
 #ifdef DPK_REPERR
                                        printf("mhmt-depack-megalz.c:{} - Wrong lookback displacement of %d, greater than maxwin\n",(-disp) );
 #endif
                                        return 0;
                                }
#endif

#ifdef DPK_DEPACK
                                success = success && depack_repeat(disp,1);
#endif
                                break;


                        case 0x01: // %001

                                byte = depack_getbyte(DEPACK_GETBYTE_NEXT);
#ifdef DPK_CHECK
                                if( 0xFFFFFFFF == byte ) goto NO_BYTE;
#endif

                                disp = (-256) | (0x00FF&byte); // -1..-256
#ifdef DPK_CHECK
                                if( (ULONG)(-disp) > wrk.maxwin ) goto WRONG_DISP;
#endif

#ifdef DPK_DEPACK
                                success = success && depack_repeat(disp,2);
#endif
                                break;


                        case 0x02: // %010

                                length = 3;
FAR_DISP:
                                bits = depack_getbits(1,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                                if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif
                                if( !(1&bits) ) // -1..-256
                                {
                                        byte = depack_getbyte(DEPACK_GETBYTE_NEXT);
#ifdef DPK_CHECK
                                        if( 0xFFFFFFFF == byte ) goto NO_BYTE;
#endif
                                        disp = (-256) | (0x00FF&byte); // -1..-256
#ifdef DPK_CHECK
                                        if( (ULONG)(-disp) > wrk.maxwin ) goto WRONG_DISP;
#endif

#ifdef DPK_DEPACK
                                        success = success && depack_repeat(disp,length);
#endif
                                }
                                else // -257..-4352
                                {
                                        bits = depack_getbits(4,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                                        if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif
                                        byte = depack_getbyte(DEPACK_GETBYTE_NEXT);
#ifdef DPK_CHECK
                                        if( 0xFFFFFFFF == byte ) goto NO_BYTE;
#endif
                                        disp = ( ((-16)|(15&bits)) - 1 )*0x100 + byte;
#ifdef DPK_CHECK
                                        if( (ULONG)(-disp) > wrk.maxwin ) goto WRONG_DISP;
#endif

#ifdef DPK_DEPACK
                                        success = success && depack_repeat(disp,length);
#endif
                                }

                                break;


                        case 0x03: // %011 - variable length

                                bitlen = 0;
                                do
                                {
                                        bits = depack_getbits(1,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                                        if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif
                                        bitlen++;

                                } while ( !(1&bits) );

                                if( bitlen==9 ) // happy final! WARNING: does not check whether there is remaining of input stream left unused!
                                {
                                        stop = 1;
                                        break; // exit switch(){}
                                }
#ifdef DPK_CHECK
                                if( bitlen>7 )
                                {
 #ifdef DPK_REPERR
                                        printf("mhmt-depack-megalz.c:{} - Wrong LZ code\n");
 #endif
                                        return 0;
                                }
#endif
                                bits = depack_getbits(bitlen,DEPACK_GETBITS_NEXT);
#ifdef DPK_CHECK
                                if( 0xFFFFFFFF == bits ) goto NO_BITS;
#endif
                                length = 2 + (1<<bitlen) + ( bits & ((1<<bitlen)-1) );
#ifdef DPK_CHECK
                                if( length>255 )
                                {
 #ifdef DPK_REPERR
                                        printf("mhmt-depack-megalz.c:{} - Wrong LZ code\n");
 #endif
                                        return 0;
                                }
#endif
                                goto FAR_DISP;

                                break;
                        }
                }

        }

        return success;
}