+++ /dev/null
-/* File: main-dos.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, Robert Ruehlmann, and others
- *
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies.
- */
-
-
-/*
- * This file helps Angband work with DOS computers.
- *
- * Adapted from "main-ibm.c".
- *
- * Author: Robert Ruehlmann (rr9@angband.org).
- * See "http://thangorodrim.angband.org/".
- *
- * Initial framework (and some code) by Ben Harrison (benh@phial.com).
- *
- * This file requires the (free) DJGPP compiler (based on "gcc").
- * See "http://www.delorie.com/djgpp/".
- *
- * This file uses the (free) "Allegro" library (SVGA graphics library).
- * See "http://www.talula.demon.co.uk/allegro/".
- *
- * To compile this file, use "Makefile.dos", which defines "USE_DOS".
- *
- * See also "main-ibm.c" and "main-win.c".
- *
- *
- * The "lib/user/pref.prf" file contains macro definitions and possible
- * alternative color set definitions.
- *
- * The "lib/user/font.prf" contains attr/char mappings for use with the
- * special fonts in the "lib/xtra/font/" directory.
- *
- * The "lib/user/graf.prf" contains attr/char mappings for use with the
- * special bitmaps in the "lib/xtra/graf/" directory.
- *
- *
- * Both "shift" keys are treated as "identical", and all the modifier keys
- * (control, shift, alt) are ignored when used with "normal" keys, unless
- * they modify the underlying "ascii" value of the key. You must use the
- * new "user pref files" to be able to interact with the keypad and such.
- *
- * Note that "Term_xtra_dos_react()" allows runtime color, graphics,
- * screen resolution, and sound modification.
- *
- *
- * The sound code uses *.wav files placed in the "lib/xtra/sound" folder.
- * Every sound-event can have several samples assigned to it and a random
- * one will be played when the event occures. Look at the
- * "lib/xtra/sound/sound.cfg" configuration file for more informations.
- *
- * The background music uses midi-files (and mod files) from the
- * "lib/xtra/music" folder.
- *
- *
- * Comment by Ben Harrison (benh@phial.com):
- *
- * On my Windows NT box, modes "VESA1" and "VESA2B" seem to work, but
- * result in the game running with no visible output. Mode "VESA2L"
- * clears the screen and then fails silently. All other modes fail
- * instantly. To recover from such "invisible" modes, you can try
- * typing escape, plus control-x, plus escape. XXX XXX XXX
- */
-
-#include "angband.h"
-
-
-#ifdef USE_DOS
-
-#include <allegro.h>
-
-#ifdef USE_MOD_FILES
-#include <jgmod.h>
-#endif /* USE_MOD_FILES */
-
-#include <bios.h>
-#include <dos.h>
-#include <keys.h>
-#include <unistd.h>
-#include <dir.h>
-
-/*
- * Index of the first standard Angband color.
- *
- * All colors below this index are defined by
- * the palette of the tiles-bitmap.
- */
-#define COLOR_OFFSET 240
-
-
-/*
- * Maximum number of terminals
- */
-#define MAX_TERM_DATA 8
-
-
-/*
- * Forward declare
- */
-typedef struct term_data term_data;
-
-
-/*
- * Extra "term" data
- */
-struct term_data
-{
- term t;
-
- int number;
-
- int x;
- int y;
-
- int cols;
- int rows;
-
- int tile_wid;
- int tile_hgt;
-
- int font_wid;
- int font_hgt;
-
- FONT *font;
-
-#ifdef USE_GRAPHICS
-
- BITMAP *tiles;
-
-#endif /* USE_GRAPHICS */
-
-#ifdef USE_BACKGROUND
-
- int window_type;
-
-#endif /* USE_BACKGROUND */
-
-};
-
-/*
- * The current screen resolution
- */
-static int resolution;
-
-#ifdef USE_BACKGROUND
-
-/*
- * The background images
- */
-BITMAP *background[17];
-
-#endif /* USE_BACKGROUND */
-
-
-/*
- * An array of term_data's
- */
-static term_data data[MAX_TERM_DATA];
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * Are graphics already initialized ?
- */
-static bool graphics_initialized = FALSE;
-
-#endif /* USE_GRAPHICS */
-
-
-/*
- * Small bitmap for the cursor
- */
-static BITMAP *cursor;
-
-
-#ifdef USE_SOUND
-
-/*
- * Is the sound already initialized ?
- */
-static bool sound_initialized = FALSE;
-
-# ifdef USE_MOD_FILES
-/*
- * Is the mod-file support already initialized ?
- */
-static bool mod_file_initialized = FALSE;
-
-# endif /* USE_MOD_FILES */
-
-/*
- * Volume settings
- */
-static int digi_volume;
-static int midi_volume;
-
-/*
- * The currently playing song
- */
-static MIDI *midi_song = NULL;
-
-# ifdef USE_MOD_FILES
-
-static JGMOD *mod_song = NULL;
-
-# endif /* USE_MOD_FILES */
-
-static int current_song;
-
-/*
- * The number of available songs
- */
-static int song_number;
-
-/*
- * The maximum number of available songs
- */
-#define MAX_SONGS 255
-
-static char music_files[MAX_SONGS][16];
-
-/*
- * The maximum number of samples per sound-event
- */
-#define SAMPLE_MAX 10
-
-/*
- * An array of sound files
- */
-static SAMPLE* samples[SOUND_MAX][SAMPLE_MAX];
-
-/*
- * The number of available samples for every event
- */
-static int sample_count[SOUND_MAX];
-
-#endif /* USE_SOUND */
-
-
-/*
- * Extra paths
- */
-static char xtra_font_dir[1024];
-static char xtra_graf_dir[1024];
-static char xtra_sound_dir[1024];
-static char xtra_music_dir[1024];
-
-/*
- * List of used videomodes to reduce executable size
- */
-BEGIN_GFX_DRIVER_LIST
- GFX_DRIVER_VBEAF
- GFX_DRIVER_VGA
- GFX_DRIVER_VESA3
- GFX_DRIVER_VESA2L
- GFX_DRIVER_VESA2B
- GFX_DRIVER_VESA1
-END_GFX_DRIVER_LIST
-
-
-/*
- * List of used color depths to reduce executeable size
- */
-BEGIN_COLOR_DEPTH_LIST
- COLOR_DEPTH_8
-END_COLOR_DEPTH_LIST
-
-
-/*
- * Keypress input modifier flags (hard-coded by DOS)
- */
-#define K_RSHIFT 0 /* Right shift key down */
-#define K_LSHIFT 1 /* Left shift key down */
-#define K_CTRL 2 /* Ctrl key down */
-#define K_ALT 3 /* Alt key down */
-#define K_SCROLL 4 /* Scroll lock on */
-#define K_NUM 5 /* Num lock on */
-#define K_CAPS 6 /* Caps lock on */
-#define K_INSERT 7 /* Insert on */
-
-
-/*
- * Prototypes
- */
-static errr Term_xtra_dos_event(int v);
-static void Term_xtra_dos_react(void);
-static void Term_xtra_dos_clear(void);
-static errr Term_xtra_dos(int n, int v);
-static errr Term_user_dos(int n);
-static errr Term_curs_dos(int x, int y);
-static errr Term_wipe_dos(int x, int y, int n);
-static errr Term_text_dos(int x, int y, int n, byte a, const char *cp);
-static void Term_init_dos(term *t);
-static void Term_nuke_dos(term *t);
-static void term_data_link(term_data *td);
-static void dos_dump_screen(void);
-static void dos_quit_hook(concptr str);
-static bool init_windows(void);
-errr init_dos(void);
-#ifdef USE_SOUND
-static bool init_sound(void);
-static errr Term_xtra_dos_sound(int v);
-static void play_song(void);
-#endif /* USE_SOUND */
-#ifdef USE_GRAPHICS
-static bool init_graphics(void);
-static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp);
-#endif /* USE_GRAPHICS */
-
-
-/*
- * Process an event (check for a keypress)
- *
- * The keypress processing code is often the most system dependant part
- * of Angband, since sometimes even the choice of compiler is important.
- *
- * For this file, we divide all keypresses into two catagories, first, the
- * "normal" keys, including all keys required to play Angband, and second,
- * the "special" keys, such as keypad keys, function keys, and various keys
- * used in combination with various modifier keys.
- *
- * To simplify this file, we use Angband's "macro processing" ability, in
- * combination with the "lib/user/pref.prf" file, to handle most of the
- * "special" keys, instead of attempting to fully analyze them here. This
- * file only has to determine when a "special" key has been pressed, and
- * translate it into a simple string which signals the use of a "special"
- * key, the set of modifiers used, if any, and the hardware scan code of
- * the actual key which was pressed. To simplify life for the user, we
- * treat both "shift" keys as identical modifiers.
- *
- * The final encoding is "^_MMMxSS\r", where "MMM" encodes the modifiers
- * ("C" for control, "S" for shift, "A" for alt, or any ordered combination),
- * and "SS" encodes the keypress (as the two "digit" hexidecimal encoding of
- * the scan code of the key that was pressed), and the "^_" and "x" and "\r"
- * delimit the encoding for recognition by the macro processing code.
- *
- * Some important facts about scan codes follow. All "normal" keys use
- * scan codes from 1-58. The "function" keys use 59-68 (and 133-134).
- * The "keypad" keys use 69-83. Escape uses 1. Enter uses 28. Control
- * uses 29. Left Shift uses 42. Right Shift uses 54. PrtScrn uses 55.
- * Alt uses 56. Space uses 57. CapsLock uses 58. NumLock uses 69.
- * ScrollLock uses 70. The "keypad" keys which use scan codes 71-83
- * are ordered KP7,KP8,KP9,KP-,KP4,KP5,KP6,KP+,KP1,KP2,KP3,INS,DEL.
- *
- * Using "bioskey(0x10)" instead of "bioskey(0)" apparently provides more
- * information, including better access to the keypad keys in combination
- * with various modifiers, but only works on "PC's after 6/1/86", and there
- * is no way to determine if the function is provided on a machine. I have
- * been told that without it you cannot detect, for example, control-left.
- * The basic scan code + ascii value pairs returned by the keypad follow,
- * with values in parentheses only available to "bioskey(0x10)".
- *
- * / * - + 1 2 3 4
- * Norm: 352f 372a 4a2d 4e2b 4f00 5000 5100 4b00
- * Shft: 352f 372a 4a2d 4e2b 4f31 5032 5133 4b34
- * Ctrl: (9500) (9600) (8e00) (9000) 7500 (9100) 7600 7300
- *
- * 5 6 7 8 9 0 . Enter
- * Norm: (4c00) 4d00 4700 4800 4900 5200 5300 (e00d)
- * Shft: 4c35 4d36 4737 4838 4939 5230 532e (e00d)
- * Ctrl: (8f00) 7400 7700 (8d00) 8400 (9200) (9300) (e00a)
- *
- * See "lib/user/pref-win.prf" for the "standard" macros for various keys.
- *
- * Certain "bizarre" keypad keys (such as "enter") return a "scan code"
- * of "0xE0", and a "usable" ascii value. These keys should be treated
- * like the normal keys, see below. XXX XXX XXX Note that these "special"
- * keys could be prefixed with an optional "ctrl-^" which would allow them
- * to be used in macros without hurting their use in normal situations.
- *
- * This function also appears in "main-ibm.c". XXX XXX XXX
- *
- * Addition for the DOS version: Dump-screen function with the
- * "Ctrl-Print" key saves a bitmap with the screen contents to
- * "lib/user/dump.bmp".
- */
-static errr Term_xtra_dos_event(int v)
-{
- int i, k, s;
-
- bool mc = FALSE;
- bool ms = FALSE;
- bool ma = FALSE;
-
- /* Hack -- Check for a keypress */
- if (!v && !bioskey(1)) return (1);
-
- /* Wait for a keypress */
- k = bioskey(0x10);
-
- /* Access the "modifiers" */
- i = bioskey(2);
-
- /* Extract the "scan code" */
- s = ((k >> 8) & 0xFF);
-
- /* Extract the "ascii value" */
- k = (k & 0xFF);
-
- /* Process "normal" keys */
- if ((s <= 58) || (s == 0xE0))
- {
- /* Enqueue it */
- if (k) Term_keypress(k);
-
- /* Success */
- return (0);
- }
-
- /* Extract the modifier flags */
- if (i & (1 << K_CTRL)) mc = TRUE;
- if (i & (1 << K_LSHIFT)) ms = TRUE;
- if (i & (1 << K_RSHIFT)) ms = TRUE;
- if (i & (1 << K_ALT)) ma = TRUE;
-
- /* Dump the screen with "Ctrl-Print" */
- if ((s == 0x72) && mc)
- {
- /* Dump the screen */
- dos_dump_screen();
-
- /* Success */
- return (0);
- }
-
- /* Begin a "macro trigger" */
- Term_keypress(31);
-
- /* Hack -- Send the modifiers */
- if (mc) Term_keypress('C');
- if (ms) Term_keypress('S');
- if (ma) Term_keypress('A');
-
- /* Introduce the hexidecimal scan code */
- Term_keypress('x');
-
- /* Encode the hexidecimal scan code */
- Term_keypress(hexsym[s/16]);
- Term_keypress(hexsym[s%16]);
-
- /* End the "macro trigger" */
- Term_keypress(13);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * React to global changes in the colors, graphics, and sound settings.
- */
-static void Term_xtra_dos_react(void)
-{
- int i;
-
-#ifdef USE_SPECIAL_BACKGROUND
-
- int j;
-
- term_data *td;
-
-#endif /* USE_SPECIAL_BACKGROUND */
-
- /*
- * Set the Angband colors
- */
- for (i = 0; i < 16; i++)
- {
- /* Extract desired values */
- char rv = angband_color_table[i][1] >> 2;
- char gv = angband_color_table[i][2] >> 2;
- char bv = angband_color_table[i][3] >> 2;
-
- RGB color = { rv, gv, bv };
-
- set_color(COLOR_OFFSET + i, &color);
- }
-
-#ifdef USE_GRAPHICS
-
- /*
- * Handle "arg_graphics"
- */
- if (use_graphics != arg_graphics)
- {
- /* Initialize (if needed) */
- if (arg_graphics && !init_graphics())
- {
- /* Warning */
- plog("Cannot initialize graphics!");
-
- /* Cannot enable */
- arg_graphics = GRAPHICS_NONE;
- }
-
- /* Change setting */
- use_graphics = arg_graphics;
- }
-
-#endif /* USE_GRAPHICS */
-
-#ifdef USE_SOUND
-
- /*
- * Handle "arg_sound"
- */
- if (use_sound != arg_sound)
- {
- /* Clear the old song */
- if (midi_song) destroy_midi(midi_song);
- midi_song = NULL;
-
-#ifdef USE_MOD_FILES
- if (mod_file_initialized)
- {
- stop_mod();
- destroy_mod(mod_song);
- }
-#endif /* USE_MOD_FILES */
-
- /* Initialize (if needed) */
- if (arg_sound && !init_sound())
- {
- /* Warning */
- plog("Cannot initialize sound!");
-
- /* Cannot enable */
- arg_sound = FALSE;
- }
-
- /* Change setting */
- use_sound = arg_sound;
- }
-
-#endif /* USE_SOUND */
-
-#ifdef USE_SPECIAL_BACKGROUND
-
- /*
- * Initialize the window backgrounds
- */
- for (i = 0; i < 8; i++)
- {
- td = &data[i];
-
- /* Window flags */
- for (j = 0; j < 16; j++)
- {
- if (op_ptr->window_flag[i] & (1L << j))
- {
- if (background[j + 1])
- {
- td->window_type = j + 1;
- }
- else
- {
- td->window_type = 0;
- }
- }
- }
- }
-#endif /* USE_SPECIAL_BACKGROUND */
-}
-
-
-/*
- * Clear a terminal
- *
- * Fills the terminal area with black color or with
- * the background image
- */
-static void Term_xtra_dos_clear(void)
-{
- term_data *td = (term_data*)(Term->data);
-
-#ifdef USE_BACKGROUND
- int bgrnd;
-#endif /* USE_BACKGROUND */
-
- int x1, y1;
- int w1, h1;
-
- /* Location */
- x1 = td->x;
- y1 = td->y;
-
- /* Size */
- w1 = td->tile_wid * td->cols;
- h1 = td->tile_hgt * td->rows;
-
-#ifdef USE_BACKGROUND
-
- bgrnd = td->window_type;
-
- if (background[bgrnd])
- {
- /* Draw the background */
- stretch_blit(background[bgrnd], screen,
- 0, 0, background[bgrnd]->w, background[bgrnd]->h,
- x1, y1, w1, h1);
- }
- else
-
-#endif /* USE_BACKGROUND */
-
- {
- /* Draw the Term black */
- rectfill(screen,
- x1, y1, x1 + w1 - 1, y1 + h1 - 1,
- COLOR_OFFSET + TERM_DARK);
- }
-}
-
-
-/*
- * Handle a "special request"
- *
- * The given parameters are "valid".
- */
-static errr Term_xtra_dos(int n, int v)
-{
- /* Analyze the request */
- switch (n)
- {
- /* Make a "bell" noise */
- case TERM_XTRA_NOISE:
- {
- /* Make a bell noise */
- (void)write(1, "\007", 1);
-
- /* Success */
- return (0);
- }
-
- /* Clear the screen */
- case TERM_XTRA_CLEAR:
- {
- /* Clear the screen */
- Term_xtra_dos_clear();
-
- /* Success */
- return (0);
- }
-
- /* Process events */
- case TERM_XTRA_EVENT:
- {
- /* Process one event */
- return (Term_xtra_dos_event(v));
- }
-
- /* Flush events */
- case TERM_XTRA_FLUSH:
- {
- /* Strip events */
- while (!Term_xtra_dos_event(FALSE));
-
- /* Success */
- return (0);
- }
-
- /* Do something useful if bored */
- case TERM_XTRA_BORED:
- {
-#ifdef USE_SOUND
- /*
- * Check for end of song and start a new one
- */
- if (!use_sound) return (0);
-
-#ifdef USE_MOD_FILES
- if (song_number && (midi_pos == -1) && !is_mod_playing())
-#else /* USE_MOD_FILES */
- if (song_number && (midi_pos == -1))
-#endif /* USE_MOD_FILES */
- {
- if (song_number > 1)
- {
- /* Get a *new* song at random */
- while (1)
- {
- n = randint1(song_number);
- if (n != current_song) break;
- }
- current_song = n;
- }
- else
- {
- /* We only have one song, so loop it */
- current_song = 1;
- }
-
- /* Play the song */
- play_song();
- }
-
-#endif /* USE_SOUND */
-
- /* Success */
- return (0);
- }
-
- /* React to global changes */
- case TERM_XTRA_REACT:
- {
- /* Change the colors */
- Term_xtra_dos_react();
-
- /* Success */
- return (0);
- }
-
- /* Delay for some milliseconds */
- case TERM_XTRA_DELAY:
- {
- /* Delay if needed */
- if (v > 0) delay(v);
-
- /* Success */
- return (0);
- }
-
-#ifdef USE_SOUND
-
- /* Make a sound */
- case TERM_XTRA_SOUND:
- {
- return (Term_xtra_dos_sound(v));
- }
-
-#endif /* USE_SOUND */
-
- }
-
- /* Unknown request */
- return (1);
-}
-
-
-/*
- * Do a "user action" on the current "term"
- */
-static errr Term_user_dos(int n)
-{
- int k;
-
- char status[4];
-
- char section[80];
-
- /* Interact */
- while (1)
- {
- /* Clear screen */
- Term_clear();
-
- /* Print date and time of compilation */
- prt(format("Compiled: %s %s\n", __TIME__, __DATE__), 1, 45);
-
- /* Why are we here */
- prt("DOS options", 2, 0);
-
- /* Give some choices */
-#ifdef USE_SOUND
- prt("(V) Sound Volume", 4, 5);
- prt("(M) Music Volume", 5, 5);
-#endif /* USE_SOUND */
-
-#ifdef USE_GRAPHICS
-
- if (arg_graphics)
- {
- strcpy(status, "On");
- }
- else
- {
- strcpy(status, "Off");
- }
- prt(format("(G) Graphics : %s", status), 7, 5);
-
-#endif /* USE_GRAPHICS */
-
-#ifdef USE_SOUND
-
- if (arg_sound)
- {
- strcpy(status, "On");
- }
- else
- {
- strcpy(status, "Off");
- }
- prt(format("(S) Sound/Music : %s", status), 8, 5);
-
-#endif /* USE_SOUND */
-
- prt("(R) Screen resolution", 12, 5);
-
- prt("(W) Save current options", 14, 5);
-
- /* Prompt */
- prt("Command: ", 18, 0);
-
- /* Get command */
- k = inkey();
-
- /* Exit */
- if (k == ESCAPE) break;
-
- /* Analyze */
- switch (k)
- {
-#ifdef USE_SOUND
- /* Sound Volume */
- case 'V':
- case 'v':
- {
- /* Prompt */
- prt("Command: Sound Volume", 18, 0);
-
- /* Get a new value */
- while (1)
- {
- prt(format("Current Volume: %d", digi_volume), 22, 0);
- prt("Change Volume (+, - or ESC to accept): ", 20, 0);
- k = inkey();
- if (k == ESCAPE) break;
- switch (k)
- {
- case '+':
- {
- digi_volume++;
- if (digi_volume > 255) digi_volume = 255;
- break;
- }
- case '-':
- {
- digi_volume--;
- if (digi_volume < 0) digi_volume = 0;
- break;
- }
- /* Unknown option */
- default:
- {
- break;
- }
- }
- set_volume(digi_volume, -1);
- }
- break;
- }
-
- /* Music Volume */
- case 'M':
- case 'm':
- {
- /* Prompt */
- prt("Command: Music Volume", 18, 0);
-
- /* Get a new value */
- while (1)
- {
- prt(format("Current Volume: %d", midi_volume), 22, 0);
- prt("Change Volume (+, - or ESC to accept): ", 20, 0);
- k = inkey();
- if (k == ESCAPE) break;
- switch (k)
- {
- case '+':
- {
- midi_volume++;
- if (midi_volume > 255) midi_volume = 255;
- break;
- }
- case '-':
- {
- midi_volume--;
- if (midi_volume < 0) midi_volume = 0;
- break;
- }
- /* Unknown option */
- default:
- {
- break;
- }
- }
- set_volume(-1, midi_volume);
- }
- break;
- }
-
-#endif /* USE_SOUND */
-
-#ifdef USE_GRAPHICS
-
- /* Switch graphics on/off */
- case 'G':
- case 'g':
- {
- /* Toggle "arg_graphics" */
- arg_graphics = !arg_graphics;
-
- /* React to changes */
- Term_xtra_dos_react();
-
- /* Reset visuals */
-#ifdef ANGBAND_2_8_1
- reset_visuals();
-#else /* ANGBAND_2_8_1 */
- reset_visuals(TRUE);
-#endif /* ANGBAND_2_8_1 */
- break;
- }
-
-#endif /* USE_GRAPHICS */
-
-#ifdef USE_SOUND
-
- /* Sound/Music On/Off */
- case 'S':
- case 's':
- {
- /* Toggle "arg_sound" */
- arg_sound = !arg_sound;
-
- /* React to changes */
- Term_xtra_dos_react();
-
- break;
- }
-
-#endif /* USE_SOUND */
-
- /* Screen Resolution */
- case 'R':
- case 'r':
- {
- int h, w, i = 1;
- char *descr;
-
- /* Clear screen */
- Term_clear();
-
- /* Prompt */
- prt("Command: Screen Resolution", 1, 0);
- prt("Restart Angband to get the new screenmode.", 3, 0);
-
- /* Get a list of the available presets */
- while (1)
- {
- /* Section name */
- sprintf(section, "Mode-%d", i);
-
- /* Get new values or end the list */
- if (!(w = get_config_int(section, "screen_wid", 0)) || (i == 16)) break;
- h = get_config_int(section, "screen_hgt", 0);
-
- /* Get a extra description of the resolution */
- descr = get_config_string(section, "Description", "");
-
- /* Print it */
- prt(format("(%d) %d x %d %s", i, w, h, descr), 4 + i, 0);
-
- /* Next */
- i++;
- }
-
- /* Get a new resolution */
- prt(format("Screen Resolution : %d", resolution), 20, 0);
- k = inkey();
- if (k == ESCAPE) break;
- if (isdigit(k)) resolution = D2I(k);
-
- /* Check for min, max value */
- if ((resolution < 1) || (resolution >= i)) resolution = 1;
-
- /* Save the resolution */
- set_config_int("Angband", "Resolution", resolution);
-
- /* Return */
- break;
- }
-
-
- /* Save current option */
- case 'W':
- case 'w':
- {
- prt("Saving current options", 18, 0);
-
-#ifdef USE_SOUND
- set_config_int("sound", "digi_volume", digi_volume);
- set_config_int("sound", "midi_volume", midi_volume);
-#endif /* USE_SOUND */
- set_config_int("Angband", "Graphics", arg_graphics);
- set_config_int("Angband", "Sound", arg_sound);
-
- break;
- }
-
- /* Unknown option */
- default:
- {
- break;
- }
- }
-
- /* Flush messages */
- msg_print(NULL);
- }
-
- /* Redraw it */
- Term_key_push(KTRL('R'));
-
- /* Unknown */
- return (0);
-}
-
-
-/*
- * Move the cursor
- *
- * The given parameters are "valid".
- */
-static errr Term_curs_dos(int x, int y)
-{
- term_data *td = (term_data*)(Term->data);
-
- int x1, y1;
-
- /* Location */
- x1 = x * td->tile_wid + td->x;
- y1 = y * td->tile_hgt + td->y;
-
- /* Draw the cursor */
- draw_sprite(screen, cursor, x1, y1);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Erase a block of the screen
- *
- * The given parameters are "valid".
- */
-static errr Term_wipe_dos(int x, int y, int n)
-{
- term_data *td = (term_data*)(Term->data);
-
-#ifdef USE_BACKGROUND
- int bgrnd;
-#endif /* USE_BACKGROUND */
-
- int x1, y1;
- int w1, h1;
-
- /* Location */
- x1 = x * td->tile_wid + td->x;
- y1 = y * td->tile_hgt + td->y;
-
- /* Size */
- w1 = n * td->tile_wid;
- h1 = td->tile_hgt;
-
-#ifdef USE_BACKGROUND
-
- bgrnd = td->window_type;
-
- if (background[bgrnd])
- {
- int source_x = x * background[bgrnd]->w / td->cols;
- int source_y = y * background[bgrnd]->h / td->rows;
- int source_w = n * background[bgrnd]->w / td->cols;
- int source_h = background[bgrnd]->h / td->rows;
-
- /* Draw the background */
- stretch_blit(background[bgrnd], screen,
- source_x, source_y, source_w, source_h,
- x1, y1, w1, h1);
- }
- else
-
-#endif /* USE_BACKGROUND */
-
- {
- /* Draw a black block */
- rectfill(screen, x1, y1, x1 + w1 - 1, y1 + h1 - 1,
- COLOR_OFFSET + TERM_DARK);
- }
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Place some text on the screen using an attribute
- *
- * The given parameters are "valid". Be careful with "a".
- *
- * The string "cp" has length "n" and is NOT null-terminated.
- */
-static errr Term_text_dos(int x, int y, int n, byte a, const char *cp)
-{
- term_data *td = (term_data*)(Term->data);
-
- int i;
-
- int x1, y1;
-
- char text[257];
-
- /* Location */
- x1 = x * td->tile_wid + td->x;
- y1 = y * td->tile_hgt + td->y;
-
- /* Erase old contents */
- Term_wipe_dos(x, y, n);
-
-#ifdef USE_SPECIAL_BACKGROUND
-
- /* Show text in black in the message window */
- if (op_ptr->window_flag[td->number] & (PW_MESSAGE)) a = 0;
-
-#endif /* USE_SPECIAL_BACKGROUND */
-
- /* No stretch needed */
- if (td->font_wid == td->tile_wid)
- {
- /* Copy the string */
- for (i = 0; i < n; ++i) text[i] = cp[i];
-
- /* Terminate */
- text[i] = '\0';
-
- /* Dump the text */
- textout(screen, td->font, text, x1, y1,
- COLOR_OFFSET + (a & 0x0F));
- }
- /* Stretch needed */
- else
- {
- /* Pre-Terminate */
- text[1] = '\0';
-
- /* Write the chars to the screen */
- for (i = 0; i < n; ++i)
- {
- /* Build a one character string */
- text[0] = cp[i];
-
- /* Dump some text */
- textout(screen, td->font, text, x1, y1,
- COLOR_OFFSET + (a & 0x0F));
-
- /* Advance */
- x1 += td->tile_wid;
- }
- }
-
- /* Success */
- return (0);
-}
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * Place some attr/char pairs on the screen
- *
- * The given parameters are "valid".
- *
- * To prevent crashes, we must not only remove the high bits of the
- * "ap[i]" and "cp[i]" values, but we must map the resulting value
- * onto the legal bitmap size, which is normally 32x32. XXX XXX XXX
- */
-static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
-{
- term_data *td = (term_data*)(Term->data);
-
- int i;
-
- int w, h;
-
- int x1, y1;
- int x2, y2;
- int x3, y3;
-
- /* Size */
- w = td->tile_wid;
- h = td->tile_hgt;
-
- /* Location (window) */
- x1 = x * w + td->x;
- y1 = y * h + td->y;
-
- /* Dump the tiles */
- for (i = 0; i < n; i++)
- {
- /* Location (bitmap) */
- x2 = (cp[i] & 0x7F) * w;
- y2 = (ap[i] & 0x7F) * h;
-
- x3 = (tcp[i] & 0x7F) * w;
- y3 = (tap[i] & 0x7F) * h;
-
- /* Blit the tile to the screen */
- blit(td->tiles, screen, x3, y3, x1, y1, w, h);
-
- /* Blit the tile to the screen */
- masked_blit(td->tiles, screen, x2, y2, x1, y1, w, h);
-
- /* Advance (window) */
- x1 += w;
- }
-
- /* Success */
- return (0);
-}
-
-#endif /* USE_GRAPHICS */
-
-
-/*
- * Init a Term
- */
-static void Term_init_dos(term *t)
-{
- /* XXX Nothing */
-}
-
-
-/*
- * Nuke a Term
- */
-static void Term_nuke_dos(term *t)
-{
- term_data *td = (term_data*)(t->data);
-
- /* Free the terminal font */
- if (td->font) destroy_font(td->font);
-
-#ifdef USE_GRAPHICS
-
- /* Free the terminal bitmap */
- if (td->tiles) destroy_bitmap(td->tiles);
-
-#endif /* USE_GRAPHICS */
-}
-
-
-
-/*
- * Instantiate a "term_data" structure
- */
-static void term_data_link(term_data *td)
-{
- term *t = &td->t;
-
- /* Initialize the term */
- term_init(t, td->cols, td->rows, 255);
-
- /* Use a "software" cursor */
- t->soft_cursor = TRUE;
-
- /* Ignore the "TERM_XTRA_BORED" action */
- t->never_bored = FALSE;
-
- /* Ignore the "TERM_XTRA_FROSH" action */
- t->never_frosh = TRUE;
-
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
- /* Prepare the init/nuke hooks */
- t->init_hook = Term_init_dos;
- t->nuke_hook = Term_nuke_dos;
-
- /* Prepare the template hooks */
- t->xtra_hook = Term_xtra_dos;
- t->curs_hook = Term_curs_dos;
- t->wipe_hook = Term_wipe_dos;
- t->user_hook = Term_user_dos;
- t->text_hook = Term_text_dos;
-
-#ifdef USE_GRAPHICS
-
- /* Prepare the graphics hook */
- t->pict_hook = Term_pict_dos;
-
- /* Use "Term_pict" for "graphic" data */
- t->higher_pict = TRUE;
-
-#endif /* USE_GRAPHICS */
-
- /* Remember where we came from */
- t->data = (vptr)(td);
-}
-
-
-/*
- * Shut down visual system, then fall back into standard "quit()"
- */
-static void dos_quit_hook(concptr str)
-{
- int i;
-
- /* Destroy sub-windows */
- for (i = MAX_TERM_DATA - 1; i >= 1; i--)
- {
- /* Unused */
- if (!angband_term[i]) continue;
-
- /* Nuke it */
- term_nuke(angband_term[i]);
- }
-
-
- /* Free all resources */
- if (cursor) destroy_bitmap(cursor);
-
-#ifdef USE_BACKGROUND
-
- /* Free the background bitmaps */
- for (i = 0; i < 17; i++)
- {
- if (background[i]) destroy_bitmap(background[i]);
- }
-
-#endif /* USE_BACKGROUND */
-
-
-#ifdef USE_SOUND
-
- if (sound_initialized)
- {
- /* Destroy samples */
- for (i = 1; i < SOUND_MAX; i++)
- {
- int j;
-
- for (j = 0; j < sample_count[i]; j++)
- {
- if (samples[i][j]) destroy_sample(samples[i][j]);
- }
- }
- }
-
- /* Clear the old song */
- if (midi_song) destroy_midi(midi_song);
- midi_song =NULL;
-# ifdef USE_MOD_FILES
- if (mod_file_initialized)
- {
- stop_mod();
- destroy_mod(mod_song);
- }
-# endif /* USE_MOD_FILES */
-
-#endif /* USE_SOUND */
-
- /* Shut down Allegro */
- allegro_exit();
-}
-
-
-/*
- * Dump the screen to "lib/user/dump.bmp"
- */
-static void dos_dump_screen(void)
-{
- /* Bitmap and palette of the screen */
- BITMAP *bmp;
- PALETTE pal;
-
- /* Filename */
- char filename[1024];
-
- /* Get bitmap and palette of the screen */
- bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
- get_palette(pal);
-
- /* Build the filename for the screen-dump */
- path_build(filename, sizeof(filename), ANGBAND_DIR_USER, "dump.bmp");
-
- /* Save it */
- save_bmp(filename, bmp, pal);
-
- /* Free up the memory */
- if (bmp) destroy_bitmap(bmp);
-
- /* Success message */
- msg_print("Screen dump saved.");
- msg_print(NULL);
-}
-
-
-/* GRX font file reader by Mark Wodrich.
- *
- * GRX FNT files consist of the header data (see struct below). If the font
- * is proportional, followed by a table of widths per character (unsigned
- * shorts). Then, the data for each character follows. 1 bit/pixel is used,
- * with each line of the character stored in contiguous bytes. High bit of
- * first byte is leftmost pixel of line.
- *
- * Note : FNT files can have a variable number of characters, so we must
- * check that the chars 32..127 exist.
- */
-
-#define FONTMAGIC 0x19590214L
-
-
-/* .FNT file header */
-typedef struct
-{
- unsigned long magic;
- unsigned long bmpsize;
- unsigned short width;
- unsigned short height;
- unsigned short minchar;
- unsigned short maxchar;
- unsigned short isfixed;
- unsigned short reserved;
- unsigned short baseline;
- unsigned short undwidth;
- char fname[16];
- char family[16];
-} FNTfile_header;
-
-
-#define GRX_TMP_SIZE 4096
-
-
-
-/* converts images from bit to byte format */
-static void convert_grx_bitmap(int width, int height, unsigned char *src, unsigned char *dest)
-{
- unsigned short x, y, bytes_per_line;
- unsigned char bitpos, bitset;
-
- bytes_per_line = (width + 7) >> 3;
-
- for (y = 0; y < height; y++)
- {
- for (x = 0; x < width; x++)
- {
- bitpos = 7-(x&7);
- bitset = !!(src[(bytes_per_line * y) + (x >> 3)] & (1 << bitpos));
- dest[y * width + x] = bitset;
- }
- }
-}
-
-
-
-/* reads GRX format images from disk */
-static unsigned char **load_grx_bmps(PACKFILE *f, FNTfile_header *hdr, int numchar, unsigned short *wtable)
-{
- int t, width, bmp_size;
- unsigned char *temp;
- unsigned char **bmp;
-
- /* alloc array of bitmap pointers */
- bmp = malloc(sizeof(unsigned char *) * numchar);
-
- /* assume it's fixed width for now */
- width = hdr->width;
-
- /* temporary working area to store FNT bitmap */
- temp = malloc(GRX_TMP_SIZE);
-
- for (t = 0; t < numchar; t++)
- {
- /* if prop. get character width */
- if (!hdr->isfixed)
- width = wtable[t];
-
- /* work out how many bytes to read */
- bmp_size = ((width + 7) >> 3) * hdr->height;
-
- /* oops, out of space! */
- if (bmp_size > GRX_TMP_SIZE)
- {
- free(temp);
- for (t--; t >= 0; t--)
- free(bmp[t]);
- free(bmp);
- return NULL;
- }
-
- /* alloc space for converted bitmap */
- bmp[t] = malloc(width * hdr->height);
-
- /* read data */
- pack_fread(temp, bmp_size, f);
-
- /* convert to 1 byte/pixel */
- convert_grx_bitmap(width, hdr->height, temp, bmp[t]);
- }
-
- free(temp);
- return bmp;
-}
-
-
-
-/* main import routine for the GRX font format */
-static FONT *import_grx_font(char *fname)
-{
- PACKFILE *f;
- FNTfile_header hdr; /* GRX font header */
- int numchar; /* number of characters in the font */
- unsigned short *wtable = NULL; /* table of widths for each character */
- unsigned char **bmp; /* array of font bitmaps */
- FONT *font = NULL; /* the Allegro font */
- FONT_PROP *font_prop;
- int c, c2, start, width;
-
- f = pack_fopen(fname, F_READ);
- if (!f)
- return NULL;
-
- pack_fread(&hdr, sizeof(hdr), f); /* read the header structure */
-
- if (hdr.magic != FONTMAGIC) /* check magic number */
- {
- pack_fclose(f);
- return NULL;
- }
-
- numchar = hdr.maxchar - hdr.minchar + 1;
-
- if (!hdr.isfixed) /* proportional font */
- {
- wtable = malloc(sizeof(unsigned short) * numchar);
- pack_fread(wtable, sizeof(unsigned short) * numchar, f);
- }
-
- bmp = load_grx_bmps(f, &hdr, numchar, wtable);
- if (!bmp)
- goto get_out;
-
- if (pack_ferror(f))
- goto get_out;
-
- font = malloc(sizeof(FONT));
- font->height = -1;
- font->dat.dat_prop = font_prop = malloc(sizeof(FONT_PROP));
- font_prop->render = NULL;
-
- start = 32 - hdr.minchar;
- width = hdr.width;
-
- for (c = 0; c <FONT_SIZE; c++)
- {
- c2 = c+start;
-
- if ((c2 >= 0) && (c2 < numchar))
- {
- if (!hdr.isfixed)
- width = wtable[c2];
-
- font_prop->dat[c] = create_bitmap_ex(8, width, hdr.height);
- memcpy(font_prop->dat[c]->dat, bmp[c2], width * hdr.height);
- }
- else
- {
- font_prop->dat[c] = create_bitmap_ex(8, 8, hdr.height);
- clear(font_prop->dat[c]);
- }
- }
-
- get_out:
-
- pack_fclose(f);
-
- if (wtable)
- free(wtable);
-
- if (bmp)
- {
- for (c = 0; c < numchar; c++)
- free(bmp[c]);
-
- free(bmp);
- }
-
- return font;
-}
-
-
-/*
- * Initialize the terminal windows
- */
-static bool init_windows(void)
-{
- int i, num_windows;
-
- term_data *td;
-
- char section[80];
-
- char filename[1024];
-
- char buf[128];
-
- /* Section name */
- sprintf(section, "Mode-%d", resolution);
-
- /* Get number of windows */
- num_windows = get_config_int(section, "num_windows", 1);
-
- /* Paranoia */
- if (num_windows > 8) num_windows = 8;
-
- /* Init the terms */
- for (i = 0; i < num_windows; i++)
- {
- td = &data[i];
- WIPE(td, term_data);
-
- /* Section name */
- sprintf(section, "Term-%d-%d", resolution, i);
-
- /* Term number */
- td->number = i;
-
- /* Coordinates of left top corner */
- td->x = get_config_int(section, "x", 0);
- td->y = get_config_int(section, "y", 0);
-
- /* Rows and cols of term */
- td->rows = get_config_int(section, "rows", 24);
- td->cols = get_config_int(section, "cols", 80);
-
- /* Tile size */
- td->tile_wid = get_config_int(section, "tile_wid", 8);
- td->tile_hgt = get_config_int(section, "tile_hgt", 13);
-
- /* Font size */
- td->font_wid = get_config_int(section, "tile_wid", 8);
- td->font_hgt = get_config_int(section, "tile_hgt", 13);
-
- /* Get font filename */
- strcpy(buf, get_config_string(section, "font_file", "xm8x13.fnt"));
-
- /* Build the name of the font file */
- path_build(filename, sizeof(filename), xtra_font_dir, buf);
-
- /* Load a "*.fnt" file */
- if (suffix(filename, ".fnt"))
- {
- /* Load the font file */
- if (!(td->font = import_grx_font(filename)))
- {
- quit_fmt("Error reading font file '%s'", filename);
- }
- }
-
- /* Load a "*.dat" file */
- else if (suffix(filename, ".dat"))
- {
- DATAFILE *fontdata;
-
- /* Load the font file */
- if (!(fontdata = load_datafile(filename)))
- {
- quit_fmt("Error reading font file '%s'", filename);
- }
-
- /* Save the font data */
- td->font = fontdata[1].dat;
-
- /* Unload the font file */
- unload_datafile_object(fontdata);
- }
-
- /* Oops */
- else
- {
- quit_fmt("Unknown suffix in font file '%s'", filename);
- }
-
- /* Link the term */
- term_data_link(td);
- angband_term[i] = &td->t;
- }
-
- /* Success */
- return 0;
-}
-
-
-#ifdef USE_BACKGROUND
-
-/*
- * Initialize the window backgrounds
- */
-static void init_background(void)
-{
- int i;
-
- char filename[1024];
-
- char buf[128];
-
- PALLETE background_pallete;
-
- /* Get the backgrounds */
- for (i = 0; i < 16; i++)
- {
- /* Get background filename */
- strcpy(buf, get_config_string("Background", format("Background-%d", i), ""));
-
- /* Build the filename for the background-bitmap */
- path_build(filename, sizeof(filename), xtra_graf_dir, buf);
-
- /* Try to open the bitmap file */
- background[i] = load_bitmap(filename, background_pallete);
- }
-
-#ifndef USE_SPECIAL_BACKGROUND
- /*
- * Set the palette for the background
- */
- if (background[0])
- {
- set_palette_range(background_pallete, 0, COLOR_OFFSET - 1, 0);
- }
-#endif /* USE_SPECIAL_BACKGROUND */
-}
-
-#endif /* USE_BACKGROUND */
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * Initialize graphics
- */
-static bool init_graphics(void)
-{
- char filename[1024];
- char section[80];
- char name_tiles[128];
-
- /* Large bitmap for the tiles */
- BITMAP *tiles = NULL;
- PALLETE tiles_pallete;
-
- /* Size of each bitmap tile */
- int bitmap_wid;
- int bitmap_hgt;
-
- int num_windows;
-
- if (!graphics_initialized)
- {
- /* Section name */
- sprintf(section, "Mode-%d", resolution);
-
- /* Get bitmap tile size */
- bitmap_wid = get_config_int(section, "bitmap_wid", 8);
- bitmap_hgt = get_config_int(section, "bitmap_hgt", 8);
-
- /* Get bitmap filename */
- strcpy(name_tiles, get_config_string(section, "bitmap_file", "8x8.bmp"));
-
- /* Get number of windows */
- num_windows = get_config_int(section, "num_windows", 1);
-
- /* Build the name of the bitmap file */
- path_build(filename, sizeof(filename), xtra_graf_dir, name_tiles);
-
- /* Open the bitmap file */
- if ((tiles = load_bitmap(filename, tiles_pallete)) != NULL)
- {
- int i;
-
- /*
- * Set the graphics mode to "new" if Adam Bolt's
- * new 16x16 tiles are used.
- */
- ANGBAND_GRAF = get_config_string(section, "graf-mode", "old");
-
- /* Select the bitmap pallete */
- set_palette_range(tiles_pallete, 0, COLOR_OFFSET - 1, 0);
-
- /* Prepare the graphics */
- for (i = 0; i < num_windows; i++)
- {
- term_data *td;
-
- int col, row;
- int cols, rows;
- int width, height;
- int src_x, src_y;
- int tgt_x, tgt_y;
-
- td = &data[i];
-
- cols = tiles->w / bitmap_wid;
- rows = tiles->h / bitmap_hgt;
-
- width = td->tile_wid * cols;
- height = td->tile_hgt * rows;
-
- /* Initialize the tile graphics */
- td->tiles = create_bitmap(width, height);
-
- for (row = 0; row < rows; ++row)
- {
- src_y = row * bitmap_hgt;
- tgt_y = row * td->tile_hgt;
-
- for (col = 0; col < cols; ++col)
- {
- src_x = col * bitmap_wid;
- tgt_x = col * td->tile_wid;
-
- stretch_blit(tiles, td->tiles,
- src_x, src_y,
- bitmap_wid, bitmap_hgt,
- tgt_x, tgt_y,
- td->tile_wid, td->tile_hgt);
- }
- }
- }
-
- /* Free the old tiles bitmap */
- if (tiles) destroy_bitmap(tiles);
-
- graphics_initialized = TRUE;
-
- /* Success */
- return (TRUE);
- }
-
- /* Failure */
- return (FALSE);
- }
-
- /* Success */
- return (TRUE);
-}
-
-#endif /* USE_GRAPHICS */
-
-#ifdef USE_SOUND
-
-/*
- * Initialize sound
- * We try to get a list of the available sound-files from "lib/xtra/sound/sound.cfg"
- * and then preload the samples. Every Angband-sound-event can have several samples
- * assigned. Angband will randomly select which is played. This makes it easy to
- * create "sound-packs", just copy wav-files into the "lib/xtra/sound/" folder and
- * add the filenames to "sound.cfg" in the same folder.
- */
-static bool init_sound(void)
-{
- int i, j, done;
-
- char section[128];
- char filename[1024];
- char **argv;
-
- struct ffblk f;
-
- if (sound_initialized) return (TRUE);
-
- reserve_voices(16, -1);
-
- /* Initialize Allegro sound */
- if (!install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL))
- {
-#ifdef USE_MOD_FILES
- /*
- * Try to enable support for MOD-, and S3M-files
- * The parameter for install_mod() is the number
- * of channels reserved for the MOD/S3M-file.
- */
- if (install_mod(8) > 0) mod_file_initialized = TRUE;
-#endif /* USE_MOD_FILES */
-
- /* Access the new sample */
- path_build(filename, sizeof(filename), xtra_sound_dir, "sound.cfg");
-
- /* Read config info from "lib/xtra/sound/sound.cfg" */
- override_config_file(filename);
-
- /* Sound section */
- strcpy(section, "Sound");
-
- /* Prepare the sounds */
- for (i = 1; i < SOUND_MAX; i++)
- {
- /* Get the sample names */
- argv = get_config_argv(section, angband_sound_name[i], &sample_count[i]);
-
- /* Limit the number of samples */
- if (sample_count[i] > SAMPLE_MAX) sample_count[i] = SAMPLE_MAX;
-
- for (j = 0; j < sample_count[i]; j++)
- {
- /* Access the new sample */
- path_build(filename, sizeof(filename), xtra_sound_dir, argv[j]);
-
- /* Load the sample */
- samples[i][j] = load_sample(filename);
- }
- }
-
- /*
- * Get a list of music files
- */
-#ifdef USE_MOD_FILES
- if (mod_file_initialized)
- {
- done = findfirst(format("%s/*.*", xtra_music_dir), &f, FA_ARCH|FA_RDONLY);
- }
- else
-#endif /* USE_MOD_FILES */
- done = findfirst(format("%s/*.mid", xtra_music_dir), &f, FA_ARCH|FA_RDONLY);
-
-
- while (!done && (song_number <= MAX_SONGS))
- {
- /* Add music files */
- {
- strcpy(music_files[song_number], f.ff_name);
- song_number++;
- }
-
- done = findnext(&f);
- }
-
- /* Use "angdos.cfg" */
- override_config_file("angdos.cfg");
-
- /* Sound section */
- strcpy(section, "Sound");
-
- /* Get the volume setting */
- digi_volume = get_config_int(section, "digi_volume", 255);
- midi_volume = get_config_int(section, "midi_volume", 255);
-
- /* Set the volume */
- set_volume(digi_volume, midi_volume);
-
- /* Success */
- return (TRUE);
- }
-
- /* Init failed */
- return (FALSE);
-}
-
-
-/*
- * Make a sound
- */
-static errr Term_xtra_dos_sound(int v)
-{
- int n;
-
- /* Sound disabled */
- if (!use_sound) return (1);
-
- /* Illegal sound */
- if ((v < 0) || (v >= SOUND_MAX)) return (1);
-
- /* Get a random sample from the available ones */
- n = randint0(sample_count[v]);
-
- /* Play the sound, catch errors */
- if (samples[v][n])
- {
- return (play_sample(samples[v][n], 255, 128, 1000, 0) == 0);
- }
-
- /* Oops */
- return (1);
-}
-
-
-/*
- * Play a song-file
- */
-static void play_song(void)
-{
- char filename[256];
-
- /* Clear the old song */
- if (midi_song) destroy_midi(midi_song);
- midi_song = NULL;
-
-#ifdef USE_MOD_FILES
- if (mod_file_initialized)
- {
- stop_mod();
- destroy_mod(mod_song);
- }
-#endif /* USE_MOD_FILES */
-
- /* Access the new song */
- path_build(filename, sizeof(filename), xtra_music_dir, music_files[current_song - 1]);
-
- /* Load and play the new song */
- midi_song = load_midi(filename);
-
- if (midi_song)
- {
- play_midi(midi_song, 0);
- }
-#ifdef USE_MOD_FILES
- else if (mod_file_initialized)
- {
- mod_song = load_mod(filename);
-
- if (mod_song) play_mod(mod_song, FALSE);
- }
-#endif /* USE_MOD_FILES */
-}
-
-#endif /* USE_SOUND */
-
-
-/*
- * Attempt to initialize this file
- *
- * Hack -- we assume that "blank space" should be "white space"
- * (and not "black space" which might make more sense).
- *
- * Note the use of "((x << 2) | (x >> 4))" to "expand" a 6 bit value
- * into an 8 bit value, without losing much precision, by using the 2
- * most significant bits as the least significant bits in the new value.
- *
- * We should attempt to "share" bitmaps (and fonts) between windows
- * with the same "tile" size. XXX XXX XXX
- */
-errr init_dos(void)
-{
- term_data *td;
-
- char section[80];
-
- int screen_wid;
- int screen_hgt;
-
- /* Initialize the Allegro library (never fails) */
- (void)allegro_init();
-
- /* Install timer support for music and sound */
- install_timer();
-
- /* Read config info from filename */
- set_config_file("angdos.cfg");
-
- /* Main section */
- strcpy(section, "Angband");
-
- /* Get screen size */
- resolution = get_config_int(section, "Resolution", 1);
-
- /* Section name */
- sprintf(section, "Mode-%d", resolution);
-
- /* Get the screen dimensions */
- screen_wid = get_config_int(section, "screen_wid", 640);
- screen_hgt = get_config_int(section, "screen_hgt", 480);
-
- /* Set the color depth */
- set_color_depth(8);
-
- /* Auto-detect, and instantiate, the appropriate graphics mode */
- if ((set_gfx_mode(GFX_AUTODETECT, screen_wid, screen_hgt, 0, 0)) < 0)
- {
- /*
- * Requested graphics mode is not available
- * We retry with the basic 640x480 mode
- */
- resolution = 1;
-
- if ((set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0)) < 0)
- {
- char error_text[1024];
-
- /* Save the Allegro error description */
- strcpy(error_text, allegro_error);
-
- /* Shut down Allegro */
- allegro_exit();
-
- /* Print the error description */
- plog_fmt("Error selecting screen mode: %s", error_text);
-
- /* Failure */
- return (-1);
- }
- }
-
- /* Hook in "z-util.c" hook */
- quit_aux = dos_quit_hook;
-
- /* Build the "graf" path */
- path_build(xtra_graf_dir, sizeof(xtra_graf_dir), ANGBAND_DIR_XTRA, "graf");
-
- /* Build the "font" path */
- path_build(xtra_font_dir, sizeof(xtra_font_dir), ANGBAND_DIR_XTRA, "font");
-
- /* Build the "sound" path */
- path_build(xtra_sound_dir, sizeof(xtra_sound_dir), ANGBAND_DIR_XTRA, "sound");
-
- /* Build the "music" path */
- path_build(xtra_music_dir, sizeof(xtra_music_dir), ANGBAND_DIR_XTRA, "music");
-
- /* Initialize the windows */
- init_windows();
-
-#ifdef USE_SOUND
-
- /* Look for the sound preferences in "angdos.cfg" */
- if (!arg_sound)
- {
- arg_sound = get_config_int("Angband", "Sound", TRUE);
- }
-
-#endif /* USE_SOUND */
-
-#ifdef USE_GRAPHICS
-
- /* Look for the graphic preferences in "angdos.cfg" */
- if (!arg_graphics)
- {
- arg_graphics = get_config_int("Angband", "Graphics", GRAPHICS_ORIGINAL);
- }
-
-#endif /* USE_GRAPHICS */
-
- /* Initialize the "complex" RNG for the midi-shuffle function */
- Rand_quick = FALSE;
- Rand_state_init(time(NULL));
-
- /* Set the Angband colors/graphics/sound mode */
- Term_xtra_dos_react();
-
-#ifdef USE_BACKGROUND
-
- /* Initialize the background graphics */
- init_background();
-
-#endif /* USE_BACKGROUND */
-
- /* Clear the screen */
- clear_to_color(screen, COLOR_OFFSET + TERM_DARK);
-
- /* Main screen */
- td = &data[0];
-
- /* Build a cursor bitmap */
- cursor = create_bitmap(td->tile_wid, td->tile_hgt);
-
- /* Erase the cursor sprite */
- clear(cursor);
-
- /* Draw the cursor sprite (yellow rectangle) */
- rect(cursor, 0, 0, td->tile_wid - 1, td->tile_hgt - 1,
- COLOR_OFFSET + TERM_YELLOW);
-
- /* Activate the main term */
- Term_activate(angband_term[0]);
-
- /* Place the cursor */
- Term_curs_dos(0, 0);
-
-#ifdef USE_BACKGROUND
-
- /* Use transparent text */
- text_mode(-1);
-
-#endif /* USE_BACKGROUND */
-
- /* Success */
- return 0;
-}
-
-#endif /* USE_DOS */
-
+++ /dev/null
-/* File: main-ibm.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, and others
- *
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies.
- */
-
-/* Purpose: Visual Display Support for "term.c", for the IBM */
-
-
-/*
- * Original code by "Billy Tanksley (wtanksle@ucsd.edu)"
- * Use "Makefile.ibm" to compile Angband using this file.
- *
- * Support for DJGPP v2 by "Scott Egashira (egashira@u.washington.edu)"
- *
- * Extensive modifications by "Ben Harrison (benh@phial.com)",
- * including "collation" of the Watcom C/C++ and DOS-286 patches.
- *
- * Watcom C/C++ changes by "David Boeren (akemi@netcom.com)"
- * Use "Makefile.wat" to compile this file with Watcom C/C++, and
- * be sure to define "USE_IBM" and "USE_WAT".
- *
- * DOS-286 (conio.h) changes by (Roland Jay Roberts (jay@map.com)
- * Use "Makefile.286" (not ready) to compile this file for DOS-286,
- * and be sure to define "USE_IBM", "USE_WAT", and "USE_286". Also,
- * depending on your compiler, you may need to define "USE_CONIO".
- *
- * True color palette support by "Mike Marcelais (michmarc@microsoft.com)",
- * with interface to the "color_table" array by Ben Harrison.
- *
- * Both "shift" keys are treated as "identical", and all the modifier keys
- * (control, shift, alt) are ignored when used with "normal" keys, unless
- * they modify the underlying "ascii" value of the key. You must use the
- * new "user pref files" to be able to interact with the keypad and such.
- *
- * The "lib/user/pref-ibm.prf" file contains macro definitions and possible
- * alternative color set definitions. The "lib/user/font-ibm.prf" contains
- * attr/char mappings for walls and floors and such.
- *
- * Note the "Term_user_ibm()" function hook, which could allow the user
- * to interact with the "main-ibm.c" visual system. Currently this hook
- * is unused, but, for example, it could allow the user to toggle "sound"
- * or "graphics" modes, or to select the number of screen rows, with the
- * extra screen rows being used for the mirror window.
- */
-
-
-#include "angband.h"
-
-
-#ifdef USE_IBM
-
-#define USE_CONIO
-
-/*
- * Use a "virtual" screen to "buffer" screen writes.
- */
-#define USE_VIRTUAL
-
-
-#include <bios.h>
-#include <dos.h>
-
-#ifdef USE_WAT
-
-# include <conio.h>
-
-# ifdef USE_CONIO
-# else /* USE_CONIO */
-
-# include <graph.h>
-
-# define bioskey(C) _bios_keybrd(C)
-
-# endif /* USE_CONIO */
-
-# ifndef USE_286
-# define int86(a,b,c) int386(a,b,c)
-# endif
-
-# define inportb(x) inp(x)
-# define outportb(x,y) outp(x,y)
-
-#else /* USE_WAT */
-
-# if __DJGPP__ > 1
-
-# include <pc.h>
-# include <osfcn.h>
-
-# else /* __DJGPP__ > 1 */
-# ifdef __DJGPP__
-# error "Upgrade to version 2.0 of DJGPP"
-# endif /* __DJGPP__ */
-# endif /* __DJGPP__ > 1 */
-
-#endif /* USE_WAT */
-
-
-#ifdef USE_CONIO
-
-# include <conio.h>
-
-/*
- * Hack -- write directly to video card
- */
-/* extern int directvideo = 1; */
-
-/*
- * Hack -- no virtual screen
- */
-# undef USE_VIRTUAL
-
-#endif /* USE_CONIO */
-
-
-/*
- * Keypress input modifier flags (hard-coded by DOS)
- */
-#define K_RSHIFT 0 /* Right shift key down */
-#define K_LSHIFT 1 /* Left shift key down */
-#define K_CTRL 2 /* Ctrl key down */
-#define K_ALT 3 /* Alt key down */
-#define K_SCROLL 4 /* Scroll lock on */
-#define K_NUM 5 /* Num lock on */
-#define K_CAPS 6 /* Caps lock on */
-#define K_INSERT 7 /* Insert on */
-
-
-/*
- * Foreground color bits (hard-coded by DOS)
- */
-#define VID_BLACK 0x00
-#define VID_BLUE 0x01
-#define VID_GREEN 0x02
-#define VID_CYAN 0x03
-#define VID_RED 0x04
-#define VID_MAGENTA 0x05
-#define VID_YELLOW 0x06
-#define VID_WHITE 0x07
-
-/*
- * Bright text (hard-coded by DOS)
- */
-#define VID_BRIGHT 0x08
-
-/*
- * Background color bits (hard-coded by DOS)
- */
-#define VUD_BLACK 0x00
-#define VUD_BLUE 0x10
-#define VUD_GREEN 0x20
-#define VUD_CYAN 0x30
-#define VUD_RED 0x40
-#define VUD_MAGENTA 0x50
-#define VUD_YELLOW 0x60
-#define VUD_WHITE 0x70
-
-/*
- * Blinking text (hard-coded by DOS)
- */
-#define VUD_BRIGHT 0x80
-
-
-/*
- * Screen Size
- */
-static int rows = 25;
-static int cols = 80;
-
-
-/*
- * Physical Screen
- */
-#ifdef USE_286
-# define PhysicalScreen ((byte *)MK_FP(0xB800,0x0000))
-#else
-# define PhysicalScreen ((byte *)(0xB800 << 4))
-#endif
-
-
-#ifdef USE_VIRTUAL
-
-/*
- * Virtual Screen Contents
- */
-static byte *VirtualScreen;
-
-#else
-
-/*
- * Physical screen access
- */
-#define VirtualScreen PhysicalScreen
-
-#endif
-
-
-/*
- * Hack -- the cursor "visibility"
- */
-static int saved_cur_v;
-static int saved_cur_high;
-static int saved_cur_low;
-
-
-#ifdef USE_CONIO
-#else /* USE_CONIO */
-
-/*
- * This array is used for "wiping" the screen
- */
-static byte wiper[160];
-
-#endif /* USE_CONIO */
-
-
-/*
- * The main screen (currently the only screen)
- */
-static term term_screen_body;
-
-
-/*
- * Choose between the "complex" and "simple" color methods
- */
-static byte use_color_complex = FALSE;
-
-
-/*
- * The "complex" color set
- */
-static long ibm_color_complex[16];
-
-
-/*
- * The "simple" color set
- *
- * This table is used by the "color" code to instantiate the "approximate"
- * Angband colors using the only colors available on crappy monitors.
- *
- * The entries below are taken from the "color bits" defined above.
- *
- * Note that values from 16 to 255 are extremely ugly.
- *
- * The values below came from various sources, if you do not like them,
- * get a better monitor, or edit "pref-ibm.prf" to use different codes.
- *
- * Note that many of the choices below suck, but so do crappy monitors.
- */
-static byte ibm_color_simple[16] =
-{
- VID_BLACK, /* Dark */
- VID_WHITE, /* White */
- VID_CYAN, /* Slate XXX */
- VID_RED | VID_BRIGHT, /* Orange XXX */
- VID_RED, /* Red */
- VID_GREEN, /* Green */
- VID_BLUE, /* Blue */
- VID_YELLOW, /* Umber XXX */
- VID_BLACK | VID_BRIGHT, /* Light Dark */
- VID_CYAN | VID_BRIGHT, /* Light Slate XXX */
- VID_MAGENTA, /* Violet */
- VID_YELLOW | VID_BRIGHT, /* Yellow */
- VID_MAGENTA | VID_BRIGHT, /* Light Red XXX */
- VID_GREEN | VID_BRIGHT, /* Light Green */
- VID_BLUE | VID_BRIGHT, /* Light Blue */
- VID_YELLOW /* Light Umber XXX */
-};
-
-
-
-/*
- * Activate the "ibm_color_complex" palette information.
- *
- * Code by Mike Marcelais, with help from "The programmer's guide
- * to the EGA and VGA video cards" [Farraro].
- *
- * On VGA cards, colors go through a double-indirection when looking
- * up the `real' color when in 16 color mode. The color value in the
- * attribute is looked up in the EGA color registers. Then that value
- * is looked up in the VGA color registers. Then the color is displayed.
- * This is done for compatability. However, the EGA registers are
- * initialized by default to 0..5, 14, 7, 38..3F and not 0..F which means
- * that unless these are reset, the VGA setpalette function will not
- * update the correct palette register!
- *
- * DJGPP's GrSetColor() does _not_ set the EGA palette list, only the
- * VGA color list.
- *
- * Note that the "traditional" method, using "int86(0x10)", is very slow
- * when called in protected mode, so we use a faster method using video
- * ports instead.
- *
- * On Watcom machines, we could simply use the special "_remapallpalette()"
- * function, which not only sets both palette lists (see below) but also
- * checks for legality of the monitor mode, but, if we are doing bitmapped
- * graphics, that function forgets to set the EGA registers for some reason.
- */
-static void activate_color_complex(void)
-{
- int i;
- printf("%c%c%c%c",8,8,8,8);
-
-#if 1
-
- /* Edit the EGA palette */
- inportb(0x3da);
-
- /* Edit the colors */
- for (i = 0; i < 16; i++)
- {
- /* Set color "i" */
- outportb(0x3c0, i);
-
- /* To value "i" */
- outportb(0x3c0, i);
- };
-
- /* Use that EGA palette */
- outportb(0x3c0, 0x20);
-
- /* Edit VGA palette, starting at color zero */
- outportb(0x3c8, 0);
-
- /* Send the colors */
- for (i = 0; i < 16; i++)
- {
- /* Send the red, green, blue components */
- outportb(0x3c9, ((ibm_color_complex[i]) & 0xFF));
- outportb(0x3c9, ((ibm_color_complex[i] >> 8) & 0xFF));
- outportb(0x3c9, ((ibm_color_complex[i] >> 16) & 0xFF));
- }
-
-#else /* 1 */
-
- /* Set the colors */
- for (i = 0; i < 16; i++)
- {
- union REGS r;
-
- /* Set EGA color */
- r.h.ah = 0x10;
- r.h.al = 0x00;
-
- /* Set color "i" */
- r.h.bl = i;
-
- /* To value "i" */
- r.h.bh = i;
-
- /* Do it */
- int86(0x10, &r, &r);
-
- /* Set VGA color */
- r.h.ah = 0x10;
- r.h.al = 0x10;
-
- /* Set color "i" */
- r.h.bh = 0x00;
- r.h.bl = i;
-
- /* Use this "green" value */
- r.h.ch = ((ibm_color_complex[i] >> 8) & 0xFF);
-
- /* Use this "blue" value */
- r.h.cl = ((ibm_color_complex[i] >> 16) & 0xFF);
-
- /* Use this "red" value */
- r.h.dh = ((ibm_color_complex[i]) & 0xFF);
-
- /* Do it */
- int86(0x10, &r, &r);
- }
-
-#endif /* 1 */
-
-}
-
-
-/*
- * Note the use of "(x >> 2)" to convert an 8 bit value to a 6 bit value
- * without losing much precision.
- */
-static int Term_xtra_ibm_react(void)
-{
- int i;
-
- /* Complex method */
- if (use_color_complex)
- {
- long rv, gv, bv, code;
-
- bool change = FALSE;
-
- /* Save the default colors */
- for (i = 0; i < 16; i++)
- {
- /* Extract desired values */
- rv = angband_color_table[i][1] >> 2;
- gv = angband_color_table[i][2] >> 2;
- bv = angband_color_table[i][3] >> 2;
-
- /* Extract a full color code */
- code = ((rv) | (gv << 8) | (bv << 16));
-
- /* Activate changes */
- if (ibm_color_complex[i] != code)
- {
- /* Note the change */
- change = TRUE;
-
- /* Apply the desired color */
- ibm_color_complex[i] = code;
- }
- }
-
- /* Activate the palette if needed */
- if (change) activate_color_complex();
- }
-
- /* Simple method */
- else
- {
- /* Save the default colors */
- for (i = 0; i < 16; i++)
- {
- /* Simply accept the desired colors */
- ibm_color_simple[i] = angband_color_table[i][0];
- }
- }
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Hack -- set the cursor "visibility"
- */
-static void curs_set(int v)
-{
- /* If needed */
- if (saved_cur_v != v)
- {
- union REGS r;
-
- /* Set cursor */
- r.h.ah = 1;
-
- /* Visible */
- if (v)
- {
- /* Use the saved values */
- r.h.ch = saved_cur_high;
- r.h.cl = saved_cur_low;
- }
-
- /* Invisible */
- else
- {
- /* Make it invisible */
- r.h.ch = 0x20;
- r.h.cl = 0x00;
- }
-
- /* Make the call */
- int86(0x10, &r, &r);
-
- /* Save the cursor state */
- saved_cur_v = v;
- }
-}
-
-
-
-/*
- * Process an event (check for a keypress)
- *
- * The keypress processing code is often the most system dependant part
- * of Angband, since sometimes even the choice of compiler is important.
- *
- * For the IBM, we divide all keypresses into two catagories, first, the
- * "normal" keys, including all keys required to play Angband, and second,
- * the "special" keys, such as keypad keys, function keys, and various keys
- * used in combination with various modifier keys.
- *
- * To simplify this file, we use Angband's "macro processing" ability, in
- * combination with a specialized "pref-ibm.prf" file, to handle most of the
- * "special" keys, instead of attempting to fully analyze them here. This
- * file only has to determine when a "special" key has been pressed, and
- * translate it into a simple string which signals the use of a "special"
- * key, the set of modifiers used, if any, and the hardware scan code of
- * the actual key which was pressed. To simplify life for the user, we
- * treat both "shift" keys as identical modifiers.
- *
- * The final encoding is "^_MMMxSS\r", where "MMM" encodes the modifiers
- * ("C" for control, "S" for shift, "A" for alt, or any ordered combination),
- * and "SS" encodes the keypress (as the two "digit" hexidecimal encoding of
- * the scan code of the key that was pressed), and the "^_" and "x" and "\r"
- * delimit the encoding for recognition by the macro processing code.
- *
- * Some important facts about scan codes follow. All "normal" keys use
- * scan codes from 1-58. The "function" keys use 59-68 (and 133-134).
- * The "keypad" keys use 69-83. Escape uses 1. Enter uses 28. Control
- * uses 29. Left Shift uses 42. Right Shift uses 54. PrtScrn uses 55.
- * Alt uses 56. Space uses 57. CapsLock uses 58. NumLock uses 69.
- * ScrollLock uses 70. The "keypad" keys which use scan codes 71-83
- * are ordered KP7,KP8,KP9,KP-,KP4,KP5,KP6,KP+,KP1,KP2,KP3,INS,DEL.
- *
- * Using "bioskey(0x10)" instead of "bioskey(0)" apparently provides more
- * information, including better access to the keypad keys in combination
- * with various modifiers, but only works on "PC's after 6/1/86", and there
- * is no way to determine if the function is provided on a machine. I have
- * been told that without it you cannot detect, for example, control-left.
- * The basic scan code + ascii value pairs returned by the keypad follow,
- * with values in parentheses only available to "bioskey(0x10)".
- *
- * / * - + 1 2 3 4
- * Norm: 352f 372a 4a2d 4e2b 4f00 5000 5100 4b00
- * Shft: 352f 372a 4a2d 4e2b 4f31 5032 5133 4b34
- * Ctrl: (9500) (9600) (8e00) (9000) 7500 (9100) 7600 7300
- *
- * 5 6 7 8 9 0 . Enter
- * Norm: (4c00) 4d00 4700 4800 4900 5200 5300 (e00d)
- * Shft: 4c35 4d36 4737 4838 4939 5230 532e (e00d)
- * Ctrl: (8f00) 7400 7700 (8d00) 8400 (9200) (9300) (e00a)
- *
- * See "pref-ibm.prf" for the "standard" macros for various keys.
- *
- * Certain "bizarre" keypad keys (such as "enter") return a "scan code"
- * of "0xE0", and a "usable" ascii value. These keys should be treated
- * like the normal keys, see below. XXX XXX XXX Note that these "special"
- * keys could be prefixed with an optional "ctrl-^" which would allow them
- * to be used in macros without hurting their use in normal situations.
- */
-static errr Term_xtra_ibm_event(int v)
-{
- int i, k, s;
-
- bool mc = FALSE;
- bool ms = FALSE;
- bool ma = FALSE;
-
-
- /* Hack -- Check for a keypress */
- if (!v && !bioskey(1)) return (1);
-
- /* Wait for a keypress */
- k = bioskey(0x10);
-
- /* Access the "modifiers" */
- i = bioskey(2);
-
- /* Extract the "scan code" */
- s = ((k >> 8) & 0xFF);
-
- /* Extract the "ascii value" */
- k = (k & 0xFF);
-
- /* Process "normal" keys */
- if ((s <= 58) || (s == 0xE0))
- {
- /* Enqueue it */
- if (k) Term_keypress(k);
-
- /* Success */
- return (0);
- }
-
- /* Extract the modifier flags */
- if (i & (1 << K_CTRL)) mc = TRUE;
- if (i & (1 << K_LSHIFT)) ms = TRUE;
- if (i & (1 << K_RSHIFT)) ms = TRUE;
- if (i & (1 << K_ALT)) ma = TRUE;
-
-
- /* Begin a "macro trigger" */
- Term_keypress(31);
-
- /* Hack -- Send the modifiers */
- if (mc) Term_keypress('C');
- if (ms) Term_keypress('S');
- if (ma) Term_keypress('A');
-
- /* Introduce the hexidecimal scan code */
- Term_keypress('x');
-
- /* Encode the hexidecimal scan code */
- Term_keypress(hexsym[s/16]);
- Term_keypress(hexsym[s%16]);
-
- /* End the "macro trigger" */
- Term_keypress(13);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Handle a "special request"
- *
- * The given parameters are "valid".
- */
-static errr Term_xtra_ibm(int n, int v)
-{
- int i;
-
- /* Analyze the request */
- switch (n)
- {
- /* Make a "bell" noise */
- case TERM_XTRA_NOISE:
- {
- /* Make a bell noise */
- (void)write(1, "\007", 1);
-
- /* Success */
- return (0);
- }
-
- /* Set the cursor shape */
- case TERM_XTRA_SHAPE:
- {
- /* Set cursor shape */
- curs_set(v);
-
- /* Success */
- return (0);
- }
-
- /* Flush one line of output */
- case TERM_XTRA_FROSH:
- {
-
-#ifdef USE_VIRTUAL
-
-# ifdef USE_WAT
-
- /* Copy the virtual screen to the physical screen */
- memcpy(PhysicalScreen + (v*160), VirtualScreen + (v*160), 160);
-
-# else /* USE_WAT */
-
- /* Apply the virtual screen to the physical screen */
- ScreenUpdateLine(VirtualScreen + ((v*cols) << 1), v);
-
-# endif /* USE_WAT */
-
-#endif /* USE_VIRTUAL */
-
- /* Success */
- return (0);
- }
-
- /* Clear the screen */
- case TERM_XTRA_CLEAR:
- {
-
-#ifdef USE_CONIO
-
- /* Clear the screen */
- clrscr();
-
-#else /* USE_CONIO */
-
- /* Clear each line (virtual or physical) */
- for (i = 0; i < rows; i++)
- {
- /* Clear the line */
- memcpy((VirtualScreen + ((i*cols) << 1)), wiper, (cols << 1));
- }
-
-# ifdef USE_VIRTUAL
-
-# ifdef USE_WAT
-
- /* Copy the virtual screen to the physical screen */
- memcpy(PhysicalScreen, VirtualScreen, 25*80*2);
-
-# else /* USE_WAT */
-
- /* Erase the physical screen */
- ScreenClear();
-
-# endif /* USE_WAT */
-
-# endif /* USE_VIRTUAL */
-
-#endif /* USE_CONIO */
-
- /* Success */
- return (0);
- }
-
- /* Process events */
- case TERM_XTRA_EVENT:
- {
- /* Process one event */
- return (Term_xtra_ibm_event(v));
- }
-
- /* Flush events */
- case TERM_XTRA_FLUSH:
- {
- /* Strip events */
- while (!Term_xtra_ibm_event(FALSE)) /* loop */;
-
- /* Success */
- return (0);
- }
-
- /* React to global changes */
- case TERM_XTRA_REACT:
- {
- /* React to "color_table" changes */
- return (Term_xtra_ibm_react());
- }
-
- /* Delay for some milliseconds */
- case TERM_XTRA_DELAY:
- {
- /* Delay if needed */
- if (v > 0) delay(v);
-
- /* Success */
- return (0);
- }
- }
-
- /* Unknown request */
- return (1);
-}
-
-
-
-/*
- * Move the cursor
- *
- * The given parameters are "valid".
- */
-static errr Term_curs_ibm(int x, int y)
-{
-
-#ifdef USE_WAT
-
-# ifdef USE_CONIO
-
- /* Place the cursor */
- gotoxy(x+1, y+1);
-
-# else /* USE_CONIO */
-
- union REGS r;
-
- r.h.ah = 2;
- r.h.bh = 0;
- r.h.dl = x;
- r.h.dh = y;
-
- /* Place the cursor */
- int86(0x10, &r, &r);
-
-# endif /* USE_CONIO */
-
-#else /* USE_WAT */
-
- /* Move the cursor */
- ScreenSetCursor(y, x);
-
-#endif /* USE_WAT */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Erase a block of the screen
- *
- * The given parameters are "valid".
- */
-static errr Term_wipe_ibm(int x, int y, int n)
-{
-
-#ifdef USE_CONIO
-
- /* Wipe the region */
- window(x+1, y+1, x+n, y+1);
- clrscr();
- window(1, 1, cols, rows);
-
-#else /* USE_CONIO */
-
- /* Wipe part of the virtual (or physical) screen */
- memcpy(VirtualScreen + ((cols*y + x)<<1), wiper, n<<1);
-
-#endif /* USE_CONIO */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Place some text on the screen using an attribute
- *
- * The given parameters are "valid". Be careful with "a".
- *
- * The string "cp" has length "n" and is NOT null-terminated.
- */
-static errr Term_text_ibm(int x, int y, int n, byte a, const char *cp)
-{
- register int i;
- register byte attr;
- register byte *dest;
-
-
- /* Handle "complex" color */
- if (use_color_complex)
- {
- /* Extract a color index */
- attr = (a & 0x0F);
- }
-
- /* Handle "simple" color */
- else
- {
- /* Extract a color value */
- attr = ibm_color_simple[a & 0x0F];
- }
-
-#ifdef USE_CONIO
-
- /* Place the cursor */
- gotoxy(x+1, y+1);
-
- /* Set the attribute */
- textattr(attr);
-
-#ifdef JP
- /* Dump the text */
- for (i = 0; i < n; i++) {
- if (iskanji(cp[i])) {
- char jbuf[3];
- jbuf[0] = cp[i++];
- jbuf[1] = cp[i];
- jbuf[2] = '\0';
- cputs(jbuf);
- } else {
- putch(cp[i]);
- }
- }
-#else
- /* Dump the text */
- for (i = 0; i < n; i++) putch(cp[i]);
-#endif
-
-#else /* USE_CONIO */
-
- /* Access the virtual (or physical) screen */
- dest = VirtualScreen + (((cols * y) + x) << 1);
-
- /* Save the data */
- for (i = 0; i < n; i++)
- {
- /* Apply */
- *dest++ = cp[i];
- *dest++ = attr;
- }
-
-#endif /* USE_CONIO */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Place some attr/char pairs on the screen
- *
- * The given parameters are "valid".
- */
-static errr Term_pict_ibm(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp)
-{
- register int i;
- register byte attr;
- register byte *dest;
-
-
-#ifdef USE_CONIO
-
- /* Place the cursor */
- gotoxy(x+1, y+1);
-
- /* Dump the text */
- for (i = 0; i < n; i++)
- {
- /* Handle "complex" color */
- if (use_color_complex)
- {
- /* Extract a color index */
- attr = (ap[i] & 0x0F);
- }
-
- /* Handle "simple" color */
- else
- {
- /* Extract a color value */
- attr = ibm_color_simple[ap[i] & 0x0F];
- }
-
- /* Set the attribute */
- textattr(attr);
-
- /* Dump the char */
- putch(cp[i]);
- }
-
-#else /* USE_CONIO */
-
- /* Access the virtual (or physical) screen */
- dest = VirtualScreen + (((cols * y) + x) << 1);
-
- /* Save the data */
- for (i = 0; i < n; i++)
- {
- /* Handle "complex" color */
- if (use_color_complex)
- {
- /* Extract a color index */
- attr = (ap[i] & 0x0F);
- }
-
- /* Handle "simple" color */
- else
- {
- /* Extract a color value */
- attr = ibm_color_simple[ap[i] & 0x0F];
- }
-
- /* Apply */
- *dest++ = cp[i];
- *dest++ = attr;
- }
-
-#endif /* USE_CONIO */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Init a Term
- */
-static void Term_init_ibm(term *t)
-{
- /* XXX Nothing */
-}
-
-
-/*
- * Nuke a Term
- */
-static void Term_nuke_ibm(term *t)
-{
-
-#ifdef USE_WAT
-
- /* Nothing */
-
-#else /* USE_WAT */
-
- union REGS r;
-
-#endif /* USE_WAT */
-
- /* Move the cursor to the bottom of the screen */
- Term_curs_ibm(0, rows-1);
-
-#ifdef USE_WAT
-
- /* Restore the original video mode */
- _setvideomode(_DEFAULTMODE);
-
-#else /* USE_WAT */
-
- /* Restore the original video mode */
- r.h.ah = 0x00;
- r.h.al = 0x03;
- int86(0x10, &r, &r);
-
-#endif /* USE_WAT */
-
- /* Make the cursor visible */
- curs_set(1);
-}
-
-
-
-#ifdef USE_GRAPHICS
-
-#ifdef USE_286
-
-/*
- * In 286 mode we don't need to worry about translating from a 32bit
- * pointer to a 16 bit pointer so we just call the interrupt function
- *
- * Note the use of "intr()" instead of "int86()" so we can pass
- * segment registers.
- */
-void enable_graphic_font(void *font)
-{
- union REGPACK regs =
- {0};
-
- regs.h.ah = 0x11; /* Text font function */
- regs.h.bh = 0x10; /* Size of a character -- 16 bytes */
- regs.h.cl = 0xFF; /* Last character in font */
- regs.x.es = FP_SEG(font); /* Pointer to font */
- regs.x.bp = FP_OFF(font);
- intr(0x10, ®s);
-};
-
-#else /* USE_286 */
-
-#ifdef USE_WAT
-
-/*
- * This structure is used by the DMPI function to hold registers when
- * doing a real mode interrupt call. (Stolen from the DJGPP <dpmi.h>
- * header file).
- */
-
-typedef union
-{
- struct
- {
- unsigned long edi;
- unsigned long esi;
- unsigned long ebp;
- unsigned long res;
- unsigned long ebx;
- unsigned long edx;
- unsigned long ecx;
- unsigned long eax;
- } d;
- struct
- {
- unsigned short di, di_hi;
- unsigned short si, si_hi;
- unsigned short bp, bp_hi;
- unsigned short res, res_hi;
- unsigned short bx, bx_hi;
- unsigned short dx, dx_hi;
- unsigned short cx, cx_hi;
- unsigned short ax, ax_hi;
- unsigned short flags;
- unsigned short es;
- unsigned short ds;
- unsigned short fs;
- unsigned short gs;
- unsigned short ip;
- unsigned short cs;
- unsigned short sp;
- unsigned short ss;
- } x;
- struct
- {
- unsigned char edi[4];
- unsigned char esi[4];
- unsigned char ebp[4];
- unsigned char res[4];
- unsigned char bl, bh, ebx_b2, ebx_b3;
- unsigned char dl, dh, edx_b2, edx_b3;
- unsigned char cl, ch, ecx_b2, ecx_b3;
- unsigned char al, ah, eax_b2, eax_b3;
- } h;
-} __dpmi_regs;
-
-unsigned __dpmi_allocate_dos_memory(int size, unsigned *selector)
-{
- union REGPACK regs =
- {0};
-
- regs.w.ax = 0x100; /* DPMI function -- allocate low memory */
- regs.w.bx = size; /* Number of Paragraphs to allocate */
- intr(0x31, ®s); /* DPMI interface */
-
- *selector = regs.w.dx;
- return (regs.w.ax);
-};
-
-void __dpmi_free_dos_memory(unsigned sel)
-{
- union REGPACK regs =
- {0};
-
- regs.w.ax = 0x101; /* DPMI function -- free low memory */
- regs.x.edx = sel; /* PM selector for memory block */
- intr(0x31, ®s); /* DPMI interface */
-};
-
-void __dpmi_int(int intno, __dpmi_regs *dblock)
-{
- union REGPACK regs =
- {0};
-
- regs.w.ax = 0x300; /* DPMI function -- real mode interrupt */
- regs.h.bl = intno; /* interrupt 0x10 */
- regs.x.edi = FP_OFF(dblock); /* Pointer to dblock (offset and segment) */
- regs.x.es = FP_SEG(dblock);
- intr(0x31, ®s); /* DPMI interface */
-};
-
-unsigned short __dpmi_sel = 0x0000;
-#define _farsetsel(x) __dpmi_sel=(x)
-extern void _farnspokeb(unsigned long offset, unsigned char value);
-#pragma aux _farnspokeb = \
- "push fs" \
- "mov fs,__dpmi_sel" \
- "mov fs:[eax],bl" \
- "pop fs" \
- parm [eax] [bl];
-
-#else /* USE_WAT */
-
-#include <dpmi.h>
-#include <go32.h>
-#include <sys/farptr.h>
-
-#endif /* USE_WAT */
-
-
-/*
- * Since you cannot send 32bit pointers to a 16bit interrupt handler
- * and the video BIOS wants a (16bit) pointer to the font, we have
- * to allocate a block of dos memory, copy the font into it, then
- * translate a 32bit pointer into a 16bit pointer to that block.
- *
- * DPMI - Dos Protected Mode Interface provides functions that let
- * us do that.
- */
-void enable_graphic_font(const char *font)
-{
- __dpmi_regs dblock = {{0}};
-
- unsigned int seg, i;
- int sel;
-
- /*
- * Allocate a block of memory 4096 bytes big in `low memory' so a real
- * mode interrupt can access it. Real mode pointer is returned as seg:0
- * Protected mode pointer is sel:0.
- */
- seg = __dpmi_allocate_dos_memory(256, &sel);
-
- /* Copy the information into low memory buffer, by copying one byte at
- * a time. According to the info in <sys/farptr.h>, the functions
- * _farsetsel() and _farnspokeb() will optimise away completely
- */
- _farsetsel(sel); /* Set the selector to write to */
- for (i = 0; i<4096; i++)
- {
- _farnspokeb(i, *font++); /* Copy 1 byte into low (far) memory */
- }
-
- /*
- * Now we use DPMI as a jumper to call the real mode interrupt. This
- * is needed because loading `es' while in protected mode with a real
- * mode pointer will cause an Protection Fault and calling the interrupt
- * directly using the protected mode pointer will result in garbage
- * being received by the interrupt routine
- */
- dblock.d.eax = 0x1100; /* BIOS function -- set font */
- dblock.d.ebx = 0x1000; /* bh = size of a letter; bl = 0 (reserved) */
- dblock.d.ecx = 0x00FF; /* Last character in font */
- dblock.x.es = seg; /* Pointer to font segment */
- dblock.d.ebp = 0x0000; /* Pointer to font offset */
-
- __dpmi_int(0x10, &dblock);
-
- /* We're done with the low memory, free it */
- __dpmi_free_dos_memory(sel);
-}
-
-#endif /* USE_286 */
-
-#endif /* ALLOW_GRAPH */
-
-
-
-/*
- * Initialize the IBM "visual module"
- *
- * Hack -- we assume that "blank space" should be "white space"
- * (and not "black space" which might make more sense).
- *
- * Note the use of "((x << 2) | (x >> 4))" to "expand" a 6 bit value
- * into an 8 bit value, without losing much precision, by using the 2
- * most significant bits as the least significant bits in the new value.
- */
-errr init_ibm(void)
-{
- int i;
- int mode;
-
- term *t = &term_screen_body;
-
- union REGS r;
-
- /* Check for "Windows" */
- if (getenv("windir"))
- {
- r.h.ah = 0x16; /* Windows API Call -- Set device focus */
- r.h.al = 0x8B; /* Causes Dos boxes to become fullscreen */
- r.h.bh = r.h.bl = 0x00; /* 0x0000 = current Dos box */
- int86(0x2F, &r, &r); /* Call the Windows API */
- };
-
- /* Initialize "color_table" */
- for (i = 0; i < 16; i++)
- {
- long rv, gv, bv;
-
- /* Extract desired values */
- rv = angband_color_table[i][1] >> 2;
- gv = angband_color_table[i][2] >> 2;
- bv = angband_color_table[i][3] >> 2;
-
- /* Extract the "complex" codes */
- ibm_color_complex[i] = ((rv) | (gv << 8) | (bv << 16));
-
- /* Save the "simple" codes */
- angband_color_table[i][0] = ibm_color_simple[i];
- }
-
-#ifdef USE_WAT
-
- /* Set the video mode */
- if (_setvideomode(_VRES16COLOR))
- {
- mode = 0x13;
- }
-
- /* Wimpy monitor */
- else
- {
- mode = 0x03;
- }
-
- /* Force 25 line mode */
- _setvideomode(_TEXTC80);
- _settextrows(25);
-
-#else /* USE_WAT */
-
- /* Set video mode */
- r.h.ah = 0x00;
- r.h.al = 0x13; /* VGA only mode */
- int86(0x10, &r, &r);
-
- /* Get video mode */
- r.h.ah = 0x0F;
- int86(0x10, &r, &r);
- mode = r.h.al;
-
- /* Set video mode */
- r.h.ah = 0x00;
- r.h.al = 0x03; /* Color text mode */
- int86(0x10, &r, &r);
-
-#endif /* USE_WAT */
-
- /* Check video mode */
- if (mode == 0x13)
- {
- /* Remember the mode */
- use_color_complex = TRUE;
-
- /* Instantiate the color set */
- activate_color_complex();
- }
-
-#ifdef USE_GRAPHICS
-
- /* Try to activate bitmap graphics */
- if (arg_graphics && use_color_complex)
- {
- FILE *f;
-
- char buf[4096];
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, "angband.fnt");
-
- /* Open the file */
- f = fopen(buf, "rb");
-
- /* Okay */
- if (f)
- {
- /* Load the bitmap data */
- if (fread(buf, 1, 4096, f) != 4096)
- {
- quit("Corrupt 'angband.fnt' file");
- }
-
- /* Close the file */
- fclose(f);
-
- /* Enable graphics */
- enable_graphic_font(buf);
-
- /* Enable colors (again) */
- activate_color_complex();
-
- /* Use graphics */
- use_graphics = TRUE;
- }
- }
-
-#endif
-
-#ifdef USE_CONIO
-#else /* USE_CONIO */
-
- /* Build a "wiper line" */
- for (i = 0; i < 80; i++)
- {
- /* Space */
- wiper[2*i] = ' ';
-
- /* Black */
- wiper[2*i+1] = TERM_WHITE;
- }
-
-#endif /* USE_CONIO */
-
-
-#ifdef USE_VIRTUAL
-
- /* Make the virtual screen */
- C_MAKE(VirtualScreen, rows * cols * 2, byte);
-
-#endif /* USE_VIRTUAL */
-
-
- /* Erase the screen */
- Term_xtra_ibm(TERM_XTRA_CLEAR, 0);
-
-
- /* Place the cursor */
- Term_curs_ibm(0, 0);
-
-
- /* Access the "default" cursor info */
- r.h.ah = 3;
- r.h.bh = 0;
-
- /* Make the call */
- int86(0x10, &r, &r);
-
- /* Extract the standard cursor info */
- saved_cur_v = 1;
- saved_cur_high = r.h.ch;
- saved_cur_low = r.h.cl;
-
-
- /* Initialize the term */
- term_init(t, 80, 24, 256);
-
-#ifdef USE_CONIO
-#else /* USE_CONIO */
-
- /* Always use "Term_pict()" */
- t->always_pict = TRUE;
-
-#endif /* USE_CONIO */
-
- /* Use "white space" to erase */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
- /* Prepare the init/nuke hooks */
- t->init_hook = Term_init_ibm;
- t->nuke_hook = Term_nuke_ibm;
-
- /* Connect the hooks */
- t->xtra_hook = Term_xtra_ibm;
- t->curs_hook = Term_curs_ibm;
- t->wipe_hook = Term_wipe_ibm;
- t->text_hook = Term_text_ibm;
- t->pict_hook = Term_pict_ibm;
-
- /* Save it */
- term_screen = t;
-
- /* Activate it */
- Term_activate(term_screen);
-
- /* Success */
- return 0;
-}
-
-
-#endif /* USE_IBM */
-