1 /* SCCS Id: @(#)video.c 3.4 2001/04/07 */
2 /* Copyright (c) NetHack PC Development Team 1993, 1994, 2001 */
3 /* NetHack may be freely redistributed. See license for details. */
6 * video.c - Hardware video support front-ends
9 * Initial Creation M. Allison 1993/04/04
10 * Add djgpp support K. Smolkowski 1993/04/26
11 * Add txt/graphics mode support M. Allison 1993/10/30
12 * Add graphics mode cursor sim. M. Allison 1994/02/19
13 * Add hooks for decals on vga M. Allison 2001/04/07
24 #pragma warning(disable:4018) /* signed/unsigned mismatch */
25 #pragma warning(disable:4127) /* conditional expression is constant */
26 #pragma warning(disable:4131) /* old style declarator */
27 #pragma warning(disable:4305) /* prevents complaints with MK_FP */
28 #pragma warning(disable:4309) /* initializing */
29 #pragma warning(disable:4759) /* prevents complaints with MK_FP */
32 /*=========================================================================
33 * General PC Video routines.
35 * The following routines are the video interfacing functions.
36 * In general these make calls to more hardware specific
37 * routines in other source files.
39 * Assumptions (94/04/23):
41 * - Supported defaults.nh file video options:
43 * If OPTIONS=video:autodetect is defined in defaults.nh then
44 * check for a VGA video adapter. If one is detected, then
45 * use the VGA code, otherwise resort to using the 'standard'
46 * video BIOS routines.
48 * If OPTIONS=video:vga is defined in defaults.nh, then use
51 * If OPTIONS=video:default is defined in defaults.nh use the
52 * 'standard' video BIOS routines (in the overlaid version),
53 * or DJGPPFAST routines (under djgpp). This is equivalent to
54 * having no OPTIONS=video:xxxx entry at all.
58 * - The handler for defaults.nh file entry:
62 * has now been added. The handler is in video.c and is called
65 * - Handling of videocolors and videoshades are now done with
66 * OPTIONS= statements. The new syntax separates the colour
67 * values with dashes ('-') rather than spaces (' ').
72 *=========================================================================
90 * --------------------------------------------------------------
91 * The rest of this file is only compiled if NO_TERMS is defined.
92 * --------------------------------------------------------------
103 #if !(__DJGPP__ >= 2)
104 typedef long clock_t;
109 #include <dos.h> /* needed for delay() */
112 # ifdef SCREEN_DJGPPFAST /* parts of this block may be unecessary now */
113 #define get_cursor(x,y) ScreenGetCursor(y,x)
117 void FDECL(get_cursor, (int *, int *));
120 void FDECL(adjust_cursor_flags, (struct WinDesc *));
121 void FDECL(cmov, (int, int));
122 void FDECL(nocmov, (int, int));
123 STATIC_DCL void NDECL(init_ttycolor);
126 int savevmode; /* store the original video mode in here */
127 int curcol,currow; /* graphics mode current cursor locations */
128 int g_attribute; /* Current attribute to use */
129 int monoflag; /* 0 = not monochrome, else monochrome */
130 int attrib_text_normal; /* text mode normal attribute */
131 int attrib_gr_normal; /* graphics mode normal attribute */
132 int attrib_text_intense; /* text mode intense attribute */
133 int attrib_gr_intense; /* graphics mode intense attribute */
134 boolean traditional = FALSE; /* traditonal TTY character mode */
135 boolean inmap = FALSE; /* in the map window */
137 char ttycolors[CLR_MAX]; /* also used/set in options.c */
138 # endif /* TEXTCOLOR */
140 extern int savevmode;
141 extern int curcol,currow;
142 extern int g_attribute;
144 extern int attrib_text_normal;
145 extern int attrib_gr_normal;
146 extern int attrib_text_intense;
147 extern int attrib_gr_intense;
148 extern boolean traditonal;
149 extern boolean inmap;
151 extern char ttycolors[CLR_MAX]; /* also used/set in options.c */
152 # endif /* TEXTCOLOR */
159 if (!iflags.grmode) {
162 } else if (iflags.usevga) {
173 if (!iflags.grmode) {
176 } else if (iflags.usevga) {
177 vga_clear_screen(BACKGROUND_VGA_COLOR);
183 cl_end() /* clear to end of line */
187 col = (int)ttyDisplay->curx;
188 row = (int)ttyDisplay->cury;
189 if (!iflags.grmode) {
192 } else if (iflags.usevga) {
196 tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
197 (int)ttyDisplay->cury);
201 cl_eos() /* clear to end of screen */
203 int cy = (int)ttyDisplay->cury+1;
205 if (!iflags.grmode) {
208 } else if (iflags.usevga) {
212 tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
213 (int)ttyDisplay->cury);
218 register int col, row;
220 ttyDisplay->cury = (uchar)row;
221 ttyDisplay->curx = (uchar)col;
222 if (!iflags.grmode) {
225 } else if (iflags.usevga) {
226 vga_gotoloc(col,row);
236 ++color; /* prevents compiler warning (unref. param) */
238 return (monoflag) ? 0 : 1;
249 tty_curs(BASE_WINDOW, 1, 0);
250 ttyDisplay->curx = ttyDisplay->cury = (uchar)0;
251 if (!iflags.grmode) {
254 } else if (iflags.usevga) {
264 if (!iflags.grmode) {
267 } else if (iflags.usevga) {
268 vga_gotoloc(col,row);
276 g_attribute = iflags.grmode ? attrib_gr_intense
277 : attrib_text_intense;
283 g_attribute = iflags.grmode ? attrib_gr_normal
284 : attrib_text_normal;
291 term_end_attr(int attr)
299 g_attribute = iflags.grmode ? attrib_gr_normal
300 : attrib_text_normal;
307 g_attribute = iflags.grmode ? attrib_gr_normal
308 : attrib_text_normal;
312 term_end_raw_bold(void)
319 term_start_attr(int attr)
325 g_attribute = ATTRIB_MONO_UNDERLINE;
327 g_attribute = iflags.grmode ? attrib_gr_intense
328 : attrib_text_intense;
332 g_attribute = iflags.grmode ? attrib_gr_intense
333 : attrib_text_intense;
337 g_attribute = ATTRIB_MONO_BLINK;
339 g_attribute = iflags.grmode ? attrib_gr_intense
340 : attrib_text_intense;
345 g_attribute = ATTRIB_MONO_REVERSE;
347 g_attribute = iflags.grmode ? attrib_gr_intense
348 : attrib_text_intense;
352 g_attribute = iflags.grmode ? attrib_gr_normal
353 : attrib_text_normal;
360 term_start_color(int color)
364 g_attribute = attrib_text_normal;
366 if (color >= 0 && color < CLR_MAX) {
370 g_attribute = ttycolors[color];
377 term_start_raw_bold(void)
389 (void) fflush(stdout);
390 msleep(50); /* sleep for 50 milliseconds */
403 if (!iflags.grmode) {
406 fputs("\033[>1l", stdout);
409 } else if (iflags.usevga) {
410 vga_tty_end_screen();
423 tty_number_pad(state)
426 ++state; /* prevents compiler warning (unref. param) */
430 tty_startup(wid, hgt)
434 /* code to sense display adapter is required here - MJA */
436 attrib_text_normal = ATTRIB_NORMAL;
437 attrib_text_intense = ATTRIB_INTENSE;
439 /* These are defaults and may get overridden */
440 attrib_gr_normal = attrib_text_normal;
441 attrib_gr_intense = attrib_text_intense;
442 g_attribute = attrib_text_normal; /* Give it a starting value */
446 vga_tty_startup(wid, hgt);
449 txt_startup(wid, hgt);
455 if (CO < COLNO || LI < ROWNO+3) setclipped();
463 monoflag = txt_monoadapt_check();
474 fputs("\033[>1h", stdout);
476 if (iflags.num_pad) tty_number_pad(1); /* make keypad send digits */
486 } else if (iflags.usevesa) {
491 } else if (iflags.use8514) {
506 } else if (iflags.usevesa) {
510 } else if (iflags.use8514) {
520 * Screen output routines (these are heavily used).
522 * These are the 3 routines used to place information on the screen
523 * in the NO_TERMS PC tty port of NetHack. These are the routines
524 * that get called by routines in other NetHack source files (such
525 * as those in win/tty).
527 * xputs - Writes a c null terminated string at the current location.
528 * Depending on compile options, this could just be a series
529 * of repeated calls to xputc() for each character.
531 * xputc - Writes a single character at the current location. Since
532 * various places in the code assume that control characters
533 * can be used to control, we are forced to interpret some of
534 * the more common ones, in order to keep things looking correct.
536 * xputg - If using a graphics mode display mechanism (such as VGA, this
537 * routine is used to display a graphical representation of a
538 * NetHack glyph at the current location. For more information on
539 * NetHack glyphs refer to the comments in include/display.h.
542 * wintty.h uses macros to redefine common output functions
543 * such as puts, putc, putchar, so that they get steered into
544 * either xputs (for strings) or xputc (for single characters).
545 * References to puts, putc, and putchar in other source files
546 * (that include wintty.h) are actually using these routines.
556 col = (int)ttyDisplay->curx;
557 row = (int)ttyDisplay->cury;
559 if (!iflags.grmode) {
560 txt_xputs(s,col,row);
562 } else if (iflags.usevga) {
563 vga_xputs(s,col,row);
569 xputc(ch) /* write out character (and attribute) */
575 i = iflags.grmode ? attrib_gr_normal
576 : attrib_text_normal;
578 attribute = (char)((g_attribute == 0) ? i : g_attribute);
579 if (!iflags.grmode) {
580 txt_xputc(ch,attribute);
582 } else if (iflags.usevga) {
583 vga_xputc(ch,attribute);
584 # endif /*SCREEN_VGA*/
589 xputg(glyphnum,ch,special) /* write out a glyph picture at current location */
594 if (!iflags.grmode || !iflags.tile_view) {
598 vga_xputg(glyphnum, ch, special);
605 video_update_positionbar(posbar)
612 vga_update_positionbar(posbar);
618 adjust_cursor_flags(cw)
621 # ifdef SIMULATE_CURSOR
623 if (cw->type == NHW_MAP) cursor_flag = 1;
624 else cursor_flag = 0;
626 if (cw->type == NHW_MAP) {
634 # endif /* SIMULATE_CURSOR */
637 # ifdef SIMULATE_CURSOR
639 /* change the defaults in pcvideo.h, not here */
640 int cursor_type = CURSOR_DEFAULT_STYLE;
641 int cursor_color = CURSOR_DEFAULT_COLOR;
644 /* The check for iflags.grmode is made BEFORE calling these. */
661 # endif /* SIMULATE_CURSOR */
669 * CLR_BROWN 3 low-intensity yellow
673 * CLR_GRAY 7 low-intensity white
676 * CLR_BRIGHT_GREEN 10
679 * CLR_BRIGHT_MAGENTA 13
687 /* assign_videoshades() is prototyped in extern.h */
688 /* assign_videocolors() is prototyped in extern.h */
689 /* assign_video() is prototyped in extern.h */
692 int shadeflag; /* shades are initialized */
693 int colorflag; /* colors are initialized */
694 char *schoice[3] = {"dark","normal","light"};
697 extern int shadeflag;
698 extern int colorflag;
699 extern char *schoice[3];
700 extern char *shade[3];
703 # endif /* VIDEOSHADES */
711 ttycolors[CLR_BLACK] = M_BLACK; /* 8 = dark gray */
712 ttycolors[CLR_WHITE] = M_WHITE; /* 15 = bright white */
713 ttycolors[CLR_GRAY] = M_GRAY; /* 7 = normal white */
714 shade[0] = schoice[0];
715 shade[1] = schoice[1];
716 shade[2] = schoice[2];
719 ttycolors[CLR_BLACK] = M_GRAY; /* mapped to white */
720 ttycolors[CLR_WHITE] = M_GRAY; /* mapped to white */
721 ttycolors[CLR_GRAY] = M_GRAY; /* mapped to white */
727 ttycolors[CLR_RED] = M_RED;
728 ttycolors[CLR_GREEN] = M_GREEN;
729 ttycolors[CLR_BROWN] = M_BROWN;
730 ttycolors[CLR_BLUE] = M_BLUE;
731 ttycolors[CLR_MAGENTA] = M_MAGENTA;
732 ttycolors[CLR_CYAN] = M_CYAN;
733 ttycolors[BRIGHT] = M_WHITE;
734 ttycolors[CLR_ORANGE] = M_ORANGE;
735 ttycolors[CLR_BRIGHT_GREEN] = M_BRIGHTGREEN;
736 ttycolors[CLR_YELLOW] = M_YELLOW;
737 ttycolors[CLR_BRIGHT_BLUE] = M_BRIGHTBLUE;
738 ttycolors[CLR_BRIGHT_MAGENTA] = M_BRIGHTMAGENTA;
739 ttycolors[CLR_BRIGHT_CYAN] = M_BRIGHTCYAN;
747 static int FDECL(convert_uchars,(char *, uchar *, int));
749 int assign_videoshades(char *choiceptr)
752 char *cptr, *cvalue[3];
753 int i,icolor = CLR_WHITE;
755 strcpy(choices,choiceptr);
758 /* find the next ' ' or tab */
759 cptr = index(cvalue[0], '-');
760 if (!cptr) cptr = index(cvalue[0], ' ');
761 if (!cptr) cptr = index(cvalue[0], '\t');
764 /* skip whitespace between '=' and value */
765 do { ++cptr; } while (isspace(*cptr) || (*cptr == '-'));
768 cptr = index(cvalue[1], '-');
769 if (!cptr) cptr = index(cvalue[0], ' ');
770 if (!cptr) cptr = index(cvalue[0], '\t');
773 do { ++cptr; } while (isspace(*cptr) || (*cptr == '-'));
776 for (i=0; i < 3; ++i) {
778 case 0: icolor = CLR_BLACK;
780 case 1: icolor = CLR_GRAY;
782 case 2: icolor = CLR_WHITE;
787 if ((strncmpi(cvalue[i],"black",5) == 0) ||
788 (strncmpi(cvalue[i],"dark",4) == 0)) {
789 shade[i] = schoice[0];
790 ttycolors[icolor] = M_BLACK; /* dark gray */
791 } else if ((strncmpi(cvalue[i],"gray",4) == 0) ||
792 (strncmpi(cvalue[i],"grey",4) == 0) ||
793 (strncmpi(cvalue[i],"medium",6) == 0) ||
794 (strncmpi(cvalue[i],"normal",6) == 0)) {
795 shade[i] = schoice[1];
796 ttycolors[icolor] = M_GRAY; /* regular gray */
797 } else if ((strncmpi(cvalue[i],"white",5) == 0) ||
798 (strncmpi(cvalue[i],"light",5) == 0)) {
799 shade[i] = schoice[2];
800 ttycolors[icolor] = M_WHITE; /* bright white */
810 * Process defaults.nh OPTIONS=videocolors:xxx
811 * Left to right assignments for:
812 * red green brown blue magenta cyan orange br.green yellow
813 * br.blue br.mag br.cyan
815 * Default Mapping (BIOS): 4-2-6-1-5-3-12-10-14-9-13-11
817 int assign_videocolors(char *colorvals)
822 init_ttycolor(); /* in case defaults.nh entry wasn't complete */
823 i = strlen(colorvals);
824 tmpcolor = (uchar *)alloc(i);
825 (void)convert_uchars(colorvals,tmpcolor,i);
827 for( i = 0; tmpcolor[i] != 0; ++i) {
828 if (icolor < (CLR_WHITE)) {
829 ttycolors[icolor++] = tmpcolor[i];
830 if ((icolor > CLR_CYAN) && (icolor < CLR_ORANGE)) {
836 free((genericptr_t)tmpcolor);
841 convert_uchars(bufp,list,size)
842 char *bufp; /* current pointer */
843 uchar *list; /* return list */
846 unsigned int num = 0;
858 if ((count==size) || !*bufp) return count;
862 case '0': case '1': case '2': case '3':
863 case '4': case '5': case '6': case '7':
865 num = num*10 + (*bufp-'0');
874 # endif /* VIDEOSHADES */
876 # endif /* TEXTCOLOR */
879 * Process defaults.nh OPTIONS=video:xxxx
881 * where (current) legitimate values are:
883 * autodetect (attempt to determine the adapter type)
884 * default (force use of the default video method for environment)
885 * vga (use vga adapter code)
896 * printf("video is %s",sopt);
903 if (strncmpi(sopt,"def",3) == 0) { /* default */
904 /* do nothing - default */
906 } else if (strncmpi(sopt,"vga",3) == 0) { /* vga */
911 } else if (strncmpi(sopt,"vesa",4) == 0) { /* vesa */
916 } else if (strncmpi(sopt,"8514",4) == 0) { /* 8514/A */
920 } else if (strncmpi(sopt,"auto",4) == 0) { /* autodetect */
927 if (v8514_detect()) {
937 * Auto-detect Priorities (arbitrary for now):
942 /* VGA depends on BIOS to enable function keys*/
954 void tileview(enable)
958 if (iflags.grmode) vga_traditional(enable ? FALSE : TRUE);
962 #endif /* NO_TERMS */
963 #else /* STUBVIDEO */
964 void tileview(enable)
968 #endif /* STUBVIDEO */