#ifndef __MDFN_BITS_H
#define __MDFN_BITS_H

enum
{
 MDFNBITS_PEEK = 1,
 MDFNBITS_FUNNYSIGN = 2,
};

class MDFNBits
{
 public:
 MDFNBits(uint8 *s, uint32 slen, uint8 (*ffunc)(void *), void *pdata);
 ~MDFNBits();

 INLINE uint32 Get(int32 count, uint32 how = 0)
 {
  uint32 ret;

  //assert(count >= 0);

  while(buffered_bits < count)
  {
   buffer <<= 8;
   if(FetchFunc)
   {
    buffer |= FetchFunc(ffprivate);
   }
   else
   {
    if(source_len)
    {
     buffer |= *source++;
     source_len--;
    }
    else // We've fetched too many bits, eeeeep
    {
     printf("Nooooooo\n");
    }
   }
   buffered_bits += 8;
  }

  ret = (buffer >> (buffered_bits - count)) & ((1 << count) - 1);

  if(!(how & MDFNBITS_PEEK))
   buffered_bits -= count;

  if((how & MDFNBITS_FUNNYSIGN) && count)
  {
   if(ret < (1 << (count - 1)))
    ret += 1 - (1 << count);
  }

  return(ret);
 }

 INLINE void Skip(int32 count)
 {
  // assert(count >= 0);
  // TODO: optimize
  Get(count);
 }

 private:
 uint8 *source;
 uint32 source_len;
 uint8 (*FetchFunc)(void*);
 void *ffprivate;

 uint32 buffer;
 int32 buffered_bits;

};

#endif
