int store_pixel(struct bitmap *bitmapstruct, unsigned char x,
                unsigned char y, unsigned char color)
{
  unsigned char *ptr = &bitmapstruct->bitmap[bitmapstruct->width*y+x];

  if(y >= bitmapstruct->height || x >= bitmapstruct->width)
    return 1;

  *ptr = color;

  return 0;
}

int recall_pixel(struct bitmap *bitmapstruct, unsigned char x,
                 unsigned char y)
{
  unsigned char *ptr = &bitmapstruct->bitmap[bitmapstruct->width*y+x];

  return *ptr;
}

int allocate_bitmap(unsigned char width, unsigned char height,
                    struct bitmap *retval)
{
  retval->bitmap = malloc(width*height* sizeof(unsigned char));
  retval->height = height;
  retval->width = width;

  return !retval->bitmap;
}

void fill_bitmap(struct bitmap *bitmap, unsigned char color)
{
  memset(bitmap->bitmap, color, bitmap->height*bitmap->width);
}

#ifdef GAME
unsigned char usedpixels[/*320*200/8*/8000];

void mark_pixel_used(unsigned x, unsigned y)
{
  unsigned offset = (y<<5)+(y<<3)+(x>>3);

  if(offset >= sizeof(usedpixels)) return;

  usedpixels[offset] |= 1 << (x&7);
}

unsigned char pixel_is_used(unsigned x, unsigned y)
{
  unsigned offset = (y<<5)+(y<<3)+(x>>3);

  if(offset >= sizeof(usedpixels)) return 1;

  return usedpixels[offset] & (1 << (x&7));
}
#endif

void draw_bitmap(unsigned x, unsigned y, struct bitmap *bitmap)
{
  unsigned w,h;
  unsigned char color;
  unsigned scrx, scry;

  for(h=bitmap->height;h--;)
  {
    for(w=bitmap->width;w--;)
    {
      color = recall_pixel(bitmap, w, h);
      if(color != 0xFF)
      #ifndef GAME
        put_pixel(x+w, y+h, color | (color << 4));
      #else
      {
        color |= color << 4;
        scrx = x+w;
        scry = y+h;
        if(!pixel_is_used(scrx, scry))
        {
          put_pixel(scrx, scry, color);
          mark_pixel_used(scrx, scry);
        }
      }
      #endif
    }
  }
}

/*void draw_mob_side(unsigned x, unsigned y, unsigned char *bitmap, unsigned char width, unsigned char height)
{
  unsigned n, m, o = 0;

  for(n=0;n<height;n++)
    for(m=0;m<width;m++,o++)
      if(bitmap[o] != 0xFF)
        put_pixel(x+m, y+n, bitmap[o]);
}*/

#define MOB_FRONT 0
#define MOB_LEFT 1
#define MOB_RIGHT 2
#define MOB_BACK 3
#define MOB_TOP 4
#define MOB_BOTTOM 5
void draw_mob_side(unsigned x, unsigned y, struct entitybitmap *bitmap, unsigned char side)
{
  unsigned n, m, o = 0;
  unsigned char width, height;
  unsigned char *ptr;
  unsigned scrx, scry;
  unsigned char color;

  if(side == MOB_BACK)
  {
    ptr = bitmap->back;
    goto back;
  }
  if(side == MOB_FRONT)
  {
    ptr = bitmap->front;
    back:
    width = bitmap->width;
    height = bitmap->height;
  }
  else if(side == MOB_RIGHT)
  {
    ptr = bitmap->right;
    goto right;
  }
  else if(side == MOB_LEFT)
  {
    ptr = bitmap->left;
    right:
    width = bitmap->depth;
    height = bitmap->height;
  }
  else if(side == MOB_TOP)
  {
    ptr = bitmap->top;
    goto top;
  }
  else
  {
    ptr = bitmap->bottom;
    top:
    width = bitmap->width;
    height = bitmap->depth;
  }

  for(n=0;n<height;n++)
    for(m=0;m<width;m++,o++)
    {
      color = ptr[o];
      if(color != 0xFF)
      {
        #ifndef GAME
        put_pixel(x+m, y+n, color);
        #else
        scrx = x+m;
        scry = y+n;
        if(!pixel_is_used(scrx, scry))
        {
          put_pixel(scrx, scry, color);
          mark_pixel_used(scrx, scry);
        }
        #endif
      }
    }
}

int load_bitmap(char *filename, struct bitmap *bitmap,
                unsigned char *width, unsigned char *height)
{
  unsigned read_count;
  FILE *fp = fopen(filename, "rb");
  if(!fp) return 1;

  if(!fread(width, 1, 1, fp))
  {
    error1:
    puts("Error while loading");
    exit(1);
  }

  if(!fread(height, 1, 1, fp))
    goto error1;

  if(allocate_bitmap(*width, *height, bitmap))
  {
#ifdef GAME
    outofmemory();
#else
    puts("Out of memory.");
#endif
    exit(1);
  }

  read_count = *width * *height;
  if(!fread(bitmap->bitmap, read_count, 1, fp))
    goto error1;

  fclose(fp);

  return 0;
}
