home *** CD-ROM | disk | FTP | other *** search
-
-
- /* HERCLIB.C Routines for the Hercules card
-
- This file contains graphics support functions for the Hercules card. See
- Micro Cornucopia issue #39 for an article on the subject.
-
- I used Turbo C version 1.5 compact model for compiulation.
-
-
- 12-1-87 Larry Fogg
-
- */
-
-
-
-
- #include <stdlib.h>
- #include <dos.h>
-
- #define boolean char
- #define yes 1
- #define no 0
-
- #define index 0x3b4 /* 6845 ports */
- #define data 0x3b5
- #define mode 0x3b8 /* Herc ports */
- #define status 0x3ba
- #define config 0x3bf
-
- const char normal = 0x07; /* character attributes for direct screen writes */
- const char reverse = 0x70;
- const char under_line = 0x01;
- const char normal_blink = 0x87;
- const char reverse_blink = 0xf0;
- const char under_blink = 0x81;
-
- const int page0 = 0xb000; /* base address of video pages */
- const int page1 = 0xb800;
- const int text_base = 0xb000; /* base address of text page */
- const int max_col = 719; /* Herc parameters */
- const int max_row = 347;
- const int screen_size = 0x8000; /* bytes per page */
-
- int page_drawn, page_viewed; /* current drawing and viewing pages */
-
-
-
-
-
- void init () /* set initial values for global variables */
- {
- page_drawn = page0;
- page_viewed = page0;
- } /* init */
-
-
-
-
-
- boolean herc_there () /* test for presence of Hercules card */
- {
- unsigned i;
-
- geninterrupt (0x11);
- if ((_AX & 0x30) == 0x30) /* check for monochrome card presence */
- for (i = 0; i < 0x800; i++) /* is it a Herc */
- if ((inportb (status) & 0x80)) /* watch bit 7 */
- return yes;
- return no;
- } /* herc_there */
-
-
-
-
-
- void screen_off ()
- {
- outportb (mode, 2);
- } /* screen_off */
-
-
-
-
- void set_page_viewed (int page)
- {
- if (page == page0)
- outportb (mode, 0x0a);
- else
- outportb (mode, 0x8a);
- page_viewed = page;
- } /* set_page_viewed */
-
-
-
-
-
- void set_page_drawn (int page)
- {
- page_drawn = page;
- } /* set_page_drawn */
-
-
-
-
-
- void clear_gr_scr (int page)
- {
- int i;
-
- if (page_viewed == page)
- screen_off (); /* turn off screen if page is displayed */
- for (i = 0; i < 0x3FFF; i++)
- poke (page, 2 * i, 0); /* turn off all bits */
- if (page_viewed == page) /* turn screen on again */
- set_page_viewed (page);
- } /* clear_gr_scr */
-
-
-
-
-
- void clear_txt_scr ()
- {
- int i;
-
- for (i = 0; i <= 0x3fff; i++)
- poke (text_base, 2 * i, 0x0700); /* fill text page with nulls & attrib 7 */
- } /* clear_txt_scr */
-
-
-
-
-
- void gotoXY (char X, char Y) /* position the cursor */
- {
- _AH = 2; /* service 2 */
- _BH = 0;
- _DH = Y; /* row number */
- _DL = X; /* column number */
- geninterrupt (0x10);
- } /* gotoXY */
-
-
-
-
- void scr_write (int X, int Y, char str [81], char attrib)
- { /* direct memory write of text */
- int i, offset;
-
- i = 0;
- offset = 2 * (80 * Y + X); /* find memory offset of first char in str */
- while (str [i] != '\0') /* poke each char-attribute pair */
- {
- pokeb (text_base, offset, str [i]);
- pokeb (text_base, ++offset, attrib);
- i++;
- offset++;
- }
- gotoXY (X + i, Y); /* position cursor at end of str */
- } /* scr_write */
-
-
-
-
-
- void set_graphics ()
- {
- char i;
- char params [12] = {0x35, 0x2d, 0x2e, 0x07, 0x5b, 0x02,
- 0x57, 0x57, 0x02, 0x03, 0x00, 0x00};
-
- outportb (config, 3); /* allows both graphics pages */
- screen_off ();
- for (i = 0; i < 12; i++) /* program 6845 registers for graphics */
- {
- outportb (index, i);
- outportb (data, params [i]);
- }
- clear_gr_scr (page0);
- clear_gr_scr (page1); /* clear and turn on screen */
- } /* set_graphics */
-
-
-
-
-
- void set_text ()
- {
- char i;
- char params [12] = {0x61, 0x50, 0x52, 0x0f, 0x19, 0x06,
- 0x19, 0x19, 0x02, 0x0d, 0x0b, 0x0c};
-
- outportb (config, 0); /* lock out graphics modes */
- outportb (mode, 0); /* set text mode and blank screen */
- for (i = 0; i < 12; i++) /* program 6845 registers for text */
- {
- outportb (index, i);
- outportb (data, params [i]);
- }
- clear_txt_scr ();
- outportb (mode, 0x28); /* enable blink and turn on screen */
- } /* set_text */
-
-
-
-
-
- void save_screen (char fname [13], int page) /* write to disk */
- {
- FILE *f;
- char far *screen;
-
- screen = page * 0x10000; /* wierd but it works */
- f = fopen (fname, "w");
- fwrite (screen, screen_size, 1, f);
- fclose (f);
- } /* save_screen */
-
-
-
-
-
- void get_screen (char fname [13], int page) /* read from disk */
- {
- FILE *f;
- char far *screen;
-
- screen = page * 0x10000;
- f = fopen (fname, "r");
- screen_off ();
- fread (screen, screen_size, 1, f);
- set_page_viewed (page);
- fclose (f);
- } /* get_screen */
-
-
-
-
-
- void draw_point (int col, int row, boolean fill)
- {
- int byte_ofs; /* offset within page for byte containing the point */
- char mask; /* locates point within the byte */
-
- mask = 1 << (7 - (col % 8));
- byte_ofs = 0x2000 * (row % 4) + 90 * (row / 4) + (col / 8);
- if (fill) /* draw the point */
- pokeb (page_drawn, byte_ofs, peekb (page_drawn, byte_ofs) | mask);
- else /* erase the point */
- pokeb (page_drawn, byte_ofs, peekb (page_drawn, byte_ofs) & ~mask);
- } /* draw_point */
-
-
-
-
-
- void draw_byte (int offset, boolean fill) /* draw 8 points at once for speed */
- {
- if (fill)
- poke (page_drawn, offset, 0xff);
- else
- poke (page_drawn, offset, 0x00);
- } /* draw_byte */
-
-
-
-
-
- void draw_line (int X1, int Y1, int X2, int Y2, boolean on)
- { /* uses Bresenham algorithm to draw a line */
- int dX, dY; /* vector components */
- int row, col,
- final, /* final row or column number */
- G, /* used to test for new row or column */
- inc1, /* G increment when row or column doesn't change */
- inc2; /* G increment when row or column changes */
- boolean pos_slope;
-
- dX = X2 - X1; /* find vector components */
- dY = Y2 - Y1;
- pos_slope = (dX > 0); /* is slope positive? */
- if (dY < 0)
- pos_slope = !pos_slope;
- if (abs (dX) > abs (dY)) /* shallow line case */
- {
- if (dX > 0) /* determine start point and last column */
- {
- col = X1;
- row = Y1;
- final = X2;
- }
- else
- {
- col = X2;
- row = Y2;
- final = X1;
- }
- inc1 = 2 * abs (dY); /* determine increments and initial G */
- G = inc1 - abs (dX);
- inc2 = 2 * (abs (dY) - abs (dX));
- if (pos_slope)
- while (col <= final) /* step through columns chacking for new row */
- {
- draw_point (col, row, on);
- col++;
- if (G >= 0) /* it's time to change rows */
- {
- row++; /* positive slope so increment through the rows */
- G += inc2;
- }
- else /* stay at the same row */
- G += inc1;
- }
- else
- while (col <= final) /* step through columns checking for new row */
- {
- draw_point (col, row, on);
- col++;
- if (G > 0) /* it's time to change rows */
- {
- row--; /* negative slope so decrement through the rows */
- G += inc2;
- }
- else /* stay at the same row */
- G += inc1;
- }
- } /* if |dX| > |dY| */
- else /* steep line case */
- {
- if (dY > 0) /* determine start point and last row */
- {
- col = X1;
- row = Y1;
- final = Y2;
- }
- else
- {
- col = X2;
- row = Y2;
- final = Y1;
- }
- inc1 = 2 * abs (dX); /* determine increments and initial G */
- G = inc1 - abs (dY);
- inc2 = 2 * (abs (dX) - abs (dY));
- if (pos_slope)
- while (row <= final) /* step through rows checking for new column */
- {
- draw_point (col, row, on);
- row++;
- if (G >= 0) /* it's time to change columns */
- {
- col++; /* positive slope so increment through the columns */
- G += inc2;
- }
- else /* stay at the same column */
- G += inc1;
- }
- else
- while (row <= final) /* step throuth rows checking for new column */
- {
- draw_point (col, row, on);
- row++;
- if (G > 0) /* it's time to change columns */
- {
- col--; /* negative slope so decrement through the columns */
- G += inc2;
- }
- else /* stay at the same column */
- G += inc1;
- }
- }
- } /* draw_line */
-
-
-
-
-
- void draw_box (int X1, int Y1, int X2, int Y2, boolean fill)
- { /* fast box fill - does a byte at a time when it can */
- int row, col, i,
- left_bits, right_bits, byte_draws;
- int byte_ofs;
-
- left_bits = 8 - (X1 % 8); /* individual bits that need to be drawn */
- right_bits = (X2 % 8);
- byte_draws = (X2 - X1 - left_bits) / 8; /* number of byte draws to do */
-
- for (row = Y1; row <= Y2; row++)
- {
- for (col = X1; col <= X1 + left_bits; col++) /* draw the left side bits */
- draw_point (col, row, fill);
- for (col = X2 - right_bits; col <= X2; col++) /* draw the right bits */
- draw_point (col, row, fill);
- byte_ofs = 0x2000 * (row % 4) + 90 * (row / 4) + ((X1 + left_bits) / 8);
- for (i = byte_ofs; i <= byte_ofs + byte_draws; i++) /* draw the bytes */
- draw_byte (i, fill);
- }
- } /* draw_box */
-