1 /* File: main-ibm.c */
4 * Copyright (c) 1997 Ben Harrison, and others
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies.
11 /* Purpose: Visual Display Support for "term.c", for the IBM */
15 * Original code by "Billy Tanksley (wtanksle@ucsd.edu)"
16 * Use "Makefile.ibm" to compile Angband using this file.
18 * Support for DJGPP v2 by "Scott Egashira (egashira@u.washington.edu)"
20 * Extensive modifications by "Ben Harrison (benh@phial.com)",
21 * including "collation" of the Watcom C/C++ and DOS-286 patches.
23 * Watcom C/C++ changes by "David Boeren (akemi@netcom.com)"
24 * Use "Makefile.wat" to compile this file with Watcom C/C++, and
25 * be sure to define "USE_IBM" and "USE_WAT".
27 * DOS-286 (conio.h) changes by (Roland Jay Roberts (jay@map.com)
28 * Use "Makefile.286" (not ready) to compile this file for DOS-286,
29 * and be sure to define "USE_IBM", "USE_WAT", and "USE_286". Also,
30 * depending on your compiler, you may need to define "USE_CONIO".
32 * True color palette support by "Mike Marcelais (michmarc@microsoft.com)",
33 * with interface to the "color_table" array by Ben Harrison.
35 * Both "shift" keys are treated as "identical", and all the modifier keys
36 * (control, shift, alt) are ignored when used with "normal" keys, unless
37 * they modify the underlying "ascii" value of the key. You must use the
38 * new "user pref files" to be able to interact with the keypad and such.
40 * The "lib/user/pref-ibm.prf" file contains macro definitions and possible
41 * alternative color set definitions. The "lib/user/font-ibm.prf" contains
42 * attr/char mappings for walls and floors and such.
44 * Note the "Term_user_ibm()" function hook, which could allow the user
45 * to interact with the "main-ibm.c" visual system. Currently this hook
46 * is unused, but, for example, it could allow the user to toggle "sound"
47 * or "graphics" modes, or to select the number of screen rows, with the
48 * extra screen rows being used for the mirror window.
60 * Use a "virtual" screen to "buffer" screen writes.
73 # else /* USE_CONIO */
77 # define bioskey(C) _bios_keybrd(C)
79 # endif /* USE_CONIO */
82 # define int86(a,b,c) int386(a,b,c)
85 # define inportb(x) inp(x)
86 # define outportb(x,y) outp(x,y)
95 # else /* __DJGPP__ > 1 */
97 # error "Upgrade to version 2.0 of DJGPP"
98 # endif /* __DJGPP__ */
99 # endif /* __DJGPP__ > 1 */
109 * Hack -- write directly to video card
111 /* extern int directvideo = 1; */
114 * Hack -- no virtual screen
118 #endif /* USE_CONIO */
122 * Keypress input modifier flags (hard-coded by DOS)
124 #define K_RSHIFT 0 /* Right shift key down */
125 #define K_LSHIFT 1 /* Left shift key down */
126 #define K_CTRL 2 /* Ctrl key down */
127 #define K_ALT 3 /* Alt key down */
128 #define K_SCROLL 4 /* Scroll lock on */
129 #define K_NUM 5 /* Num lock on */
130 #define K_CAPS 6 /* Caps lock on */
131 #define K_INSERT 7 /* Insert on */
135 * Foreground color bits (hard-coded by DOS)
137 #define VID_BLACK 0x00
138 #define VID_BLUE 0x01
139 #define VID_GREEN 0x02
140 #define VID_CYAN 0x03
142 #define VID_MAGENTA 0x05
143 #define VID_YELLOW 0x06
144 #define VID_WHITE 0x07
147 * Bright text (hard-coded by DOS)
149 #define VID_BRIGHT 0x08
152 * Background color bits (hard-coded by DOS)
154 #define VUD_BLACK 0x00
155 #define VUD_BLUE 0x10
156 #define VUD_GREEN 0x20
157 #define VUD_CYAN 0x30
159 #define VUD_MAGENTA 0x50
160 #define VUD_YELLOW 0x60
161 #define VUD_WHITE 0x70
164 * Blinking text (hard-coded by DOS)
166 #define VUD_BRIGHT 0x80
172 static int rows = 25;
173 static int cols = 80;
180 # define PhysicalScreen ((byte *)MK_FP(0xB800,0x0000))
182 # define PhysicalScreen ((byte *)(0xB800 << 4))
189 * Virtual Screen Contents
191 static byte *VirtualScreen;
196 * Physical screen access
198 #define VirtualScreen PhysicalScreen
204 * Hack -- the cursor "visibility"
206 static int saved_cur_v;
207 static int saved_cur_high;
208 static int saved_cur_low;
212 #else /* USE_CONIO */
215 * This array is used for "wiping" the screen
217 static byte wiper[160];
219 #endif /* USE_CONIO */
223 * The main screen (currently the only screen)
225 static term term_screen_body;
229 * Choose between the "complex" and "simple" color methods
231 static byte use_color_complex = FALSE;
235 * The "complex" color set
237 static long ibm_color_complex[16];
241 * The "simple" color set
243 * This table is used by the "color" code to instantiate the "approximate"
244 * Angband colors using the only colors available on crappy monitors.
246 * The entries below are taken from the "color bits" defined above.
248 * Note that values from 16 to 255 are extremely ugly.
250 * The values below came from various sources, if you do not like them,
251 * get a better monitor, or edit "pref-ibm.prf" to use different codes.
253 * Note that many of the choices below suck, but so do crappy monitors.
255 static byte ibm_color_simple[16] =
257 VID_BLACK, /* Dark */
258 VID_WHITE, /* White */
259 VID_CYAN, /* Slate XXX */
260 VID_RED | VID_BRIGHT, /* Orange XXX */
262 VID_GREEN, /* Green */
264 VID_YELLOW, /* Umber XXX */
265 VID_BLACK | VID_BRIGHT, /* Light Dark */
266 VID_CYAN | VID_BRIGHT, /* Light Slate XXX */
267 VID_MAGENTA, /* Violet */
268 VID_YELLOW | VID_BRIGHT, /* Yellow */
269 VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */
270 VID_GREEN | VID_BRIGHT, /* Light Green */
271 VID_BLUE | VID_BRIGHT, /* Light Blue */
272 VID_YELLOW /* Light Umber XXX */
278 * Activate the "ibm_color_complex" palette information.
280 * Code by Mike Marcelais, with help from "The programmer's guide
281 * to the EGA and VGA video cards" [Farraro].
283 * On VGA cards, colors go through a double-indirection when looking
284 * up the `real' color when in 16 color mode. The color value in the
285 * attribute is looked up in the EGA color registers. Then that value
286 * is looked up in the VGA color registers. Then the color is displayed.
287 * This is done for compatability. However, the EGA registers are
288 * initialized by default to 0..5, 14, 7, 38..3F and not 0..F which means
289 * that unless these are reset, the VGA setpalette function will not
290 * update the correct palette register!
292 * DJGPP's GrSetColor() does _not_ set the EGA palette list, only the
295 * Note that the "traditional" method, using "int86(0x10)", is very slow
296 * when called in protected mode, so we use a faster method using video
299 * On Watcom machines, we could simply use the special "_remapallpalette()"
300 * function, which not only sets both palette lists (see below) but also
301 * checks for legality of the monitor mode, but, if we are doing bitmapped
302 * graphics, that function forgets to set the EGA registers for some reason.
304 static void activate_color_complex(void)
307 printf("%c%c%c%c",8,8,8,8);
311 /* Edit the EGA palette */
314 /* Edit the colors */
315 for (i = 0; i < 16; i++)
324 /* Use that EGA palette */
325 outportb(0x3c0, 0x20);
327 /* Edit VGA palette, starting at color zero */
330 /* Send the colors */
331 for (i = 0; i < 16; i++)
333 /* Send the red, green, blue components */
334 outportb(0x3c9, ((ibm_color_complex[i]) & 0xFF));
335 outportb(0x3c9, ((ibm_color_complex[i] >> 8) & 0xFF));
336 outportb(0x3c9, ((ibm_color_complex[i] >> 16) & 0xFF));
342 for (i = 0; i < 16; i++)
367 /* Use this "green" value */
368 r.h.ch = ((ibm_color_complex[i] >> 8) & 0xFF);
370 /* Use this "blue" value */
371 r.h.cl = ((ibm_color_complex[i] >> 16) & 0xFF);
373 /* Use this "red" value */
374 r.h.dh = ((ibm_color_complex[i]) & 0xFF);
386 * Note the use of "(x >> 2)" to convert an 8 bit value to a 6 bit value
387 * without losing much precision.
389 static int Term_xtra_ibm_react(void)
394 if (use_color_complex)
396 long rv, gv, bv, code;
400 /* Save the default colors */
401 for (i = 0; i < 16; i++)
403 /* Extract desired values */
404 rv = angband_color_table[i][1] >> 2;
405 gv = angband_color_table[i][2] >> 2;
406 bv = angband_color_table[i][3] >> 2;
408 /* Extract a full color code */
409 code = ((rv) | (gv << 8) | (bv << 16));
411 /* Activate changes */
412 if (ibm_color_complex[i] != code)
414 /* Note the change */
417 /* Apply the desired color */
418 ibm_color_complex[i] = code;
422 /* Activate the palette if needed */
423 if (change) activate_color_complex();
429 /* Save the default colors */
430 for (i = 0; i < 16; i++)
432 /* Simply accept the desired colors */
433 ibm_color_simple[i] = angband_color_table[i][0];
444 * Hack -- set the cursor "visibility"
446 static void curs_set(int v)
449 if (saved_cur_v != v)
459 /* Use the saved values */
460 r.h.ch = saved_cur_high;
461 r.h.cl = saved_cur_low;
467 /* Make it invisible */
475 /* Save the cursor state */
483 * Process an event (check for a keypress)
485 * The keypress processing code is often the most system dependant part
486 * of Angband, since sometimes even the choice of compiler is important.
488 * For the IBM, we divide all keypresses into two catagories, first, the
489 * "normal" keys, including all keys required to play Angband, and second,
490 * the "special" keys, such as keypad keys, function keys, and various keys
491 * used in combination with various modifier keys.
493 * To simplify this file, we use Angband's "macro processing" ability, in
494 * combination with a specialized "pref-ibm.prf" file, to handle most of the
495 * "special" keys, instead of attempting to fully analyze them here. This
496 * file only has to determine when a "special" key has been pressed, and
497 * translate it into a simple string which signals the use of a "special"
498 * key, the set of modifiers used, if any, and the hardware scan code of
499 * the actual key which was pressed. To simplify life for the user, we
500 * treat both "shift" keys as identical modifiers.
502 * The final encoding is "^_MMMxSS\r", where "MMM" encodes the modifiers
503 * ("C" for control, "S" for shift, "A" for alt, or any ordered combination),
504 * and "SS" encodes the keypress (as the two "digit" hexidecimal encoding of
505 * the scan code of the key that was pressed), and the "^_" and "x" and "\r"
506 * delimit the encoding for recognition by the macro processing code.
508 * Some important facts about scan codes follow. All "normal" keys use
509 * scan codes from 1-58. The "function" keys use 59-68 (and 133-134).
510 * The "keypad" keys use 69-83. Escape uses 1. Enter uses 28. Control
511 * uses 29. Left Shift uses 42. Right Shift uses 54. PrtScrn uses 55.
512 * Alt uses 56. Space uses 57. CapsLock uses 58. NumLock uses 69.
513 * ScrollLock uses 70. The "keypad" keys which use scan codes 71-83
514 * are ordered KP7,KP8,KP9,KP-,KP4,KP5,KP6,KP+,KP1,KP2,KP3,INS,DEL.
516 * Using "bioskey(0x10)" instead of "bioskey(0)" apparently provides more
517 * information, including better access to the keypad keys in combination
518 * with various modifiers, but only works on "PC's after 6/1/86", and there
519 * is no way to determine if the function is provided on a machine. I have
520 * been told that without it you cannot detect, for example, control-left.
521 * The basic scan code + ascii value pairs returned by the keypad follow,
522 * with values in parentheses only available to "bioskey(0x10)".
525 * Norm: 352f 372a 4a2d 4e2b 4f00 5000 5100 4b00
526 * Shft: 352f 372a 4a2d 4e2b 4f31 5032 5133 4b34
527 * Ctrl: (9500) (9600) (8e00) (9000) 7500 (9100) 7600 7300
529 * 5 6 7 8 9 0 . Enter
530 * Norm: (4c00) 4d00 4700 4800 4900 5200 5300 (e00d)
531 * Shft: 4c35 4d36 4737 4838 4939 5230 532e (e00d)
532 * Ctrl: (8f00) 7400 7700 (8d00) 8400 (9200) (9300) (e00a)
534 * See "pref-ibm.prf" for the "standard" macros for various keys.
536 * Certain "bizarre" keypad keys (such as "enter") return a "scan code"
537 * of "0xE0", and a "usable" ascii value. These keys should be treated
538 * like the normal keys, see below. XXX XXX XXX Note that these "special"
539 * keys could be prefixed with an optional "ctrl-^" which would allow them
540 * to be used in macros without hurting their use in normal situations.
542 static errr Term_xtra_ibm_event(int v)
551 /* Hack -- Check for a keypress */
552 if (!v && !bioskey(1)) return (1);
554 /* Wait for a keypress */
557 /* Access the "modifiers" */
560 /* Extract the "scan code" */
561 s = ((k >> 8) & 0xFF);
563 /* Extract the "ascii value" */
566 /* Process "normal" keys */
567 if ((s <= 58) || (s == 0xE0))
570 if (k) Term_keypress(k);
576 /* Extract the modifier flags */
577 if (i & (1 << K_CTRL)) mc = TRUE;
578 if (i & (1 << K_LSHIFT)) ms = TRUE;
579 if (i & (1 << K_RSHIFT)) ms = TRUE;
580 if (i & (1 << K_ALT)) ma = TRUE;
583 /* Begin a "macro trigger" */
586 /* Hack -- Send the modifiers */
587 if (mc) Term_keypress('C');
588 if (ms) Term_keypress('S');
589 if (ma) Term_keypress('A');
591 /* Introduce the hexidecimal scan code */
594 /* Encode the hexidecimal scan code */
595 Term_keypress(hexsym[s/16]);
596 Term_keypress(hexsym[s%16]);
598 /* End the "macro trigger" */
607 * Handle a "special request"
609 * The given parameters are "valid".
611 static errr Term_xtra_ibm(int n, int v)
615 /* Analyze the request */
618 /* Make a "bell" noise */
619 case TERM_XTRA_NOISE:
621 /* Make a bell noise */
622 (void)write(1, "\007", 1);
628 /* Set the cursor shape */
629 case TERM_XTRA_SHAPE:
631 /* Set cursor shape */
638 /* Flush one line of output */
639 case TERM_XTRA_FROSH:
646 /* Copy the virtual screen to the physical screen */
647 memcpy(PhysicalScreen + (v*160), VirtualScreen + (v*160), 160);
651 /* Apply the virtual screen to the physical screen */
652 ScreenUpdateLine(VirtualScreen + ((v*cols) << 1), v);
654 # endif /* USE_WAT */
656 #endif /* USE_VIRTUAL */
662 /* Clear the screen */
663 case TERM_XTRA_CLEAR:
668 /* Clear the screen */
671 #else /* USE_CONIO */
673 /* Clear each line (virtual or physical) */
674 for (i = 0; i < rows; i++)
677 memcpy((VirtualScreen + ((i*cols) << 1)), wiper, (cols << 1));
684 /* Copy the virtual screen to the physical screen */
685 memcpy(PhysicalScreen, VirtualScreen, 25*80*2);
689 /* Erase the physical screen */
692 # endif /* USE_WAT */
694 # endif /* USE_VIRTUAL */
696 #endif /* USE_CONIO */
703 case TERM_XTRA_EVENT:
705 /* Process one event */
706 return (Term_xtra_ibm_event(v));
710 case TERM_XTRA_FLUSH:
713 while (!Term_xtra_ibm_event(FALSE)) /* loop */;
719 /* React to global changes */
720 case TERM_XTRA_REACT:
722 /* React to "color_table" changes */
723 return (Term_xtra_ibm_react());
726 /* Delay for some milliseconds */
727 case TERM_XTRA_DELAY:
729 /* Delay if needed */
737 /* Unknown request */
746 * The given parameters are "valid".
748 static errr Term_curs_ibm(int x, int y)
755 /* Place the cursor */
758 # else /* USE_CONIO */
767 /* Place the cursor */
770 # endif /* USE_CONIO */
774 /* Move the cursor */
775 ScreenSetCursor(y, x);
785 * Erase a block of the screen
787 * The given parameters are "valid".
789 static errr Term_wipe_ibm(int x, int y, int n)
794 /* Wipe the region */
795 window(x+1, y+1, x+n, y+1);
797 window(1, 1, cols, rows);
799 #else /* USE_CONIO */
801 /* Wipe part of the virtual (or physical) screen */
802 memcpy(VirtualScreen + ((cols*y + x)<<1), wiper, n<<1);
804 #endif /* USE_CONIO */
812 * Place some text on the screen using an attribute
814 * The given parameters are "valid". Be careful with "a".
816 * The string "cp" has length "n" and is NOT null-terminated.
818 static errr Term_text_ibm(int x, int y, int n, byte a, const char *cp)
825 /* Handle "complex" color */
826 if (use_color_complex)
828 /* Extract a color index */
832 /* Handle "simple" color */
835 /* Extract a color value */
836 attr = ibm_color_simple[a & 0x0F];
841 /* Place the cursor */
844 /* Set the attribute */
849 for (i = 0; i < n; i++) {
850 if (iskanji(cp[i])) {
862 for (i = 0; i < n; i++) putch(cp[i]);
865 #else /* USE_CONIO */
867 /* Access the virtual (or physical) screen */
868 dest = VirtualScreen + (((cols * y) + x) << 1);
871 for (i = 0; i < n; i++)
878 #endif /* USE_CONIO */
886 * Place some attr/char pairs on the screen
888 * The given parameters are "valid".
890 static errr Term_pict_ibm(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
899 /* Place the cursor */
903 for (i = 0; i < n; i++)
905 /* Handle "complex" color */
906 if (use_color_complex)
908 /* Extract a color index */
909 attr = (ap[i] & 0x0F);
912 /* Handle "simple" color */
915 /* Extract a color value */
916 attr = ibm_color_simple[ap[i] & 0x0F];
919 /* Set the attribute */
926 #else /* USE_CONIO */
928 /* Access the virtual (or physical) screen */
929 dest = VirtualScreen + (((cols * y) + x) << 1);
932 for (i = 0; i < n; i++)
934 /* Handle "complex" color */
935 if (use_color_complex)
937 /* Extract a color index */
938 attr = (ap[i] & 0x0F);
941 /* Handle "simple" color */
944 /* Extract a color value */
945 attr = ibm_color_simple[ap[i] & 0x0F];
953 #endif /* USE_CONIO */
963 static void Term_init_ibm(term *t)
972 static void Term_nuke_ibm(term *t)
985 /* Move the cursor to the bottom of the screen */
986 Term_curs_ibm(0, rows-1);
990 /* Restore the original video mode */
991 _setvideomode(_DEFAULTMODE);
995 /* Restore the original video mode */
1000 #endif /* USE_WAT */
1002 /* Make the cursor visible */
1013 * In 286 mode we don't need to worry about translating from a 32bit
1014 * pointer to a 16 bit pointer so we just call the interrupt function
1016 * Note the use of "intr()" instead of "int86()" so we can pass
1017 * segment registers.
1019 void enable_graphic_font(void *font)
1021 union REGPACK regs =
1024 regs.h.ah = 0x11; /* Text font function */
1025 regs.h.bh = 0x10; /* Size of a character -- 16 bytes */
1026 regs.h.cl = 0xFF; /* Last character in font */
1027 regs.x.es = FP_SEG(font); /* Pointer to font */
1028 regs.x.bp = FP_OFF(font);
1037 * This structure is used by the DMPI function to hold registers when
1038 * doing a real mode interrupt call. (Stolen from the DJGPP <dpmi.h>
1057 unsigned short di, di_hi;
1058 unsigned short si, si_hi;
1059 unsigned short bp, bp_hi;
1060 unsigned short res, res_hi;
1061 unsigned short bx, bx_hi;
1062 unsigned short dx, dx_hi;
1063 unsigned short cx, cx_hi;
1064 unsigned short ax, ax_hi;
1065 unsigned short flags;
1077 unsigned char edi[4];
1078 unsigned char esi[4];
1079 unsigned char ebp[4];
1080 unsigned char res[4];
1081 unsigned char bl, bh, ebx_b2, ebx_b3;
1082 unsigned char dl, dh, edx_b2, edx_b3;
1083 unsigned char cl, ch, ecx_b2, ecx_b3;
1084 unsigned char al, ah, eax_b2, eax_b3;
1088 unsigned __dpmi_allocate_dos_memory(int size, unsigned *selector)
1090 union REGPACK regs =
1093 regs.w.ax = 0x100; /* DPMI function -- allocate low memory */
1094 regs.w.bx = size; /* Number of Paragraphs to allocate */
1095 intr(0x31, ®s); /* DPMI interface */
1097 *selector = regs.w.dx;
1101 void __dpmi_free_dos_memory(unsigned sel)
1103 union REGPACK regs =
1106 regs.w.ax = 0x101; /* DPMI function -- free low memory */
1107 regs.x.edx = sel; /* PM selector for memory block */
1108 intr(0x31, ®s); /* DPMI interface */
1111 void __dpmi_int(int intno, __dpmi_regs *dblock)
1113 union REGPACK regs =
1116 regs.w.ax = 0x300; /* DPMI function -- real mode interrupt */
1117 regs.h.bl = intno; /* interrupt 0x10 */
1118 regs.x.edi = FP_OFF(dblock); /* Pointer to dblock (offset and segment) */
1119 regs.x.es = FP_SEG(dblock);
1120 intr(0x31, ®s); /* DPMI interface */
1123 unsigned short __dpmi_sel = 0x0000;
1124 #define _farsetsel(x) __dpmi_sel=(x)
1125 extern void _farnspokeb(unsigned long offset, unsigned char value);
1126 #pragma aux _farnspokeb = \
1128 "mov fs,__dpmi_sel" \
1137 #include <sys/farptr.h>
1139 #endif /* USE_WAT */
1143 * Since you cannot send 32bit pointers to a 16bit interrupt handler
1144 * and the video BIOS wants a (16bit) pointer to the font, we have
1145 * to allocate a block of dos memory, copy the font into it, then
1146 * translate a 32bit pointer into a 16bit pointer to that block.
1148 * DPMI - Dos Protected Mode Interface provides functions that let
1151 void enable_graphic_font(const char *font)
1153 __dpmi_regs dblock = {{0}};
1155 unsigned int seg, i;
1159 * Allocate a block of memory 4096 bytes big in `low memory' so a real
1160 * mode interrupt can access it. Real mode pointer is returned as seg:0
1161 * Protected mode pointer is sel:0.
1163 seg = __dpmi_allocate_dos_memory(256, &sel);
1165 /* Copy the information into low memory buffer, by copying one byte at
1166 * a time. According to the info in <sys/farptr.h>, the functions
1167 * _farsetsel() and _farnspokeb() will optimise away completely
1169 _farsetsel(sel); /* Set the selector to write to */
1170 for (i = 0; i<4096; i++)
1172 _farnspokeb(i, *font++); /* Copy 1 byte into low (far) memory */
1176 * Now we use DPMI as a jumper to call the real mode interrupt. This
1177 * is needed because loading `es' while in protected mode with a real
1178 * mode pointer will cause an Protection Fault and calling the interrupt
1179 * directly using the protected mode pointer will result in garbage
1180 * being received by the interrupt routine
1182 dblock.d.eax = 0x1100; /* BIOS function -- set font */
1183 dblock.d.ebx = 0x1000; /* bh = size of a letter; bl = 0 (reserved) */
1184 dblock.d.ecx = 0x00FF; /* Last character in font */
1185 dblock.x.es = seg; /* Pointer to font segment */
1186 dblock.d.ebp = 0x0000; /* Pointer to font offset */
1188 __dpmi_int(0x10, &dblock);
1190 /* We're done with the low memory, free it */
1191 __dpmi_free_dos_memory(sel);
1194 #endif /* USE_286 */
1196 #endif /* ALLOW_GRAPH */
1201 * Initialize the IBM "visual module"
1203 * Hack -- we assume that "blank space" should be "white space"
1204 * (and not "black space" which might make more sense).
1206 * Note the use of "((x << 2) | (x >> 4))" to "expand" a 6 bit value
1207 * into an 8 bit value, without losing much precision, by using the 2
1208 * most significant bits as the least significant bits in the new value.
1215 term *t = &term_screen_body;
1219 /* Check for "Windows" */
1220 if (getenv("windir"))
1222 r.h.ah = 0x16; /* Windows API Call -- Set device focus */
1223 r.h.al = 0x8B; /* Causes Dos boxes to become fullscreen */
1224 r.h.bh = r.h.bl = 0x00; /* 0x0000 = current Dos box */
1225 int86(0x2F, &r, &r); /* Call the Windows API */
1228 /* Initialize "color_table" */
1229 for (i = 0; i < 16; i++)
1233 /* Extract desired values */
1234 rv = angband_color_table[i][1] >> 2;
1235 gv = angband_color_table[i][2] >> 2;
1236 bv = angband_color_table[i][3] >> 2;
1238 /* Extract the "complex" codes */
1239 ibm_color_complex[i] = ((rv) | (gv << 8) | (bv << 16));
1241 /* Save the "simple" codes */
1242 angband_color_table[i][0] = ibm_color_simple[i];
1247 /* Set the video mode */
1248 if (_setvideomode(_VRES16COLOR))
1259 /* Force 25 line mode */
1260 _setvideomode(_TEXTC80);
1265 /* Set video mode */
1267 r.h.al = 0x13; /* VGA only mode */
1268 int86(0x10, &r, &r);
1270 /* Get video mode */
1272 int86(0x10, &r, &r);
1275 /* Set video mode */
1277 r.h.al = 0x03; /* Color text mode */
1278 int86(0x10, &r, &r);
1280 #endif /* USE_WAT */
1282 /* Check video mode */
1285 /* Remember the mode */
1286 use_color_complex = TRUE;
1288 /* Instantiate the color set */
1289 activate_color_complex();
1294 /* Try to activate bitmap graphics */
1295 if (arg_graphics && use_color_complex)
1301 /* Build the filename */
1302 path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, "angband.fnt");
1305 f = fopen(buf, "rb");
1310 /* Load the bitmap data */
1311 if (fread(buf, 1, 4096, f) != 4096)
1313 quit("Corrupt 'angband.fnt' file");
1316 /* Close the file */
1319 /* Enable graphics */
1320 enable_graphic_font(buf);
1322 /* Enable colors (again) */
1323 activate_color_complex();
1326 use_graphics = TRUE;
1333 #else /* USE_CONIO */
1335 /* Build a "wiper line" */
1336 for (i = 0; i < 80; i++)
1342 wiper[2*i+1] = TERM_WHITE;
1345 #endif /* USE_CONIO */
1350 /* Make the virtual screen */
1351 C_MAKE(VirtualScreen, rows * cols * 2, byte);
1353 #endif /* USE_VIRTUAL */
1356 /* Erase the screen */
1357 Term_xtra_ibm(TERM_XTRA_CLEAR, 0);
1360 /* Place the cursor */
1361 Term_curs_ibm(0, 0);
1364 /* Access the "default" cursor info */
1369 int86(0x10, &r, &r);
1371 /* Extract the standard cursor info */
1373 saved_cur_high = r.h.ch;
1374 saved_cur_low = r.h.cl;
1377 /* Initialize the term */
1378 term_init(t, 80, 24, 256);
1381 #else /* USE_CONIO */
1383 /* Always use "Term_pict()" */
1384 t->always_pict = TRUE;
1386 #endif /* USE_CONIO */
1388 /* Use "white space" to erase */
1389 t->attr_blank = TERM_WHITE;
1390 t->char_blank = ' ';
1392 /* Prepare the init/nuke hooks */
1393 t->init_hook = Term_init_ibm;
1394 t->nuke_hook = Term_nuke_ibm;
1396 /* Connect the hooks */
1397 t->xtra_hook = Term_xtra_ibm;
1398 t->curs_hook = Term_curs_ibm;
1399 t->wipe_hook = Term_wipe_ibm;
1400 t->text_hook = Term_text_ibm;
1401 t->pict_hook = Term_pict_ibm;
1407 Term_activate(term_screen);
1414 #endif /* USE_IBM */