www.pudn.com > pcx_c.zip > EGA.C


/*	EGA   -  routines to drive the EGA board. 
*/ 
 
#include "lib.h" 
#include "vgr.h" 
 
/*	proto's 
*/ 
int ega_init(); 
int ega_select_plane(); 
int ega_write_row(); 
int ega_clear(); 
int ega_set_palette(); 
int ega_clr_point(); 
int ega_xor_point(); 
int ega_get_point(); 
int ega_set_point(); 
int ega_mode(); 
int ega_null(); 
int movmem(); 
int peekb(); 
int pokeb(); 
int vgr_mode(); 
 
static int (*ega_func[])() = { 
	ega_init,       ega_clear,     ega_set_point, ega_clr_point, 
	ega_xor_point,  ega_get_point, ega_write_row, ega_select_plane, 
	ega_set_palette,ega_mode,      movmem, peekb, pokeb, 
	ega_null,       ega_null       }; 
 
 
/*	EGA stuff 
*/ 
 
#define REG_ADDRESS 0x3c4 
#define REG_MAPMASK 0x3c5 
#define REG_IDX     0x3ce 
#define REG_VAL     0x3cf 
#define OUTIDX(i,v) {outportb(REG_IDX,i);outportb(REG_VAL,v);} 
 
static unsigned char far * far *ega_column; 
 
 
static int ega_null() 
{ 
	return ERROR; 
} 
 
int ega_init() 
{ 
	void *malloc(); 
	int row; 
 
	if ( !ega_column ) 
	   ega_column = CASTUCFPP malloc( sizeof CASTUCFP * 350 ); 
 
	if ( !ega_column ) 
	   return ERROR; 
 
	for ( row = 0; row < 350; row++ ) 
	   ega_column[row] = CASTUCFP BASE_EGA + row*80l; 
 
	VGR_HRES   = 640; 
	VGR_VRES   = 350; 
	VGR_NBPL   =  80; 
	VGR_NCOLORS = 16; 
 
	movmem( ega_func, vgr_func, sizeof(vgr_func) ); 
	return OK; 
} 
 
 
int ega_select_plane( plane ) 
int plane; 
{ 
	outportb( REG_ADDRESS, 2 ); 
	outportb( REG_MAPMASK, plane >= 0 ? 1 << (plane & 0x03) : -plane ); 
} 
 
 
/*	A version for the CGA card will have to check for retrace 
	before copying each byte. 
*/ 
int ega_write_row( row, prow, nbytes ) 
register unsigned int nbytes; 
unsigned char *prow; 
int row; 
{ 
	movmem( prow, ega_column[row], nbytes ); 
} 
 
 
int ega_clear() 
{ 
	ega_select_plane( -0x0f ); 
	setmem( BASE_EGA, 0x8000, 0 ); 
	ega_select_plane( 0 ); 
} 
 
 
int ega_set_palette( reg, red, green, blue ) 
unsigned char reg, red, green, blue; 
{ 
	REGS r; 
	unsigned char v; 
 
	v = (blue  & 0x01)     | (blue  & 0x02) *  4 
	  | (green & 0x01) * 2 | (green & 0x02) *  8 
	  | (red   & 0x01) * 4 | (red   & 0x02) * 16; 
 
	r.ax = 0x1000; 
	r.bx = ((unsigned int)v << 8) | reg; 
	sysint( 0x10, &r, &r ); 
} 
 
 
int ega_clr_point( x, y ) 
unsigned int x, y; 
{ 
	ega_set_point( x, y, 0 ); 
} 
 
 
int ega_xor_point( x, y, color ) 
unsigned int x, y, color; 
{ 
	ega_set_point( x, y, ega_get_point( x, y ) ^ color ); 
} 
 
 
int ega_get_point( x, y ) 
unsigned int x, y; 
{ 
#if 1 
	REGS r; 
 
	r.ax = 0x0d00; 
	r.dx = y; 
	r.cx = x; 
 
	sysint( 0x10, &r, &r ); 
	return r.ax & 0xff; 
#endif 
#if 0 
	unsigned char plane, mask, b, color; 
	unsigned char far *p; 
 
	p = ega_column[y] + (x>>3); 
	b = 0x80 >> (x & 0x07); 
 
	outportb( REG_ADDRESS, 2 ); 
 
	for ( color=plane=0; plane < 4; plane++ ) 
	{  outportb( REG_MAPMASK, mask = (1 << plane) ); 
	   color |= !!(*p & b) * mask; 
	}; 
 
	return color; 
#endif 
} 
 
 
int ega_set_point( x, y, color ) 
unsigned int x, y, color; 
{ 
#if 1 
	/* this works, but is painfully slow!! */ 
	REGS r; 
 
	r.ax = 0x0c00 | color; 
	r.dx = y; 
	r.cx = x; 
 
	sysint( 0x10, &r, &r ); 
	return OK; 
#endif 
#if 0 
	/* This is my routine. It works if you stick to the color white! 
	   otherwise, it doesn't work because it's apparently not possible 
	   to directly read the EGA VRAM. 
	*/ 
	unsigned char plane, mask, b; 
	unsigned char far *p; 
 
	p = ega_column[y] + (x>>3); 
	b = (unsigned int)0x80 >> (x & 0x07); 
 
	outportb( REG_ADDRESS, 2 ); 
 
	for ( plane=0; plane < 4; plane++ ) 
	{  outportb( REG_MAPMASK, mask = ((unsigned int)1 << plane) ); 
	   if ( color & mask ) 
	      *p |= b; 
	   else *p &= ~b; 
	}; 
#endif 
#if 0 
	/* This is Gary Entsmingers routine, 
	   which works like an XOR function instead of 
	   a set function. I don't have the foggiest 
	   notion how it works. There's no reference in 
	   any of the (incomplete) doc that I've got 
	   to the registers used here. 
	*/ 
	unsigned char b; 
	unsigned char far *p; 
 
	p = ega_column[y] + (x>>3); 
	b = (unsigned int)0x80 >> (x & 0x07); 
 
	OUTIDX(0,color); 
	OUTIDX(1, 0x0f); 
	OUTIDX(8,    b); 
	OUTIDX(3, 0x18); 
 
	/* It doesn't seem to matter what you do here as long as you 
	   don't assign -1 to *p. *p |= -1, *p &= -1, *p ^= *p and *p = *p 
	   all have the same effect - a hardware XOR function! 
	*/ 
	*p &= 0xff; 
 
	OUTIDX(0,0); 
	OUTIDX(1,0); 
	OUTIDX(8,0xff); 
	OUTIDX(3,0); 
#endif 
} 
 
 
int ega_mode( mode ) 
int mode; 
{ 
	if ( mode == MODE_APA0 ) 
	   return vgr_mode( 16 ); 
 
	if ( mode == MODE_TEXT0 ) 
	   return vgr_mode( 3 ); 
 
	return ERROR;  /* mode not currently supported */ 
}