/* 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 */ }