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