1 /*   SCCS Id: @(#)vidvga.c   3.3     96/02/16			    */
2 /*   Copyright (c) NetHack PC Development Team 1995                 */
3 /*   NetHack may be freely redistributed.  See license for details. */
4 /*
5  * vidvga.c - VGA Hardware video support
6  */
7 
8 #include "hack.h"
9 
10 #ifdef SCREEN_VGA		/* this file is for SCREEN_VGA only    */
11 #include "pcvideo.h"
12 #include "tile.h"
13 #include "pctiles.h"
14 
15 #include <dos.h>
16 #include <ctype.h>
17 #include "wintty.h"
18 
19 # ifdef __GO32__
20 #include <pc.h>
21 #include <unistd.h>
22 # endif
23 
24 /*=========================================================================
25  * VGA Video supporting routines (for tiles).
26  *
27  * The following routines carry out the lower level video functions required
28  * to make PC NetHack work with VGA graphics.
29  *
30  *   - The binary files NetHack1.tib and NetHacko.tib must be in your
31  *     game directory.  Currently, unpredictable results may occur if they
32  *     aren't since the code hasn't been tested with it missing (yet).
33  *
34  * Notes (96/02/16):
35  *
36  *   - Cursor emulation on the map is now implemented.  The input routine
37  *     in msdos.c calls the routine to display the cursor just before
38  *     waiting for input, and hides the cursor immediately after satisfying
39  *     the input request.
40  *
41  *   - A check for a VGA adapter is implemented.
42  *
43  *   - With 640 x 480 resolution, the use of 16 x 16 icons allows only 40
44  *     columns for the map display.  This makes it necessary to support the
45  *     TTY CLIPPING code.  The right/left scrolling with this can be
46  *     a little annoying.  Feel free to rework the routines.
47  *
48  *   - NetHack1.tib is built from text files derived from bitmap files
49  *     provided by Warwick Allison, using routines developed and supplied
50  *     by Janet Walz.  The icons are very well done and thanks to
51  *     Warwick Allison for an excellent effort!
52  *
53  *   - The text fonts that this is using while in graphics mode come from
54  *     the Video BIOS ROM on board the VGA adapter.  Code in vga_WriteChar
55  *     copies the appropriate pixels from the video ROM to the Video buffer.
56  *
57  *   - Currently, most of the routines are in an ifdef OVLB.
58  *     If you change that, you may have to muck with some of the
59  *     variable declarations which now assume this.  This is not a
60  *     problem in a non-overlaid environment (djgpp for example).
61  *
62  *   - VGA 640 by 480, 16 colour mode (0x12) uses an odd method to
63  *     represent a colour value from the palette. There are four
64  *     planes of video memory, all overlaid at the same memory location.
65  *     For example, if a pixel has the colour value 7:
66  *
67  *           0 1 1 1
68  *            \ \ \ \
69  *             \ \ \ plane 0
70  *              \ \ plane 1
71  *               \ plane 2
72  *                plane 3
73  *
74  *   - VGA write mode 2 requires that a read be done before a write to
75  *     set some latches on the card.  The value read had to be placed
76  *     into a variable declared 'volatile' to prevent djgpp from
77  *     optimizing away the entire instruction (the value was assigned
78  *     to a variable which was never used).  This corrects the striping
79  *     problem that was apparent with djgpp.
80  *
81  *   - A check for valid mode switches has been added.
82  *
83  *   - No tiles are displayed on the Rogue Level in keeping with the
84  *     original Rogue.  The display adapter remains in graphics mode
85  *     however.
86  *
87  *   - Added handling for missing NetHackX.tib files, and resort to using
88  *     video:default and tty if one of them can't be located.
89  *
90  * ToDo (96/02/17):
91  *
92  *   - Nothing prior to release.
93  *=========================================================================
94  */
95 
96 
97 # if defined(_MSC_VER)
98 #  if _MSC_VER >= 700
99 #pragma warning(disable:4018)	/* signed/unsigned mismatch */
100 #pragma warning(disable:4127)	/* conditional expression is constant */
101 #pragma warning(disable:4131)	/* old style declarator */
102 #pragma warning(disable:4305)	/* prevents complaints with MK_FP */
103 #pragma warning(disable:4309)	/* initializing */
104 #    if _MSC_VER > 700
105 #pragma warning(disable:4759)	/* prevents complaints with MK_FP */
106 #    endif
107 #  endif
108 # include <conio.h>
109 # endif
110 
111 /* STATIC_DCL void FDECL(vga_NoBorder, (int)); /* */
112 void FDECL(vga_gotoloc, (int,int));  /* This should be made a macro */
113 void NDECL(vga_backsp);
114 #ifdef SCROLLMAP
115 STATIC_DCL void FDECL(vga_scrollmap,(BOOLEAN_P));
116 #endif
117 STATIC_DCL void FDECL(vga_redrawmap,(BOOLEAN_P));
118 void FDECL(vga_cliparound,(int, int));
119 
120 #ifdef POSITIONBAR
121 STATIC_DCL void NDECL(positionbar);
122 static void FDECL(vga_special,(int, int, int));
123 #endif
124 
125 extern int clipx, clipxmax;	/* current clipping column from wintty.c */
126 extern boolean clipping;	/* clipping on? from wintty.c */
127 extern int savevmode;		/* store the original video mode */
128 extern int curcol,currow;	/* current column and row        */
129 extern int g_attribute;
130 extern int attrib_text_normal;	/* text mode normal attribute */
131 extern int attrib_gr_normal;	/* graphics mode normal attribute */
132 extern int attrib_text_intense;	/* text mode intense attribute */
133 extern int attrib_gr_intense;	/* graphics mode intense attribute */
134 extern boolean inmap;		/* in the map window */
135 
136 /*
137  * Global Variables
138  */
139 
140 STATIC_VAR unsigned char __far *font;
141 STATIC_VAR char *screentable[SCREENHEIGHT];
142 STATIC_VAR char tmp[SCREENWIDTH];
143 STATIC_VAR char *paletteptr;
144 STATIC_VAR struct map_struct {
145 	int glyph;
146 	int ch;
147 	int attr;
148 }  map[ROWNO][COLNO];	/* track the glyphs */
149 
150 # define vga_clearmap() { int x,y; for (y=0; y < ROWNO; ++y) \
151 	for (x=0; x < COLNO; ++x) { map[y][x].glyph = cmap_to_glyph(S_stone); \
152 	map[y][x].ch = S_stone; map[y][x].attr = 0;} }
153 # define TOP_MAP_ROW 1
154 #  if defined(OVLB)
155 STATIC_VAR int vgacmap[CLR_MAX] = {0,3,5,9,4,8,12,14,11,2,6,7,1,8,12,13};
156 STATIC_VAR int viewport_size = 40;
157 STATIC_VAR char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
158 STATIC_VAR char bittable[8]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
159 STATIC_VAR char defpalette[] = {	/* Default VGA palette         */
160 	0x00, 0x00, 0x00,
161 	0x00, 0x00, 0xaa,
162 	0x00, 0xaa, 0x00,
163 	0x00, 0xaa, 0xaa,
164 	0xaa, 0x00, 0x00,
165 	0xaa, 0x00, 0xaa,
166 	0xaa, 0xaa, 0x00,
167 	0xaa, 0xaa, 0xaa,
168 	0x55, 0x55, 0x55,
169 	0xcc, 0xcc, 0xcc,
170 	0x00, 0x00, 0xff,
171 	0x00, 0xff, 0x00,
172 	0xff, 0x00, 0x00,
173 	0xff, 0xff, 0x00,
174 	0xff, 0x00, 0xff,
175 	0xff, 0xff, 0xff
176 	};
177 #   ifndef ALTERNATE_VIDEO_METHOD
178 int vp[SCREENPLANES] = {8,4,2,1};
179 #   endif
180 int vp2[SCREENPLANES] = {1,2,4,8};
181 #  else
182 extern int vgacmap[CLR_MAX];
183 extern int viewport_size;
184 extern char masktable[8];
185 extern char bittable[8];
186 extern char defpalette[];
187 #   ifndef ALTERNATE_VIDEO_METHOD
188 extern int vp[SCREENPLANES];
189 #   endif
190 extern int vp2[SCREENPLANES];
191 #  endif /* OVLB */
192 
193 STATIC_VAR struct planar_cell_struct *planecell;
194 STATIC_VAR struct overview_planar_cell_struct *planecell_O;
195 
196 # if defined(USE_TILES)
197 STATIC_VAR struct tibhdr_struct tibheader;
198 /* extern FILE *tilefile; /* Not needed in here most likely */
199 # endif
200 
201 /* STATIC_VAR int  g_attribute;		/* Current attribute to use */
202 
203 #ifdef OVLB
204 void
vga_get_scr_size()205 vga_get_scr_size()
206 {
207 	CO = 80;
208 	LI = 29;
209 }
210 #endif /*OVLB*/
211 
212 
213 
214 # ifdef OVLB
215 
216 void
vga_backsp()217 vga_backsp()
218 {
219 	int col,row;
220 
221 	col = curcol; 		/* Character cell row and column */
222 	row = currow;
223 
224 	if (col > 0) col = col-1;
225 	vga_gotoloc(col,row);
226 	vga_xputc(' ',g_attribute);
227 	vga_gotoloc(col,row);
228 }
229 
230 # endif /* OVLB */
231 # ifdef OVL0
232 
233 void
vga_clear_screen(colour)234 vga_clear_screen(colour)
235 int colour;
236 {
237 	char __far *pch;
238 	int y,j;
239 	char volatile a;
240 
241 	outportb(0x3ce,5);
242 	outportb(0x3cf,2);
243 
244 	for (y=0; y < SCREENHEIGHT; ++y) {
245 		pch = screentable[y];
246 		for (j=0; j < SCREENBYTES; ++j) {
247 			outportb(0x3ce,8);
248 			outportb(0x3cf,255);
249 			a = READ_ABSOLUTE(pch); /* Must read , then write */
250 			WRITE_ABSOLUTE(pch, (char)colour);
251 			++pch;
252 		}
253 	}
254 	outportb(0x3ce,5);
255 	outportb(0x3cf,0);
256 	if (iflags.tile_view) vga_clearmap();
257 	vga_gotoloc(0,0);	/* is this needed? */
258 }
259 
260 void
vga_cl_end(col,row)261 vga_cl_end(col,row)	/* clear to end of line */
262 int col,row;
263 {
264 	int count;
265 
266 	/*
267 	 * This is being done via character writes.
268 	 * This should perhaps be optimized for speed by using VGA write
269 	 * mode 2 methods as did clear_screen()
270 	 */
271 	for (count = col; count < (CO-1); ++count) {
272 		vga_WriteChar(' ',count,row,BACKGROUND_VGA_COLOR);
273 	}
274 }
275 
276 void
vga_cl_eos(cy)277 vga_cl_eos(cy)	/* clear to end of screen */
278 int cy;
279 {
280 	int count;
281 
282 	cl_end();
283 	while(cy <= LI-2) {
284 		for (count = 0; count < (CO-1); ++count) {
285 			vga_WriteChar(' ',count,cy,
286 				BACKGROUND_VGA_COLOR);
287 		}
288 		cy++;
289 	}
290 }
291 
292 
293 # endif /* OVL0 */
294 
295 # ifdef OVLB
296 void
vga_tty_end_screen()297 vga_tty_end_screen()
298 {
299 	vga_clear_screen(BACKGROUND_VGA_COLOR);
300 	vga_SwitchMode(MODETEXT);
301 }
302 
303 
304 void
vga_tty_startup(wid,hgt)305 vga_tty_startup(wid, hgt)
306     int *wid, *hgt;
307 {
308 
309 	/* code to sense display adapter is required here - MJA */
310 
311 	vga_get_scr_size();
312 	if (CO && LI) {
313 		*wid = CO;
314 		*hgt = LI;
315 	}
316 
317 	attrib_gr_normal    = ATTRIB_VGA_NORMAL;
318 	attrib_gr_intense   = ATTRIB_VGA_INTENSE;
319 	g_attribute         = attrib_gr_normal;	/* Give it a starting value */
320 }
321 # endif /* OVLB */
322 
323 /*
324  * Screen output routines (these are heavily used).
325  *
326  * These are the 3 routines used to place information on the screen
327  * in the VGA PC tty port of NetHack.  These are the routines
328  * that get called by the general interface routines in video.c.
329  *
330  * vga_xputs -Writes a c null terminated string at the current location.
331  *
332  * vga_xputc -Writes a single character at the current location. Since
333  *            various places in the code assume that control characters
334  *            can be used to control, we are forced to interpret some of
335  *            the more common ones, in order to keep things looking correct.
336  *
337  * vga_xputg -This routine is used to display a graphical representation of a
338  *            NetHack glyph (a tile) at the current location.  For more
339  *            information on NetHack glyphs refer to the comments in
340  *            include/display.h.
341  *
342  */
343 
344 # ifdef OVL0
345 void
vga_xputs(s,col,row)346 vga_xputs(s,col,row)
347 const char *s;
348 int col,row;
349 {
350 
351 	if (s != (char *)0) {
352 		vga_WriteStr((char *)s,strlen(s),col,row,g_attribute);
353 	}
354 }
355 
356 void
vga_xputc(ch,attr)357 vga_xputc(ch,attr)	/* write out character (and attribute) */
358 char ch;
359 int attr;
360 {
361 	int col,row;
362 
363 	col = curcol;
364 	row = currow;
365 
366 	switch(ch) {
367 	    case '\n':
368 			col = 0;
369 			++row;
370 			break;
371 	    default:
372 			vga_WriteChar((unsigned char)ch,col,row,attr);
373 			if (col < (CO -1 )) ++col;
374 			break;
375 	} /* end switch */
376 	vga_gotoloc(col,row);
377 }
378 
379 #  if defined(USE_TILES)
380 void
vga_xputg(glyphnum,ch)381 vga_xputg(glyphnum,ch)	/* Place tile represent. a glyph at current location */
382 int glyphnum;
383 int ch;
384 {
385 	int col,row;
386 	int attr;
387 
388 	row = currow;
389 	col = curcol;
390 	if ((col < 0 || col >= COLNO) ||
391 	    (row < TOP_MAP_ROW || row >= (ROWNO + TOP_MAP_ROW))) return;
392 	map[row - TOP_MAP_ROW][col].glyph = glyphnum;
393 	map[row - TOP_MAP_ROW][col].ch = ch;
394 	attr = (g_attribute == 0) ? attrib_gr_normal : g_attribute;
395 	map[row - TOP_MAP_ROW][col].attr = attr;
396 	if (iflags.traditional_view) {
397 	    vga_WriteChar((unsigned char)ch,col,row,attr);
398 	} else if (!iflags.over_view) {
399 	    if ((col >= clipx) && (col <= clipxmax)) {
400 		if (!ReadPlanarTileFile(glyph2tile[glyphnum], &planecell))
401 			vga_DisplayCell(planecell,
402 					col - clipx, row);
403 		else
404 			pline("vga_xputg: Error reading tile (%d,%d) from file",
405 					glyphnum,glyph2tile[glyphnum]);
406 	    }
407 	} else {
408 	    if (!ReadPlanarTileFile_O(glyph2tile[glyphnum], &planecell_O))
409 			vga_DisplayCell_O(planecell_O, col, row);
410 	    else
411 			pline("vga_xputg: Error reading tile (%d,%d) from file",
412 					glyphnum,glyph2tile[glyphnum]);
413 	}
414 	if (col < (CO - 1 )) ++col;
415 	vga_gotoloc(col,row);
416 }
417 #  endif /* USE_TILES */
418 
419 /*
420  * Cursor location manipulation, and location information fetching
421  * routines.
422  * These include:
423  *
424  * vga_gotoloc(x,y)     - Moves the "cursor" on screen to the specified x
425  *			 and y character cell location.  This routine
426  *                       determines the location where screen writes
427  *                       will occur next, it does not change the location
428  *                       of the player on the NetHack level.
429  */
430 
431 void
vga_gotoloc(col,row)432 vga_gotoloc(col,row)
433 int col,row;
434 {
435 	curcol = min(col,CO - 1); /* protection from callers */
436 	currow = min(row,LI - 1);
437 }
438 
439 #  if defined(USE_TILES) && defined(CLIPPING)
440 void
vga_cliparound(x,y)441 vga_cliparound(x, y)
442 int x, y;
443 {
444 	extern boolean restoring;
445 	int oldx = clipx;
446 
447 	if (!iflags.tile_view || iflags.over_view || iflags.traditional_view)
448 		return;
449 
450 	if (x < clipx + 5) {
451 		clipx = max(0, x - (viewport_size / 2));
452 		clipxmax = clipx + (viewport_size - 1);
453 	}
454 	else if (x > clipxmax - 5) {
455 		clipxmax = min(COLNO - 1, x + (viewport_size / 2));
456 		clipx = clipxmax - (viewport_size - 1);
457 	}
458 	if (clipx != oldx) {
459 	    if (on_level(&u.uz0, &u.uz) && !restoring)
460 		/* (void) doredraw(); */
461 		vga_redrawmap(1);
462 	}
463 }
464 
465 STATIC_OVL void
vga_redrawmap(clearfirst)466 vga_redrawmap(clearfirst)
467 boolean clearfirst;
468 {
469 	int j,x,y,t;
470 	char __far *pch;
471 	char volatile a;
472 
473 	if (clearfirst) {
474 		/* y here is in pixel rows */
475 		outportb(0x3ce,5);
476 		outportb(0x3cf,2);
477 		t = TOP_MAP_ROW * ROWS_PER_CELL;
478 		for (y = t; y < (ROWNO * ROWS_PER_CELL) + t; ++y) {
479 			pch = screentable[y];
480 			for (j=0; j < SCREENBYTES; ++j) {
481 				outportb(0x3ce,8);
482 				outportb(0x3cf,255);
483 				 /* On VGA mode2, must read first, then write */
484 				a = READ_ABSOLUTE(pch);
485 				WRITE_ABSOLUTE(pch, (char)BACKGROUND_VGA_COLOR);
486 				++pch;
487 			}
488 		}
489 		outportb(0x3ce,5);
490 		outportb(0x3cf,0);
491 	}
492 	/* y here is in screen rows*/
493 #    ifdef ROW_BY_ROW
494 	for (y = 0; y < ROWNO; ++y)
495 		for (x = clipx; x <= clipxmax; ++x) {
496 #    else
497 	for (x = clipx; x <= clipxmax; ++x)
498 		for (y = 0; y < ROWNO; ++y) {
499 #    endif
500 		    if (iflags.traditional_view) {
501 			if (!(clearfirst && map[y][x].ch == S_stone))
502 				vga_WriteChar(
503 					(unsigned char)map[y][x].ch,
504 					x,y + TOP_MAP_ROW,map[y][x].attr);
505 		    } else {
506 		      t = map[y][x].glyph;
507 		      if (!(clearfirst && t == cmap_to_glyph(S_stone))) {
508 			if (!iflags.over_view) {
509 			  	if (!ReadPlanarTileFile(glyph2tile[t],
510 				    &planecell)) {
511 					vga_DisplayCell(planecell,
512 						x - clipx, y + TOP_MAP_ROW);
513 		  	  	} else
514 			      pline("vga_redrawmap: Error reading tile (%d,%d)",
515 					 t,glyph2tile[t]);
516 		     	} else {
517 				if (!ReadPlanarTileFile_O(glyph2tile[t],
518 				     &planecell_O)) {
519 					vga_DisplayCell_O(planecell_O,
520 						x, y + TOP_MAP_ROW);
521 		  	  	} else
522 			     pline("vga_redrawmap: Error reading tile (%d,%d)",
523 					t,glyph2tile[t]);
524 		  	}
525 		      }
526 		    }
527 		}
528 }
529 #  endif /* USE_TILES && CLIPPING */
530 # endif /* OVL0 */
531 # ifdef OVL2
532 
533 void
vga_userpan(left)534 vga_userpan(left)
535 boolean left;
536 {
537 	int x;
538 
539 /*	pline("Into userpan"); */
540 	if (iflags.over_view || iflags.traditional_view) return;
541 	if (left)
542 		x = min(COLNO - 1, clipxmax + 10);
543 	else
544 		x = max(0, clipx - 10);
545 	vga_cliparound(x, 10);	/* y value is irrelevant on VGA clipping */
546 	positionbar();
547 	vga_DrawCursor();
548 }
549 
550 
vga_overview(on)551 void vga_overview(on)
552 boolean on;
553 {
554 /*	vga_HideCursor(); */
555 	if (on) {
556 		iflags.over_view = TRUE;
557 		clipx = 0;
558 		clipxmax = CO - 1;
559 	} else {
560 		iflags.over_view = FALSE;
561 		clipx = max(0, (curcol - viewport_size / 2));
562 		if (clipx > ((CO - 1) - viewport_size))
563 			clipx = (CO - 1) - viewport_size;
564      		clipxmax = clipx + (viewport_size - 1);
565 	}
566 }
567 
vga_traditional(on)568 void vga_traditional(on)
569 boolean on;
570 {
571 /*	vga_HideCursor(); */
572 	if (on) {
573 /*		switch_graphics(ASCII_GRAPHICS); */
574 		iflags.traditional_view = TRUE;
575 		clipx = 0;
576 		clipxmax = CO - 1;
577 	} else {
578 		iflags.traditional_view = FALSE;
579 		if (!iflags.over_view) {
580 			clipx = max(0, (curcol - viewport_size / 2));
581 			if (clipx > ((CO - 1) - viewport_size))
582 				clipx = (CO - 1) - viewport_size;
583      			clipxmax = clipx + (viewport_size - 1);
584 		}
585 	}
586 }
587 
vga_refresh()588 void vga_refresh()
589 {
590 	positionbar();
591 	vga_redrawmap(1);
592 	vga_DrawCursor();
593 }
594 
595 #  ifdef SCROLLMAP
596 STATIC_OVL void
vga_scrollmap(left)597 vga_scrollmap(left)
598 boolean left;
599 {
600 	int j,x,y,t;
601 	int i,pixx,pixy,x1,y1,x2,y2;
602 	int byteoffset, vplane;
603 	char __far *tmp1;
604 	char __far *tmp2;
605 	unsigned char source[SCREENPLANES][80];
606 	unsigned char first,second;
607 
608 
609 	pixy = row2y(TOP_MAP_ROW);		  /* convert to pixels */
610 	pixx = col2x(x1);
611 	if (left) {
612 		x1 = 20;
613 		x2 = 0;
614 	} else {
615 		x1 = 0;
616 		x2 = 20;
617 	}
618 	/* read each row, all columns but the one to be replaced */
619 	for(i = 0;i < (ROWNO-1) * ROWS_PER_CELL; ++i) {
620 	    tmp1 = screentable[i + pixy];
621 	    tmp1 += x1;
622 	    for(vplane=0; vplane < SCREENPLANES; ++vplane) {
623 		egareadplane(vplane);
624 		for (byteoffset = 0; byteoffset < 20; ++byteoffset) {
625 			tmp2 = tmp1 + byteoffset;
626 			source[vplane][byteoffset] = READ_ABSOLUTE(tmp2);
627 		}
628 	    }
629 	    tmp1 = screentable[i + pixy];
630 	    tmp1 += x2;
631 	    for(vplane=0; vplane < SCREENPLANES; ++vplane) {
632 		egawriteplane(vp2[vplane]);
633 		for (byteoffset = 0; byteoffset < 20; ++byteoffset) {
634 			tmp2 = tmp1 + byteoffset;
635 			WRITE_ABSOLUTE(tmp2,source[vplane][byteoffset]);
636 		}
637 	    }
638 	    egawriteplane(15);
639 	}
640 
641 	if (left) {
642 		i = clipxmax - 1;
643 		j = clipxmax;
644 	} else {
645 		i = clipx;
646 		j = clipx + 1;
647 	}
648 	for (y = 0; y < ROWNO; ++y) {
649 	    for (x = i; x < j; x += 2) {
650 		t = map[y][x].glyph;
651 		if (!ReadPlanarTileFile(glyph2tile[t], &planecell))
652 			vga_DisplayCell(planecell, x - clipx, y + TOP_MAP_ROW);
653 		else
654 			pline("vga_shiftmap: Error reading tile (%d,%d)",
655 				t, glyph2tile[t]);
656 	    }
657 	}
658 }
659 #   endif /* SCROLLMAP */
660 # endif /* OVL2 */
661 
662 # ifdef OVLB
663 
664 /*
665  * Open tile files,
666  * initialize the SCREEN, switch it to graphics mode,
667  * initialize the pointers to the fonts, clear
668  * the screen.
669  *
670  */
vga_Init(void)671 void vga_Init(void)
672 {
673      int i, c;
674 
675 #   ifdef USE_TILES
676      int tilefailure = 0;
677 /*
678  * Attempt to open the required tile files. If we can't
679  * don't perform the video mode switch, use TTY code instead.
680  *
681  */
682      if (OpenTileFile(NETHACK_PLANAR_TILEFILE, FALSE)) tilefailure |= 1;
683      if (OpenTileFile(NETHACK_OVERVIEW_TILEFILE, TRUE)) tilefailure |= 2;
684      if (ReadTileFileHeader(&tibheader, FALSE)) tilefailure |= 4;
685 
686      if (tilefailure) {
687 	raw_printf("Reverting to TTY mode, tile initialization failure (%d).",
688 		tilefailure);
689 	wait_synch();
690 	iflags.usevga = 0;
691 	iflags.tile_view = FALSE;
692 	iflags.over_view = FALSE;
693 	CO = 80;
694 	LI = 25;
695 /*	clear_screen()	/* not vga_clear_screen() */
696 	return;
697      }
698 #   endif
699 
700      if (iflags.usevga) {
701 	for (i=0; i < SCREENHEIGHT; ++i) {
702 		screentable[i]=MK_PTR(VIDEOSEG, (i * SCREENBYTES));
703 	}
704      }
705      vga_SwitchMode(MODE640x480);
706      windowprocs.win_cliparound = vga_cliparound;
707 /*     vga_NoBorder(BACKGROUND_VGA_COLOR);   /* Not needed after palette mod */
708 #   ifdef USE_TILES
709      paletteptr = tibheader.palette;
710      iflags.tile_view = TRUE;
711      iflags.over_view = FALSE;
712 #   else
713      paletteptr = defpalette;
714 #   endif
715      vga_SetPalette(paletteptr);
716      g_attribute  = attrib_gr_normal;
717      font = vga_FontPtrs();
718      clear_screen();
719      clipx = 0;
720      clipxmax = clipx + (viewport_size - 1);
721 }
722 
723 /*
724  * Switches modes of the video card.
725  *
726  * If mode == MODETEXT (0x03), then the card is placed into text
727  * mode.  If mode == 640x480, then the card is placed into vga
728  * mode (video mode 0x12). No other modes are currently supported.
729  *
730  */
vga_SwitchMode(unsigned int mode)731 void vga_SwitchMode(unsigned int mode)
732 {
733 	union REGS regs;
734 
735 	if ((mode == MODE640x480) || (mode == MODETEXT)) {
736 		if (iflags.usevga && (mode == MODE640x480)) {
737      			iflags.grmode = 1;
738 		} else {
739 	        	iflags.grmode = 0;
740 		}
741 		regs.x.ax = mode;
742 		(void) int86(VIDEO_BIOS, &regs, &regs);
743 	} else {
744 		iflags.grmode = 0;	/* force text mode for error msg */
745 		regs.x.ax = MODETEXT;
746 		(void) int86(VIDEO_BIOS, &regs, &regs);
747 		g_attribute  = attrib_text_normal;
748 		impossible("vga_SwitchMode: Bad video mode requested 0x%X",
749 			mode);
750 	}
751 }
752 
753 /*
754  * This allows grouping of several tasks to be done when
755  * switching back to text mode. This is a public (extern) function.
756  *
757  */
vga_Finish(void)758 void vga_Finish(void)
759 {
760      CloseTileFile(0);
761      CloseTileFile(1);
762      vga_SwitchMode(MODETEXT);
763      windowprocs.win_cliparound = tty_cliparound;
764      g_attribute  = attrib_text_normal;
765      iflags.tile_view = FALSE;
766 }
767 
768 #if 0
769 /*
770  * Turn off any border colour that might be enabled in the VGA card
771  * register.
772  *
773  * I disabled this after modifying tile2bin.c to remap black & white
774  * to a more standard values - MJA 94/04/23.
775  *
776  */
777 STATIC_OVL void
778 vga_NoBorder(int bc)
779 {
780 	union REGS regs;
781 
782 	regs.h.ah = (char)0x10;
783 	regs.h.al = (char)0x01;
784 	regs.h.bh = (char)bc;
785 	regs.h.bl = 0;
786 	(void) int86(VIDEO_BIOS, &regs, &regs);
787 }
788 #endif
789 
790 /*
791  *
792  * Returns a far pointer (or flat 32 bit pointer under djgpp) to the
793  * location of the appropriate ROM font for the _current_ video mode
794  * (so you must place the card into the desired video mode before
795  * calling this function).
796  *
797  * This function takes advantage of the video BIOS loading the
798  * address of the appropriate character definition table for
799  * the current graphics mode into interrupt vector 0x43 (0000:010C).
800  */
vga_FontPtrs(void)801 char __far  *vga_FontPtrs(void)
802 {
803 	USHORT  __far *tmp;
804 	char __far *retval;
805 	USHORT fseg, foff;
806 	tmp  = (USHORT __far *)MK_PTR(((USHORT)FONT_PTR_SEGMENT),
807 					((USHORT)FONT_PTR_OFFSET));
808 	foff = READ_ABSOLUTE_WORD(tmp);
809 	++tmp;
810 	fseg = READ_ABSOLUTE_WORD(tmp);
811 	retval = (char __far *)MK_PTR(fseg,foff);
812 	return retval;
813 }
814 
815 /*
816  * This will verify the existance of a VGA adapter on the machine.
817  * Video function call 0x1a returns 0x1a in AL if successful, and
818  * returns the following values in BL for the active display:
819  *
820  * 0=no display, 1=MDA, 2=CGA, 4=EGA(color-monitor),
821  * 5=EGA(mono-monitor), 6=PGA, 7=VGA(mono-monitor), 8=VGA(color-monitor),
822  * 0xB=MCGA(mono-monitor), 0xC=MCGA(color-monitor), 0xFF=unknown)
823  */
vga_detect()824 int vga_detect()
825 {
826 	union REGS regs;
827 
828 	regs.h.al = 0;
829 	regs.h.ah = 0x1a;
830 	(void) int86(VIDEO_BIOS, &regs, &regs);
831 /*
832  * debug
833  *
834  *	printf("vga_detect returned al=%02x, bh=%02x, bl=%02x\n",
835  *			(int)regs.h.al, (int)regs.h.bh, (int)regs.h.bl);
836  *	getch();
837  */
838 	if ((int)regs.h.al == 0x1a) {
839 		if (((int)regs.h.bl == 8) || ((int)regs.h.bl == 7)) {
840 			return 1;
841 		}
842 	}
843 	return 0;
844 }
845 
846 /*
847  * Write character 'ch', at (x,y) and
848  * do it using the colour 'colour'.
849  *
850  */
851 void
vga_WriteChar(chr,col,row,colour)852 vga_WriteChar(chr,col,row,colour)
853 int chr,col,row,colour;
854 {
855 	int i;
856 	int x,pixy;
857 	int floc;
858 	char volatile tc;
859 	char __far *cp;
860 	unsigned char __far *fp = font;
861 	unsigned char fnt;
862 	int actual_colour = vgacmap[colour];
863 
864 
865 	x = min(col,(CO-1));	       /* min() used protection from callers */
866 	pixy = min(row,(LI-1)) * 16; /* assumes 8 x 16 char set */
867 /*	if (chr < ' ') chr = ' ';    /* assumes ASCII set */
868 
869 	outportb(0x3ce,5);
870 	outportb(0x3cf,2);
871 
872 	chr = chr<<4;
873 	for (i=0; i < MAX_ROWS_PER_CELL; ++i) {
874 		cp = screentable[pixy+i] + x;
875 		fnt = READ_ABSOLUTE((fp + chr + i));
876 		outportb(0x3ce,8);
877 		outportb(0x3cf,fnt);
878 		tc = READ_ABSOLUTE(cp);	/* wrt mode 2, must read, then write */
879 		WRITE_ABSOLUTE(cp, (char)actual_colour);
880 		outportb(0x3ce,8);
881 		outportb(0x3cf,~fnt);
882 		tc = READ_ABSOLUTE(cp);	/* wrt mode 2, must read, then write */
883 		WRITE_ABSOLUTE(cp, (char)BACKGROUND_VGA_COLOR);
884 	}
885 	outportb(0x3ce,5);
886 	outportb(0x3cf,0);
887 	outportb(0x3ce,8);
888 	outportb(0x3cf,255);
889 }
890 
891 /*
892  * This is the routine that displays a high-res "cell" pointed to by 'gp'
893  * at the desired location (col,row).
894  *
895  * Note: (col,row) in this case refer to the coordinate location in
896  * NetHack character grid terms, (ie. the 40 x 25 character grid),
897  * not the x,y pixel location.
898  *
899  */
900 void
vga_DisplayCell(gp,col,row)901 vga_DisplayCell(gp,col,row)
902 struct planar_cell_struct *gp;
903 int col,row;
904 {
905 	int i,pixx,pixy;
906 	char __far *tmp_s;	/* source pointer */
907 	char __far *tmp_d;	/* destination pointer */
908 	int vplane;
909 
910 	pixy = row2y(row);		/* convert to pixels */
911 	pixx = col2x(col);
912 	for(vplane=0; vplane < SCREENPLANES; ++vplane) {
913 		egawriteplane(vp[vplane]);
914 		for(i=0;i < ROWS_PER_CELL; ++i) {
915 			tmp_d = screentable[i+pixy];
916  			tmp_d += pixx;
917 		/*
918 		 * memcpy((void *)tmp,(void *)gp->plane[vplane].image[i],
919 		 *         BYTES_PER_CELL);
920 		 */
921 			tmp_s = gp->plane[vplane].image[i];
922 			WRITE_ABSOLUTE(tmp_d, (*tmp_s));
923 			++tmp_s; ++tmp_d;
924 			WRITE_ABSOLUTE(tmp_d, (*tmp_s));
925 		}
926 	}
927 	egawriteplane(15);
928 }
929 
930 void
vga_DisplayCell_O(gp,col,row)931 vga_DisplayCell_O(gp,col,row)
932 struct overview_planar_cell_struct *gp;
933 int col,row;
934 {
935 	int i,pixx,pixy;
936 	char __far *tmp_s;	/* source pointer */
937 	char __far *tmp_d;	/* destination pointer */
938 	int vplane;
939 
940 	pixy = row2y(row);		/* convert to pixels */
941 	pixx = col;
942 	for(vplane=0; vplane < SCREENPLANES; ++vplane) {
943 		egawriteplane(vp[vplane]);
944 		for(i=0;i < ROWS_PER_CELL; ++i) {
945 			tmp_d = screentable[i+pixy];
946  			tmp_d += pixx;
947 		/*
948 		 * memcpy((void *)tmp,(void *)gp->plane[vplane].image[i],
949 		 *         BYTES_PER_CELL);
950 		 */
951 			tmp_s = gp->plane[vplane].image[i];
952 			WRITE_ABSOLUTE(tmp_d, (*tmp_s));
953 		}
954 	}
955 	egawriteplane(15);
956 }
957 
958 /*
959  * Write the character string pointed to by 's', whose maximum length
960  * is 'len' at location (x,y) using the 'colour' colour.
961  *
962  */
963 void
vga_WriteStr(s,len,col,row,colour)964 vga_WriteStr(s,len,col,row,colour)
965 char *s;
966 int len,col,row,colour;
967 {
968 	unsigned char *us;
969 	int i = 0;
970 
971 	/* protection from callers */
972 	if (row > (LI-1)) return;
973 
974 	i  = 0;
975 	us = (unsigned char *)s;
976 	while( (*us != 0) && (i < len) && (col < (CO - 1))) {
977 		vga_WriteChar(*us,col,row,colour);
978 		++us;
979 		++i;
980 		++col;
981 	}
982 }
983 
984 # endif /* OVLB */
985 
986 
987 # ifdef OVLB
988 /*
989  * Initialize the VGA palette with the desired colours. This
990  * must be a series of 48 bytes for use with a card in
991  * 16 colour mode at 640 x 480.
992  *
993  */
994 void
vga_SetPalette(p)995 vga_SetPalette(p)
996 	char *p;
997 {
998 	union REGS regs;
999 	int i;
1000 
1001 	outportb(0x3c6,0xff);
1002 	for(i=0;i < COLORDEPTH; ++i) {
1003 		outportb(0x3c8,i);
1004 		outportb(0x3c9,(*p++) >> 2);
1005 		outportb(0x3c9,(*p++) >> 2);
1006 		outportb(0x3c9,(*p++) >> 2);
1007 	}
1008 	regs.x.bx = 0x0000;
1009 	for(i=0;i < COLORDEPTH; ++i) {
1010 		regs.x.ax = 0x1000;
1011 		(void) int86(VIDEO_BIOS,&regs,&regs);
1012 		regs.x.bx += 0x0101;
1013 	}
1014 }
1015 
1016 /*static unsigned char colorbits[]={0x01,0x02,0x04,0x08}; /* wrong */
1017 static unsigned char colorbits[]={0x08,0x04,0x02,0x01};
1018 
1019 #ifdef POSITIONBAR
1020 
1021 #define PBAR_ROW (LI - 4)
1022 #define PBAR_COLOR_ON	  15	/* slate grey background colour of tiles */
1023 #define PBAR_COLOR_OFF	  12	/* bluish grey, used in old style only */
1024 #define PBAR_COLOR_STAIRS  9	/* brown */
1025 #define PBAR_COLOR_HERO   14	/* creamy white */
1026 
1027 static unsigned char pbar[COLNO];
1028 
1029 void
vga_update_positionbar(posbar)1030 vga_update_positionbar(posbar)
1031 char *posbar;
1032 {
1033 	char *p = pbar;
1034 	if (posbar) while (*posbar) *p++ = *posbar++;
1035 	*p = 0;
1036 }
1037 
1038 STATIC_OVL void
positionbar()1039 positionbar()
1040 {
1041 	char *posbar = pbar;
1042 	int feature, ucol;
1043 	int k, y, colour, row;
1044 	char __far *pch;
1045 	char bitblock;
1046 	int startk, stopk;
1047 	char volatile a;
1048 	boolean nowhere = FALSE;
1049 	int pixy = (PBAR_ROW * MAX_ROWS_PER_CELL);
1050 	int tmp;
1051 
1052 	if (!iflags.grmode || !iflags.tile_view) return;
1053 	if ((clipx < 0)  || (clipxmax <= 0) || (clipx >= clipxmax))
1054 		nowhere = TRUE;
1055 	if (nowhere) {
1056 #ifdef DEBUG
1057 		pline("Would have put bar using %d - %d.",clipx,clipxmax);
1058 #endif
1059 		return;
1060         }
1061 #ifdef OLD_STYLE
1062 	outportb(0x3ce,5);
1063 	outportb(0x3cf,2);
1064 	for (y=pixy; y < (pixy + MAX_ROWS_PER_CELL); ++y) {
1065 		pch = screentable[y];
1066 		for (k=0; k < SCREENBYTES; ++k) {
1067 			if ((k < clipx) || (k > clipxmax)) {
1068 				colour = PBAR_COLOR_OFF;
1069 			} else colour = PBAR_COLOR_ON;
1070 			outportb(0x3ce,8);
1071 			outportb(0x3cf,255);
1072 			a = READ_ABSOLUTE(pch); /* Must read , then write */
1073 			WRITE_ABSOLUTE(pch, (char)colour);
1074 			++pch;
1075 		}
1076 	}
1077 	outportb(0x3ce,5);
1078 	outportb(0x3cf,0);
1079 #else
1080 	colour = PBAR_COLOR_ON;
1081 	outportb(0x3ce,5);
1082 	outportb(0x3cf,2);
1083 	for (y=pixy, row = 0; y < (pixy + MAX_ROWS_PER_CELL); ++y, ++row) {
1084 		pch = screentable[y];
1085 		if ((!row) || (row == (ROWS_PER_CELL-1))) {
1086 			startk = 0;
1087 			stopk  = SCREENBYTES;
1088 		} else {
1089 			startk = clipx;
1090 			stopk  = clipxmax;
1091 		}
1092 		for (k=0; k < SCREENBYTES; ++k) {
1093 			if ((k < startk) || (k > stopk))
1094 				colour = BACKGROUND_VGA_COLOR;
1095 			else
1096 				colour = PBAR_COLOR_ON;
1097 			outportb(0x3ce,8);
1098 			outportb(0x3cf,255);
1099 			a = READ_ABSOLUTE(pch); /* Must read , then write */
1100 			WRITE_ABSOLUTE(pch, (char)colour);
1101 			++pch;
1102 		}
1103 	}
1104 	outportb(0x3ce,5);
1105 	outportb(0x3cf,0);
1106 #endif
1107 	ucol = 0;
1108 	if (posbar) {
1109 	    while (*posbar != 0) {
1110 		feature = *posbar++;
1111 		switch (feature) {
1112 		    case '>':
1113 			vga_special(feature, (int)*posbar++, PBAR_COLOR_STAIRS);
1114 			break;
1115 		    case '<':
1116 			vga_special(feature, (int)*posbar++, PBAR_COLOR_STAIRS);
1117 			break;
1118 		    case '@':
1119 			ucol = (int)*posbar++;
1120 			vga_special(feature, ucol, PBAR_COLOR_HERO);
1121 			break;
1122 		    default: /* unanticipated symbols */
1123 			vga_special(feature, (int)*posbar++, PBAR_COLOR_STAIRS);
1124 			break;
1125 		}
1126 	    }
1127 	}
1128 #  ifdef SIMULATE_CURSOR
1129 	if (inmap) {
1130 		tmp = curcol + 1;
1131 		if ((tmp != ucol) && (curcol >= 0))
1132 			vga_special('_', tmp, PBAR_COLOR_HERO);
1133 	}
1134 #  endif
1135 }
1136 
1137 void
vga_special(chr,col,color)1138 vga_special(chr,col,color)
1139 int chr,col,color;
1140 {
1141 	int i,y,pixx,pixy;
1142 	char __far *tmp_d;	/* destination pointer */
1143 	int vplane;
1144 	char fnt;
1145 	char bits[SCREENPLANES][ROWS_PER_CELL];
1146 
1147 	pixy = PBAR_ROW * MAX_ROWS_PER_CELL;
1148 	for(vplane=0; vplane < SCREENPLANES; ++vplane) {
1149 		egareadplane(vplane);
1150 		y = pixy;
1151 		for(i=0;i < ROWS_PER_CELL; ++i) {
1152 			tmp_d = screentable[y++] + col;
1153 			bits[vplane][i] = READ_ABSOLUTE(tmp_d);
1154 			fnt = READ_ABSOLUTE((font + ((chr<<4) + i)));
1155 			if (colorbits[vplane] & color)
1156 				bits[vplane][i] |= fnt;
1157 			else
1158 				bits[vplane][i] &= ~fnt;
1159 		}
1160 	}
1161 	for(vplane=0; vplane < SCREENPLANES; ++vplane) {
1162 		egawriteplane(vp[vplane]);
1163 		y = pixy;
1164 		for(i=0;i < ROWS_PER_CELL; ++i) {
1165 			tmp_d = screentable[y++] + col;
1166 			WRITE_ABSOLUTE(tmp_d, (bits[vplane][i]));
1167 		}
1168      	}
1169 	egawriteplane(15);
1170 }
1171 
1172 #  endif POSITIONBAR
1173 
1174 #  ifdef SIMULATE_CURSOR
1175 
1176 static struct planar_cell_struct undercursor;
1177 static struct planar_cell_struct cursor;
1178 
1179 void
vga_DrawCursor()1180 vga_DrawCursor()
1181 {
1182 	int i,pixx,pixy,x,y,p;
1183 	char __far *tmp1;
1184 	char __far *tmp2;
1185 	unsigned char first,second;
1186 /*	char on[2] =  {0xFF,0xFF}; */
1187 /*	char off[2] = {0x00,0x00}; */
1188 #ifdef REINCARNATION
1189 	boolean isrogue = Is_rogue_level(&u.uz);
1190 	boolean singlebyte = (isrogue || iflags.over_view
1191 			      || iflags.traditional_view || !inmap);
1192 #else
1193 	boolean singlebyte = (iflags.over_view
1194 			      || iflags.traditional_view || !inmap);
1195 #endif
1196 	int curtyp;
1197 
1198 	if (!cursor_type && inmap) return;	/* CURSOR_INVIS - nothing to do */
1199 
1200 	x = min(curcol,(CO - 1)); /* protection from callers */
1201 	y = min(currow,(LI - 1));		  /* protection from callers */
1202 	if (!singlebyte && ((x < clipx) || (x > clipxmax))) return;
1203 	    pixy = row2y(y);		  /* convert to pixels */
1204 	    if (singlebyte)
1205 		    pixx = x;
1206 	    else
1207 		    pixx = col2x((x-clipx));
1208 
1209 	    for(i=0;i < ROWS_PER_CELL; ++i) {
1210 		tmp1 = screentable[i+pixy];
1211  		tmp1 += pixx;
1212  		tmp2 = tmp1 + 1;
1213 		egareadplane(3);
1214 		/* memcpy(undercursor.plane[3].image[i],tmp1,BYTES_PER_CELL); */
1215 		undercursor.plane[3].image[i][0] = READ_ABSOLUTE(tmp1);
1216 		if (!singlebyte)
1217 			undercursor.plane[3].image[i][1] = READ_ABSOLUTE(tmp2);
1218 
1219 		egareadplane(2);
1220 		/* memcpy(undercursor.plane[2].image[i],tmp1,BYTES_PER_CELL); */
1221 		undercursor.plane[2].image[i][0] = READ_ABSOLUTE(tmp1);
1222 		if (!singlebyte)
1223 			undercursor.plane[2].image[i][1] = READ_ABSOLUTE(tmp2);
1224 
1225 		egareadplane(1);
1226 		/* memcpy(undercursor.plane[1].image[i],tmp1,BYTES_PER_CELL); */
1227 		undercursor.plane[1].image[i][0] = READ_ABSOLUTE(tmp1);
1228 		if (!singlebyte)
1229 			undercursor.plane[1].image[i][1] = READ_ABSOLUTE(tmp2);
1230 
1231 		egareadplane(0);
1232 		/* memcpy(undercursor.plane[0].image[i],tmp1,BYTES_PER_CELL); */
1233 		undercursor.plane[0].image[i][0] = READ_ABSOLUTE(tmp1);
1234 		if (!singlebyte)
1235 			undercursor.plane[0].image[i][1] = READ_ABSOLUTE(tmp2);
1236 	    }
1237 
1238 	    /*
1239              * Now we have a snapshot of the current cell.
1240              * Make a copy of it, then manipulate the copy
1241              * to include the cursor, and place the tinkered
1242              * version on the display.
1243              */
1244 
1245 	    cursor = undercursor;
1246 	    if (inmap) curtyp = cursor_type;
1247 	    else curtyp = CURSOR_UNDERLINE;
1248 
1249 	    switch(curtyp) {
1250 
1251 		case CURSOR_CORNER:
1252 		    for(i = 0; i < 2; ++i) {
1253 			if (!i) {
1254 				if (singlebyte) first = 0xC3;
1255 				else first  = 0xC0;
1256 				second = 0x03;
1257 			} else {
1258 				if (singlebyte) first = 0x81;
1259 				else first  = 0x80;
1260 				second = 0x01;
1261 			}
1262 			for (p=0; p < 4; ++p) {
1263 				if (cursor_color & colorbits[p]) {
1264 					cursor.plane[p].image[i][0] |= first;
1265 					if (!singlebyte)
1266 					cursor.plane[p].image[i][1] |= second;
1267 				} else {
1268 					cursor.plane[p].image[i][0] &= ~first;
1269 					if (!singlebyte)
1270 					cursor.plane[p].image[i][1] &= ~second;
1271 				}
1272 			}
1273 		    }
1274 
1275 		    for(i = ROWS_PER_CELL - 2; i < ROWS_PER_CELL; ++i) {
1276 			if (i != (ROWS_PER_CELL-1)) {
1277 				if (singlebyte) first = 0x81;
1278 				else first  = 0x80;
1279 				second = 0x01;
1280 			} else {
1281 				if (singlebyte) first = 0xC3;
1282 				else first  = 0xC0;
1283 				second = 0x03;
1284 			}
1285 			for (p=0; p < SCREENPLANES; ++p) {
1286 				if (cursor_color & colorbits[p]) {
1287 					cursor.plane[p].image[i][0] |= first;
1288 					if (!singlebyte)
1289 					cursor.plane[p].image[i][1] |= second;
1290 				} else {
1291 					cursor.plane[p].image[i][0] &= ~first;
1292 					if (!singlebyte)
1293 					cursor.plane[p].image[i][1] &= ~second;
1294 				}
1295 			}
1296 		    }
1297 		    break;
1298 
1299 		case CURSOR_UNDERLINE:
1300 
1301 		    i = ROWS_PER_CELL - 1;
1302 		    first  = 0xFF;
1303 		    second = 0xFF;
1304 		    for (p=0; p < SCREENPLANES; ++p) {
1305 			if (cursor_color & colorbits[p]) {
1306 				cursor.plane[p].image[i][0] |= first;
1307 				if (!singlebyte)
1308 				cursor.plane[p].image[i][1] |= second;
1309 			} else {
1310 				cursor.plane[p].image[i][0] &= ~first;
1311 				if (!singlebyte)
1312 				cursor.plane[p].image[i][1] &= ~second;
1313 			}
1314 		    }
1315 		    break;
1316 
1317 		case CURSOR_FRAME:
1318 
1319 		    /* fall through */
1320 
1321 		default:
1322 		    for(i = 0; i < ROWS_PER_CELL; ++i) {
1323 
1324 			if ((i == 0) || (i == (ROWS_PER_CELL-1))) {
1325 				first  = 0xFF;
1326 				second = 0xFF;
1327 			} else {
1328 				if (singlebyte) first = 0x81;
1329 				else first  = 0x80;
1330 				second = 0x01;
1331 			}
1332 			for (p=0; p < SCREENPLANES; ++p) {
1333 				if (cursor_color & colorbits[p]) {
1334 					cursor.plane[p].image[i][0] |= first;
1335 					if (!singlebyte)
1336 					cursor.plane[p].image[i][1] |= second;
1337 				} else {
1338 					cursor.plane[p].image[i][0] &= ~first;
1339 					if (!singlebyte)
1340 					cursor.plane[p].image[i][1] &= ~second;
1341 				}
1342 			}
1343 		    }
1344 		    break;
1345 	    }
1346 
1347 	   /*
1348             * Place the new cell onto the display.
1349             *
1350             */
1351 
1352 	    for(i=0;i < ROWS_PER_CELL; ++i) {
1353  		tmp1 = screentable[i+pixy];
1354  		tmp1 += pixx;
1355  		tmp2 = tmp1 + 1;
1356 		egawriteplane(8);
1357 		/* memcpy(tmp1,cursor.plane[3].image[i],BYTES_PER_CELL); */
1358 		WRITE_ABSOLUTE(tmp1,cursor.plane[3].image[i][0]);
1359 		if (!singlebyte)
1360 		WRITE_ABSOLUTE(tmp2,cursor.plane[3].image[i][1]);
1361 
1362 		egawriteplane(4);
1363 		/* memcpy(tmp1,cursor.plane[2].image[i],BYTES_PER_CELL); */
1364 		WRITE_ABSOLUTE(tmp1,cursor.plane[2].image[i][0]);
1365 		if (!singlebyte)
1366 		WRITE_ABSOLUTE(tmp2,cursor.plane[2].image[i][1]);
1367 
1368 		egawriteplane(2);
1369 		/* memcpy(tmp1,cursor.plane[1].image[i],BYTES_PER_CELL); */
1370 		WRITE_ABSOLUTE(tmp1,cursor.plane[1].image[i][0]);
1371 		if (!singlebyte)
1372 		WRITE_ABSOLUTE(tmp2,cursor.plane[1].image[i][1]);
1373 
1374 		egawriteplane(1);
1375 		/* memcpy(tmp1,cursor.plane[0].image[i],BYTES_PER_CELL); */
1376 		WRITE_ABSOLUTE(tmp1,cursor.plane[0].image[i][0]);
1377 		if (!singlebyte)
1378 		WRITE_ABSOLUTE(tmp2,cursor.plane[0].image[i][1]);
1379 	    }
1380 	    egawriteplane(15);
1381 #ifdef POSITIONBAR
1382 	    if (inmap) positionbar();
1383 #endif
1384 }
1385 
1386 void
vga_HideCursor()1387 vga_HideCursor()
1388 {
1389 
1390 	int i,pixx,pixy,x,y;
1391 	char __far *tmp1;
1392 	char __far *tmp2;
1393 #ifdef REINCARNATION
1394 	boolean isrogue = Is_rogue_level(&u.uz);
1395 	boolean singlebyte = (isrogue || iflags.over_view
1396 			      || iflags.traditional_view || !inmap);
1397 #else
1398 	boolean singlebyte = (iflags.over_view
1399 			      || iflags.traditional_view || !inmap);
1400 #endif
1401 	int curtyp;
1402 
1403 	if (inmap && !cursor_type) return;	/* CURSOR_INVIS - nothing to do */
1404 	/* protection from callers */
1405 	x = min(curcol,(CO - 1));
1406 	y = min(currow,(LI-1));
1407 	if (!singlebyte && ((x < clipx) || (x > clipxmax))) return;
1408 
1409 	    pixy = row2y(y);		/* convert to pixels */
1410 	    if (singlebyte)
1411 		    pixx = x;
1412 	    else
1413 		    pixx = col2x((x-clipx));
1414 
1415 	    if (inmap) curtyp = cursor_type;
1416 	    else curtyp = CURSOR_UNDERLINE;
1417 
1418 	    if (curtyp == CURSOR_UNDERLINE)  /* optimization for uline */
1419 		i = ROWS_PER_CELL - 1;
1420 	    else
1421 		i = 0;
1422 
1423 	    for(;i < ROWS_PER_CELL; ++i) {
1424 		tmp1 = screentable[i+pixy];
1425  		tmp1 += pixx;
1426  		tmp2 = tmp1 + 1;
1427 		egawriteplane(8);
1428 		/* memcpy(tmp,undercursor.plane[3].image[i],BYTES_PER_CELL); */
1429 		WRITE_ABSOLUTE(tmp1,undercursor.plane[3].image[i][0]);
1430 		if (!singlebyte)
1431 		WRITE_ABSOLUTE(tmp2,undercursor.plane[3].image[i][1]);
1432 
1433 		egawriteplane(4);
1434 		/* memcpy(tmp,undercursor.plane[2].image[i],BYTES_PER_CELL); */
1435 		WRITE_ABSOLUTE(tmp1,undercursor.plane[2].image[i][0]);
1436 		if (!singlebyte)
1437 		WRITE_ABSOLUTE(tmp2,undercursor.plane[2].image[i][1]);
1438 
1439 		egawriteplane(2);
1440 		/* memcpy(tmp,undercursor.plane[1].image[i],BYTES_PER_CELL); */
1441 		WRITE_ABSOLUTE(tmp1,undercursor.plane[1].image[i][0]);
1442 		if (!singlebyte)
1443 		WRITE_ABSOLUTE(tmp2,undercursor.plane[1].image[i][1]);
1444 
1445 		egawriteplane(1);
1446 		/* memcpy(tmp,undercursor.plane[0].image[i],BYTES_PER_CELL); */
1447 		WRITE_ABSOLUTE(tmp1,undercursor.plane[0].image[i][0]);
1448 		if (!singlebyte)
1449 		WRITE_ABSOLUTE(tmp2,undercursor.plane[0].image[i][1]);
1450 	    }
1451 	    egawriteplane(15);
1452 }
1453 #  endif /* SIMULATE_CURSOR */
1454 # endif /* OVLB */
1455 #endif /* SCREEN_VGA  */
1456 
1457 /* vidvga.c */
1458