/* * scr_gfx.ega: * IBM PC screen handling, enhanced graphics * * Copyright (c) 1989 University of Toronto. All rights reserved. * Anyone may use or copy this software, except that it may not be * sold for profit, that this copyright notice remain intact, and that * credit is given where it is due. The University of Toronto and the * author make no warranty and accept no liability for this software. */ static char GFXid[] = "$Header: scr_gfx.ega,v 1.1 89/04/13 16:11:36 pkern Exp $"; /* video mode parameters */ unsigned int txt_mode=0x07, txt_addr=0xb000; unsigned int avm_mode=0, avm_addr=0; unsigned int gfx_mode=0x06, gfx_addr=0xb800; unsigned int gfx_xres=640, gfx_yres=200, gfx_numclr=2; /* Enhanced Graphics nitty-gritty */ #ifndef BIOS static uchar ofs, msk; #define GBOFS(a,b) ((((b)>>1)*80)+((a)/8)) /* x,y byte offset */ #define GMASK(a) (0x80 >> ((a)%8)) /* bit offset for x */ #define GBe(b) *((uchar far *)0xb8000000+b) /* even number lines */ #define GBo(b) *((uchar far *)0xba000000+b) /* odd number lines */ #define BeNK(a) if (a) GBe(ofs) |= msk; else GBe(ofs) &= ~msk; #define BoNK(a) if (a) GBo(ofs) |= msk; else GBo(ofs) &= ~msk; #define BOINK(aa,b) if ((b)&1) { BoNK(aa) } else { BeNK(aa) } #endif init_gfx() { extern uchar interlace, gcolour; extern int gmax_x, gmax_y, gmax_clr; if (interlace && gfx_mode) { r.h.ah = 0; r.h.al = gfx_mode; crtint; r.h.ah = 0x0f; /* get current video mode */ crtint; ncols = r.h.ah; /* num of cols */ vmode = r.h.al; /* video mode */ pgnum = r.h.bh; /* page number */ } gmax_x = gfx_xres; gmax_y = gfx_yres; gmax_clr = gfx_numclr; gcolour = gmax_clr-1; } /* gfx_erase -- clear the graphics screen */ gfx_erase() { r.h.ah = 0; r.h.al = vmode & 0x7f; crtint; } gfx_colour(n) uchar n; { return(n>0); } /* gpeek -- get a pixel's colour */ gpeek(x, y) int x, y; { uchar c = 0; /* #ifdef BIOS */ r.h.ah = 0x0d; r.x.cx = x; r.h.dl = y; crtint; return(r.h.al); /* #else */ #ifdef notdef ofs = GBOFS(x,y); msk = GMASK(x); c = (y&1) ? GBo(ofs) : GBe(ofs); return(((c & msk) == msk)); #endif } /* boink -- light a pixel */ boink(x,y,c) int x, y; uchar c; { /* #ifdef BIOS */ r.h.ah = 0x0c; r.h.al = c; r.x.cx = x; r.h.dl = y; crtint; /* #else */ #ifdef notdef ofs = GBOFS(x,y); msk = GMASK(x); BOINK(c,y) #endif } /* * hline -- only does horizontal lines (union regulations :-) * (called from bline(), should be optimized for speed). */ hline(x,y,n,c) int x; register int y,n; uchar c; { register int i; if (n < 0) { n = -n; x -= n; if (x < 0) { n += x; x = 0; } } /* #ifdef BIOS */ /* needs optimizing! */ for (i=x; i < x+n; i++) boink(i, y, c); /* #else */ #ifdef notdef msk = 0xff >> (x%8); /* move mask to end of byte */ if (y&1) { for(ofs=GBOFS(x,y); ofs < GBOFS(x+n, y); ofs++) { BoNK(c) /* solid line between end-points */ msk = 0xff; } /* remainder word mask */ msk &= ~(0xff >> ((x+n)%8)); BoNK(c) } else { for(ofs=GBOFS(x,y); ofs < GBOFS(x+n, y); ofs++) { BeNK(c) msk = 0xff; } msk &= ~(0xff >> ((x+n)%8)); BeNK(c) } #endif } /* * vline -- vertical lines only * (again, called from bline(), should be optimized for speed). */ vline(x,y,n,c) int y; register int x,n; uchar c; { register int i; if (n < 0) { n = -n; y -= n; if (y < 0) { n += y; y = 0; } } /* #ifdef BIOS */ /* needs optimizing! */ for (i=y; i < y+n; i++) boink(x, i, c); /* #else */ #ifdef notdef msk = GMASK(x); ofs = GBOFS(x,y); for (; n; n--, y++) { if (y&1) { BoNK(c) ofs += 80; } else { BeNK(c) } } #endif } /* * xrun -- optimize search for runs to colour c in x direction * (called from dofill(), should be quicker that gpeek()-ing each pixel) */ xrun(x, y, c, dir) int x, y, dir; uchar c; { uchar cx; extern int gmax_x; /* #ifdef BIOS */ while (0 <= x && x < gmax_x) { cx = gpeek(x, y); /* needs optimizing! */ if (c == cx) break; x += dir; } /* #else */ #ifdef notdef uchar bm; msk = GMASK(x); ofs = GBOFS(x,y); bm = (y&1) ? GBo(ofs) : GBe(ofs); while (0 <= x && x < gmax_x) { cx = ((bm & msk) == msk); if (c == cx) break; x += dir; msk = GMASK(x); if (((dir > 0) && (x%8) == 0) || ((dir < 0) && (x%8) == 7)) { ofs = GBOFS(x,y); bm = (y&1) ? GBo(ofs) : GBe(ofs); } } #endif if (c == cx) x -= dir; if (x < 0) return(0); if (x >= gmax_x) return(gmax_x-1); return(x); }