1 /* aNetHack 0.0.1 video.c $ANH-Date: 1457207042 2016/03/05 19:44:02 $ $ANH-Branch: chasonr $:$ANH-Revision: 1.11 $ */
2 /* Copyright (c) aNetHack PC Development Team 1993, 1994, 2001 */
3 /* aNetHack 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 *=========================================================================
92 * --------------------------------------------------------------
93 * The rest of this file is only compiled if NO_TERMS is defined.
94 * --------------------------------------------------------------
105 #if !(__DJGPP__ >= 2)
106 typedef long clock_t;
111 #include <dos.h> /* needed for delay() */
114 #ifdef SCREEN_DJGPPFAST /* parts of this block may be unecessary now */
115 #define get_cursor(x, y) ScreenGetCursor(y, x)
119 void FDECL(get_cursor
, (int *, int *));
122 void FDECL(adjust_cursor_flags
, (struct WinDesc
*));
123 void FDECL(cmov
, (int, int));
124 void FDECL(nocmov
, (int, int));
125 STATIC_DCL
void NDECL(init_ttycolor
);
127 int savevmode
; /* store the original video mode in here */
128 int curcol
, currow
; /* graphics mode current cursor locations */
129 int g_attribute
; /* Current attribute to use */
130 int monoflag
; /* 0 = not monochrome, else monochrome */
131 int attrib_text_normal
; /* text mode normal attribute */
132 int attrib_gr_normal
; /* graphics mode normal attribute */
133 int attrib_text_intense
; /* text mode intense attribute */
134 int attrib_gr_intense
; /* graphics mode intense attribute */
135 boolean traditional
= FALSE
; /* traditonal TTY character mode */
136 boolean inmap
= FALSE
; /* in the map window */
138 char ttycolors
[CLR_MAX
]; /* also used/set in options.c */
139 #endif /* TEXTCOLOR */
144 if (!iflags
.grmode
) {
147 } else if (iflags
.usevga
) {
151 } else if (iflags
.usevesa
) {
160 if (!iflags
.grmode
) {
163 } else if (iflags
.usevga
) {
164 vga_clear_screen(BACKGROUND_VGA_COLOR
);
167 } else if (iflags
.usevesa
) {
168 vesa_clear_screen(BACKGROUND_VGA_COLOR
);
173 void cl_end() /* clear to end of line */
177 col
= (int) ttyDisplay
->curx
;
178 row
= (int) ttyDisplay
->cury
;
179 if (!iflags
.grmode
) {
180 txt_cl_end(col
, row
);
182 } else if (iflags
.usevga
) {
183 vga_cl_end(col
, row
);
186 } else if (iflags
.usevesa
) {
187 vesa_cl_end(col
, row
);
190 tty_curs(BASE_WINDOW
, (int) ttyDisplay
->curx
+ 1, (int) ttyDisplay
->cury
);
193 void cl_eos() /* clear to end of screen */
195 int cy
= (int) ttyDisplay
->cury
+ 1;
197 if (!iflags
.grmode
) {
200 } else if (iflags
.usevga
) {
204 } else if (iflags
.usevesa
) {
208 tty_curs(BASE_WINDOW
, (int) ttyDisplay
->curx
+ 1, (int) ttyDisplay
->cury
);
213 register int col
, row
;
215 ttyDisplay
->cury
= (uchar
) row
;
216 ttyDisplay
->curx
= (uchar
) col
;
217 if (!iflags
.grmode
) {
218 txt_gotoxy(col
, row
);
220 } else if (iflags
.usevga
) {
221 vga_gotoloc(col
, row
);
224 } else if (iflags
.usevesa
) {
225 vesa_gotoloc(col
, row
);
233 ++color
; /* prevents compiler warning (unref. param) */
235 return (monoflag
) ? 0 : 1;
244 tty_curs(BASE_WINDOW
, 1, 0);
245 ttyDisplay
->curx
= ttyDisplay
->cury
= (uchar
) 0;
246 if (!iflags
.grmode
) {
249 } else if (iflags
.usevga
) {
253 } else if (iflags
.usevesa
) {
263 if (!iflags
.grmode
) {
264 txt_gotoxy(col
, row
);
266 } else if (iflags
.usevga
) {
267 vga_gotoloc(col
, row
);
270 } else if (iflags
.usevesa
) {
271 vesa_gotoloc(col
, row
);
279 g_attribute
= iflags
.grmode
? attrib_gr_intense
: attrib_text_intense
;
285 g_attribute
= iflags
.grmode
? attrib_gr_normal
: attrib_text_normal
;
289 term_end_attr(int attr
)
297 g_attribute
= iflags
.grmode
? attrib_gr_normal
: attrib_text_normal
;
304 g_attribute
= iflags
.grmode
? attrib_gr_normal
: attrib_text_normal
;
308 term_end_raw_bold(void)
314 term_start_attr(int attr
)
319 g_attribute
= ATTRIB_MONO_UNDERLINE
;
322 iflags
.grmode
? attrib_gr_intense
: attrib_text_intense
;
326 g_attribute
= iflags
.grmode
? attrib_gr_intense
: attrib_text_intense
;
330 g_attribute
= ATTRIB_MONO_BLINK
;
333 iflags
.grmode
? attrib_gr_intense
: attrib_text_intense
;
338 g_attribute
= ATTRIB_MONO_REVERSE
;
341 iflags
.grmode
? attrib_gr_intense
: attrib_text_intense
;
345 g_attribute
= iflags
.grmode
? attrib_gr_normal
: attrib_text_normal
;
351 term_start_color(int color
)
355 g_attribute
= attrib_text_normal
;
357 if (color
>= 0 && color
< CLR_MAX
) {
361 g_attribute
= ttycolors
[color
];
368 term_start_raw_bold(void)
378 (void) fflush(stdout
);
379 msleep(50); /* sleep for 50 milliseconds */
388 if (!iflags
.grmode
) {
391 fputs("\033[>1l", stdout
);
394 } else if (iflags
.usevga
) {
395 vga_tty_end_screen();
398 } else if (iflags
.usevesa
) {
399 vesa_tty_end_screen();
411 tty_number_pad(state
)
414 ++state
; /* prevents compiler warning (unref. param) */
418 tty_startup(wid
, hgt
)
421 /* code to sense display adapter is required here - MJA */
423 attrib_text_normal
= ATTRIB_NORMAL
;
424 attrib_text_intense
= ATTRIB_INTENSE
;
426 /* These are defaults and may get overridden */
427 attrib_gr_normal
= attrib_text_normal
;
428 attrib_gr_intense
= attrib_text_intense
;
429 g_attribute
= attrib_text_normal
; /* Give it a starting value */
433 vga_tty_startup(wid
, hgt
);
437 if (iflags
.usevesa
) {
438 vesa_tty_startup(wid
, hgt
);
441 txt_startup(wid
, hgt
);
447 if (CO
< COLNO
|| LI
< ROWNO
+ 3)
456 monoflag
= txt_monoadapt_check();
466 fputs("\033[>1h", stdout
);
469 tty_number_pad(1); /* make keypad send digits */
481 if (iflags
.usevesa
) {
486 if (iflags
.use8514
) {
503 if (iflags
.usevesa
) {
508 if (iflags
.use8514
) {
517 * Screen output routines (these are heavily used).
519 * These are the 3 routines used to place information on the screen
520 * in the NO_TERMS PC tty port of aNetHack. These are the routines
521 * that get called by routines in other aNetHack source files (such
522 * as those in win/tty).
524 * xputs - Writes a c null terminated string at the current location.
525 * Depending on compile options, this could just be a series
526 * of repeated calls to xputc() for each character.
528 * xputc - Writes a single character at the current location. Since
529 * various places in the code assume that control characters
530 * can be used to control, we are forced to interpret some of
531 * the more common ones, in order to keep things looking correct.
533 * xputg - If using a graphics mode display mechanism (such as VGA, this
534 * routine is used to display a graphical representation of a
535 * aNetHack glyph at the current location. For more information on
536 * aNetHack glyphs refer to the comments in include/display.h.
539 * wintty.h uses macros to redefine common output functions
540 * such as puts, putc, putchar, so that they get steered into
541 * either xputs (for strings) or xputc (for single characters).
542 * References to puts, putc, and putchar in other source files
543 * (that include wintty.h) are actually using these routines.
552 col
= (int) ttyDisplay
->curx
;
553 row
= (int) ttyDisplay
->cury
;
555 if (!iflags
.grmode
) {
556 txt_xputs(s
, col
, row
);
558 } else if (iflags
.usevga
) {
559 vga_xputs(s
, col
, row
);
562 } else if (iflags
.usevesa
) {
563 vesa_xputs(s
, col
, row
);
568 void xputc(ch
) /* write out character (and attribute) */
574 i
= iflags
.grmode
? attrib_gr_normal
: attrib_text_normal
;
576 attribute
= (char) ((g_attribute
== 0) ? i
: g_attribute
);
577 if (!iflags
.grmode
) {
578 txt_xputc(ch
, attribute
);
580 } else if (iflags
.usevga
) {
581 vga_xputc(ch
, attribute
);
582 #endif /*SCREEN_VGA*/
584 } else if (iflags
.usevesa
) {
585 vesa_xputc(ch
, attribute
);
586 #endif /*SCREEN_VESA*/
590 void xputg(glyphnum
, ch
,
591 special
) /* write out a glyph picture at current location */
596 if (!iflags
.grmode
|| !iflags
.tile_view
) {
599 } else if (iflags
.grmode
&& iflags
.usevga
) {
600 vga_xputg(glyphnum
, ch
, special
);
603 } else if (iflags
.grmode
&& iflags
.usevesa
) {
604 vesa_xputg(glyphnum
, ch
, special
);
611 video_update_positionbar(posbar
)
617 else if (iflags
.usevga
)
618 vga_update_positionbar(posbar
);
621 else if (iflags
.usevesa
)
622 vesa_update_positionbar(posbar
);
628 adjust_cursor_flags(cw
)
631 #ifdef SIMULATE_CURSOR
633 if (cw
->type
== NHW_MAP
) cursor_flag
= 1;
634 else cursor_flag
= 0;
636 if (cw
->type
== NHW_MAP
) {
644 #endif /* SIMULATE_CURSOR */
647 #ifdef SIMULATE_CURSOR
649 /* change the defaults in pcvideo.h, not here */
650 int cursor_type
= CURSOR_DEFAULT_STYLE
;
651 int cursor_color
= CURSOR_DEFAULT_COLOR
;
654 /* The check for iflags.grmode is made BEFORE calling these. */
681 #endif /* SIMULATE_CURSOR */
688 * CLR_BROWN 3 low-intensity yellow
692 * CLR_GRAY 7 low-intensity white
695 * CLR_BRIGHT_GREEN 10
698 * CLR_BRIGHT_MAGENTA 13
706 /* assign_videoshades() is prototyped in extern.h */
707 /* assign_videocolors() is prototyped in extern.h */
708 /* assign_video() is prototyped in extern.h */
710 int shadeflag
; /* shades are initialized */
711 int colorflag
; /* colors are initialized */
712 char *schoice
[3] = { "dark", "normal", "light" };
714 #endif /* VIDEOSHADES */
721 ttycolors
[CLR_BLACK
] = M_BLACK
; /* 8 = dark gray */
722 ttycolors
[CLR_WHITE
] = M_WHITE
; /* 15 = bright white */
723 ttycolors
[CLR_GRAY
] = M_GRAY
; /* 7 = normal white */
724 shade
[0] = schoice
[0];
725 shade
[1] = schoice
[1];
726 shade
[2] = schoice
[2];
729 ttycolors
[CLR_BLACK
] = M_GRAY
; /* mapped to white */
730 ttycolors
[CLR_WHITE
] = M_GRAY
; /* mapped to white */
731 ttycolors
[CLR_GRAY
] = M_GRAY
; /* mapped to white */
737 ttycolors
[CLR_RED
] = M_RED
;
738 ttycolors
[CLR_GREEN
] = M_GREEN
;
739 ttycolors
[CLR_BROWN
] = M_BROWN
;
740 ttycolors
[CLR_BLUE
] = M_BLUE
;
741 ttycolors
[CLR_MAGENTA
] = M_MAGENTA
;
742 ttycolors
[CLR_CYAN
] = M_CYAN
;
743 ttycolors
[BRIGHT
] = M_WHITE
;
744 ttycolors
[CLR_ORANGE
] = M_ORANGE
;
745 ttycolors
[CLR_BRIGHT_GREEN
] = M_BRIGHTGREEN
;
746 ttycolors
[CLR_YELLOW
] = M_YELLOW
;
747 ttycolors
[CLR_BRIGHT_BLUE
] = M_BRIGHTBLUE
;
748 ttycolors
[CLR_BRIGHT_MAGENTA
] = M_BRIGHTMAGENTA
;
749 ttycolors
[CLR_BRIGHT_CYAN
] = M_BRIGHTCYAN
;
755 static int FDECL(convert_uchars
, (char *, uchar
*, int));
758 assign_videoshades(char *choiceptr
)
761 char *cptr
, *cvalue
[3];
762 int i
, icolor
= CLR_WHITE
;
764 strcpy(choices
, choiceptr
);
767 /* find the next ' ' or tab */
768 cptr
= index(cvalue
[0], '-');
770 cptr
= index(cvalue
[0], ' ');
772 cptr
= index(cvalue
[0], '\t');
776 /* skip whitespace between '=' and value */
779 } while (isspace(*cptr
) || (*cptr
== '-'));
782 cptr
= index(cvalue
[1], '-');
784 cptr
= index(cvalue
[0], ' ');
786 cptr
= index(cvalue
[0], '\t');
792 } while (isspace(*cptr
) || (*cptr
== '-'));
795 for (i
= 0; i
< 3; ++i
) {
809 if ((strncmpi(cvalue
[i
], "black", 5) == 0)
810 || (strncmpi(cvalue
[i
], "dark", 4) == 0)) {
811 shade
[i
] = schoice
[0];
812 ttycolors
[icolor
] = M_BLACK
; /* dark gray */
813 } else if ((strncmpi(cvalue
[i
], "gray", 4) == 0)
814 || (strncmpi(cvalue
[i
], "grey", 4) == 0)
815 || (strncmpi(cvalue
[i
], "medium", 6) == 0)
816 || (strncmpi(cvalue
[i
], "normal", 6) == 0)) {
817 shade
[i
] = schoice
[1];
818 ttycolors
[icolor
] = M_GRAY
; /* regular gray */
819 } else if ((strncmpi(cvalue
[i
], "white", 5) == 0)
820 || (strncmpi(cvalue
[i
], "light", 5) == 0)) {
821 shade
[i
] = schoice
[2];
822 ttycolors
[icolor
] = M_WHITE
; /* bright white */
832 * Process defaults.nh OPTIONS=videocolors:xxx
833 * Left to right assignments for:
834 * red green brown blue magenta cyan orange br.green yellow
835 * br.blue br.mag br.cyan
837 * Default Mapping (BIOS): 4-2-6-1-5-3-12-10-14-9-13-11
840 assign_videocolors(char *colorvals
)
845 init_ttycolor(); /* in case defaults.nh entry wasn't complete */
846 i
= strlen(colorvals
);
847 tmpcolor
= (uchar
*) alloc(i
);
848 (void) convert_uchars(colorvals
, tmpcolor
, i
);
850 for (i
= 0; tmpcolor
[i
] != 0; ++i
) {
851 if (icolor
< (CLR_WHITE
)) {
852 ttycolors
[icolor
++] = tmpcolor
[i
];
853 if ((icolor
> CLR_CYAN
) && (icolor
< CLR_ORANGE
)) {
859 free((genericptr_t
) tmpcolor
);
864 convert_uchars(bufp
, list
, size
)
865 char *bufp
; /* current pointer */
866 uchar
*list
; /* return list */
869 unsigned int num
= 0;
883 if ((count
== size
) || !*bufp
)
898 num
= num
* 10 + (*bufp
- '0');
907 #endif /* VIDEOSHADES */
908 #endif /* TEXTCOLOR */
911 * Process defaults.nh OPTIONS=video:xxxx
913 * where (current) legitimate values are:
915 * autodetect (attempt to determine the adapter type)
916 * default (force use of the default video method for environment)
917 * vga (use vga adapter code)
926 * printf("video is %s",sopt);
935 if (strncmpi(sopt
, "def", 3) == 0) { /* default */
936 /* do nothing - default */
938 } else if (strncmpi(sopt
, "vga", 3) == 0) { /* vga */
943 } else if (strncmpi(sopt
, "vesa", 4) == 0) { /* vesa */
948 } else if (strncmpi(sopt
, "8514", 4) == 0) { /* 8514/A */
952 } else if (strncmpi(sopt
, "auto", 4) == 0) { /* autodetect */
959 if (v8514_detect()) {
969 * Auto-detect Priorities (arbitrary for now):
972 if (iflags
.hasvesa
) iflags
.usevesa
= 1;
973 else if (iflags
.hasvga
) {
975 /* VGA depends on BIOS to enable function keys*/
990 if (iflags
.grmode
&& iflags
.usevga
)
991 vga_traditional(enable
? FALSE
: TRUE
);
994 if (iflags
.grmode
&& iflags
.usevesa
)
995 vesa_traditional(enable
? FALSE
: TRUE
);
998 #endif /* NO_TERMS */
1000 #else /* STUBVIDEO */
1007 #endif /* STUBVIDEO */