#include #include #include #define SQUARE(root) ((root) * (root)) #define ABS(num) (((num) < 0) ? (-num) : (num)) #define PI 3.14159265 /* Function prototypes */ int init (int); void dot ( int, int, int ); int isqrt ( int ); void circle ( int, int, int, int ); void palette ( int ); void background ( int ); /* Arrays for storing address information for all pixels */ unsigned yaddr[200]; unsigned xaddr[640]; char shift[640]; char point[640]; char far *scrn = (char far *)0xB8000000; /* Screen buffer */ int max_x, max_y, max_clr, shifter, back = 3, pal = 1; /* * Use variables rather than constants for the following * values so we can change them in the debugger */ int aspect = 270, x_wid = 85, y_wid = 78; main() { int i, x, y, mode = 4, tmode, p = 1, b = 8; tmode = getmode(); init(mode); background(b); palette(p); for (i = 0; i <= 90; ++i) { /* Draw circles */ x = x_wid * atan(sin(i / PI)); y = y_wid * atan(cos(i / PI)); circle((max_x / 2) + x,100 + y,i % 40,(i % max_clr) + 1); } for (i = 0; i <= 90; ++i) { /* Erase them */ x = x_wid * atan(sin(i / PI)); y = y_wid * atan(cos(i / PI)); circle((max_x / 2)+x,100+y,i % 40,0); } init(tmode); /* Restore original mode */ return(0); } int getmode() { union REGS inregs, outregs; inregs.h.ah = 0x0F; /* Use BIOS call to get mode */ inregs.h.al = 0; int86(0x10,&inregs,&outregs); if (outregs.h.al == 7) { puts("Can't run with monochrome adapter.\a"); exit(7); } else return(outregs.h.al); } int init (num) int num; { int indx = 0, indx2 = 0; unsigned clr_wid, mask; union REGS inregs, outregs; if (num > 6) { /* Can't assign EGA modes */ /* (they could be added easily) */ puts("Invalid mode.\x07"); exit(0); } switch (num) { case 4 : /* Set variables for each mode */ max_clr = 3; max_x = 320; max_y = 200; shifter = 4; clr_wid = 2; break; case 5 : max_clr = 1; max_x = 320; max_y = 200; shifter = 4; clr_wid = 2; break; case 6 : max_clr = 1; max_x = 640; max_y = 200; shifter = 8; clr_wid = 1; break; } if (num > 3) { /* For graphics modes only, */ while (indx < max_y) { /* calculate all y offsets */ yaddr[indx] = 80 * indx2; ++indx; yaddr[indx] = (80 * indx2) + 0x2000; ++indx; ++indx2; } /* Calculate all x offsets */ for (indx = 0; indx < max_x; ++indx) { mask = 0x80 >> (clr_wid * (indx % shifter)); if (num != 6) { /* Medium resolution offsets */ mask |= (mask >> 1); shift[indx] = 6 - (clr_wid * (indx % shifter)); } else /* High resolution offsets */ shift[indx] = 7 - (indx % shifter); point[indx] = ~mask; xaddr[indx] = indx / shifter; } } inregs.h.ah = 0; /* Use BIOS call to set mode */ inregs.h.al = num; int86(0x10,&inregs,&outregs); return(num); } /* Draw a dot */ void dot ( x, y, clr ) int x, y, clr; { unsigned total; char tcolor; clr = ABS(clr) & max_clr; /* Check color boundary */ total = xaddr[x] + yaddr[y]; /* Put in screen buffer */ scrn[total] = (clr << shift[x]) | (scrn[total] & point[x]); } int isqrt ( arg ) /* Calculate integer square root */ int arg; /* (real square root is too slow) */ { int odd_int, old_arg, first_sqrt; odd_int = 1; /* Initialize with 1 */ old_arg = arg; /* Save argument */ while (arg >= 0) { /* Find double approximate root */ arg = arg - odd_int; odd_int = odd_int + 2; } first_sqrt = odd_int >> 1; /* Divide by two */ /* Return adjusted root */ if (SQUARE(first_sqrt) - first_sqrt + 1 > old_arg) return(first_sqrt - 1); else return(first_sqrt); } void circle ( cx, cy, radius, clr ) int cx, cy, radius, clr; { int a, af, b, bf, target, r2, temp; clr = ABS(clr) & max_clr; /* Check color boundary */ target = 0; a = radius; b = 0; r2 = SQUARE(radius); while (a >= b) { /* Calculate new point */ b = isqrt(r2 - SQUARE(a)); temp = target; target = b; b = temp; while (b < target) { /* Plot point in each */ /* quadrant */ af = max_x * a / aspect; bf = max_x * b / aspect; dot(cx + af,cy + b,clr); dot(cx + bf,cy + a,clr); dot(cx - af,cy + b,clr); dot(cx - bf,cy + a,clr); dot(cx - af,cy - b,clr); dot(cx - bf,cy - a,clr); dot(cx + af,cy - b,clr); dot(cx + bf,cy - a,clr); b = b + 1; } a = a - 1; } } void palette ( color ) int color; { union REGS inregs, outregs; color &= 0x01; inregs.h.ah = 0x0B; /* Call BIOS to set palette */ inregs.h.bh = 1; inregs.h.bl = color; int86(0x10,&inregs,&outregs); } void background ( color ) int color; { union REGS inregs, outregs; color &= 0x0F; inregs.h.ah = 0x0B; /* Call BIOS to set background */ inregs.h.bh = 0; inregs.h.bl = color; int86(0x10,&inregs,&outregs); }