#include #include #include #include "misc.hpp" #include "screen.hpp" #include "vgalib.hpp" GraphicsAPI::GraphicsAPI(int xr, int yr, int vxr, int vyr, int clrs) { int segm, offs; xres = xr; yres = yr; vxres = vxr; vyres = vyr; colors = clrs; libID = "Generic Graphics"; asm { push bp mov ax, 1130h mov bh, 03h int 10h mov ax, bp pop bp mov [segm], es mov [offs], ax } font = (unsigned char *)MK_FP(segm, offs); fontHeight = fontWidth = 8; } void GraphicsAPI::hLine(int x, int y, int l) { while (l--) putPixel(x++, y); } void GraphicsAPI::vLine(int x, int y, int l) { while (l--) putPixel(x, y++); } /* * Generic line drawing routine, using Bresenham's algorithm. * Taken from Richard Wilton: "PC & PS/2 Video Systems" p. 166-7 */ void GraphicsAPI::line(int x1, int y1, int x2, int y2) { if (x1==x2) { sort(y1, y2); vLine(x1, y1, y2-y1+1); return; } if (y1==y2) { sort(x1, x2); hLine(x1, y1, x2-x1+1); } int dx = absolute(x2-x1); int dy = absolute(y2-y1); if (dx >= dy) { if (x1>x2) { swap(x1, x2); swap(y1, y2); } int yincr = 1; if (y2= 0) { y += yincr; d += aincr; } else d += bincr; putPixel(x, y); } } else { if (y1>y2) { swap(x1, x2); swap(y1, y2); } int xincr = 1; if (x2= 0) { x += xincr; d += aincr; } else d += bincr; putPixel(x, y); } } } void GraphicsAPI::rectangle(int x1, int y1, int x2, int y2) { sort(x1, x2); sort(y1, y2); hLine(x1, y1, x2-x1); hLine(x1, y2, x2-x1); vLine(x1, y1, y2-y1); vLine(x2, y1, y2-y1); } void GraphicsAPI::bar(int x1, int y1, int x2, int y2) { int width = x2-x1+1; for (int y = y1; y < y2; ++y) hLine(x1, y, width); } void GraphicsAPI::wipe() { bar(0, 0, vxres, vyres); } void GraphicsAPI::putChar(int x, int y, int ch) { unsigned char *fptr = font + fontHeight*ch; for (int j=0; j>3, 16) { libID = "4-plane 16-color mode"; outpw(0x3ce, 0x0f01); // enable set/reset } void Planar16::putPixel(int x, int y, int c) { outpw(0x3ce, 0x00 | (c<<8)); // set/reset to select color outpw(0x3ce, 0x08 | 0x8000>>(x&7)); // bit mask to select bit unsigned char *pos = graphScr+y*xbytes+(x>>3); *pos = *pos; } int Planar16::getPixel(int x, int y) { return videoBuf[y*xbytes+x]; } void Planar16::hLine(int x, int y, int l) { outpw(0x3ce, 0x00 | (color<<8)); // set/reset to select color unsigned char *pos = graphScr+y*xbytes+(x>>3); int mask; int shift = x & 7; if (shift > 0) { mask = 0x00ff >> shift; l -= 8 - shift; if (l<0) mask &= 0xff << -l; outpw(0x3ce, 0x08 | mask << 8); // bit mask to select first bits *pos = *pos; ++pos; } if (l >= 8) { outpw(0x3ce, 0xff08); // bit mask to select 8 bits memset(pos, 0, l>>3); pos += l>>3; l -= l & 0xf8; } if (l >= 0) { mask = 0xff00 << (8-l); outpw(0x3ce, 0x08 | mask); // bit mask to select last bits *pos = *pos; } } int Planar16::getPelPan(int x) { return x & 7; } /* * Chained256 */ Chained256::Chained256(int xr, int yr, int vxr) : VGAGraphicsAPI(xr, yr, vxr, vxr, 256) { libID = "Chained 256-color mode"; } void Chained256::putPixel(int x, int y, int c) { videoBuf[y*xbytes+x] = c; } int Chained256::getPixel(int x, int y) { return videoBuf[y*xbytes+x]; } void Chained256::hLine(int x, int y, int l) { memset(graphScr+y*xbytes+x, color, l); } unsigned Chained256::getOffset(int x, int y) { return (y * xbytes + x/(vxres/xbytes)) >> 2; } int Chained256::getPelPan(int x) { return 2*(x & 3); } /* * Unchained256 */ Unchained256::Unchained256(int xr, int yr, int vxr) : VGAGraphicsAPI(xr, yr, vxr, vxr>>2, 256) { libID = "Unchained 256-color mode"; } void Unchained256::putPixel(int x, int y, int c) { outpw(0x3c4, 0x02 | 0x0100<<(x&3)); videoBuf[y*xbytes+(x>>2)] = c; } int Unchained256::getPixel(int x, int y) { return videoBuf[y*xbytes+x]; } void Unchained256::hLine(int x, int y, int l) { unsigned char *pos = graphScr+y*xbytes+(x>>2); int mask; int shift = x & 3; if (shift > 0) { mask = 0x000f << shift & 0x000f; l -= 4-shift; if (l<0) mask &= 0x0f >> -l; outpw(0x3c4, 0x02 | mask << 8); // write enable first pixels *(pos++) = color; } if (l >= 4) { outpw(0x3c4, 0x0f02); // write enable 4 pixels memset(pos, color, l>>2); pos += l>>2; l -= l & 0xfc; } if (l >= 0) { mask = 0x0f00 >> (4-l) & 0x0f00; outpw(0x3c4, 0x02 | mask); // write enable last pixels *pos = color; } } int Unchained256::getPelPan(int x) { return 2*(x & 3); }