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, ®s, ®s);
743 } else {
744 iflags.grmode = 0; /* force text mode for error msg */
745 regs.x.ax = MODETEXT;
746 (void) int86(VIDEO_BIOS, ®s, ®s);
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, ®s, ®s);
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, ®s, ®s);
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,®s,®s);
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