/******************************/
/* Header Datei von PV Intern */
/******************************/

/* Diese Datei enthält nützliche Funktionen zur Programmierung des Pocket Viewers */
/* event mask defines */

#define EVENT_TCH       1
#define EVENT_CRADLE    4
#define EVENT_BLD1      8


#define GETBATTSEG 0xC000
#define GETBATTOFS 0x06D1
#define GETBATTTARGET {0xCB, 0xE4, 0x6A, 0x0C, 0x10}

typedef struct sprites
{
	int x;
	int y;
	int xsize;
	int ysize;
	byte *background;
	byte *sprite;
} SPRITE;


void SpriteInit(SPRITE *man, int x, int y, byte *background, byte *graf);
void SpriteOn(SPRITE *man);
void SpriteOff(SPRITE *man);
void SpriteMove(SPRITE *man, int newx, int newy);
int TestDot(unsigned int x, unsigned int y);
void PollEvent(TCHSTS far* tsts, byte event_mask);
void hoch(int x, int y);
void breit(int x, int y);
int Segment(int x, int y, byte code);
void GetSeed(void);
int GetBatt();
int ADToVoltage(int *AD);
void LibGdsEllipse (int center_x, int center_y, int rx, int ry);

/*******************************************************************************/
char _osmajor = '1'; 
void *sbrk(size_t s){ return(NULL); }; 

