#include <dos.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <pc.h>

#include "hicolor.h"

/*  CONSTANTS  */
#define bytesPerPixel		2
#define INFORM_PROG_NAME	"hiview"
#define PAGESIZE  			(64L*1024L)

/*  GLOBALS  */
int i;

void 
himode ()
{
  union REGS regs;

  regs.x.ax = 0x10f0;
  regs.x.bx = 0x30;
  regs.x.cx = 0;
  regs.x.dx = 0;

  int86 (0x10, &regs, &regs);
}

void 
Textmode ()
{
  union REGS regs;

  regs.x.ax = 0x03;
  regs.x.bx = 0x0;
  regs.x.cx = 0;
  regs.x.dx = 0;

  int86 (0x10, &regs, &regs);
}

void 
Putpixel (x, y, r, g, b)
     int x, y;
     char r, g, b;
{
  union REGS regs;

  if (x < 800 && y < 600)
    {
      regs.h.ah = 0x0c;
      regs.h.al = ((g & 7) << 5) + (b & 31);
      regs.x.bx = 0;
      regs.x.cx = 2 * x;
      regs.x.dx = y;

      int86 (0x10, &regs, &regs);

      regs.h.ah = 0x0c;
      regs.h.al = ((g & 24) >> 3) + ((r & 31) << 2);
      regs.x.bx = 0;
      regs.x.cx = 2 * x + 1;
      regs.x.dx = y;

      int86 (0x10, &regs, &regs);
    }
}



/*
main()
{
int  i, j;
char r, g, b;
int  d1, d2, d3;

himode();

for ( j=0; j<800; j+= 1 )
  for ( i=0; i<600; i+=1 )
	{
	d1 = (int)sqrt( (double)i*(double)i + (double)j*(double)j );
	d2 = (int)sqrt( (double)(j-800)*(double)(j-800) + (double)i*(double)i );
	d3 = (int)sqrt( (double)(i-600)*(double)(i-600) + (double)(j-400)*(double)(j-400) );

	r = ((d1/8)%32);
	g = ((d2/8)%32);
	b = ((d3/8)%32);
	Putpixel(j, i, r, g, b );
	}

printf("I'm finished.\n");
getch();
Textmode();
printf("Hello, World!\n");
getch();
}
  */

/*
	NAME
		PutVideoRow30H - display a row in High-Color mode 30h (800x600x32K)
*/

void 
PutVideoRow30H (
		 int startRow,	/* location to start display */
		 int startCol,	/* location to start display */
		 int length,	/* number of pixels to display */
		 WORD * buffer	/* data to be displayed */
)
{
  static
  ulong bytesPerRow = 800 * bytesPerPixel;
  uint length0;
  uint length1;
  ulong lOffset;
  uint offset;
  int page;
  static
  ulong pagesize = 64L * 1024L;
  uint segment;
  unsigned short *videoptr;

  /* calculate video page and offset */
  lOffset = (ulong) startRow *bytesPerRow +
   (ulong) (startCol * bytesPerPixel);

  videoptr = (unsigned short *) (0xd0200000 + lOffset);
  memcpy (videoptr, buffer, 2 * length);
#ifdef OLDBRUCE
  page = (int) (lOffset / pagesize);
  SetVideoPage (page);
  segment = 0xA000;
  offset = (uint) (lOffset % pagesize);


  /* display row, possibly in two parts, if it spills over page boundary */
  length *= bytesPerPixel;	/* converts length units from pixels to bytes */
  length0 = (uint) (pagesize - (ulong) offset);
  length1 = length - length0;
  if ((ulong) offset + (ulong) length < pagesize)
    {
/*
        movedata(FP_SEG(buffer), FP_OFF(buffer), segment, offset, length);
*/
    }
  else
    {
/*
        movedata(FP_SEG(buffer), FP_OFF(buffer), segment, offset, length0);
*/
      SetVideoPage (page + 1);
      /* in next line, have to divide length0 by 2 because it is units */
      /* of bytes, and buffer is a word pointer */
/*
        movedata(FP_SEG(buffer), FP_OFF(buffer + length0 / 2), segment, 0, length1);
*/
    }
#endif
}

void 
SetHicolorMode (int mode)
{
  union REGS inregs;
  union REGS outregs;

  inregs.h.ah = 0x10;
  inregs.h.al = 0xF0;
  inregs.h.bl = (unsigned char) mode;
  int86 (0x10, &inregs, &outregs);
  if (outregs.h.ah != 0)
    {
      SetVideoMode (0x03);
      InformFatal ("failed to set High-Color mode");
    }
}

void 
SetVideoMode (int mode)
{
  union REGS inregs;
  union REGS outregs;

  inregs.h.ah = 0;
  inregs.h.al = (unsigned char) mode;
  int86 (0x10, &inregs, &outregs);
}
/*
	NAME
		SetVideoPage - set read/write video memory page on Tseng ET4000
*/

void 
SetVideoPage (int page)
{
  outportb (0x03CD, (char) page);
}
/*
	NAME
		InformFatal - print an error message and exit
*/

void 
InformFatal (char *fmt,...)
{
  va_list args;

  va_start (args, fmt);
  fprintf (stderr, "\n%s: ", INFORM_PROG_NAME);
  (void) vfprintf (stderr, fmt, args);
  fprintf (stderr, "\n");
  va_end (args);
  exit (1);
}
