Subversion Repositories Games.Carmageddon

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/**
2
        libsmacker - A C library for decoding .smk Smacker Video files
3
        Copyright (C) 2012-2017 Greg Kennedy
4
 
5
        See smacker.h for more information.
6
 
7
        smk_bitstream.c
8
                Implements a bitstream structure, which can extract and
9
                return a bit at a time from a raw block of bytes.
10
*/
11
 
12
#include "smk_bitstream.h"
13
 
14
/* malloc and friends */
15
#include "smk_malloc.h"
16
 
17
/*
18
        Bitstream structure
19
        Pointer to raw block of data and a size limit.
20
        Maintains internal pointers to byte_num and bit_number.
21
*/
22
struct smk_bit_t
23
{
24
        const unsigned char* buffer;
25
        unsigned long size;
26
 
27
        unsigned long byte_num;
28
        char bit_num;
29
};
30
 
31
/* BITSTREAM Functions */
32
struct smk_bit_t* smk_bs_init(const unsigned char* b, const unsigned long size)
33
{
34
        struct smk_bit_t* ret = NULL;
35
 
36
        /* sanity check */
37
        smk_assert(b);
38
 
39
        /* allocate a bitstream struct */
40
        smk_malloc(ret, sizeof(struct smk_bit_t));
41
 
42
        /* set up the pointer to bitstream, and the size counter */
43
        ret->buffer = b;
44
        ret->size = size;
45
 
46
        /* point to initial byte: note, smk_malloc already sets these to 0 */
47
        /* ret->byte_num = 0;
48
        ret->bit_num = 0; */
49
 
50
        /* return ret or NULL if error : ) */
51
error:
52
        return ret;
53
}
54
 
55
/* Reads a bit
56
        Returns -1 if error encountered */
57
char _smk_bs_read_1(struct smk_bit_t* bs)
58
{
59
        unsigned char ret = -1;
60
 
61
        /* sanity check */
62
        smk_assert(bs);
63
 
64
        /* don't die when running out of bits, but signal */
65
        if (bs->byte_num >= bs->size)
66
        {
67
                fprintf(stderr, "libsmacker::_smk_bs_read_1(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size);
68
                goto error;
69
        }
70
 
71
        /* get next bit and return */
72
        ret = (((bs->buffer[bs->byte_num]) & (1 << bs->bit_num)) != 0);
73
 
74
        /* advance to next bit */
75
        bs->bit_num ++;
76
 
77
        /* Out of bits in this byte: next! */
78
        if (bs->bit_num > 7)
79
        {
80
                bs->byte_num ++;
81
                bs->bit_num = 0;
82
        }
83
 
84
        /* return ret, or (default) -1 if error */
85
error:
86
        return ret;
87
}
88
 
89
/* Reads a byte
90
        Returns -1 if error. */
91
short _smk_bs_read_8(struct smk_bit_t* bs)
92
{
93
        unsigned char ret = -1;
94
 
95
        /* sanity check */
96
        smk_assert(bs);
97
 
98
        /* don't die when running out of bits, but signal */
99
        if (bs->byte_num + (bs->bit_num > 0) >= bs->size)
100
        {
101
                fprintf(stderr, "libsmacker::_smk_bs_read_8(bs): ERROR: bitstream (length=%lu) exhausted.\n", bs->size);
102
                goto error;
103
        }
104
 
105
        if (bs->bit_num)
106
        {
107
                /* unaligned read */
108
                ret = bs->buffer[bs->byte_num] >> bs->bit_num;
109
                bs->byte_num ++;
110
                ret |= (bs->buffer[bs->byte_num] << (8 - bs->bit_num));
111
        } else {
112
                /* aligned read */
113
                ret = bs->buffer[bs->byte_num ++];
114
        }
115
 
116
        /* return ret, or (default) -1 if error */
117
error:
118
        return ret;
119
}