summaryrefslogtreecommitdiff
path: root/src/main-dos.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main-dos.c')
-rw-r--r--src/main-dos.c2417
1 files changed, 2417 insertions, 0 deletions
diff --git a/src/main-dos.c b/src/main-dos.c
new file mode 100644
index 00000000..0a93cdc8
--- /dev/null
+++ b/src/main-dos.c
@@ -0,0 +1,2417 @@
+/* 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
+ *
+ * Comment by Eric Stevens (tome@eastevens.com):
+ *
+ * This file has been modified to work with Allegro 4.0.3 that comes with
+ * DJGPP 2.0.3. This modification allows ToME to use the .dat font files
+ * provided with the Angband release for DOS.
+ *
+ */
+
+#include "angband.h"
+
+
+#ifdef USE_DOS
+
+#include <allegro.h>
+
+#ifdef USE_MOD_FILES
+#include <jgmod.h>
+#endif /* USE_MOD_FILES */
+
+#include "load_gif.c"
+
+
+#include <bios.h>
+#include <dos.h>
+#include <keys.h>
+#include <unistd.h>
+#include <dir.h>
+
+/*
+ * ZAngband remapping for race and class in the enhanced bitmap
+ */
+/* #define PLAYER_REMAP */
+
+
+/*
+ * 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 the available videomodes to reduce executable size
+ */
+ /*
+DECLARE_GFX_DRIVER_LIS
+(
+ GFX_DRIVER_VBEAF
+ GFX_DRIVER_VESA2L
+ GFX_DRIVER_VESA2B
+ GFX_DRIVER_ATI
+ GFX_DRIVER_MACH64
+ GFX_DRIVER_CIRRUS64
+ GFX_DRIVER_CIRRUS54
+ GFX_DRIVER_PARADISE
+ GFX_DRIVER_S3
+ GFX_DRIVER_TRIDENT
+ GFX_DRIVER_ET3000
+ GFX_DRIVER_ET4000
+ GFX_DRIVER_VIDEO7
+ GFX_DRIVER_VESA1
+)
+*/
+
+/*
+ * Declare the videomode list
+ */
+//DECLARE_COLOR_DEPTH_LIST(COLOR_DEPTH_8)
+
+
+/*
+ * 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(cptr 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);
+# ifdef USE_TRANSPARENCY
+# ifdef USE_EGO_GRAPHICS
+static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp,
+ const byte *tap, const char *tcp, const byte *eap, const char *ecp);
+# else /* USE_EGO_GRAPHICS */
+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_EGO_GRAPHICS */
+# else /* USE_TRANSPARENCY */
+static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp);
+# endif /* USE_TRANSPARENCY */
+#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 categories, 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" hexadecimal 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);
+}
+
+
+#ifdef SUPPORT_GAMMA
+
+/*
+ * When set to TRUE, indicates that we can use gamma_table
+ */
+static bool gamma_table_ready = FALSE;
+
+
+/*
+ * Build gamma correction table if requested and applicable
+ */
+static void setup_gamma_table(void)
+{
+ static u16b old_gamma_val = 0;
+
+ /* (Re)build the table only when gamma value changes */
+ if (gamma_val == old_gamma_val) return;
+
+ /* Temporarily inactivate the table */
+ gamma_table_ready = FALSE;
+
+ /* Validate gamma_val */
+ if ((gamma_val <= 0) || (gamma_val >= 256))
+ {
+ /* Reset */
+ old_gamma_val = gamma_val = 0;
+
+ /* Leave it inactive */
+ return;
+ }
+
+ /* (Re)build the table */
+ build_gamma_table(gamma_val);
+
+ /* Remember gamma_val */
+ old_gamma_val = gamma_val;
+
+ /* Activate the table */
+ gamma_table_ready = TRUE;
+}
+
+#endif /* SUPPORT_GAMMA */
+
+
+/*
+ * 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 */
+
+
+#ifdef SUPPORT_GAMMA
+
+ /* Setup gamma_table */
+ setup_gamma_table();
+
+#endif /* SUPPORT_GAMMA */
+
+ /*
+ * Set the Angband colors
+ */
+ for (i = 0; i < 16; i++)
+ {
+ byte rv, gv, bv;
+ RGB colour;
+
+ /* Extract desired values */
+ rv = angband_color_table[i][1];
+ gv = angband_color_table[i][2];
+ bv = angband_color_table[i][3];
+
+#ifdef SUPPORT_GAMMA
+
+ /* Hack - Gamma correction */
+ if (gamma_table_ready)
+ {
+ rv = gamma_table[rv];
+ gv = gamma_table[gv];
+ bv = gamma_table[bv];
+ }
+
+#endif /* SUPPORT_GAMMA */
+
+ /* 8 bit to 6 bit conversion */
+ colour.r = rv >> 2;
+ colour.g = gv >> 2;
+ colour.b = bv >> 2;
+
+ set_color(COLOR_OFFSET + i, &colour);
+ }
+
+#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 = FALSE;
+ }
+
+ /* 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();
+ if (mod_song) destroy_mod(mod_song);
+ mod_song = NULL;
+ }
+#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:
+ {
+ irc_poll();
+
+ /* 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:
+ {
+ irc_poll();
+
+#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 = randint(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:
+ {
+ irc_poll();
+
+ /* 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 */
+
+ /*
+ * Scans for subdirectories in a directory "scansubdir_dir"
+ * and place teh result in "scansubdir_result/scansubdir_max"
+ */
+ case TERM_XTRA_SCANSUBDIR:
+ {
+ struct ffblk f;
+ int done;
+
+ done = findfirst(format("%s\\*", scansubdir_dir), &f, FA_DIREC);
+
+ scansubdir_max = 0;
+ while ((!done) && (scansubdir_max < 255))
+ {
+ if ((f.ff_attrib & FA_DIREC) && (strcmp(f.ff_name, ".")) && (strcmp(f.ff_name, "..")))
+ {
+ string_free(scansubdir_result[scansubdir_max]);
+ scansubdir_result[scansubdir_max] = string_make(f.ff_name);
+ scansubdir_max++;
+ }
+
+ done = findnext(&f);
+ }
+
+ return 0;
+ }
+
+ }
+
+ /* 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
+ */
+#ifdef USE_TRANSPARENCY
+# ifdef USE_EGO_GRAPHICS
+static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp,
+ const byte *tap, const char *tcp, const byte *eap, const char *ecp)
+# else /* USE_EGO_GRAPHICS */
+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_EGO_GRAPHICS */
+#else /* USE_TRANSPARENCY */
+static errr Term_pict_dos(int x, int y, int n, const byte *ap, const char *cp)
+#endif /* USE_TRANSPARENCY */
+{
+ term_data *td = (term_data*)(Term->data);
+
+ int i;
+
+ int w, h;
+
+ int x1, y1;
+ int x2, y2;
+
+# ifdef USE_TRANSPARENCY
+
+ int x3, y3;
+
+# ifdef USE_EGO_GRAPHICS
+
+ int x4, y4;
+ bool has_overlay;
+
+# endif /* USE_EGO_GRAPHICS */
+
+# endif /* USE_TRANSPARENCY */
+
+ /* 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;
+
+# ifdef USE_TRANSPARENCY
+ x3 = (tcp[i] & 0x7F) * w;
+ y3 = (tap[i] & 0x7F) * h;
+
+# ifdef EGO_GRAPHICS
+ x4 = (ecp[i] & 0x7F) * w;
+ y4 = (eap[i] & 0x7F) * h;
+ has_overlay = (ecp[i] && eap[i]);
+
+# endif /* EGO_GRAPHICS */
+
+ /* 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);
+
+# ifdef EGO_GRAPHICS
+
+ /* Blit the overlay to the screen */
+ if (has_overlay)
+ masked_blit(td->tiles, screen, x4, y4, x1, y1, w, h);
+
+# endif /* EGO_GRAPHICS */
+
+# else /* USE_TRANSPARENCY */
+
+ /* Blit the tile to the screen */
+ blit(td->tiles, screen, x2, y2, x1, y1, w, h);
+
+# endif /* USE_TRANSPARENCY */
+
+ /* 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(cptr 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();
+ if (mod_song) destroy_mod(mod_song);
+ mod_song = NULL;
+ }
+# 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, 1024, 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 that GRX FNT files can have a variable number of characters, so you
+ * must verify that any "necessary" characters exist before using them.
+ *
+ * The GRX FNT files were developed by ???.
+ */
+
+
+/*
+ * Magic value
+ */
+#define FONTMAGIC 0x19590214L
+
+
+/*
+ * Forward declare
+ */
+typedef struct FNTfile_header FNTfile_header;
+
+
+/*
+ * .FNT file header
+ */
+struct FNTfile_header
+{
+ 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];
+};
+
+
+/*
+ * A "bitmap" is simply an array of bytes
+ */
+typedef byte *GRX_BITMAP;
+
+
+/*
+ * Temporary space to store font bitmap
+ */
+#define GRX_TMP_SIZE 4096
+
+
+/*
+ * ???
+ */
+void convert_grx_bitmap(int width, int height, GRX_BITMAP src, GRX_BITMAP 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;
+ }
+ }
+}
+
+
+/*
+ * ???
+ */
+GRX_BITMAP *load_grx_bmps(PACKFILE *f, FNTfile_header *hdr,
+ int numchar, unsigned short *wtable)
+{
+ int t, width, bmp_size;
+ GRX_BITMAP temp;
+ GRX_BITMAP *bmp;
+
+ /* alloc array of bitmap pointers */
+ bmp = malloc(sizeof(GRX_BITMAP) * 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;
+}
+
+
+/*
+ * ???
+ */
+
+FONT* import_grx_font(char *fname)
+ {
+ return NULL;
+ }
+
+//FONT *import_grx_font(char *fname)
+//{
+// PACKFILE *f;
+//
+// /* GRX font header */
+// FNTfile_header hdr;
+//
+// /* number of characters in the font */
+// int numchar;
+//
+// /* table of widths for each character */
+// unsigned short *wtable = NULL;
+//
+// /* array of font bitmaps */
+// GRX_BITMAP *bmp;
+//
+// /* the Allegro font */
+// FONT *font = NULL;
+//
+// FONT_PROP *font_prop;
+// int c, c2, start, width;
+//
+//
+// f = pack_fopen(fname, F_READ);
+//
+// if (!f) return NULL;
+//
+// /* read the header structure */
+// pack_fread(&hdr, sizeof(hdr), f);
+//
+// /* check magic number */
+// if (hdr.magic != FONTMAGIC)
+// {
+// pack_fclose(f);
+// return NULL;
+// }
+//
+// numchar = hdr.maxchar - hdr.minchar + 1;
+//
+// /* proportional font */
+// if (!hdr.isfixed)
+// {
+// 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));
+//
+// 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, 1024, 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, 1024, 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, 1024, 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);
+
+ /* 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(16) > 0) mod_file_initialized = TRUE;
+#endif /* USE_MOD_FILES */
+
+ /* Access the new sample */
+ path_build(filename, 1024, 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 + 1; 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, 1024, 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 = rand_int(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();
+ if (mod_song) destroy_mod(mod_song);
+ mod_song = NULL;
+ }
+#endif /* USE_MOD_FILES */
+
+ /* Access the new song */
+ path_build(filename, 1024, xtra_music_dir, music_files[current_song - 1]);
+
+ /* Load and play the new song */
+ if ((midi_song = load_midi(filename))) play_midi(midi_song, 0);
+#ifdef USE_MOD_FILES
+ else if (mod_file_initialized)
+ {
+ if ((mod_song = load_mod(filename))) 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();
+
+ /* Enable the gif-loading function */
+ register_bitmap_file_type("GIF", load_gif , NULL);
+
+ /* 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, 1024, ANGBAND_DIR_XTRA, "graf");
+
+ /* Build the "font" path */
+ path_build(xtra_font_dir, 1024, ANGBAND_DIR_XTRA, "font");
+
+ /* Build the "sound" path */
+ path_build(xtra_sound_dir, 1024, ANGBAND_DIR_XTRA, "sound");
+
+ /* Build the "music" path */
+ path_build(xtra_music_dir, 1024, 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", TRUE);
+ }
+
+#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 */