Subversion Repositories Games.Carmageddon

Rev

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

  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. }
  120.