/*	HERC.c   - Video routines specific to the Hercules board.
*/

#include "lib.h"
#include "vgr.h"

#define REG_INDEX   0x3b4
#define REG_DATA    0x3b5
#define REG_MODE    0x3b8
#define REG_STATUS  0x3ba
#define REG_CONFIG  0x3bf

int herc_mode();
int herc_write_row();
int herc_init();
int herc_set_page();
int herc_clear();
int herc_clr_point();
int herc_set_point();
int herc_xor_point();
int herc_get_point();
int herc_null();
int movmem();
int peekb();
int pokeb();


static int herc_page = 0;
static int (*herc_func[])() =
	{  herc_init,      herc_clear,    herc_set_point,   herc_clr_point,
	   herc_xor_point, herc_get_point,herc_write_row,   herc_null,
	   herc_null,      herc_mode,     movmem, peekb, pokeb,
	   herc_set_page,  herc_null   };


static unsigned char far * far *herc_column[2];


static int herc_null()
{
	return ERROR;	/* do nothing */
}


int herc_set_page( page )
int page;
{
	outportb( REG_MODE, (herc_page = !!page) ? 0x8a : 0x0a );
	return OK;
}


int herc_clear()
{
	setmem( (herc_page ? BASE_HERC1 : BASE_HERC0), 0x8000, 0 );
	return OK;
}


int herc_write_row( row, prow, nbytes )
unsigned int nbytes, row;
char *prow;
{
	movmem( prow, herc_column[herc_page][row], nbytes );
	return OK;
}


int herc_init()
{
	unsigned int i,j;
	void *malloc();

	VGR_HRES  = 720;
	VGR_VRES  = 348;
	VGR_NBPL  =  90;
	VGR_NCOLORS = 2;

	if ( !herc_column[0] )
	   herc_column[0] = CASTUCFPP malloc( sizeof(uchar far *) * VGR_VRES );
	if ( !herc_column[0] )
	   return ERROR;

	if ( !herc_column[1] )
	   herc_column[1] = CASTUCFPP malloc( sizeof(uchar far *) * VGR_VRES );

	if ( !herc_column[1] )
	{  allocf( herc_column[0] );
	   return ERROR;
	};

	for ( i = 0; i < VGR_VRES; i++ )
	{   j = 0x2000 * (i & 0x03) + VGR_NBPL * (i >> 2);
	    herc_column[0][i] = CASTUCFP BASE_HERC0 + j;
	    herc_column[1][i] = CASTUCFP BASE_HERC1 + j;
	};

	movmem( herc_func, vgr_func, sizeof(vgr_func) );
	return OK;
}


int herc_set_point( x, y )
unsigned int x, y;
{
	herc_column[herc_page][y][x>>3] |= (x >> 3);
}


int herc_clr_point( x, y )
unsigned int x, y;
{
	herc_column[herc_page][y][x>>3] &= ~(x >> 3);
}


int herc_get_point( x, y )
unsigned int x, y;
{
	return !!(herc_column[herc_page][y][x>>3] & (x >> 3));
}


int herc_xor_point( x, y )
unsigned int x, y;
{
	herc_column[herc_page][y][x>>3] ^= (x >> 3);
}


int herc_mode( mode )
int mode;
{
	int i;
	static char setup[2][12] = {
	   { 0x35,0x2d,0x2e,0x07,0x5b,0x02,0x57,0x57,0x02,0x03,0x00,0x00 },
	   { 0x61,0x50,0x52,0x0f,0x19,0x06,0x19,0x19,0x02,0x0d,0x0b,0x0c }
	                           };

	if ( mode == MODE_TEXT0 )
	{  outportb( REG_CONFIG, 0 );
	   outportb( REG_MODE,   0 );
	   for ( i=0; i < 12; i++ )
	   {  outportb( REG_INDEX, i );
	      outportb( REG_DATA,  setup[1][i] );
	   };
	   outportb( REG_MODE, 0x28 );
	   vgr_mode(3);   /* the cursor is missing if I don't do this... */
	   return OK;
	};

	if ( mode == MODE_APA1 )
	{  outportb( REG_CONFIG, 3 );
	   outportb( REG_MODE,   2 );
	   for ( i=0; i < 12; i++ )
	   {  outportb( REG_INDEX, i );
	      outportb( REG_DATA,  setup[0][i] );
	   };
	   setmem( BASE_HERC0, 0x8000, 0 );
	   setmem( BASE_HERC1, 0x8000, 0 );
	   herc_set_page( 1 );
	   return OK;
	};

	return ERROR;
}

