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