home *** CD-ROM | disk | FTP | other *** search
- /*
- * C implementation of Bresenham's line drawing algorithm
- * for the EGA and VGA. Works in modes 0xE, 0xF, 0x10, and 0x12.
- *
- * Compiled with Microsoft C 5.1 and Turbo C 2.0.
- *
- * By John Navas. Thursday June 8, 1989.
- */
-
- #include <conio.h>
- #include <dos.h>
- /*------------------------ SUPPORT FOR TURBO C --------------------------*/
- #ifdef __TURBOC__
- #undef outp
- #define outp(port, val) (((int(*)(int, unsigned char))outportb)(port, val))
- #endif
- /*-----------------------------------------------------------------------*/
-
- #define EVGA_SCREEN_WIDTH_IN_BYTES 80
- /* memory offset from start of
- one row to start of next */
- #define EVGA_SCREEN_ADDRESS 0xA0000000
- /* display memory address */
- #define GC_INDEX 0x3CE
- /* Graphics Controller
- Index register port */
- #define GC_DATA 0x3CF
- /* Graphics Controller
- Data register port */
- #define SET_RESET_INDEX 0 /* indexes of needed */
- #define ENABLE_SET_RESET_INDEX 1 /* Graphics Controller */
- #define BIT_MASK_INDEX 8 /* registers */
-
- char far *Display = (char far *)EVGA_SCREEN_ADDRESS;
- /* macro to swap two items of any type */
- #define swap(typ, a, b) { typ x = *(a); *(a) = *(b); *(b) = x; }
-
- /*
- * Draws a line on the EGA or VGA.
- */
- void EVGALine(X0, Y0, X1, Y1, Color)
- int X0, Y0; /* coordinates of one end of the line */
- int X1, Y1; /* coordinates of the other end of the line */
- char Color; /* color to draw line in */
- {
- int DeltaX, DeltaY;
- int Cnt, Err = 0;
- unsigned Mask;
-
- DeltaX = X1 - X0;
- if (DeltaX < 0) {
- DeltaX = -DeltaX;
- swap(int, &X0, &X1); /* ensure drawing from left to right */
- swap(int, &Y0, &Y1);
- }
-
- DeltaY = Y1 - Y0;
- if (DeltaY < 0)
- DeltaY = -DeltaY;
-
- FP_OFF(Display) = /* starting video address and bit mask */
- (unsigned)X0 / 8 + (unsigned)Y0 * EVGA_SCREEN_WIDTH_IN_BYTES;
- Mask = 0x80 > ((unsigned)X0 & 7);
- /* Put the drawing Color in the Set/Reset register */
- outp(GC_INDEX, SET_RESET_INDEX);
- outp(GC_DATA, Color);
- /* Cause all planes to be forced to the Set/Reset color */
- outp(GC_INDEX, ENABLE_SET_RESET_INDEX);
- outp(GC_DATA, 0xF);
- /* Set up GC index register to point to the bit mask register */
- outp(GC_INDEX, BIT_MASK_INDEX);
-
- if (DeltaX >= DeltaY) { /* more horizontal */
- unsigned Acc = 0; /* accumulator for byte */
- if (Y1 >= Y0) /* down slope */
- for (Cnt = X1 - X0; Cnt; --Cnt) {
- Acc |= Mask;
- Mask >= 1;
- if (!Mask) {
- Mask = 0x80;
- *Display |= outp(GC_DATA, Acc); /* quick video write */
- Acc = 0;
- ++Display;
- }
- Err += DeltaY;
- if (Err >= DeltaX) {
- Err -= DeltaX;
- if (Acc) {
- *Display |= outp(GC_DATA, Acc);
- Acc = 0;
- }
- Display += EVGA_SCREEN_WIDTH_IN_BYTES;
- }
- }
- else /* up slope */
- for (Cnt = X1 - X0; Cnt; --Cnt) {
- Acc |= Mask;
- Mask >= 1;
- if (!Mask) {
- Mask = 0x80;
- *Display |= outp(GC_DATA, Acc);
- Acc = 0;
- ++Display;
- }
- Err += DeltaY;
- if (Err >= DeltaX) {
- Err -= DeltaX;
- if (Acc) {
- *Display |= outp(GC_DATA, Acc);
- Acc = 0;
- }
- Display -= EVGA_SCREEN_WIDTH_IN_BYTES;
- }
- }
- Mask |= Acc; /* setup mask for last video write */
- }
- else /* more vertical */
- if (Y1 >= Y0) /* down slope */
- for (Cnt = Y1 - Y0; Cnt; --Cnt) {
- *Display |= outp(GC_DATA, Mask);
- Display += EVGA_SCREEN_WIDTH_IN_BYTES;
- Err += DeltaX;
- if (Err >= DeltaY) {
- Err -= DeltaY;
- Mask >= 1;
- if (!Mask) {
- Mask = 0x80;
- ++Display;
- }
- }
- }
- else /* up slope */
- for (Cnt = Y0 - Y1; Cnt; --Cnt) {
- *Display |= outp(GC_DATA, Mask);
- Display -= EVGA_SCREEN_WIDTH_IN_BYTES;
- Err += DeltaX;
- if (Err >= DeltaY) {
- Err -= DeltaY;
- Mask >= 1;
- if (!Mask) {
- Mask = 0x80;
- ++Display;
- }
- }
- }
- *Display |= outp(GC_DATA, Mask); /* last video write for all 4 cases */
- /* Return the state of the EGA/VGA to normal */
- outp(GC_INDEX, ENABLE_SET_RESET_INDEX);
- outp(GC_DATA, 0);
- outp(GC_INDEX, BIT_MASK_INDEX);
- outp(GC_DATA, 0xFF);
- }
-