/* 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 ); } ///}