#include <vga.h>
#include <vgagl.h>
#include "sintab.h"

#define STARS 256
#define SHIFT 16
#define CINC 8

struct star {
  int x,y,dx,dy;
  int c,d;
} stars[STARS];

GraphicsContext screen, buffer;

#define MODE G320x200x256

#define PLOTFC(x,y,c) gl_setpixel((x)>>SHIFT,(y)>>SHIFT,(c))
#define CLEAR() gl_fillbox(0,0,WIDTH,HEIGHT,0)

__inline__ newstar(int s)  {
  int t,u;
  stars[s].x=WIDTH<<(SHIFT-1);
  stars[s].y=HEIGHT<<(SHIFT-1);
  stars[s].c=64*(rand()%4);
#if 1
  t=rand()%TABSIZE;
  u=rand()%128+32;
  stars[s].dx=sintab[t]*(u<<SHIFT/TABMAG);
  stars[s].dy=sintab[(t+TABSIZE/4)%TABSIZE]*(u<<SHIFT/TABMAG);
#else
  stars[s].dx=(rand()%2==0?1:-1)*(rand()%(1<<(SHIFT+4))+(1<<(SHIFT+1)));
  stars[s].dy=(rand()%2==0?1:-1)*(rand()%(1<<(SHIFT+4))+(1<<(SHIFT+1)));
#endif
  t=rand()%4+1;
  stars[s].x+=t*stars[s].dx;
  stars[s].y+=t*stars[s].dy;
}

__inline__ plotstar(int s)  {
  PLOTFC(stars[s].x,stars[s].y,stars[s].c);
}

__inline__ updatestar(int s)  {
  stars[s].x+=stars[s].dx;
  stars[s].y+=stars[s].dy;
  if(++stars[s].d==CINC)  {
    stars[s].d=0;
    stars[s].c++;
    if((stars[s].c&63)==0) stars[s].c--;
  }
  
  if ((stars[s].x<0)
      ||(stars[s].x>=(WIDTH<<SHIFT))
      ||(stars[s].y<0)
      ||(stars[s].y>=(HEIGHT<<SHIFT))
      ) 
    newstar(s);
  plotstar(s);
}

__inline__ update()  {
  int i;
  for(i=0;i<STARS;i++) updatestar(i);
  gl_copyscreen(&screen);
  CLEAR();
}

main()  {  
  vga_setmode(MODE);
  srand(getpid());
  gl_setcontextvga(MODE); gl_getcontext(&screen);
  gl_setcontextvgavirtual(MODE); gl_getcontext(&buffer);
  
    {
      int i;
      for(i=0;i<STARS;i++) newstar(i);
      for(i=0;i<64;i++)  {
	gl_setpalettecolor(i,i,i,i);
	gl_setpalettecolor(i+64,i,0,0);
	gl_setpalettecolor(i+128,0,i,0);
	gl_setpalettecolor(i+192,0,0,i);
      }
    }
  while(1) update();
  
  vga_setmode(TEXT);
  return 0;
}
