Exemple #1
0
 private static void normalize(LzrcDecode rc)
 {
     if (rc.range >= 0 && rc.range < 0x01000000)
     {
         rc.range <<= 8;
         rc.code    = (rc.code << 8) | rc_getbyte(rc);
     }
 }
Exemple #2
0
        private static void rc_putbyte(LzrcDecode rc, sbyte b)
        {
            if (rc.out_ptr == rc.out_len)
            {
                Console.WriteLine("Output overflow!");
                return;
            }

            rc.output[rc.out_ptr++] = b;
        }
Exemple #3
0
        private static int rc_getbyte(LzrcDecode rc)
        {
            if (rc.in_ptr == rc.in_len)
            {
                Console.WriteLine("End of input!");
                return(0);
            }

            return(u8(rc.input, rc.in_ptr++));
        }
Exemple #4
0
        // Decode a bittree starting from MSB
        private static int rc_bittree(LzrcDecode rc, sbyte[] probs, int offset, int limit)
        {
            int number = 1;

            do
            {
                number = (number << 1) | rc_bit(rc, probs, offset + number);
            } while (number < limit);

            return(number);
        }
Exemple #5
0
        // Decode a number
        //
        // A number is divided into three parts:
        //   MSB 2 bits
        //   direct bits (don't use probability model)
        //   LSB 3 bits
        private static int rc_number(LzrcDecode rc, sbyte[] prob, int offset, int n)
        {
            int number = 1;

            if (n > 3)
            {
                number = (number << 1) | rc_bit(rc, prob, offset + 3);
                if (n > 4)
                {
                    number = (number << 1) | rc_bit(rc, prob, offset + 3);
                    if (n > 5)
                    {
                        // direct bits
                        normalize(rc);

                        for (int i = 0; i < n - 5; i++)
                        {
                            rc.range = (int)((uint)rc.range >> 1);
                            number <<= 1;
                            if ((rc.code & 0xFFFFFFFFL) < (rc.range & 0xFFFFFFFFL))
                            {
                                number += 1;
                            }
                            else
                            {
                                rc.code -= rc.range;
                            }
                        }
                    }
                }
            }

            if (n > 0)
            {
                number = (number << 1) | rc_bit(rc, prob, offset);
                if (n > 1)
                {
                    number = (number << 1) | rc_bit(rc, prob, offset + 1);
                    if (n > 2)
                    {
                        number = (number << 1) | rc_bit(rc, prob, offset + 2);
                    }
                }
            }

            return(number);
        }
Exemple #6
0
        // Decode a bit
        private static int rc_bit(LzrcDecode rc, sbyte[] probs, int offset)
        {
            normalize(rc);

            long bound = ((long)((int)((uint)rc.range >> 8))) * u8(probs, offset);

            probs[offset] -= (sbyte)(u8(probs, offset) >> 3);

            if ((rc.code & 0xFFFFFFFFL) < bound)
            {
                rc.range       = unchecked ((int)(bound & 0xFFFFFFFFL));
                probs[offset] += 31;
                return(1);
            }

            rc.code  -= (int)bound;
            rc.range -= (int)bound;
            return(0);
        }
Exemple #7
0
        private static void rc_init(LzrcDecode rc, sbyte[] @out, int out_len, sbyte[] @in, int in_len)
        {
            rc.input  = @in;
            rc.in_len = in_len;
            rc.in_ptr = 0;

            rc.output  = @out;
            rc.out_len = out_len;
            rc.out_ptr = 0;

            rc.range = -1;
            rc.lc    = rc_getbyte(rc);
            rc.code  = (rc_getbyte(rc) << 24) | (rc_getbyte(rc) << 16) | (rc_getbyte(rc) << 8) | rc_getbyte(rc);

            for (int i = 0; i < rc.bm_values.Length; i++)
            {
                rc.bm_values[i] = unchecked ((sbyte)0x80);
            }
        }
Exemple #8
0
        public static int lzrc_decompress(sbyte[] @out, int out_len, sbyte[] @in, int in_len)
        {
            LzrcDecode rc = new LzrcDecode();

            rc_init(rc, @out, out_len, @in, in_len);

            if ((rc.lc & 0x80) != 0)
            {
                // Plain text
                Array.Copy(rc.input, 5, rc.output, 0, rc.code);
                return(rc.code);
            }

            int rc_state  = 0;
            int last_byte = 0;

            while (true)
            {
                int match_step = 0;

                int bit = rc_bit(rc, rc.bm_values, rc.bm_match(rc_state, match_step));
                if (bit == 0)
                {
                    // 0 -> raw char
                    if (rc_state > 0)
                    {
                        rc_state--;
                    }

                    int b = rc_bittree(rc, rc.bm_values, rc.bm_literal((last_byte >> rc.lc) & 0x07, 0), 0x100);
                    b -= 0x100;

                    rc_putbyte(rc, (sbyte)b);
                }
                else
                {
                    // 1 -> a match

                    // Find bits of match Length
                    int len_bits = 0;
                    for (int i = 0; i < 7; i++)
                    {
                        match_step++;
                        bit = rc_bit(rc, rc.bm_values, rc.bm_match(rc_state, match_step));
                        if (bit == 0)
                        {
                            break;
                        }
                        len_bits++;
                    }

                    // Find match Length
                    int match_len;
                    if (len_bits == 0)
                    {
                        match_len = 1;
                    }
                    else
                    {
                        int len_state = ((len_bits - 1) << 2) + ((rc.out_ptr << (len_bits - 1)) & 0x03);
                        match_len = rc_number(rc, rc.bm_values, rc.bm_len(rc_state, len_state), len_bits);
                        if (match_len == 0xFF)
                        {
                            // End of stream
                            return(rc.out_ptr);
                        }
                    }

                    // Find number of bits of match distance
                    int dist_state = 0;
                    int limit      = 8;
                    if (match_len > 2)
                    {
                        dist_state += 7;
                        limit       = 44;
                    }
                    int dist_bits = rc_bittree(rc, rc.bm_values, rc.bm_dist_bits(len_bits, dist_state), limit);
                    dist_bits -= limit;

                    // Find match distance
                    int match_dist;
                    if (dist_bits > 0)
                    {
                        match_dist = rc_number(rc, rc.bm_values, rc.bm_dist(dist_bits, 0), dist_bits);
                    }
                    else
                    {
                        match_dist = 1;
                    }

                    // Copy match bytes
                    if (match_dist > rc.out_ptr || match_dist < 0)
                    {
                        Console.WriteLine(string.Format("match_dist out of range! 0x{0:X8}", match_dist));
                        return(-1);
                    }

                    int match_src = rc.out_ptr - match_dist;
                    for (int i = 0; i < match_len + 1; i++)
                    {
                        rc_putbyte(rc, rc.output[match_src++]);
                    }
                    rc_state = 6 + ((rc.out_ptr + 1) & 1);
                }
                last_byte = rc.output[rc.out_ptr - 1];
            }
        }