/* 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 #ifdef USE_MOD_FILES #include #endif /* USE_MOD_FILES */ #include "load_gif.c" #include #include #include #include #include /* * 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 */