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


/*	CGA.c -  Low level drivers for the CGA board 
*/ 
 
 
#include "lib.h" 
#include "vgr.h" 
 
int cga_init(); 
int cga_write_row(); 
int cga_clear(); 
int cga_clr_point(); 
int cga_xor_point(); 
int cga_get_point(); 
int cga_set_point(); 
int cga_mode(); 
int cga_null(); 
int cga_palette(); /* not tested! */ 
int cga_movmem(); 
int cga_peekb(); 
int cga_pokeb(); 
 
static int mode; 
static int (*cga_func[])() = { 
	cga_init,       cga_clear,     cga_set_point, cga_clr_point, 
	cga_xor_point,  cga_get_point, cga_write_row, cga_null, 
	cga_null,       cga_mode,      cga_movmem, cga_peekb, cga_pokeb, 
	cga_null,       cga_palette    }; 
 
 
static unsigned char far * far *cga_column; 
 
 
static int cga_null() 
{ 
	return ERROR; 
} 
 
 
int cga_peekb( p ) 
unsigned char far *p; 
{ 
#asm 
	les   bx, dword ptr 4[bp] 
	mov   dx, 03dah 
x1:	in    al, dx 
	test  al, 1 
	jnz   x1 
x2:	in    al, dx 
	test  al, 1 
	jz    x2 
	mov   al, es:byte ptr [bx] 
	sub ah,ah 
#endasm 
} 
 
 
int cga_pokeb( p, b ) 
unsigned char far *p; 
unsigned char b; 
{ 
#asm 
	mov   ah,byte ptr 8[bp] 
	les   bx,dword ptr 4[bp] 
	mov   dx, 03dah 
y1:	in    al, dx 
	test  al, 1 
	jnz   y1 
y2:	in    al, dx 
	test  al, 1 
	jz    y2 
	mov   es:byte ptr [bx],ah 
#endasm 
} 
 
 
/*	WARNING: cga_movmem() doesn't check for overlapping blocks!!!! 
*/ 
 
int cga_movmem( s, d, n ) 
unsigned char far *s, *d; 
int n; 
{ 
	for ( ; n--; s++, d++ ) 
	{ 
#asm 
	les   bx, dword ptr 4[bp] 
	mov   ah, es:byte ptr [bx] 
	les   bx, dword ptr 8[bp] 
	mov   dx, 03dah 
z1:	in    al, dx 
	test  al, 1 
	jnz   z1 
z2:	in    al, dx 
	test  al, 1 
	jz    z2 
	mov   es:byte ptr [bx],ah 
#endasm 
	}; 
} 
 
int cga_init() 
{ 
	void *malloc(); 
	int row; 
 
	if ( !cga_column ) 
	   cga_column = CASTUCFPP malloc( sizeof CASTUCFP * 200 ); 
 
	if ( !cga_column ) 
	   return ERROR; 
 
	for ( row = 0; row < 200; row++ ) 
	   cga_column[row] = CASTUCFP BASE_CGA + ((uint)row >> 1)*80l + (row & 1)*0x2000; 
 
	VGR_NBPL = VGR_NCOLORS =  
	VGR_HRES = VGR_VRES = 0;   /* must set mode first! */ 
 
	movmem( cga_func, vgr_func, sizeof(vgr_func) ); 
	return OK; 
} 
 
 
/*	Warning: NOT TESTED 
*/ 
int cga_palette( bg, fg ) 
int fg, bg; 
{ 
	if ( !mode ) 
	   return OK;  /* no meaning if not in 320x200x4 mode */ 
 
	outportb( 0x3d9, ((uint)(fg & 0x07)<<5) | (bg & 0x0f) ); 
	return OK; 
} 
 
 
int cga_write_row( row, prow, nbytes ) 
register unsigned int nbytes; 
unsigned char far *prow; 
int row; 
{ 
	cga_movmem( prow, cga_column[row], nbytes ); 
} 
 
 
int cga_clear() 
{ 
	int i; 
 
	for ( i=0; i < 0x4000; i++ ) 
	   cga_pokeb( CASTUCFP (BASE_CGA + (long)i), 0 ); 
} 
 
 
int cga_clr_point( x, y ) 
unsigned int x, y; 
{ 
	unsigned char far *p; 
 
	if ( mode ) 
	{  p = cga_column[y] + (x>>2); 
	   cga_pokeb( p, cga_peekb(p) & ~(0xc0 >> ((x & 0x03) << 1)) ); 
	} else  
	{  p = cga_column[y] + (x>>3); 
	   cga_pokeb( p, cga_peekb(p) & ~(0x80 >> (x & 0x07)) ); 
	}; 
} 
 
 
int cga_xor_point( x, y, color ) 
unsigned int x, y, color; 
{ 
	cga_set_point( x, y, cga_get_point( x, y ) ^ color ); 
} 
 
 
int cga_get_point( x, y ) 
unsigned int x, y; 
{ 
	uint i; 
 
	if ( mode ) 
	{  i = (unsigned int)(x & 0x03) << 1; 
	   return (uint)(cga_peekb(cga_column[y]+(x>>2))&(0xc0>>i)) >> (6-i); 
	} else  
	   return !!( cga_peekb( cga_column[y] + (x>>3) )  
	                                   & (0x80 >> (x & 0x07))); 
} 
 
 
int cga_set_point( x, y, color ) 
unsigned int x, y, color; 
{ 
	unsigned char far *p; 
	unsigned char i; 
 
	if ( !mode ) 
	{  p = cga_column[y] + (x>>3); 
	   return cga_pokeb( p, cga_peekb(p) | (0x80 >> (x & 0x07)) ); 
	}; 
 
	p = cga_column[y] + (x>>2); 
	i = (x & 3) << 1; 
	cga_pokeb( p, cga_peekb(p) & ~(0xc0 >> i) ); 
	cga_pokeb( p, cga_peekb(p) | ((color & 0x03) << (6-i)) ); 
} 
 
 
int cga_mode( m ) 
int m; 
{ 
	if ( m == MODE_TEXT0 ) 
	   return vgr_mode(3); 
 
	if ( m == MODE_APA3 )   /* 320x200x4 */ 
	{  VGR_HRES = 320; 
	   VGR_VRES = 200; 
	   VGR_NCOLORS = 4; 
	   VGR_NBPL =  80; 
	   mode = 1; 
	   return vgr_mode(4); 
	}; 
 
	if ( m == MODE_APA2 )   /* 640x200x2 */ 
	{  VGR_HRES = 640; 
	   VGR_VRES = 200; 
	   VGR_NCOLORS = 2; 
	   VGR_NBPL =  80; 
	   mode = 0; 
	   return vgr_mode(6); 
	}; 
 
	return ERROR;  /* mode not currently supported */ 
}