From 6aa48afdd57d03314fdf4be6c9da911c32277c84 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jan 2010 20:28:34 +0100 Subject: Import tome-2.3.5. --- src/main-ami.c | 3250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3250 insertions(+) create mode 100644 src/main-ami.c (limited to 'src/main-ami.c') diff --git a/src/main-ami.c b/src/main-ami.c new file mode 100644 index 00000000..da267b53 --- /dev/null +++ b/src/main-ami.c @@ -0,0 +1,3250 @@ +/* + + File: main-ami.c + + Version: 2.7.9v6 (09.May.96) + + Purpose: Amiga module for Angband with graphics and sound + + Author: Lars Haugseth + Email: larshau@ifi.uio.no + WWW: http://www.ifi.uio.no/~larshau + +*/ + +#define VERSION "Angband 2.7.9v6" + +///{ "includes" + +#include "angband.h" +#include "sound-ami.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///} +///{ "macros" + +/* Pen number convertion */ +#define PEN( p ) ( penconv[ p ] ) + +/* Graphics pen number convertion */ +#define GPEN( p ) ( use_pub ? pubpens[ p ] : p ) + +/* Failure */ +#define FAIL( str ) return ( amiga_fail( str )) + +/* Message */ +#define MSG( x, y, txt ) amiga_text( x, y, strlen( txt ), 1, txt ); + +/* Char and attr under cursor */ +#define CUR_A ( td->t.scr->a[ td->cursor_ypos ][ td->cursor_xpos ] ) +#define CUR_C ( td->t.scr->c[ td->cursor_ypos ][ td->cursor_xpos ] ) + +///} +///{ "defines" + +/* Color to use for cursor */ +#define CURSOR_PEN 4 + +/* Size of graphical tile */ +#define TILEW 8 +#define TILEH 8 + +/* Size of tile image */ +#define GFXW 256 +#define GFXH 256 +#define GFXB 32 + +/* Size of tombstone image */ +#define TOMW 512 +#define TOMH 168 +#define TOMB 64 + +/* Filename of tile image */ +#define MGFX "Angband:xtra/gfx/tiles.raw" + +/* Filename of tombstone image */ +#define MTOM "Angband:xtra/gfx/tomb.raw" + +/* Filename of preferences file */ +#define WPRF "Angband:user/settings.prf" + +///} +///{ "globals" + +/* DisplayID specified with option -m */ +char modestr[ 256 ] = ""; + +/* Font specified with option -f */ +char fontstr[ 32 ] = ""; + +/* Library bases */ +struct Library *DiskfontBase = NULL; +struct Library *KeymapBase = NULL; +struct Library *GadToolsBase = NULL; + +/* Term data structure */ +typedef struct term_data +{ + term t; /* Term structure */ + cptr name; /* Name string */ + + BYTE use; /* Use this window */ + + BYTE cols; /* Number of columns */ + BYTE rows; /* Number of rows */ + + UWORD wx; /* Window x-pos */ + UWORD wy; /* Window y-pos */ + UWORD ww; /* Window width */ + UWORD wh; /* Window height */ + + BYTE fw; /* Font width */ + BYTE fh; /* Font height */ + BYTE fb; /* Font baseline */ + + struct TextFont *font; /* Font pointers */ + + BYTE ownf; /* Font is owned by this term */ + + struct Window *win; /* Window pointer */ + struct RastPort *wrp; /* RastPort of window */ + struct RastPort *rp; /* RastPort of screen or window */ + + struct BitMap *gfxbm; + struct BitMap *mapbm; + struct BitMap *mskbm; + + int gfx_w; + int gfx_h; + + int map_w; + int map_h; + int map_x; + int map_y; + + int mpt_w; + int mpt_h; + + int cursor_xpos; + int cursor_ypos; + int cursor_visible; + int cursor_lit; + int cursor_frame; + int cursor_map; + + int notitle; + int avoidbar; +} +term_data; + +/* Term data for all windows */ +static term_data screen; +static term_data mirror; +static term_data recall; +static term_data choice; + +/* Window names */ +static char screen_name[] = "Main"; +static char choice_name[] = "Choice"; +static char recall_name[] = "Recall"; +static char mirror_name[] = "Mirror"; + +/* Screen pointers */ +static struct Screen *amiscr = NULL; +static struct Screen *pubscr = NULL; + +/* Visual info for gadtools menus */ +static APTR *visinfo; + +/* TextAttr for screen font */ +static struct TextAttr ScrAttr, *scrattr = &ScrAttr; + +/* Screen DisplayID */ +static ULONG scr_m = 0; + +/* Last term for cursor */ +static term_data *term_curs = NULL; + +/* Temporary string */ +static char tmpstr[ 256 ]; + +/* Iconify status of windows */ +static int iconified = FALSE; + +/* Use intuition menus? */ +static int use_menus = TRUE; + +/* Use mouseblanking? */ +static int blankmouse = FALSE; + +/* Window input event */ +static struct InputEvent ie; + +/* KickStart 3.0+ present */ +static int v39 = FALSE; + +/* Use a public screen */ +static int use_pub = FALSE; + +/* Public screen lock */ +static int publock = FALSE; + +/* Use a backdrop main window */ +static int backdrop = FALSE; + +/* Use 32 colors on custom screen */ +static int deep = FALSE; + +/* Invisible pointer for blanking */ +static __chip UWORD blankpointer[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* Pointer visibility status */ +static int pointer_visible = TRUE; + +/* Convert textual pens to screen pens */ +static UWORD penconv[ 16 ] = +{ + 0, 1, 2, 4, 11, 15, 9, 6, 3, 1, 13, 4, 11, 15, 8, 5 +}; + +/* Public screen obtained pens */ +static LONG pubpens[ 32 ] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/* Default color palette, 16 for graphics, 16 for text */ +static ULONG default_colors[ 32 ] = +{ + 0x000000, 0xf0e0d0, 0x808080, 0x505050, + 0xe0b000, 0xc0a070, 0x806040, 0x403020, + 0x00a0f0, 0x0000f0, 0x000070, 0xf00000, + 0x800000, 0x9000b0, 0x006010, 0x60f040, + + 0x000000, 0xffffff, 0xc7c7c7, 0xff9200, + 0xff0000, 0x00cd00, 0x0000fe, 0xc86400, + 0x8a8a8a, 0xe0e0e0, 0xa500ff, 0xfffd00, + 0xff00bc, 0x00ff00, 0x00c8ff, 0xffcc80 +}; + +/* Palette, 32 bits per gun */ +static ULONG palette32[ 32 * 3 + 2 ]; + +/* Palette, 4 bits per gun */ +static UWORD palette4[ 32 ]; + +/* Version string */ +static char ver[] = "$VER: " VERSION " (" __DATE__ ")"; + +///} +///{ "sound" + +#define NSAMPLES 25 + +struct AmiSound +{ + char *Name; + int Volume; + int Channel; + int Rate; + int Repeats; + int Memory; + struct SoundInfo *Address; +}; + +static struct AmiSound sound_data[ NSAMPLES ] = +{ + { "intro.8svx", 64, 0, 0, 1, 0, NULL }, /* Intro */ + { "hit.8svx", 64, 0, 0, 1, 1, NULL }, /* Hit */ + { "miss.8svx", 64, 3, 0, 1, 1, NULL }, /* Miss */ + { "flee.8svx", 64, 1, 0, 1, 1, NULL }, /* Flee */ + { "drop.8svx", 64, 2, 0, 1, 1, NULL }, /* Drop */ + { "kill.8svx", 64, 1, 0, 1, 1, NULL }, /* Kill */ + { "study.8svx", 64, 2, 0, 1, 1, NULL }, /* Level */ + { "death.8svx", 64, 0, 0, 1, 0, NULL }, /* Death */ + { "study.8svx", 64, 2, 0, 1, 1, NULL }, /* Study */ + { "teleport.8svx", 64, 3, 0, 1, 1, NULL }, /* Teleport */ + { "shoot.8svx", 64, 0, 0, 1, 1, NULL }, /* Shoot */ + { "quaff.8svx", 64, 1, 0, 1, 1, NULL }, /* Quaff */ + { "zap.8svx", 64, 3, 0, 1, 1, NULL }, /* Zap */ + { "walk.8svx", 64, 0, 0, 1, 1, NULL }, /* Walk */ + { "tpother.8svx", 64, 3, 0, 1, 1, NULL }, /* Teleport Other */ + { "hitwall.8svx", 64, 3, 0, 1, 1, NULL }, /* Hit Wall */ + { "eat.8svx", 64, 3, 0, 1, 1, NULL }, /* Eat */ + { "store1.8svx", 64, 0, 0, 1, 0, NULL }, /* Shopkeeper furious */ + { "store2.8svx", 64, 0, 0, 1, 0, NULL }, /* Shopkeeper angry */ + { "store3.8svx", 64, 0, 0, 1, 0, NULL }, /* Shopkeeper glad */ + { "store4.8svx", 64, 0, 0, 1, 0, NULL }, /* Shopkeeper happy */ + { "dig.8svx", 64, 0, 0, 1, 1, NULL }, /* Dig */ + { "opendoor.8svx", 64, 0, 0, 1, 1, NULL }, /* Open door */ + { "closedoor.8svx", 64, 0, 0, 1, 1, NULL }, /* Close door */ + { "tplevel.8svx", 64, 0, 0, 1, 0, NULL }, /* Teleport level */ +}; + +static int channel_last[ 4 ] = { -1, -1, -1, -1 }; + +static int has_sound = FALSE; + +///} +///{ "menus" + +#define MENUMAX 256 + +/* Menu userdata indexes */ +#define MNU_SCALEDMAP 1001 + +/* Special offset indexes */ +#define MNU_KEYCOM 2001 +#define MNU_CKEYCOM 3001 +#define MNU_OPTION 4001 +#define MNU_HELP 5001 + +/* Macro for menu userdata keycodes and help */ +#define MKC( c ) (void *)( MNU_KEYCOM + c ) +#define MCC( c ) (void *)( MNU_CKEYCOM + c ) +#define MHL( c ) (void *)( MNU_HELP + c ) + +struct Menu *menu = NULL; + +/* Menu items that comes before the options */ +struct NewMenu pre_item[] = +{ + { NM_TITLE, "Options", 0, 0, 0, 0}, + { 255, 0, 0, 0, 0, 0 } +}; + +/* Option menu items, titles of submenus */ +struct NewMenu opt_item[] = +{ + { NM_ITEM, "User Interface", 0, 0, 0, 0 }, + { NM_ITEM, "Disturbance", 0, 0, 0, 0 }, + { NM_ITEM, "Inventory", 0, 0, 0, 0 }, + { NM_ITEM, "Game-Play", 0, 0, 0, 0 }, + { NM_ITEM, "Efficiency", 0, 0, 0, 0 }, + { NM_ITEM, "Special", 0, 0, 0, 0 }, + { NM_ITEM, "Cheating", 0, 0, 0, 0 }, + { 255, 0, 0, 0, 0, 0 } +}; + +/* Menu items that comes after the options */ +struct NewMenu post_item[] = +{ + /* + { NM_ITEM, "Hitpoint Warning", 0, 0, 0, 0 }, + { NM_SUB, "90%", 0, CHECKIT, ~1, 0 }, + { NM_SUB, "80%", 0, CHECKIT, ~2, 0 }, + { NM_SUB, "70%", 0, CHECKIT, ~4, 0 }, + { NM_SUB, "60%", 0, CHECKIT, ~8, 0 }, + { NM_SUB, "50%", 0, CHECKIT, ~16, 0 }, + { NM_SUB, "40%", 0, CHECKIT, ~32, 0 }, + { NM_SUB, "30%", 0, CHECKIT, ~64, 0 }, + { NM_SUB, "20%", 0, CHECKIT, ~128, 0 }, + { NM_SUB, "10%", 0, CHECKIT, ~256, 0 }, + { NM_SUB, "Off", 0, CHECKIT, ~512, 0 }, + */ + + { NM_TITLE, "Cmd1", 0, 0, 0, 0 }, + { NM_ITEM, "a Aim a wand", 0, 0, 0, MKC('a') }, + { NM_ITEM, "b Browse a book", 0, 0, 0, MKC('b') }, + { NM_ITEM, "c Close a door", 0, 0, 0, MKC('c') }, + { NM_ITEM, "d Drop an item", 0, 0, 0, MKC('d') }, + { NM_ITEM, "e Equipment list", 0, 0, 0, MKC('e') }, + { NM_ITEM, "f Fire an item", 0, 0, 0, MKC('f') }, + { NM_ITEM, "g Stay still", 0, 0, 0, MKC('g') }, + { NM_ITEM, "i Inventory list", 0, 0, 0, MKC('i') }, + { NM_ITEM, "j Jam a door", 0, 0, 0, MKC('j') }, + { NM_ITEM, "k Destroy an item", 0, 0, 0, MKC('k') }, + { NM_ITEM, "l Look around", 0, 0, 0, MKC('l') }, + + { NM_TITLE, "Cmd2", 0, 0, 0, 0 }, + { NM_ITEM, "m Cast a spell", 0, 0, 0, MKC('m') }, + { NM_ITEM, "o Open a door or chest", 0, 0, 0, MKC('o') }, + { NM_ITEM, "p Pray a prayer", 0, 0, 0, MKC('p') }, + { NM_ITEM, "q Quaff a potion", 0, 0, 0, MKC('q') }, + { NM_ITEM, "r Read a scroll", 0, 0, 0, MKC('r') }, + { NM_ITEM, "s Search for traps/doors", 0, 0, 0, MKC('s') }, + { NM_ITEM, "t Take off equipment", 0, 0, 0, MKC('t') }, + { NM_ITEM, "u Use a staff", 0, 0, 0, MKC('u') }, + { NM_ITEM, "v Throw an item", 0, 0, 0, MKC('v') }, + { NM_ITEM, "w Wear/wield equipment", 0, 0, 0, MKC('w') }, + { NM_ITEM, "z Zap a rod", 0, 0, 0, MKC('z') }, + + { NM_TITLE, "Cmd3", 0, 0, 0, 0 }, + { NM_ITEM, "A Activate an artifact", 0, 0, 0, MKC('A') }, + { NM_ITEM, "B Bash a door", 0, 0, 0, MKC('B') }, + { NM_ITEM, "C Character description", 0, 0, 0, MKC('C') }, + { NM_ITEM, "D Disarm a trap", 0, 0, 0, MKC('D') }, + { NM_ITEM, "E Eat some food", 0, 0, 0, MKC('E') }, + { NM_ITEM, "F Fuel your lantern/torch", 0, 0, 0, MKC('F') }, + { NM_ITEM, "G Gain new spells/prayers", 0, 0, 0, MKC('G') }, + { NM_ITEM, "I Observe an item", 0, 0, 0, MKC('I') }, + { NM_ITEM, "L Locate player on map", 0, 0, 0, MKC('L') }, + { NM_ITEM, "M Full dungeon map", 0, 0, 0, MKC('M') }, + { NM_ITEM, "Q Quit (commit suicide)", 0, 0, 0, MKC('Q') }, + { NM_ITEM, "R Rest for a period", 0, 0, 0, MKC('R') }, + { NM_ITEM, "S Toggle search mode", 0, 0, 0, MKC('S') }, + { NM_ITEM, "T Dig a tunnel", 0, 0, 0, MKC('T') }, + { NM_ITEM, "V Version info", 0, 0, 0, MKC('V') }, + + { NM_TITLE, "Cmd4", 0, 0, 0, 0 }, + { NM_ITEM, "@ Interact with macros", 0, 0, 0, MKC('@') }, + { NM_ITEM, "% Interact with visuals", 0, 0, 0, MKC('%') }, + { NM_ITEM, "& Interact with colors", 0, 0, 0, MKC('&') }, + { NM_ITEM, "* Target monster or location", 0, 0, 0, MKC('*') }, + { NM_ITEM, "( Load screen dump", 0, 0, 0, MKC('(') }, + { NM_ITEM, ") Dump screen dump", 0, 0, 0, MKC(')') }, + { NM_ITEM, "{ Inscribe an object", 0, 0, 0, MKC('{') }, + { NM_ITEM, "} Uninscribe an object", 0, 0, 0, MKC('}') }, + { NM_ITEM, "- Walk (flip pickup)", 0, 0, 0, MKC('-') }, + + { NM_TITLE, "Cmd5", 0, 0, 0, 0 }, + { NM_ITEM, "+ Dig tunnel", 0, 0, 0, MKC('+') }, + { NM_ITEM, "= Set options", 0, 0, 0, MKC('=') }, + { NM_ITEM, "; Walk (with pickup)", 0, 0, 0, MKC(';') }, + { NM_ITEM, ": Take notes", 0, 0, 0, MKC(':') }, + { NM_ITEM, "\" Enter a user pref command", 0, 0, 0, MKC('\"') }, + { NM_ITEM, ", Stay still (with pickup)", 0, 0, 0, MKC(',') }, + { NM_ITEM, "< Go up staircase", 0, 0, 0, MKC('<') }, + { NM_ITEM, ". Run", 0, 0, 0, MKC('.') }, + { NM_ITEM, "> Go down staircase", 0, 0, 0, MKC('>') }, + { NM_ITEM, "/ Identify symbol", 0, 0, 0, MKC('/') }, + { NM_ITEM, "| Check uniques", 0, 0, 0, MKC('|') }, + { NM_ITEM, "~ Check artifacts", 0, 0, 0, MKC('~') }, + { NM_ITEM, "? Help", 0, 0, 0, MKC('?') }, + + { NM_TITLE, "Cmd6", 0, 0, 0, 0 }, + { NM_ITEM, "^f Repeat level feeling", 0, 0, 0, MCC('f') }, + { NM_ITEM, "^k Quit", 0, 0, 0, MCC('k') }, + { NM_ITEM, "^p Show previous messages", 0, 0, 0, MCC('p') }, + { NM_ITEM, "^r Redraw the screen", 0, 0, 0, MCC('r') }, + { NM_ITEM, "^s Save and don't quit", 0, 0, 0, MCC('s') }, + { NM_ITEM, "^x Save and quit", 0, 0, 0, MCC('x') }, + { NM_ITEM, NM_BARLABEL, 0, 0, 0, 0 }, + { NM_ITEM, "Draw dungeon map", "m", 0, 0, (void *)MNU_SCALEDMAP }, + + { NM_TITLE, "Help", 0, 0, 0, 0 }, + { NM_ITEM, "General Information", 0, 0, 0, MHL('1') }, + { NM_ITEM, "Creating a Character", 0, 0, 0, MHL('2') }, + { NM_ITEM, "Exploring the Dungeon", 0, 0, 0, MHL('3') }, + { NM_ITEM, "Attacking Monsters", 0, 0, 0, MHL('4') }, + { NM_ITEM, "List of Commands", 0, 0, 0, MHL('5') }, + { NM_ITEM, "List of Options", 0, 0, 0, MHL('6') }, + { NM_ITEM, "Version Information", 0, 0, 0, MHL('7') }, + + { NM_END, NULL, 0, 0, 0, 0 }, + { 255, 0, 0, 0, 0, 0 } +}; + +/* Menu array */ +struct NewMenu newmenu[ MENUMAX ]; + +///} +///{ "protos" + +extern void map_info( int y, int x, byte *ap, char *cp ); +extern void center_string( char *buf, cptr str ); +errr init_ami( void ); +static void init_term( term_data *td ); +static term *link_term( term_data *td ); +static void free_term( term_data *td ); +static char *stripstr( char *src, char *dst ); +void request_font( char *str ); +void request_mode( char *str ); +int read_prefs( void ); +static void amiga_open( term *t ); +static void amiga_nuke( term *t ); +static errr amiga_curs( int x, int y ); +static errr amiga_wipe( int x, int y, int n ); +static errr amiga_clear( void ); +static errr amiga_pict( int x, int y, byte a, char c ); +static errr amiga_text( int x, int y, int n, byte a, cptr s ); +static errr amiga_xtra( int n, int v ); +static errr amiga_flush( int v ); +static errr amiga_event( int v ); +static errr amiga_react( int v ); +static errr amiga_fail( char *msg ); +static void cursor_on( term_data *td ); +static void cursor_off( term_data *td ); +void amiga_tomp( void ); +void tomb_str( int y, char *str ); +int load_gfx( void ); +int conv_gfx( void ); +int size_gfx( term_data *td ); +void scale_bitmap( struct BitMap *srcbm, int srcw, int srch, struct BitMap *dstbm, int dstw, int dsth ); +void remap_bitmap( struct BitMap *srcbm, struct BitMap *dstbm, long *pens, int width, int height ); +static void put_gfx( struct RastPort *rp, int x, int y, int chr, int col ); +static void put_gfx_map( term_data *td, int x, int y, int c, int a ); +static void cursor_anim( void ); +void load_palette( void ); +static void amiga_map( void ); +int init_sound( void ); +void free_sound( void ); +static void play_sound( int v ); +struct BitMap *alloc_bitmap( int width, int height, int depth, ULONG flags, struct BitMap *friend ); +void free_bitmap( struct BitMap *bitmap ); +int depth_of_bitmap( struct BitMap *bm ); +int create_menus( void ); +void update_menus( void ); +void handle_menupick( int mnum ); +void handle_rawkey( UWORD code, UWORD qual, APTR addr ); + +///} + +///{ "init_ami()" - Initialize all Amiga spesific stuff + +errr init_ami( void ) +{ + char *s; + int i; + LONG pen; + struct DimensionInfo diminfo; + int pw, ph, maxw, maxh, th, barh; + + /* XXX XXX XXX */ + use_sound = arg_sound; + use_graphics = arg_graphics; + + /* Term data pointers */ + term_data *ts = &screen; + term_data *tc = &choice; + term_data *tr = &recall; + term_data *tm = &mirror; + + /* Clear the term data */ + init_term( ts ); + init_term( tc ); + init_term( tr ); + init_term( tm ); + + /* Always use the main term */ + ts->use = TRUE; + + /* We *must* have kickstart 37 or later */ + if ( IntuitionBase->LibNode.lib_Version < 37 ) + FAIL( "Sorry, this program requires KickStart 2.04 or later." ); + + /* Check if we have kickstart 39 or later */ + v39 = ( IntuitionBase->LibNode.lib_Version >= 39 ); + + /* Open diskfont.library */ + if (( DiskfontBase = OpenLibrary( "diskfont.library", 0 )) == NULL ) + FAIL( "Unable to open diskfont.library." ); + + /* Read preferences file */ + read_prefs(); + + /* Initialize keyboard stuff */ + ie.ie_NextEvent = NULL; + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_SubClass = 0; + if (( KeymapBase = OpenLibrary( "keymap.library", 36 )) == NULL ) + FAIL( "Unable to open keymap.library v36+." ); + + /* Open gadtools.library */ + if ( use_menus ) + { + if (( GadToolsBase = OpenLibrary( "gadtools.library", 36 )) == NULL ) + { + use_menus = FALSE; + } + } + + /* Initialize color palette */ + for ( i = 0; i < 32; i++ ) + { + /* If undefined, use default palette */ + if ( color_table[ i ][ 0 ] == 0 && + color_table[ i ][ 1 ] == 0 && + color_table[ i ][ 2 ] == 0 && + color_table[ i ][ 3 ] == 0 ) + { + color_table[ i ][ 0 ] = 1; + color_table[ i ][ 1 ] = ( default_colors[ i ] & 0xff0000 ) >> 16; + color_table[ i ][ 2 ] = ( default_colors[ i ] & 0x00ff00 ) >> 8; + color_table[ i ][ 3 ] = ( default_colors[ i ] & 0x0000ff ); + } + } + + /* Search for prefered screenmode or public screen */ + if ( strlen( modestr ) > 0 ) + { + /* Convert string to long */ + scr_m = strtol( modestr, &s, 0 ); + + /* It was not a number, so treat it as a public screen name */ + if ( scr_m == 0 ) + { + /* We need kickstart 3.0+ to use a public screen */ + if ( !v39 ) + { + FAIL( "Public screen can only be used on kickstart 3.0 or later." ); + } + + /* Try to lock the named public screen if it isn't already */ + if ( !pubscr ) + { + pubscr = LockPubScreen( modestr ); + } + + /* Failed */ + if ( !pubscr ) + { + sprintf( tmpstr, "Unable to get a lock on screen '%s'.", modestr ); + FAIL( tmpstr ); + } + + /* We got a lock now */ + publock = TRUE; + + scr_m = -1; + + use_pub = TRUE; + + /* Don't blank mouse on public screen */ + blankmouse = FALSE; + + /* Find suitable pens to use on public screen */ + for ( i = 0; i < 32; i++ ) + { + pen = ObtainBestPen( pubscr->ViewPort.ColorMap, + color_table[ i ][ 1 ] << 24, + color_table[ i ][ 2 ] << 24, + color_table[ i ][ 3 ] << 24, + OBP_Precision, PRECISION_EXACT ); + if ( pen == -1 ) + { + FAIL( "Unable to obtain suitable pens to use on public screen. "); + } + + pubpens[ i ] = pen; + } + + for ( i = 0; i < 16; i++ ) penconv[ i ] = (UWORD) pubpens[ i + 16 ]; + } + + /* Use specified screenmode if available */ + else + { + /* Check if requested mode is available */ + if ( ModeNotAvailable( scr_m )) scr_m = 0; + } + } + + if ( !use_pub ) + { + /* Extra windows not allowed on custom screen */ + tc->use = tr->use = tm->use = FALSE; + } + + /* Calculate window dimensions */ + ts->ww = ts->fw * ts->cols; ts->wh = ts->fh * ts->rows; + tc->ww = tc->fw * tc->cols; tc->wh = tc->fh * tc->rows; + tr->ww = tr->fw * tr->cols; tr->wh = tr->fh * tr->rows; + tm->ww = tm->fw * tm->cols; tm->wh = tm->fh * tm->rows; + + /* Find a nice screenmode */ + if ( scr_m == 0 && v39 ) + { + scr_m = BestModeID( + BIDTAG_NominalWidth, ts->ww, + BIDTAG_NominalHeight, ts->wh, + BIDTAG_DesiredWidth, ts->ww, + BIDTAG_DesiredHeight, ts->wh, + BIDTAG_Depth, 4, + TAG_END ); + } + + /* Use default screenmode if we don't have any */ + if ( scr_m == 0 || scr_m == INVALID_ID ) + { + scr_m = ( DEFAULT_MONITOR_ID | HIRES_KEY ); + } + + /* Open custom screen */ + if ( !use_pub ) + { + /* Use 32 colors with graphics */ + if ( use_graphics ) + { + /* Get dimension data for screenmode */ + if ( GetDisplayInfoData( NULL, (UBYTE *) &diminfo, sizeof( struct DimensionInfo ), DTAG_DIMS, scr_m )) + { + /* Check if we support deep screens */ + if ( diminfo.MaxDepth > 4 ) + { + /* Use 32 colors */ + deep = TRUE; + + /* Use colors 16..31 for text */ + for ( i = 0; i < 16; i++ ) penconv[ i ] = i + 16; + } + } + } + + /* Use only 16 colors with no graphics */ + if ( !use_graphics ) + { + /* Use 16 colors */ + deep = FALSE; + + /* Use colors 0..15 for text */ + for ( i = 0; i < 16; i++ ) penconv[ i ] = i; + } + + if (( amiscr = OpenScreenTags( NULL, + SA_Width, ts->ww, + SA_Height, ts->wh, + SA_Depth, deep ? 5 : 4, + SA_DisplayID, scr_m, + SA_Font, scrattr, + SA_Type, CUSTOMSCREEN, + SA_Title, "Angband Screen", + SA_ShowTitle, FALSE, + SA_Quiet, TRUE, + SA_Behind, TRUE, + SA_AutoScroll, TRUE, + SA_Overscan, OSCAN_TEXT, + v39 ? SA_Interleaved : TAG_IGNORE, TRUE, + TAG_END )) == NULL) + { + FAIL( "Unable to open screen." ); + } + + /* Initialize screen rastport */ + ts->rp = &amiscr->RastPort; + SetRast( ts->rp, PEN( 0 )); + SetAPen( ts->rp, 1 ); + SetBPen( ts->rp, 0 ); + SetDrMd( ts->rp, JAM2 ); + SetFont( ts->rp, ts->font ); + + /* Always use backdrop window on custom screen */ + backdrop = TRUE; + } + + /* We are using a public screen */ + else + { + /* Size of public screen */ + pw = pubscr->Width; + ph = pubscr->Height; + + /* Height difference between a window with or without a title bar */ + th = pubscr->Font->ta_YSize + 1; + + /* Find width of widest window */ + maxw = ts->ww; + maxw = tc->ww > maxw ? tc->ww : maxw; + maxw = tr->ww > maxw ? tr->ww : maxw; + maxw = tm->ww > maxw ? tm->ww : maxw; + maxw += pubscr->WBorLeft + pubscr->WBorRight; + + /* Find height of tallest window */ + maxh = ts->wh + ts->notitle ? 0 : th; + maxh = ( tc->wh + tc->notitle ? 0 : th ) > maxh ? ( tc->wh + tc->notitle ? 0 : th ) : maxh; + maxh = ( tr->wh + tr->notitle ? 0 : th ) > maxh ? ( tr->wh + tr->notitle ? 0 : th ) : maxh; + maxh = ( tm->wh + tm->notitle ? 0 : th ) > maxh ? ( tm->wh + tm->notitle ? 0 : th ) : maxh; + maxh += pubscr->WBorTop + pubscr->WBorBottom; + + /* Check if the public screen is large enough */ + if ( pw < maxw || ph < maxh ) + { + sprintf( tmpstr, "Public screen is too small for window (%d x %d).", maxw, maxh ); + FAIL( tmpstr ); + } + + /* Use backdrop window if pubscreen is quiet */ + backdrop = ( pubscr->Flags & SCREENQUIET ) ? TRUE : FALSE; + + /* Calculate screen bar height */ + barh = pubscr->BarHeight + 1; + + /* Check if windows are to be positioned at the right or bottom */ + if ( ts->wx == -1 ) ts->wx = pw - 1; + if ( ts->wy == -1 ) ts->wy = ph - 1; + if ( tc->wx == -1 ) tc->wx = pw - 1; + if ( tc->wy == -1 ) tc->wy = ph - 1; + if ( tr->wx == -1 ) tr->wx = pw - 1; + if ( tr->wy == -1 ) tr->wy = ph - 1; + if ( tm->wx == -1 ) tm->wx = pw - 1; + if ( tm->wy == -1 ) tm->wy = ph - 1; + + /* Position windows below screen bar if requested */ + if ( ts->wy == -2 ) ts->wy = barh; + if ( tc->wy == -2 ) tc->wy = barh; + if ( tr->wy == -2 ) tr->wy = barh; + if ( tm->wy == -2 ) tm->wy = barh; + } + + /* Get visual info for GadTools */ + if ( use_menus ) + { + if (( visinfo = GetVisualInfo( use_pub ? pubscr : amiscr, TAG_END )) == NULL ) + { + use_menus = FALSE; + } + } + + /* Open window, backdrop if on custom screen */ + if (( ts->win = OpenWindowTags( NULL, + WA_Left, ts->wx, + WA_Top, ts->wy, + WA_InnerWidth, ts->ww, + WA_InnerHeight, ts->wh, + use_pub ? WA_PubScreen : WA_CustomScreen, use_pub ? pubscr : amiscr, + WA_Backdrop, backdrop, + WA_Borderless, backdrop, + WA_GimmeZeroZero, !backdrop, + WA_DragBar, !backdrop && !ts->notitle, + WA_DepthGadget, !backdrop && !ts->notitle, + WA_NewLookMenus, TRUE, + backdrop ? TAG_IGNORE : WA_ScreenTitle, VERSION, + ( backdrop || ts->notitle ) ? TAG_IGNORE : WA_Title, ts->name, + WA_Activate, TRUE, + WA_RMBTrap, !use_menus, + WA_ReportMouse, TRUE, + WA_IDCMP, IDCMP_RAWKEY | IDCMP_INTUITICKS | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | IDCMP_MENUPICK | IDCMP_MENUVERIFY, + TAG_END )) == NULL ) + { + FAIL("Unable to open window."); + } + + /* Unlock public screen */ + if ( publock ) + { + UnlockPubScreen( NULL, pubscr ); + publock = FALSE; + } + + /* Initialize main rastport */ + ts->wrp = ts->win->RPort; + SetRast( ts->wrp, PEN( 0 )); + SetAPen( ts->wrp, 1 ); + SetBPen( ts->wrp, 0 ); + SetDrMd( ts->wrp, JAM2 ); + SetFont( ts->wrp, ts->font ); + + /* Never use screen's rastport on public screen */ + if ( use_pub ) + { + ts->rp = ts->wrp; + } + + /* Use mirror window? */ + if ( tm->use ) + { + /* Open mirror window */ + if (( tm->win = OpenWindowTags( NULL, + WA_Left, tm->wx, + WA_Top, tm->wy, + WA_InnerWidth, tm->ww, + WA_InnerHeight, tm->wh, + WA_PubScreen, pubscr, + WA_GimmeZeroZero, TRUE, + WA_DragBar, !tm->notitle, + WA_DepthGadget, !tm->notitle, + WA_NewLookMenus, TRUE, + WA_ScreenTitle, VERSION, + tm->notitle ? TAG_IGNORE : WA_Title, tm->name, + WA_ReportMouse, TRUE, + TAG_END )) == NULL ) + { + FAIL("Unable to open recall window."); + } + + /* Initialize mirror rastport */ + tm->rp = tm->wrp = tm->win->RPort; + SetRast( tm->rp, PEN( 0 )); + SetAPen( tm->rp, 1 ); + SetBPen( tm->rp, 0 ); + SetDrMd( tm->rp, JAM2 ); + SetFont( tm->rp, tm->font ); + } + + /* Use recall window? */ + if ( tr->use ) + { + /* Open recall window */ + if (( tr->win = OpenWindowTags( NULL, + WA_Left, tr->wx, + WA_Top, tr->wy, + WA_InnerWidth, tr->ww, + WA_InnerHeight, tr->wh, + WA_PubScreen, pubscr, + WA_GimmeZeroZero, TRUE, + WA_DragBar, !tr->notitle, + WA_DepthGadget, !tr->notitle, + WA_NewLookMenus, TRUE, + WA_ScreenTitle, VERSION, + tr->notitle ? TAG_IGNORE : WA_Title, tr->name, + WA_ReportMouse, TRUE, + TAG_END )) == NULL ) + { + FAIL("Unable to open recall window."); + } + + /* Initialize recall rastport */ + tr->rp = tr->wrp = tr->win->RPort; + SetRast( tr->rp, PEN( 0 )); + SetAPen( tr->rp, 1 ); + SetBPen( tr->rp, 0 ); + SetDrMd( tr->rp, JAM2 ); + SetFont( tr->rp, tr->font ); + } + + /* Use choice window? */ + if ( tc->use ) + { + /* Open choice window */ + if (( tc->win = OpenWindowTags( NULL, + WA_Left, tc->wx, + WA_Top, tc->wy, + WA_InnerWidth, tc->ww, + WA_InnerHeight, tc->wh, + WA_PubScreen, pubscr, + WA_GimmeZeroZero, TRUE, + WA_DragBar, !tc->notitle, + WA_DepthGadget, !tc->notitle, + WA_NewLookMenus, TRUE, + WA_ScreenTitle, VERSION, + tc->notitle ? TAG_IGNORE : WA_Title, tc->name, + WA_ReportMouse, TRUE, + TAG_END )) == NULL ) + { + FAIL("Unable to open recall window."); + } + + /* Initialize choice rastport */ + tc->rp = tc->wrp = tc->win->RPort; + SetRast( tc->rp, PEN( 0 )); + SetAPen( tc->rp, 1 ); + SetBPen( tc->rp, 0 ); + SetDrMd( tc->rp, JAM2 ); + SetFont( tc->rp, tc->font ); + } + + /* Create palette for screen */ + load_palette(); + + /* Link terms with the metaterm */ + if ( tc->use ) term_choice = link_term( tc ); + if ( tr->use ) term_recall = link_term( tr ); + if ( tm->use ) term_mirror = link_term( tm ); + if ( ts->use ) term_screen = link_term( ts ); + + /* Bring main window to front */ + if ( !backdrop ) WindowToFront( ts->win ); + + /* Bring screen to front */ + ScreenToFront( use_pub ? pubscr : amiscr ); + + /* Load and convert graphics */ + if ( use_graphics ) + { + MSG( 0, 0, "Loading graphics" ); + if ( !load_gfx() ) FAIL( NULL ); + + /* Check if conversion is necessary */ + if ( use_pub || ( depth_of_bitmap( ts->rp->BitMap ) != depth_of_bitmap( ts->gfxbm ))) + { + MSG( 0, 1, "Remapping graphics" ); + if ( !conv_gfx() ) FAIL( "Out of memory while remapping graphics." ); + } + + /* Scale the graphics to fit font sizes */ + if ( tm->use ) if ( !size_gfx( tm ) ) FAIL( "Out of memory while scaling graphics." ); + if ( tr->use ) if ( !size_gfx( tr ) ) FAIL( "Out of memory while scaling graphics." ); + if ( tc->use ) if ( !size_gfx( tc ) ) FAIL( "Out of memory while scaling graphics." ); + if ( ts->use ) if ( !size_gfx( ts ) ) FAIL( "Out of memory while scaling graphics." ); + + /* Use graphics */ + use_graphics = TRUE; + } + + /* Load sound effects */ + if ( use_sound ) + { + MSG( 0, 2, "Loading sound effects" ); + init_sound(); + } + + /* Success */ + return ( 0 ); +} +///} +///{ "init_term()" + +static void init_term( term_data *td ) +{ + /* Set term name */ + if ( td == &screen ) td->name = screen_name; + if ( td == &choice ) td->name = choice_name; + if ( td == &recall ) td->name = recall_name; + if ( td == &mirror ) td->name = mirror_name; + + /* Term off */ + td->use = FALSE; + + /* Term size */ + td->cols = 80; + td->rows = 24; + + /* Term dimension */ + td->wx = 0; + td->wy = 0; + td->ww = 0; + td->wh = 0; + + /* System default font */ + td->font = GfxBase->DefaultFont; + td->ownf = FALSE; + td->fw = td->font->tf_XSize; + td->fh = td->font->tf_YSize; + td->fb = td->font->tf_Baseline; + + /* No window or rastports */ + td->win = NULL; + td->wrp = NULL; + td->rp = NULL; + + /* No bitmaps */ + td->gfxbm = NULL; + td->mskbm = NULL; + td->mapbm = NULL; + + /* Cursor status */ + td->cursor_xpos = 0; + td->cursor_ypos = 0; + td->cursor_visible = FALSE; + td->cursor_lit = FALSE; + td->cursor_frame = 0; + td->cursor_map = FALSE; + + /* Use window title */ + td->notitle = FALSE; +} + +///} +///{ "link_term()" + +static term *link_term( term_data *td ) +{ + term *t; + + /* Term pointer */ + t = &td->t; + + /* Initialize the term */ + term_init( t, td->cols, td->rows, 256 ); + + /* Hooks */ + t->init_hook = amiga_open; + t->nuke_hook = amiga_nuke; + t->text_hook = amiga_text; + t->pict_hook = amiga_pict; + t->wipe_hook = amiga_wipe; + t->curs_hook = amiga_curs; + t->xtra_hook = amiga_xtra; + + /* We are emulating a hardware cursor */ + t->soft_cursor = FALSE; + + /* Draw graphical tiles one by one */ + t->always_text = FALSE; + t->always_pict = FALSE; + t->higher_pict = TRUE; + + /* Misc. efficiency flags */ + t->never_bored = TRUE; + t->never_frosh = TRUE; + + /* Erase with "white space" */ + t->attr_blank = TERM_WHITE; + t->char_blank = ' '; + + /* Remember where we come from */ + t->data = (vptr) td; + + /* Activate it */ + Term_activate( t ); + + /* Return pointer to the term */ + return ( t ); +} + +///} +///{ "free_term()" + +static void free_term( term_data *td ) +{ + /* Do we own the font? */ + if ( td->ownf && td->font ) CloseFont( td->font ); + + /* Is the window opened? */ + if ( td->win ) CloseWindow( td->win ); + + /* Free bitmaps */ + if ( td->gfxbm ) free_bitmap( td->gfxbm ); + if ( td->mskbm ) free_bitmap( td->mskbm ); + if ( td->mapbm ) free_bitmap( td->mapbm ); +} + +///} +///{ "stripstr()" + +static char *stripstr( char *src, char *dst ) +{ + int len; + + /* Ignore leading spaces */ + while ( *src == ' ' ) src++; + + /* Copy string */ + for ( len = 0; *src != 0; len++ ) *dst++ = *src++; + *dst = 0; + + /* Remove trailing spaces */ + for ( dst--; *dst == ' ' && len; len-- ) *dst-- = 0; + + /* Return pointer to destination */ + return ( dst ); +} + +///} +///{ "yesno()" + +static int yesno( char *str ) +{ + char tmp[ 256 ]; + char *s; + + /* Strip spaces around string */ + stripstr( str, tmp); + + /* Make lowercase */ + for ( s = tmp; *s != 0; s++ ) *s = tolower( *s ); + + return ( !strcmp( tmp, "y" ) || !strcmp( tmp, "yes" ) || !strcmp( tmp, "true" ) || !strcmp( tmp, "on" )); +} + +///} +///{ "request_font()" + +void request_font( char *str ) +{ + struct Library *AslBase = NULL; + struct FontRequester *req = NULL; + + /* Blank string as default */ + *str = 0; + + /* Open asl.library */ + if ( AslBase = OpenLibrary ( "asl.library", 37 )) + { + /* Allocate screenmode requester */ + if ( req = AllocAslRequestTags( ASL_FontRequest, TAG_DONE )) + { + /* Open screenmode requester */ + if ( AslRequestTags( req, ASLFO_FixedWidthOnly, TRUE, TAG_DONE )) + { + /* Store font name and size */ + sprintf( str, "%s/%d", req->fo_Attr.ta_Name, req->fo_Attr.ta_YSize ); + } + /* Free requester */ + FreeAslRequest( req ); + } + /* Close asl.library */ + CloseLibrary( AslBase ); + } +} + +///} +///{ "request_mode()" + +void request_mode( char *str ) +{ + struct Library *AslBase = NULL; + struct ScreenModeRequester *req = NULL; + + /* Blank string as default */ + *str = 0; + + /* Open asl.library */ + if ( AslBase = OpenLibrary ( "asl.library", 37 )) + { + /* Allocate screenmode requester */ + if ( req = AllocAslRequestTags( ASL_ScreenModeRequest, TAG_DONE )) + { + /* Open screenmode requester */ + if ( AslRequestTags( req, TAG_DONE )) + { + /* Store font name and size */ + sprintf( str, "0x%X", req->sm_DisplayID ); + } + /* Free requester */ + FreeAslRequest( req ); + } + /* Close asl.library */ + CloseLibrary( AslBase ); + } +} + +///} +///{ "read_prefs()" + +int read_prefs( void ) +{ + BPTR file; + char line[ 256 ]; + char fname[ 256 ]; + char *tmp, *s; + int len; + int fsize; + int val; + struct TextAttr attr; + term_data *td; + + /* Open config file */ + if (( file = Open( WPRF, MODE_OLDFILE )) == NULL ) + { + fprintf( stderr, "\nUnable to open file '%s'.\n", WPRF ); + return ( FALSE ); + } + + /* Read next line from file */ + while ( FGets( file, line, 256 )) + { + /* Cut off comments */ + if ( tmp = strchr( line, ';' )) * tmp = 0; + + /* Length of line */ + len = strlen( line ); + + /* Cut off trailing newline and blanks */ + for ( tmp = line + len - 1; len > 0 && ( *tmp == '\n' || *tmp == ' ' ); len-- ) *tmp-- = 0; + + /* Ignore blank lines */ + if ( len == 0 ) continue; + + /* Extract term */ + if ( strncmp( line, "MAIN.", 5 ) == 0 ) td = &screen; + else if ( strncmp( line, "CHOICE.", 7 ) == 0 ) td = &choice; + else if ( strncmp( line, "RECALL.", 7 ) == 0 ) td = &recall; + else if ( strncmp( line, "MIRROR.", 7 ) == 0 ) td = &mirror; + else if ( strncmp( line, "SCREEN.", 7 ) != 0 && + strncmp( line, "ANGBAND.", 8 ) != 0 ) + { + printf( "PREFS: Error in line '%s'\n", line ); + continue; + } + + /* Find start of option */ + tmp = strchr( line, '.' ) + 1; + + /* Ignore blank options */ + if ( *tmp == 0 ) continue; + + /* Option 'use' - Use this term */ + if ( !strncmp( tmp, "use", 3 )) + { + td->use = yesno( tmp + 3 ); + } + + /* Option 'cols' - Set number of columns for term */ + else if ( !strncmp( tmp, "cols", 4 ) && sscanf( tmp + 4, "%d", &val )) td->cols = val; + + /* Option 'rows' - Set number of rows for term */ + else if ( !strncmp( tmp, "rows", 4 ) && sscanf( tmp + 4, "%d", &val )) td->rows = val; + + /* Option 'xpos' - Set horizontal position for window */ + else if ( !strncmp( tmp, "xpos", 4 ) && sscanf( tmp + 4, "%d", &val )) td->wx = val; + + /* Option 'ypos' - Set vertical position for window */ + else if ( !strncmp( tmp, "ypos", 4 ) && sscanf( tmp + 4, "%d", &val )) td->wy = val; + + /* Option 'name' - Set window title */ + else if ( !strncmp( tmp, "title", 5 )) + { + /* Get parameter */ + stripstr( tmp + 5, fname ); + + /* Make a copy of the title */ + if ( strlen( fname ) > 0 ) + { + td->name = strdup( fname ); + } + + /* Don't use a title bar on this window */ + else + { + td->notitle = TRUE; + } + + continue; + } + + /* Option 'font' - Set font for this window */ + else if ( !strncmp( tmp, "font", 4 )) + { + /* Get value */ + stripstr( tmp + 4, fname ); + + /* Ask for font? */ + if ( !strcmp( fname, "?" )) + { + /* Open font requester */ + request_font( fname ); + } + + /* No font specification given */ + if ( strlen( fname ) == 0 ) + { + /* Main window */ + if ( td == &screen ) + { + /* System default font */ + td->font = GfxBase->DefaultFont; + + /* Use default font as screen font */ + scrattr = NULL; + } + + /* Extra window */ + else + { + /* Copy main window's font */ + td->font = screen.font; + } + + /* Set font dimensions */ + td->fw = td->font->tf_XSize; + td->fh = td->font->tf_YSize; + td->fb = td->font->tf_Baseline; + + /* This font is not opened by us */ + td->ownf = FALSE; + + /* Next line */ + continue; + } + + /* Get name and size */ + else + { + /* Find font name/size delimiter */ + if (( s = strchr( fname, '/' )) == NULL ) + { + printf( "\nPREFS: Illegal font specification: '%s'.\n", fname ); + continue; + } + + /* End fontname here */ + *s++ = 0; + + /* Convert size string to integer */ + fsize = atoi( s ); + + /* Make sure the font name ends with .font */ + if ( !strstr( fname, ".font" )) strcat( fname, ".font" ); + } + + /* Set font attributes */ + attr.ta_Name = fname; + attr.ta_YSize = fsize; + attr.ta_Style = FS_NORMAL; + attr.ta_Flags = ( !strcmp( fname, "topaz.font" ) && ( fsize == 8 || fsize == 9 )) ? + FPF_ROMFONT : FPF_DISKFONT; + + /* Open font from disk */ + if ( td->font = OpenDiskFont( &attr )) + { + /* We own this font */ + td->ownf = TRUE; + + /* Set font dimensions */ + td->fw = td->font->tf_XSize; + td->fh = td->font->tf_YSize; + td->fb = td->font->tf_Baseline; + + /* Copy font attr to screen font */ + if ( td == &screen ) + { + scrattr->ta_Name = strdup( fname ); + scrattr->ta_YSize = fsize; + scrattr->ta_Style = FS_NORMAL; + scrattr->ta_Flags = attr.ta_Flags; + } + } + + /* The font could not be opened */ + else + { + /* Fallback to default font */ + td->font = GfxBase->DefaultFont; + + /* Use default font as screen font */ + scrattr = NULL; + + /* Output error message */ + printf( "\nUnable to open font '%s/%d'.\n", fname, fsize ); + } + } + + /* Option .name - Set public screen name. KS 3.0+ required */ + else if ( !strncmp( tmp, "name", 4 ) && v39 ) + { + /* Copy name */ + stripstr( tmp + 4, modestr ); + } + + /* Option .mode - Set custom screen mode */ + else if ( !strncmp( tmp, "mode", 4 )) + { + /* If a public screen was also specified, check if it exist */ + if ( strlen( modestr ) > 0 ) + { + /* Don't lock it twice */ + if ( pubscr ) continue; + + /* Try to lock the named public screen */ + if ( pubscr = LockPubScreen( modestr )) + { + /* We got a lock now */ + publock = TRUE; + + /* Screen exist. Skip this option */ + continue; + } + } + + /* Get parameter */ + stripstr( tmp + 4, modestr ); + + /* Ask for mode? */ + if ( !strcmp( modestr, "?" )) + { + /* Open screenmode requester */ + request_mode( modestr ); + } + } + + /* Option .blankmouse - Use mouseblanking */ + else if ( !strncmp( tmp, "blankmouse", 10 )) + { + blankmouse = yesno( tmp + 10 ); + } + + /* Option .blankmouse - Use intuition menus */ + else if ( !strncmp( tmp, "menus", 5 )) + { + use_menus = yesno( tmp + 5 ); + } + + else if ( !strncmp( tmp, "sound", 5 )) + { + use_sound = yesno( tmp + 5 ); + } + + else if ( !strncmp( tmp, "gfx", 3 )) + { + use_graphics = yesno( tmp + 5 ); + } + + /* Unknown option */ + else + { + /* Output error message */ + printf ( "\nPREFS: Unknown option '%s'.\n", tmp ); + } + } + + /* Close the file */ + Close( file ); +} + +///} +///{ "amiga_nuke()" - Free all allocated resources + +static void amiga_nuke( term *t ) +{ + if ( t == term_screen ) + { + amiga_fail( NULL ); + /* Flush the output */ + fflush( stdout ); + } +} + +///} +///{ "amiga_open()" - Initialize terminal + +static void amiga_open( term *t ) +{ + /* Nothing to do here */ +} + +///} +///{ "amiga_curs()" - Move the cursor to a new location + +static errr amiga_curs( int x, int y ) +{ + term_data *td = term_curs; + + if ( td->cursor_visible ) + { + cursor_off( td ); + } + + td->cursor_xpos = x; + td->cursor_ypos = y; + td->cursor_frame = 0; + + if ( td->cursor_visible ) + { + cursor_on( td ); + } + + return ( 0 ); +} + +///} +///{ "amiga_wipe()" - Erase a part of a line + +static errr amiga_wipe( int x, int y, int n ) +{ + term_data *td = (term_data*)(Term->data); + + if (( n > 0 ) && !iconified ) + { + /* Erase rectangular area on screen */ + SetAPen( td->rp, PEN( 0 ) ); + RectFill( td->rp, x * td->fw, y * td->fh, ( x + n ) * td->fw - 1, ( y + 1 ) * td->fh - 1 ); + } + + return ( 0 ); +} + +///} +///{ "amiga_clear()" - Clear whole window + +static errr amiga_clear( void ) +{ + term_data *td = (term_data*)(Term->data); + + /* Fill window with background color */ + SetRast( td->rp, PEN( 0 )); + + return ( 0 ); +} + +///} +///{ "amiga_pict()" - Place one tile on the screen + +static errr amiga_pict( int x, int y, byte a, char c ) +{ + term_data *td = (term_data*)(Term->data); + char s[2]; + + /* Graphical tile */ + if ( a & 0x80 ) + { + put_gfx( td->rp, x, y, c & 0x7f, a & 0x7f ); + } + + /* Textual character */ + else + { + s[0] = c; + s[1] = 0; + SetAPen( td->rp, PEN( a & 0x0f )); + SetBPen( td->rp, PEN( 0 )); + Move( td->rp, x * td->fw, y * td->fh + td->fb ); + Text( td->rp, (char *) s, 1 ); + } + + return ( 0 ); +} + +///} +///{ "amiga_text()" - Place some text on the screen using an attribute + +static errr amiga_text( int x, int y, int n, byte a, cptr s ) +{ + term_data *td = (term_data*)(Term->data); + int i; + + if ( x >= 0 && y >= 0 && n > 0 && !iconified ) + { + /* Draw gfx one char at a time */ + if (( a & 0xc0 )) + { + for ( i = 0; i < n; i++ ) put_gfx( td->rp, x + i, y, s[ i ] & 0x7f, a & 0x7f ); + } + + /* Draw the string on screen */ + else + { + SetAPen( td->rp, PEN( a&0x0f )); + SetBPen( td->rp, PEN( 0 )); + Move( td->rp, x * td->fw, y * td->fh + td->fb ); + Text( td->rp, (char *) s, n ); + } + } + + return ( 0 ); +} + +///} +///{ "amiga_xtra()" - Handle a "special request" + +static errr amiga_xtra( int n, int v ) +{ + term_data *td = (term_data*)(Term->data); + + /* Analyze the request */ + switch ( n ) + { + /* Wait for event */ + case TERM_XTRA_EVENT: + + return ( amiga_event( v )); + + + /* Flush input */ + case TERM_XTRA_FLUSH: + + return ( amiga_flush( v )); + + + /* Make a noise */ + case TERM_XTRA_CLEAR: + + return ( amiga_clear()); + + + /* Change cursor visibility */ + case TERM_XTRA_SHAPE: + + /* Cursor on */ + if ( v ) + { + cursor_on( td ); + td->cursor_visible = TRUE; + } + /* Cursor off */ + else + { + cursor_off( td ); + td->cursor_visible = FALSE; + } + return ( 0 ); + + + /* Flash screen */ + case TERM_XTRA_NOISE: + + DisplayBeep( use_pub ? pubscr : amiscr ); + return ( 0 ); + + + /* Play a sound */ + case TERM_XTRA_SOUND: + + if ( has_sound ) + { + play_sound( v ); + } + return ( 0 ); + + + /* React on global changes */ + case TERM_XTRA_REACT: + + return ( amiga_react( v )); + + + case TERM_XTRA_LEVEL: + + term_curs = td; + return ( 0 ); + + case TERM_XTRA_DELAY: + + if (v >= 20) Delay(v / 20); + return (0); + + /* Unknown request type */ + default: + + return ( 1 ); + + } + + /* Shouldn't be able to get here */ + return ( 1 ); +} + +///} +///{ "amiga_flush()" - Flush input buffer + +static errr amiga_flush( int v ) +{ + struct IntuiMessage *imsg; + + /* Ignore all messages at the port */ + while ( imsg = (struct IntuiMessage *) GetMsg( screen.win->UserPort )) + { + ReplyMsg(( struct Message *) imsg ); + } + + return ( 1 ); +} + +///} +///{ "amiga_event()" - Wait for an event, and handle it. + +static errr amiga_event( int v ) +{ + struct IntuiMessage *imsg; + ULONG iclass; + UWORD icode; + UWORD iqual; + APTR iaddr; + + /* Check for messages to the window */ + if (( imsg = (struct IntuiMessage *) GetMsg( screen.win->UserPort )) == NULL ) + { + /* If we don't want blocking, return */ + if ( !v ) + { + return ( 0 ); + } + + /* No messages, so wait for one */ + Wait( 1 << screen.win->UserPort->mp_SigBit ); + + /* Get the new message */ + imsg = (struct IntuiMessage *) GetMsg( screen.win->UserPort ); + } + + /* Handle message */ + if ( imsg ) + { + /* Get message attributes */ + iclass = imsg->Class; + icode = imsg->Code; + iqual = imsg->Qualifier; + iaddr = imsg->IAddress; + + /* Update menus before displaying */ + if ( iclass == IDCMP_MENUVERIFY && icode == MENUHOT && use_menus ) + { + update_menus(); + } + + /* Reply the message */ + ReplyMsg(( struct Message *) imsg ); + + /* Do we have a keypress? */ + if ( iclass == IDCMP_RAWKEY ) + { + handle_rawkey( icode, iqual, iaddr ); + return ( 0 ); + } + + /* Mouse event - Make pointer visible */ + if ( iclass == IDCMP_MOUSEMOVE || + iclass == IDCMP_MOUSEBUTTONS || + iclass == IDCMP_MENUVERIFY ) + { + if ( blankmouse && !pointer_visible ) + { + ClearPointer( screen.win ); + pointer_visible = TRUE; + } + + return ( 0 ); + } + + /* Time for some cursor anim? */ + if ( iclass == IDCMP_INTUITICKS ) + { + cursor_anim(); + return ( 0 ); + } + + /* Menu item picked? */ + if ( iclass == IDCMP_MENUPICK ) + { + handle_menupick( icode ); + } + + /* Unknown message class */ + return ( 1 ); + } + + /* No events */ + return ( 1 ); +} + +///} +///{ "amiga_react()" + +static errr amiga_react( int v ) +{ + /* Apply color palette, in case it has changed */ + load_palette(); + + /* Create menus if we don't have any */ + if ( !menu && use_menus ) + { + create_menus(); + } + + return ( 0 ); +} + +///} +///{ "amiga_tomb()" + +int amiga_tomb( void ) +{ + cptr p; + char tmp[160]; + time_t ct = time((time_t)0); + BPTR file; + + char *pp; + int plane, row, error = FALSE; + struct BitMap *filebm, *scalbm, *convbm; + long stdpens[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + int depth; + BYTE *src, *dst; + int byt; + + int tw = screen.fw * 64; + int th = screen.fh * 21; + + /* Allocate bitmap for tomb graphics file */ + if (( filebm = alloc_bitmap( 512, 168, 4, BMF_CLEAR, screen.rp->BitMap )) == NULL ) + { + return ( FALSE ); + } + + /* Open tomb file */ + if (( file = Open( MTOM, MODE_OLDFILE )) == NULL ) + { + free_bitmap( filebm ); + return ( FALSE ); + } + + /* Read file into bitmap */ + for ( plane = 0; plane < 4 && !error; plane++ ) + { + pp = filebm->Planes[ plane ]; + for ( row = 0; row < 168 && !error; row++ ) + { + error = ( Read( file, pp, 64 ) != 64 ); + pp += filebm->BytesPerRow; + } + } + + /* Close tomb file */ + Close( file ); + + /* Get depth of display */ + depth = depth_of_bitmap( screen.rp->BitMap ); + + /* Remapping needed? */ + if ( depth != 4 || use_pub ) + { + /* Allocate bitmap for remapped image */ + if (( convbm = alloc_bitmap( 512, 168, depth, BMF_CLEAR, screen.rp->BitMap )) == NULL ) + { + free_bitmap( filebm ); + return ( FALSE ); + } + + /* Simple remapping from 4 to 5 planes? */ + if ( depth == 5 && !use_pub ) + { + for ( plane = 0; plane < 4; plane++ ) + { + src = filebm->Planes[ plane ]; + dst = convbm->Planes[ plane ]; + for ( row = 0; row < 168; row++ ) + { + for ( byt = 0; byt < 64; byt++ ) + { + dst[ byt ] = src[ byt ]; + } + src += filebm->BytesPerRow; + dst += convbm->BytesPerRow; + } + } + } + + /* Complex remapping */ + else + { + /* Remap old bitmap into new bitmap */ + remap_bitmap( filebm, convbm, use_pub ? pubpens : stdpens, 512, 168 ); + } + + /* Free original bitmap */ + free_bitmap( filebm ); + } + + /* No remapping needed */ + else + { + convbm = filebm; + } + + /* Allocate bitmap for scaled graphics */ + if (( scalbm = alloc_bitmap( tw, th, depth, BMF_CLEAR, screen.rp->BitMap )) == NULL ) + { + free_bitmap( convbm ); + return ( FALSE ); + } + + /* Scale the tomb bitmap */ + scale_bitmap( convbm, 512, 168, scalbm, tw, th ); + + /* Free old bitmap */ + free_bitmap( convbm ); + + /* Copy the tomb graphics to the screen, centered */ + BltBitMapRastPort( scalbm, 0, 0, screen.rp, ( screen.ww - tw ) / 2, 0, tw, th, 0xc0 ); + + /* Free bitmap */ + free_bitmap( scalbm ); + + /* King or Queen */ + if (total_winner || (p_ptr->lev > PY_MAX_LEVEL)) + { + p = "Magnificent"; + } + + /* Normal */ + else + { + p = player_title[p_ptr->pclass][(p_ptr->lev - 1) / 5]; + } + + tomb_str( 3, " R.I.P." ); + + tomb_str( 5, player_name ); + + tomb_str( 6, "the" ); + + tomb_str( 7, (char *)p ); + + tomb_str( 9, (char *)cp_ptr->title ); + + sprintf( tmp, "Level: %d", (int)p_ptr->lev ); + tomb_str( 10, tmp ); + + sprintf( tmp, "Exp: %ld", (long)p_ptr->exp ); + tomb_str( 11, tmp ); + + sprintf( tmp, "AU: %ld", (long)p_ptr->au ); + tomb_str( 12, tmp ); + + sprintf( tmp, "Killed on Level %d", dun_level ); + tomb_str( 13, tmp ); + + sprintf( tmp, "by %s", died_from ); + tomb_str( 14, tmp ); + + sprintf( tmp, "%-.24s", ctime(&ct)); + tomb_str( 16, tmp ); + + return ( TRUE ); +} + +///} +///{ "tomb_str()" + +void tomb_str( int y, char *str ) +{ + term_data *td = &screen; + int l = strlen( str ); + int xp = ( 39 * td->fw ) - (( l + 1 ) * td->fw ) / 2; + + SetDrMd( td->rp, JAM1 ); + + SetAPen( td->rp, PEN( 1 )); + Move( td->rp, xp + 1, y * td->fh + td->fb + 1 ); + Text( td->rp, str, l ); + + SetAPen( td->rp, PEN( 0 )); + Move( td->rp, xp, y * td->fh + td->fb ); + Text( td->rp, str, l ); + + SetDrMd( td->rp, JAM2 ); +} + +///} +///{ "handle_rawkey()" + +void handle_rawkey( UWORD code, UWORD qual, APTR addr ) +{ + char buf[ 80 ]; + int i; + int len; + UWORD q; + + /* Use a blank mouse-pointer on this window */ + if ( blankmouse && pointer_visible ) + { + SetPointer( screen.win, blankpointer, 2, 16, 0, 0 ); + pointer_visible = FALSE; + } + + /* Numeric keypad pressed with qualifier? */ + if (( qual & IEQUALIFIER_NUMERICPAD ) && ( qual & 0xff )) + { + /* Direction key? (1,2,3,4,6,7,8,9) */ + if (( code >= 0x1d && code <= 0x1f ) || + ( code == 0x2d || code == 0x2f ) || + ( code >= 0x3d && code <= 0x3f )) + { + /* Shift/Ctrl/Alt/Amiga keys */ + q = qual & 0xff; + + /* Shift + Direction */ + if ( q == IEQUALIFIER_LSHIFT || q == IEQUALIFIER_RSHIFT ) + { + /* Fake a keypress 'run' */ + Term_keypress( '.' ); + + /* Remove shift key from event */ + qual &= ~( IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT ); + } + + /* Alt + Direction */ + else if ( q == IEQUALIFIER_LALT || q == IEQUALIFIER_RALT ) + { + /* Fake a keypress 'tunnel' */ + Term_keypress( 'T' ); + + /* Remove alt key from event */ + qual &= ~( IEQUALIFIER_LALT | IEQUALIFIER_RALT ); + } + + /* Ctrl + Direction */ + else if ( q == IEQUALIFIER_CONTROL ) + { + /* Fake a keypress 'open' */ + Term_keypress( 'o' ); + + /* Remove ctrl key from event */ + qual &= ~IEQUALIFIER_CONTROL; + } + } + } + + /* Convert raw keycode to ANSI sequence */ + ie.ie_Code = code; + ie.ie_Qualifier = qual; + ie.ie_EventAddress = (APTR *) * ((ULONG *) addr ); + len = MapRawKey( &ie, buf, 80, NULL ); + + /* Send ANSI sequence to meta-terminal */ + for ( i = 0; i < len; i++ ) + { + if ( !iconified ) + { + Term_keypress( (unsigned char) buf[ i ]); + } + } +} + +///} +///{ "handle_menupick()" + +void handle_menupick( int mnum ) +{ + struct MenuItem *item; + ULONG ud; + int i; + + /* Be sure to handle all selections */ + while ( mnum != MENUNULL ) + { + /* Find address of menuitem */ + item = ItemAddress( menu, mnum ); + + /* Find userdata of menuitem */ + ud = (ULONG) GTMENUITEM_USERDATA( item ); + + /* Is this a help item? */ + if ( ud >= MNU_HELP ) + { + /* Send keypresses */ + Term_keypress( '\\' ); + Term_keypress( '?' ); + Term_keypress( ud - MNU_HELP ); + } + + /* Is this an option item? */ + else if ( ud >= MNU_OPTION ) + { + /* Option index */ + i = ud - MNU_OPTION; + + /* Set option according to checkmark status */ + *options[ i ].o_var = item->Flags & CHECKED ? TRUE : FALSE; + + /* Fake a dummy keypress to cause update */ + Term_keypress( ' ' ); + } + + /* Control key shortcuts */ + else if ( ud >= MNU_CKEYCOM ) + { + /* Send keycode */ + Term_keypress( '\\' ); + Term_keypress( '^' ); + Term_keypress( ud - MNU_CKEYCOM ); + } + + /* Key shortcuts */ + else if ( ud >= MNU_KEYCOM ) + { + /* Key code */ + i = ud - MNU_KEYCOM; + + /* Some functions need underlying keymap */ + if ( i != 't' && i != 'w' && i != 'T' ) + { + Term_keypress( '\\' ); + } + + /* Send keycode */ + Term_keypress( i ); + } + + /* Scaled down Map of the dungeon */ + else if ( ud == MNU_SCALEDMAP ) + { + /* Draw the map */ + amiga_map(); + } + + /* Find next menunumber */ + mnum = item->NextSelect; + } +} + +///} +///{ "cursor_on()" + +static void cursor_on( term_data *td ) +{ + int x0, y0, x1, y1; + + if ( !td->cursor_lit && !iconified ) + { + td->cursor_frame = 0; + + /* Hack - Don't draw cursor at (0,0) */ + if ( td->cursor_xpos == 0 && td->cursor_ypos == 0 ) return; + + /* Draw an outlined cursor */ + if ( CUR_A & 0xf0 && use_graphics ) + { + x0 = td->cursor_xpos * td->fw; + y0 = td->cursor_ypos * td->fh; + x1 = x0 + td->fw - 1; + y1 = y0 + td->fh - 1; + SetAPen( td->wrp, PEN( CURSOR_PEN )); + Move( td->wrp, x0, y0 ); + Draw( td->wrp, x1, y0 ); + Draw( td->wrp, x1, y1 ); + Draw( td->wrp, x0, y1 ); + Draw( td->wrp, x0, y0 ); + } + + /* Draw a filled cursor */ + else + { + SetAPen( td->wrp, PEN( CUR_A & 0x0f )); + SetBPen( td->wrp, PEN( CURSOR_PEN )); + Move( td->wrp, td->fw * td->cursor_xpos, td->fh * td->cursor_ypos + td->fb ); + Text( td->wrp, &CUR_C, 1 ); + } + + td->cursor_lit = TRUE; + } +} + +///} +///{ "cursor_off()" + +static void cursor_off( term_data *td ) +{ + if ( td->cursor_lit && !iconified ) + { + /* Restore graphics under cursor */ + if ( CUR_A & 0xf0 && use_graphics ) + { + put_gfx( td->wrp, td->cursor_xpos, td->cursor_ypos, CUR_C, CUR_A ); + } + + /* Restore char/attr under cursor */ + else + { + SetAPen( td->wrp, PEN( CUR_A & 0x0f )); + SetBPen( td->wrp, PEN( 0 )); + Move( td->wrp, td->fw * td->cursor_xpos, td->fh * td->cursor_ypos + td->fb ); + Text( td->wrp, &CUR_C, 1 ); + } + td->cursor_lit = FALSE; + } +} + +///} +///{ "cursor_anim()" + +static void cursor_anim( void ) +{ + term_data *td = term_curs; + int x0, y0, x1, y1, i = p_ptr->px, j = p_ptr->py; + byte tc, ta; + + if ( !term_curs ) return; + + td->cursor_frame = ++(td->cursor_frame) % 8; + + /* Small cursor on map */ + if ( td->cursor_map ) + { + if ( td->cursor_frame & 2 ) + { + SetAPen( td->wrp, PEN( CURSOR_PEN )); + RectFill( td->wrp, + td->map_x + i * td->mpt_w, + td->map_y + j * td->mpt_h, + td->map_x + ( i + 1) * td->mpt_w - 1, + td->map_y + ( j + 1 ) * td->mpt_h - 1 + ); + } + else + { + ta = (( p_ptr->pclass * 10 + p_ptr->prace) >> 5 ) + 12; + tc = (( p_ptr->pclass * 10 + p_ptr->prace) & 0x1f ); + put_gfx_map( td, i, j, tc, ta ); + } + } + + else if ( td->cursor_visible && !iconified ) + { + /* Hack - Don't draw cursor at (0,0) */ + if ( td->cursor_xpos == 0 && td->cursor_ypos == 0 ) return; + + /* Draw an outlined cursor */ + if ( CUR_A & 0x80 && use_graphics ) + { + /* First draw the tile under cursor */ + put_gfx( td->wrp, td->cursor_xpos, td->cursor_ypos, CUR_C, CUR_A ); + + if ( td->cursor_frame < 4 ) + { + x0 = td->cursor_xpos * td->fw; + y0 = td->cursor_ypos * td->fh; + x1 = x0 + td->fw - 1; + y1 = y0 + td->fh - 1; + SetAPen( td->wrp, PEN( CURSOR_PEN )); + Move( td->wrp, x0, y0 ); + Draw( td->wrp, x1, y0 ); + Draw( td->wrp, x1, y1 ); + Draw( td->wrp, x0, y1 ); + Draw( td->wrp, x0, y0 ); + } + } + + /* Draw a filled cursor */ + else + { + SetAPen( td->wrp, PEN( CUR_A & 0x0f )); + SetBPen( td->wrp, ( td->cursor_frame < 4 ) ? PEN( CURSOR_PEN ) : PEN( 0 )); + Move( td->wrp, td->fw * td->cursor_xpos, td->fh * td->cursor_ypos + td->fb ); + Text( td->wrp, &CUR_C, 1 ); + } + } +} + +///} +///{ "load_gfx()" + +int load_gfx( void ) +{ + term_data *ts = &screen; + BPTR file; + char *p; + int plane, row, error = FALSE; + + /* Allocate bitmaps */ + if (( ts->gfxbm = alloc_bitmap( GFXW, GFXH, 4, BMF_CLEAR, ts->rp->BitMap )) == NULL ) return ( FALSE ); + if (( ts->mskbm = alloc_bitmap( GFXW, GFXH, 1, BMF_CLEAR, ts->rp->BitMap )) == NULL ) return ( FALSE ); + + /* Open file */ + if (( file = Open( MGFX, MODE_OLDFILE )) == NULL ) + { + MSG( 0, 0, "Unable to open graphics file" ); + Delay( 100 ); + return ( FALSE ); + } + + /* Read file into bitmap */ + for ( plane = 0; plane < 4 && !error; plane++ ) + { + p = ts->gfxbm->Planes[ plane ]; + for ( row = 0; row < GFXH && !error; row++ ) + { + error = ( Read( file, p, GFXB ) != GFXB ); + p += ts->gfxbm->BytesPerRow; + } + } + + /* Read mask data into bitmap */ + p = ts->mskbm->Planes[ 0 ]; + for ( row = 0; row < GFXH && !error; row++ ) + { + error = ( Read( file, p, GFXB ) != GFXB ); + p += ts->mskbm->BytesPerRow; + } + + /* Close file */ + Close( file ); + + /* Did we get any errors while reading? */ + if ( error ) + { + MSG( 0, 0, "Error while reading graphics file" ); + Delay( 100 ); + return ( FALSE ); + } + + /* Success */ + return ( TRUE ); +} +///} +///{ "conv_gfx()" + +int conv_gfx( void ) +{ + term_data *ts = &screen; + struct BitMap *tmpbm; + struct BitMap *sbm = ts->rp->BitMap; + long stdpens[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + long mskpens[] = { 0, -1 }; + int depth; + BYTE *src, *dst; + int plane, row, byt; + + /* Get depth of display */ + depth = depth_of_bitmap( sbm ); + + /* We don't want 16 or 24 bit displays (yet) */ + if ( depth > 8 ) + { + MSG( 0, 1, "Sorry, max. 8 bit display supported." ); + Delay( 100 ); + return ( FALSE ); + } + + /* Allocate new bitmap with screen's depth */ + if (( tmpbm = alloc_bitmap( GFXW, GFXH, depth, BMF_CLEAR, sbm )) == NULL ) + { + MSG( 0, 1, "Unable to allocate temporary bitmap." ); + Delay( 100 ); + return ( FALSE ); + } + + /* Simple remapping from 4 to 5 planes? */ + if ( depth == 5 && !use_pub ) + { + for ( plane = 0; plane < 4; plane++ ) + { + src = ts->gfxbm->Planes[ plane ]; + dst = tmpbm->Planes[ plane ]; + for ( row = 0; row < GFXH; row++ ) + { + for ( byt = 0; byt < GFXB; byt++ ) + { + dst[ byt ] = src[ byt ]; + } + src += ts->gfxbm->BytesPerRow; + dst += tmpbm->BytesPerRow; + } + } + } + + /* Complex remapping */ + else + { + /* Remap old bitmat into new bitmap */ + remap_bitmap( ts->gfxbm, tmpbm, use_pub ? pubpens : stdpens, GFXW, GFXH ); + } + + /* Free old bitmap */ + free_bitmap( ts->gfxbm ); + ts->gfxbm = tmpbm; + + /* Allocate new bitmap with screen's depth */ + if (( tmpbm = alloc_bitmap( GFXW, GFXH, depth, BMF_CLEAR, sbm )) == NULL ) + { + MSG( 0, 1, "Unable to allocate temporary bitmap." ); + Delay( 100 ); + return ( FALSE ); + } + + /* Simple remapping from 4 to 5 planes? */ + if ( depth == 5 && !use_pub ) + { + for ( plane = 0; plane < 4; plane++ ) + { + src = ts->mskbm->Planes[ 0 ]; + dst = tmpbm->Planes[ plane ]; + for ( row = 0; row < GFXH; row++ ) + { + for ( byt = 0; byt < GFXB; byt++ ) + { + dst[ byt ] = src[ byt ]; + } + src += ts->mskbm->BytesPerRow; + dst += tmpbm->BytesPerRow; + } + } + } + + /* Complex remapping */ + else + { + /* Remap old bitmap into new bitmap */ + remap_bitmap( ts->mskbm, tmpbm, mskpens, GFXW, GFXH ); + } + + /* Free old bitmap */ + free_bitmap( ts->mskbm ); + ts->mskbm = tmpbm; + + /* Done */ + return ( TRUE ); +} + +///} +///{ "size_gfx()" + +int size_gfx( term_data *td ) +{ + term_data *ts = &screen; + int depth; + struct BitMap *sbm = td->rp->BitMap; + struct BitMap *tmpbm; + + /* Calculate tile bitmap dimensions */ + td->gfx_w = 32 * td->fw; + td->gfx_h = 32 * td->fh; + + /* Calculate map bitmap dimensions */ + td->mpt_w = td->ww / MAX_WID; + td->mpt_h = td->wh / MAX_HGT; + td->map_w = td->mpt_w * 32; + td->map_h = td->mpt_h * 32; + + /* Scale tile graphics into map size */ + depth = depth_of_bitmap( ts->gfxbm ); + if (( td->mapbm = alloc_bitmap( td->map_w, td->map_h, depth, BMF_CLEAR, sbm )) == NULL ) return ( FALSE ); + scale_bitmap( ts->gfxbm, GFXW, GFXH, td->mapbm, td->map_w, td->map_h ); + + /* Scale tile graphics */ + depth = depth_of_bitmap( ts->gfxbm ); + if (( tmpbm = alloc_bitmap( td->gfx_w, td->gfx_h, depth, BMF_CLEAR, sbm )) == NULL ) return ( FALSE ); + scale_bitmap( ts->gfxbm, GFXW, GFXH, tmpbm, td->gfx_w, td->gfx_h ); + if ( td->gfxbm ) free_bitmap( td->gfxbm ); + td->gfxbm = tmpbm; + + /* Scale tile mask */ + depth = depth_of_bitmap( ts->mskbm ); + if (( tmpbm = alloc_bitmap( td->gfx_w, td->gfx_h, depth, BMF_CLEAR, sbm )) == NULL ) return ( FALSE ); + scale_bitmap( ts->mskbm, GFXW, GFXH, tmpbm, td->gfx_w, td->gfx_h ); + if ( td->mskbm ) free_bitmap( td->mskbm ); + td->mskbm = tmpbm; + + /* Success */ + return ( TRUE ); +} + +///} +///{ "put_gfx()" + +static void put_gfx( struct RastPort *rp, int x, int y, int chr, int col ) +{ + term_data *td = (term_data*)(Term->data); + int fw = td->fw; + int fh = td->fh; + int x0 = x * fw; + int y0 = y * fh; + int x1 = x0 + fw - 1; + int y1 = y0 + fh - 1; + int a = col & 0x1f; + int c = chr & 0x1f; + + /* Just a black tile */ + if ( a == 0 && c == 0 ) + { + SetAPen( rp, PEN( 0 )); + RectFill( rp, x0, y0, x1, y1 ); + return; + } + + /* Player - Remap for race and class */ + if ( a == 12 && c == 0 ) + { + a = (( p_ptr->pclass * 10 + p_ptr->prace) >> 5 ) + 12; + c = (( p_ptr->pclass * 10 + p_ptr->prace) & 0x1f ); + } + + /* Draw tile through mask */ + if ( col & 0x40 ) + { + SetAPen( rp, PEN(0) ); + RectFill( rp, x0, y0, x1, y1 ); + BltMaskBitMapRastPort( td->gfxbm, c * fw, a * fh, rp, x0, y0, fw, fh, (ABC | ANBC | ABNC), td->mskbm->Planes[ 0 ] ); + } + + /* Draw full tile */ + else + { + BltBitMapRastPort( td->gfxbm, c * fw, a * fh, rp, x0, y0, fw, fh, 0xc0 ); + } +} + +///} +///{ "amiga_fail()" + +static int amiga_fail( char *msg ) +{ + int i; + + /* Print error message */ + if ( msg ) + { + fprintf( stderr, "%s\n", msg ); + } + + /* Free sound memory */ + free_sound(); + + /* Unlock public screen */ + if ( publock ) + { + UnlockPubScreen( NULL, pubscr ); + publock = FALSE; + } + + /* Remove menu from window */ + if ( menu && screen.win ) + { + ClearMenuStrip( screen.win ); + } + + /* Free menus */ + if ( menu ) + { + FreeMenus( menu ); + menu = NULL; + } + + /* Free term resources */ + free_term( &mirror ); + free_term( &recall ); + free_term( &choice ); + free_term( &screen ); + + /* Free obtained pens */ + if ( pubscr ) + { + for ( i = 0; i < 32; i++) + { + if ( pubpens[ i ] != -1 ) + { + ReleasePen( pubscr->ViewPort.ColorMap, pubpens[ i ]); + } + } + } + + /* Free visual info */ + if ( visinfo ) + { + FreeVisualInfo( visinfo ); + visinfo = NULL; + } + + /* Close intuition screen */ + if ( amiscr ) + { + CloseScreen( amiscr ); + amiscr = NULL; + } + + /* Close gadtools.library */ + if ( GadToolsBase ) + { + CloseLibrary( GadToolsBase ); + GadToolsBase = NULL; + } + + /* Close keymap.library */ + if ( KeymapBase ) + { + CloseLibrary( KeymapBase ); + KeymapBase = NULL; + } + + /* Close keymap.library */ + if ( DiskfontBase ) + { + CloseLibrary( DiskfontBase ); + DiskfontBase = NULL; + } + + // Return failure + return ( -1); +} + +///} +///{ "amiga_map()" + +static void amiga_map( void ) +{ + term_data *td = &screen; // (term_data*)(Term->data); + int i, j; + byte ta, tc; + + /* Only in graphics mode */ + if ( !use_graphics ) return; + + /* Turn off cursor */ + if ( td->cursor_visible ) cursor_off( td ); + + /* Save screen */ + Term_save(); + + /* Clear screen */ + Term_clear(); + Term_fresh(); + + /* Calculate offset values */ + td->map_x = (( td->fw * 80 ) - ( td->mpt_w * cur_wid )) / 2; + td->map_y = (( td->fh * 24 ) - ( td->mpt_h * cur_hgt )) / 2; + + /* Draw all "interesting" features */ + for ( i = 0; i < cur_wid; i++ ) + { + for ( j = 0; j < cur_hgt; j++ ) + { + /* Get frame tile */ + if ( i == 0 || i == cur_wid - 1 || j == 0 || j == cur_hgt - 1 ) + { + ta = f_info[ 63 ].z_attr; + tc = f_info[ 63 ].z_char; + } + + /* Get tile from cave table */ + else + { + map_info( j, i, &ta, (char *) &tc ); + } + + /* Ignore non-graphics */ + if ( ta & 0x80 ) + { + ta &= 0x1f; + tc &= 0x1f; + + /* Player XXX XXX XXX */ + if ( ta == 12 && tc == 0 ) + { + ta = (( p_ptr->pclass * 10 + p_ptr->prace ) >> 5 ) + 12; + tc = (( p_ptr->pclass * 10 + p_ptr->prace ) & 0x1f ); + } + + /* Put the graphics to the screen */ + put_gfx_map( td, i, j, tc, ta ); + } + } + } + + /* Draw a small cursor now */ + td->cursor_map = TRUE; + + /* Wait for a keypress, flush key buffer */ + Term_inkey( &tc, TRUE, TRUE ); + Term_flush(); + + /* Normal cursor again */ + td->cursor_map = FALSE; + + /* Restore screen */ + Term_clear(); + Term_fresh(); + Term_load(); + Term_fresh(); + + /* Turn cursor back on */ + if ( td->cursor_visible ) cursor_on( td ); +} + +///} +///{ "load_palette()" + +void load_palette( void ) +{ + int i; + int n; + + if ( amiscr == NULL ) return; + + n = deep ? 32 : 16; + + if ( v39 ) + { + palette32[ 0 ] = n << 16; + palette32[ n * 3 + 1 ] = 0; + for ( i = 0; i < n; i++ ) + { + palette32[ i * 3 + 1 ] = color_table[ use_graphics ? i : i + 16 ][ 1 ] << 24; + palette32[ i * 3 + 2 ] = color_table[ use_graphics ? i : i + 16 ][ 2 ] << 24; + palette32[ i * 3 + 3 ] = color_table[ use_graphics ? i : i + 16 ][ 3 ] << 24; + } + LoadRGB32( &amiscr->ViewPort, palette32 ); + } + else + { + for ( i = 0; i < n; i++ ) + { + palette4[ i ] = ( color_table[ use_graphics ? i : i + 16 ][ 1 ] >> 4 ) << 8; + palette4[ i ] |= ( color_table[ use_graphics ? i : i + 16 ][ 2 ] >> 4 ) << 4; + palette4[ i ] |= ( color_table[ use_graphics ? i : i + 16 ][ 3 ] >> 4 ); + } + LoadRGB4( &amiscr->ViewPort, palette4, n ); + } +} + +///} +///{ "create_menus()" + +int create_menus( void ) +{ + option_type *opt; + struct NewMenu *item = newmenu; + int nmsize = sizeof ( struct NewMenu ); + int page = -1; + int pg = 0; + int i, o; + + /* Copy all pre-items into array */ + for ( i = 0; pre_item[ i ].nm_Type != 255; i++ ) + { + memcpy( item++, &pre_item[ i ], nmsize ); + } + + /* Find next option */ + for ( opt = options, o = 0; opt->o_desc; opt++, o++ ) + { + /* Cheating options are skipped */ + if ( opt->o_page > 6 ) continue; + + /* New page of options? */ + if ( page != opt->o_page ) + { + page = opt->o_page; + + /* Copy option header */ + memcpy( item++, &opt_item[ pg++ ], nmsize ); + } + + /* Insert fields for this option */ + item->nm_Type = NM_SUB; + item->nm_CommKey = 0; + item->nm_MutualExclude = 0; + + /* Use option description as menu text */ + item->nm_Label = (STRPTR) opt->o_desc; + + /* Insert option index into userdata field */ + item->nm_UserData = (void *)( MNU_OPTION + o ); + + /* Use checkmark on this item */ + item->nm_Flags = CHECKIT | MENUTOGGLE; + + /* Done with this item */ + item++; + } + + /* Copy all post-items into array */ + for ( i = 0; post_item[ i ].nm_Type != 255; i++ ) + { + memcpy( item++, &post_item[ i ], nmsize ); + } + + /* Actually create the menu structures */ + menu = CreateMenus( newmenu, NULL ); + + if ( menu ) + { + /* Layout menus */ + if ( LayoutMenus( menu, visinfo, v39 ? GTMN_NewLookMenus : TAG_IGNORE, TRUE, TAG_END )) + { + /* Attach menu to window */ + SetMenuStrip( screen.win , menu ); + } + + /* Free menus */ + else + { + FreeMenus( menu ); + menu = NULL; + } + } + + /* Success */ + return ( menu != NULL ); +} + +///} +///{ "update_menus()" + +void update_menus( void ) +{ + struct MenuItem *father, *item; + int i; + + /* Require a window and a menu */ + if ( !screen.win || !menu ) return; + + /* Detach the menu from the window */ + // ClearMenuStrip( screen.win ); + + /* Initial menuitem and subitem for options */ + father = menu->FirstItem; + item = father->SubItem; + + /* Find next option */ + for ( i = 0; item && options[ i ].o_desc; i++ ) + { + /* Did we find it? */ + if ( item ) + { + /* Option is set, add a checkmark */ + if ( *(options[ i ].o_var )) + { + item->Flags |= CHECKED; + } + + /* Option is not set, remove checkmark */ + else + { + item->Flags &= ~CHECKED; + } + } + + /* Menuitem not found */ + else + { + fprintf( stderr, "ERROR: menuitem #%d not found.\n", i ); + return; + } + + /* Find next menuitem */ + if ((item = item->NextItem ) == NULL ) + { + /* New set */ + father = father->NextItem; + if ( father ) + { + item = father->SubItem; + } + } + } + + /* Enable/Disable the amiga map according to use_graphics */ + if ( item = ItemAddress( menu, FULLMENUNUM( 6, 7, 0 ))) + { + item->Flags = use_graphics ? item->Flags | ITEMENABLED : item->Flags & ~ITEMENABLED; + } + + /* Attach menu to window again */ + // ResetMenuStrip( screen.win, menu ); +} + +///} +///{ "init_sound()" + + +int init_sound( void ) +{ + int i; + char tmp[256]; + char buf[256]; + struct AmiSound *snd; + + /* Load samples */ + for ( i = 0; i < NSAMPLES; i++ ) + { + /* Pointer to sound data */ + snd = &sound_data[ i ]; + + /* Should this sample be loaded into memory? */ + if ( snd->Memory ) + { + /* Construct filename */ + path_build(buf, 255, ANGBAND_DIR_XTRA, "sound"); + + /* Construct filename */ + path_build(tmp, 255, buf, snd->Name ); + + /* Load the sample into memory */ + snd->Address = (struct SoundInfo *) PrepareSound( tmp ); + } + } + + /* Success */ + has_sound = TRUE; + use_sound = TRUE; + + return ( TRUE ); +} + +///} +///{ "free_sound()" + +void free_sound( void ) +{ + int i; + + /* Stop all channels */ + StopSound( LEFT0 ); + StopSound( LEFT1 ); + StopSound( RIGHT0 ); + StopSound( RIGHT1 ); + + /* Remove all sounds from memory */ + for ( i = 0; i < NSAMPLES; i++ ) + { + if ( sound_data[ i ].Address ) + { + /* Remove the sound from memory */ + RemoveSound( sound_data[ i ].Address ); + + /* Clear address field */ + sound_data[ i ].Address = NULL; + } + } + + /* Done */ + has_sound = FALSE; + use_sound = FALSE; +} + +///} +///{ "play_sound()" + +static void play_sound( int v ) +{ + struct AmiSound *snd; + struct AmiSound *old_snd; + int rate; + int channel; + int old; + char buf[256]; + char tmp[256]; + + if ( has_sound ) + { + /* Pointer to sound data */ + snd = &sound_data[ v ]; + + /* Channel number */ + channel = snd->Channel; + + /* Last sample played on channel */ + old = channel_last[ channel ]; + + /* Sample Rate */ + rate = snd->Rate; + + /* Random rate on some sounds */ + if ( v == SOUND_HIT || v == SOUND_MISS ) + { + rate = rate - 50 + rand_int( 150 ); + } + + /* Pointer to old sound data */ + old_snd = old >= 0 ? &sound_data[ old ] : NULL; + + /* Stop sound currently playing on this channel */ + StopSound( channel ); + + /* Free old sample if required */ + if ( !old_snd->Memory && old_snd->Address && old != v ) + { + /* Remove it from memory */ + RemoveSound( old_snd->Address ); + + /* Clear address field */ + old_snd->Address = NULL; + } + + /* Load new sample into memory if required */ + if ( !snd->Memory && snd->Address == NULL ) + { + /* Construct filename */ + path_build(buf, 255, ANGBAND_DIR_XTRA, "sound"); + + /* Construct filename */ + path_build(tmp, 255, buf, snd->Name ); + + /* Load the sample into memory */ + snd->Address = (struct SoundInfo *) PrepareSound( tmp ); + } + + /* Make sure the sample is loaded into memory */ + if ( snd->Address ) + { + /* Start playing the sound */ + PlaySound( snd->Address, snd->Volume, channel, rate, snd->Repeats ); + } + + /* Store sample number */ + channel_last[ channel ] = v; + } +} + +///} +///{ put_gfx_map() + +static void put_gfx_map( term_data *td, int x, int y, int c, int a ) +{ + BltBitMapRastPort( + td->mapbm, + c * td->mpt_w, + a * td->mpt_h, + td->wrp, + td->map_x + x * td->mpt_w, + td->map_y + y * td->mpt_h, + td->mpt_w, + td->mpt_h, + 0xc0 + ); +} + +///} +///{ "alloc_bitmap()" + +struct BitMap *alloc_bitmap( int width, int height, int depth, ULONG flags, struct BitMap *friend ) +{ + int p; + struct BitMap *bitmap; + unsigned char *bp; + + /* Kickstart 39+ */ + if ( v39 ) return ( AllocBitMap( width, height, depth, flags, friend )); + + /* Kickstart 38- */ + else + { + /* Allocate bitmap structure */ + if (( bitmap = AllocMem( sizeof( struct BitMap ), MEMF_PUBLIC | MEMF_CLEAR ))) + { + InitBitMap( bitmap, depth, width, height ); + /* Allocate bitplanes */ + for ( p = 0; p < depth; p++ ) + { + bp = AllocRaster( width, height ); + if ( !bp ) break; + bitmap->Planes[ p ] = bp; + } + + /* Out of memory */ + if ( p != depth ) + { + /* Free bitplanes */ + while ( --p >= 0 ) + { + FreeRaster( bitmap->Planes[ p ], width, height ); + } + /* Free bitmap structure */ + FreeMem( bitmap, sizeof( struct BitMap )); + bitmap = NULL; + } + } + return ( bitmap ); + } +} + +///} +///{ "free_bitmap()" + +void free_bitmap( struct BitMap *bitmap ) +{ + int p; + + /* Check for NULL */ + if ( !bitmap ) return; + + /* Kickstart 39+ */ + if ( v39 ) FreeBitMap( bitmap ); + + /* Kickstart 38- */ + else + { + /* Free bitplanes */ + for ( p = 0; p < bitmap->Depth; p++ ) + { + FreeRaster( bitmap->Planes[ p ], bitmap->BytesPerRow * 8, bitmap->Rows ); + } + /* Free bitmap structure */ + FreeMem( bitmap, sizeof( struct BitMap )); + } +} + +///} +///{ scale_bitmap() + +void scale_bitmap( struct BitMap *srcbm, int srcw, int srch, struct BitMap *dstbm, int dstw, int dsth ) +{ + struct BitScaleArgs bsa; + + /* Scale bitmap */ + bsa.bsa_SrcBitMap = srcbm; + bsa.bsa_DestBitMap = dstbm; + bsa.bsa_SrcX = 0; + bsa.bsa_SrcY = 0; + bsa.bsa_SrcWidth = srcw; + bsa.bsa_SrcHeight = srch; + bsa.bsa_DestX = 0; + bsa.bsa_DestY = 0; + bsa.bsa_XSrcFactor = srcw; + bsa.bsa_YSrcFactor = srch; + bsa.bsa_XDestFactor = dstw; + bsa.bsa_YDestFactor = dsth; + bsa.bsa_Flags = 0; + BitMapScale( &bsa ); +} + +///} +///{ "remap_bitmap()" + +void remap_bitmap( struct BitMap *srcbm, struct BitMap *dstbm, long *pens, int width, int height ) +{ + int x, y, p, c, ox, lpr, sd, dd; + int bm[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; + UBYTE *sp[ 4 ]; + UBYTE *dp[ 8 ]; + ULONG ls[ 4 ]; + ULONG ld[ 8 ]; + ULONG mask; + + /* Source bitplanes */ + sd = depth_of_bitmap( srcbm ); + for ( p = 0; p < sd; p++ ) + { + sp[ p ] = srcbm->Planes[ p ]; + } + + /* Destination bitplanes */ + dd = depth_of_bitmap( dstbm ); + for ( p = 0; p < dd; p++ ) + { + dp[ p ] = dstbm->Planes[ p ]; + } + + /* Number of longwords per row */ + lpr = width / 32; + + /* Convert graphics */ + for ( y = 0; y < height; y++ ) + { + ox = 0; + for ( x = 0 ; x < lpr; x++ ) + { + /* Read source longwords */ + for ( p = 0; p < sd; p++ ) ls[ p ] = *(ULONG *)( sp[ p ] + ox); + + /* Clear destination longwords */ + for ( p = 0; p < dd; ld[ p++ ] = 0 ); + + /* Remap */ + for ( mask = 0x80000000; mask != 0; mask >>= 1) + { + /* Find color index */ + for ( p = c = 0; p < sd; p++ ) if ( ls[ p ] & mask ) c |= bm[ p ]; + + /* Remap */ + c = pens[ c ]; + + /* Update destination longwords */ + for ( p = 0; p < dd; p++ ) if ( c & bm[ p ] ) ld[ p ] |= mask; + } + + /* Write destination longwords */ + for ( p = 0; p < dd; p++ ) *(ULONG *)( dp[ p ] + ox ) = ld[ p ]; + + /* Update offset */ + ox += 4; + } + + /* Update pointers to get to next line */ + for ( p = 0; p < sd; sp[ p++ ] += srcbm->BytesPerRow ); + for ( p = 0; p < dd; dp[ p++ ] += dstbm->BytesPerRow ); + } +} + +///} +///{ "depth_of_bitmap()" + +int depth_of_bitmap( struct BitMap *bm ) +{ + int depth; + + if ( v39 ) + { + depth = GetBitMapAttr( bm, BMA_DEPTH ); + } + else + { + depth = bm->Depth; + } + + return ( depth ); +} + +///} + -- cgit v1.2.3