int TestDot(unsigned int x, unsigned int y)
{
  byte far * p = MK_FP(0x0000,0x1000);
  byte mask = 0x80;

  p += y * 20;
  p += x / 8;
  mask = mask >> (x % 8);

  if (*p & mask)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

void PollEvent(TCHSTS far* tsts, byte event_mask)
{
  union REGS reg;
  
  reg.x.ax = 0x0200 | event_mask;
  reg.x.di = FP_OFF(tsts);
  reg.x.es = FP_SEG(tsts);
  int86(0x50,&reg,&reg);
}


void hoch(int x, int y)
{
  LibLine(x,y+5,1,20,1);
  LibLine(x+1,y+4,1,22,1);
  LibLine(x+2,y+3,1,24,1);
  LibLine(x+3,y+2,1,26,1);
  LibLine(x+4,y+1,1,28,1);
  LibLine(x+5,y+2,1,26,1);
  LibLine(x+6,y+3,1,24,1);
  LibLine(x+7,y+4,1,22,1);
  LibLine(x+8,y+5,1,20,1);
}

void breit(int x, int y)
{
  LibLine(x+5,y,20,1,1);
  LibLine(x+4,y+1,22,1,1);	
  LibLine(x+3,y+2,24,1,1);
  LibLine(x+2,y+3,26,1,1);
  LibLine(x+1,y+4,28,1,1);
  LibLine(x+2,y+5,26,1,1);
  LibLine(x+3,y+6,24,1,1);
  LibLine(x+4,y+7,22,1,1);
  LibLine(x+5,y+8,20,1,1);
}

int Segment(int x, int y, byte code)
{
  switch (code)
  {
    case 0:
    {
      breit(x+4,y);
      hoch(x,y+4);
      hoch(x+29,y+4);
      hoch(x,y+33);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
    case 1:
    {
      hoch(x+29,y+4);
      hoch(x+29,y+33);
    } break;
    case 2:
    {
      breit(x+4,y);
      hoch(x+29,y+4);
      breit(x+4,y+29);
      hoch(x,y+33);
      breit(x+4,y+58);
    } break;
    case 3:
    {
      breit(x+4,y);
      hoch(x+29,y+4);
      breit(x+4,y+29);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
    case 4:
    {
      hoch(x,y+4);
      hoch(x+29,y+4);
      breit(x+4,y+29);
      hoch(x+29,y+33);
    } break;
    case 5:
    {
      hoch(x,y+4);
      breit(x+4,y);
      breit(x+4,y+29);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
    case 6:
    {
      hoch(x,y+4);
      breit(x+4,y);
      breit(x+4,y+29);
      hoch(x,y+33);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
    case 7:
    {
      hoch(x+29,y+4);
      hoch(x+29,y+33);
      breit(x+4,y);
    } break;
    case 8:
    {
      hoch(x,y+4);
      breit(x+4,y);
      hoch(x+29,y+4);
      breit(x+4,y+29);
      hoch(x,y+33);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
    case 9:
    {
      hoch(x,y+4);
      breit(x+4,y);
      hoch(x+29,y+4);
      breit(x+4,y+29);
      breit(x+4,y+58);
      hoch(x+29,y+33);
    } break;
  }
  return (x+40);
}


void SpriteInit(SPRITE *man, int x, int y, byte *background, byte *graf)
{
	man->x=x;
	man->y=y;
	man->background=background;
	man->sprite=graf;
	man->xsize=(word)graf[0];
	man->ysize=(word)graf[2];
	*(word *)man->background=man->xsize;
	*(word *)(man->background+2)=man->ysize;
}

void SpriteOn(SPRITE *man)
{
	LibGetGraph(man->x,man->y,man->xsize,man->ysize,&(man->background[4]));
	LibPutGraphO(man->x,man->y,man->sprite,IB_GPOR);		
}

void SpriteOff(SPRITE *man)
{
	LibPutGraph(man->x,man->y,man->background);
}

void SpriteMove(SPRITE *man, int newx, int newy)
{
	SpriteOff(man);
	man->x=newx;
	man->y=newy;
	SpriteOn(man);
}

void GetSeed(void)
{
	byte hour,minute,sek;

	LibGetTime2(&hour,&minute,&sek);
	srand(hour*3600+min*60+sek);
}

/*
  GetBatt

  returns a 10 bit AD value (0..1023) for the battery voltage
  returns -1 if an error occured (system routine at C000:06D1 not found)
*/
int GetBatt()
{
  unsigned char test[] = GETBATTTARGET;
  unsigned int (far * GetBattValue)();
  unsigned char far * p;
  int i;
  
      /* test if GetBattValue will reach expected code */
  p = MK_FP(GETBATTSEG,GETBATTOFS-1);
  for (i=0;i<sizeof(test);++i)
  {
    if (p[i] != test[i]) break;
  }
    
  if (i != sizeof(test))
  {
        /* error: unexpected code */
    return -1;
  }
  else
  {
    GetBattValue = MK_FP(GETBATTSEG,GETBATTOFS);
    return GetBattValue();
  }
}

/* Returns voltage. 256 => 2.56 V */
int ADToVoltage(int *AD) 
{
	int volts;
	volts = *AD/3.089;
	return volts;	
}


void LibGdsEllipse (int center_x, int center_y, int rx, int ry)
{
	/* intermediate terms to speed up loop */
	long t1 = rx*rx, t2 = t1<<1, t3 = t2<<1;
	long t4 = ry*ry, t5 = t4<<1, t6 = t5<<1;
	long t7 = rx*t5, t8 = t7<<1, t9 = 0L;
	long d1 = t2 - t7 + (t4>>1);	/* error terms */
	long d2 = (t1>>1) - t8 + t5;

	register int x = rx, y = 0;	/* ellipse points */

	while (d2 < 0)			/* til slope = -1 */
	{
		/* draw 4 points using symmetry */
	    	LibDotOn(center_x + x, center_y + y);
	    	LibDotOn(center_x + x, center_y - y);
	    	LibDotOn(center_x - x, center_y + y);
	    	LibDotOn(center_x - x, center_y - y);
		y++;		/* always move up here */
		t9 += t3;	
		if (d1 < 0)	/* move straight up */
		{
			d1 += t9 + t2;
			d2 += t9;
		}
		else		/* move up and left */
		{
			x--;
			t8 -= t6;
			d1 += t9 + t2 - t8;
			d2 += t9 + t5 - t8;
		}
	}

	do 				/* rest of top right quadrant */
	{
		/* draw 4 points using symmetry */
	    	LibDotOn(center_x + x, center_y + y);
	    	LibDotOn(center_x + x, center_y - y);
	    	LibDotOn(center_x - x, center_y + y);
	    	LibDotOn(center_x - x, center_y - y);
		x--;		/* always move left here */
		t8 -= t6;	
		if (d2 < 0)	/* move up and left */
		{
			y++;
			t9 += t3;
			d2 += t9 + t5 - t8;
		}
		else		/* move straight left */
			d2 += t5 - t8;
	} while (x>=0);
}

