/* SCCS Id: @(#)winchar.c 3.1 93/07/22 */ /* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993 */ /* Copyright (c) Gregg Wonderly, Naperville Illinois, 1994. */ /* NetHack may be freely redistributed. See license for details. */ #include #include #include #ifndef _DCC #include #endif #include #ifdef TESTING # include "hack.h" #else # include "NH:src/tile.c" #endif #include "NH:win/share/tile.h" #include "NH:sys/amiga/windefs.h" #include "NH:sys/amiga/winext.h" #include "NH:sys/amiga/winproto.h" #ifdef OPT_DISPMAP # define DISPMAP /* use display_map() from dispmap.s */ #endif /* NH:sys/amiga/winvchar.c */ int main ( int , char ** ); struct BitMap *MyAllocBitMap ( int , int , int , long ); void MyFreeBitMap ( struct BitMap * ); void FreeImageFiles ( char **, struct BitMap ** ); void amiv_flush_glyph_buffer ( struct Window * ); void amiv_lprint_glyph ( winid , int , int ); void amii_lprint_glyph ( winid , int , int ); void amiv_start_glyphout ( winid ); void amii_end_glyphout ( winid ); void SetMazeType ( MazeType ); int GlyphToIcon ( int ); void amii_start_glyphout ( winid ); void amii_end_glyphout ( winid ); void amii_flush_glyph_buffer( struct Window * ); int amii_extraplanes = 0; extern int reclip; struct Library *IFFParseBase; struct BitMap *MyAllocBitMap( int xsize, int ysize, int depth, long mflags ); void MyFreeBitMap( struct BitMap *bmp ); #ifdef DISPMAP extern void display_map( struct Window * ); #endif /* * These values will be available from tile.c source * * #define MAXMONTILE 335 * #define MAXOBJTILE 722 * #define MAXOTHTILE 841 */ #define IMGROWS 12 #define IMGCOLUMNS 20 #define IMGPAGESIZE (IMGROWS*IMGCOLUMNS) #define ID_BMAP MAKE_ID('B','M','A','P') /* The type of form we use */ #define ID_BMHD MAKE_ID('B','M','H','D') /* The ILBM bitmap header */ #define ID_CAMG MAKE_ID('C','A','M','G') /* The ILBM camg (ignored) */ #define ID_CMAP MAKE_ID('C','M','A','P') /* Standard ILBM color map */ #define ID_PLNE MAKE_ID('P','L','N','E') /* The plane data */ #define ID_PDAT MAKE_ID('P','D','A','T') /* The PDAT structure below */ struct PDAT pictdata; #define NUMTILEIMAGES 3 char *tileimages[] = { #define TBLMONTILE 0 "NetHack:tiles/monsters.iff", #define TBLOBJTILE 1 "NetHack:tiles/objects.iff", #define TBLOTHTILE 2 "NetHack:tiles/other.iff", 0, }; struct BitMap *ifftimg[ NUMTILEIMAGES ], *tile; #ifdef TESTING short pens[NUMDRIPENS] = { 8, 3, 15, 0, 15, 7, 7, 8, 0 }; main( int argc, char **argv ) { BitMapHeader bmhd; struct IntuiMessage *imsg; long code, class; char buf[100]; int i, x, y, tbl, done = 0, num; struct Window *w; struct Screen *scr; bmhd = ReadTileImageFiles( ); scr = OpenScreenTags( NULL, SA_Depth, pictdata.nplanes + amii_extraplanes, SA_DisplayID, DBLNTSC_MONITOR_ID|HIRESLACE_KEY, SA_Overscan, OSCAN_TEXT, SA_Top, 0, SA_Left, 0, SA_Width, STDSCREENWIDTH, SA_Height, STDSCREENHEIGHT, SA_Type, CUSTOMSCREEN, SA_DetailPen, 0, SA_BlockPen, 1, SA_Title, "NetHack Chars", SA_Pens, pens, TAG_DONE ); if( scr == NULL ) { printf( "no screen\n" ); #undef exit exit( 1 ); } w = OpenWindowTags( 0, WA_CustomScreen, scr, WA_Flags, WFLG_DRAGBAR|WFLG_SIZEGADGET|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET, WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE|IDCMP_MOUSEBUTTONS, WA_Left, 0, WA_Top, scr->WBorTop + 1 + 13, WA_MinWidth, 100, WA_MinHeight, 100, WA_MaxWidth, 700, WA_MaxHeight, 1000, WA_Width, 640, WA_Height, 340, WA_SmartRefresh, TRUE, TAG_DONE ); if( w ) { while( !done ) { for( i = 0; i < NUMTILEIMAGES * IMGPAGESIZE; ++i ) { int dx, dy; tbl = i/IMGPAGESIZE; x = i % IMGPAGESIZE; y = x / IMGCOLUMNS; x = x % IMGCOLUMNS; dx = i % (IMGCOLUMNS*2); dy = i / (IMGCOLUMNS*2); BltBitMapRastPort( ifftimg[ tbl ], x * pictdata.xsize, y * pictdata.ysize, w->RPort, w->BorderLeft + 1 + dx*pictdata.xsize, w->BorderTop + 1 + dy*pictdata.ysize, pictdata.xsize, pictdata.ysize, 0xc0 ); } WaitPort( w->UserPort ); while( imsg = (struct IntuiMessage *)GetMsg( w->UserPort ) ) { class = imsg->Class; code = imsg->Code; ReplyMsg( (struct Message *)imsg ); switch( class ) { case IDCMP_MOUSEBUTTONS: { x = imsg->MouseX - w->BorderLeft; y = imsg->MouseY - w->BorderTop; num = ((y/pictdata.ysize)*IMGCOLUMNS*2)+(x/pictdata.xsize); sprintf( buf, "Char #%d", num ); SetWindowTitles( w, buf, buf ); } break; case IDCMP_CLOSEWINDOW: done = 1; break; } } } CloseWindow( w ); CloseScreen( scr ); } FreeImageFiles(tileimages, ifftimg ); return(0); } #endif BitMapHeader ReadTileImageFiles(){ char *errstr = NULL; BitMapHeader ret = ReadImageFiles(tileimages, ifftimg, &errstr); if(errstr){ panic(errstr); } return ret; } BitMapHeader ReadImageFiles(char **filenames, struct BitMap **iffimg, char **errstrp ) { BitMapHeader *bmhd = NULL, bmhds; unsigned char *cmap; extern int errno; register int i, j; struct IFFHandle *iff; struct StoredProperty *prop; IFFParseBase = OpenLibrary( "iffparse.library", 0L ); if( !IFFParseBase ) { *errstrp = "No iffparse.library"; return bmhds; } /* for( i = 0; filenames[i]; ++i ) memset( iffimg[i], 0, sizeof( struct BitMap ) ); */ for( i = 0; filenames[i]; ++i ) { iff = AllocIFF(); if( !iff ) { FreeImageFiles(filenames, iffimg ); *errstrp = "can't start IFF processing"; return bmhds; } iff->iff_Stream = Open( filenames[i], MODE_OLDFILE ); if( iff->iff_Stream == 0 ) { char *buf = malloc(100+strlen(filenames[i])); FreeImageFiles( filenames, iffimg ); sprintf(buf, "Can't open %s: %s", filenames[i], strerror( errno )); *errstrp = buf; return bmhds; } InitIFFasDOS( iff ); OpenIFF( iff, IFFF_READ ); PropChunk( iff, ID_BMAP, ID_BMHD ); PropChunk( iff, ID_BMAP, ID_CMAP ); PropChunk( iff, ID_BMAP, ID_CAMG ); PropChunk( iff, ID_BMAP, ID_PDAT ); StopChunk( iff, ID_BMAP, ID_PLNE ); if( ( j = ParseIFF( iff, IFFPARSE_SCAN ) ) != 0 ) { char *buf = malloc(100); FreeImageFiles( filenames, iffimg ); sprintf(buf,"ParseIFF failed for image %d, failure code: %d",i,j); *errstrp = buf; return bmhds; } if( prop = FindProp( iff, ID_BMAP, ID_BMHD ) ) { bmhd = (BitMapHeader *)prop->sp_Data; } else { FreeImageFiles(filenames, iffimg); CloseIFF( iff ); Close( iff->iff_Stream ); FreeIFF( iff ); *errstrp = "No BMHD CHUNK in file"; return bmhds; } if( prop = FindProp( iff, ID_BMAP, ID_CMAP ) ) { cmap = prop->sp_Data; for( j = 0; j < (1L << bmhd->nPlanes)*3; j+=3 ) { #if 0 /* Some day we will want to use the larger palette * resolution available under v39 and later. i.e. * 32 instead of 12 bits of color. Ususally this * just means shifting the color left by 16-20 bits * depending on what intensity looks best. Experience * says that the higher values are better intensities. * * For now though we won't do this. The color table * structure is incompatible with earlier versions of * intuition. We would have to do some funny things * to make 3*AMII_MAXCOLORS longs work like 3*AMII_MAXCOLORS * UWORD's at run time... A union would help, but... */ if( IntuitionBase->LibNode.lib_Version >= 39 ) { /* 8 bits of color, so shift to left end. */ amiv_init_map[ j+0 ] = cmap[j+0]<<24; amiv_init_map[ j+1 ] = cmap[j+1]<<24; amiv_init_map[ j+2 ] = cmap[j+2]<<24; } else #endif { /* We can only use 4 bits of the 8 that are stored in the * cmap, so mask them and then shift them into position * for the UWORD value to store. */ #ifndef TESTING amii_initmap[ j/3 ] = amiv_init_map[ j/3 ] = ((cmap[j+0]>>4)<<8)| ((cmap[j+1]>>4)<<4)| (cmap[j+2]>>4); #endif } } } else { FreeImageFiles(filenames, iffimg); CloseIFF( iff ); Close( iff->iff_Stream ); FreeIFF( iff ); *errstrp = "No CMAP CHUNK in file"; return bmhds; } if( prop = FindProp( iff, ID_BMAP, ID_PDAT ) ) { struct PDAT *pp; pp = (struct PDAT *)prop->sp_Data; pictdata = *pp; } else { FreeImageFiles(filenames, iffimg); CloseIFF( iff ); Close( iff->iff_Stream ); FreeIFF( iff ); *errstrp = "No PDAT CHUNK in file"; return bmhds; } iffimg[ i ] = MyAllocBitMap( bmhd->w, bmhd->h, pictdata.nplanes + amii_extraplanes, MEMF_CLEAR ); if( iffimg[ i ] == NULL ) { char *buf = malloc(80); FreeImageFiles(filenames, iffimg); sprintf(buf, "Can't allocate bitmap for image %d\n", i ); *errstrp = buf; return bmhds; } for( j = 0; j < pictdata.nplanes + amii_extraplanes; ++j ) { ReadChunkBytes( iff, iffimg[i]->Planes[j], RASSIZE( bmhd->w, bmhd->h ) ); } bmhds = *bmhd; CloseIFF( iff ); Close( iff->iff_Stream ); FreeIFF( iff ); } CloseLibrary( IFFParseBase ); tile = MyAllocBitMap( pictdata.xsize, pictdata.ysize, pictdata.nplanes + amii_extraplanes, MEMF_CHIP|MEMF_CLEAR ); if( tile == NULL ) { FreeImageFiles(filenames, iffimg); *errstrp = "Can't allocate tile bitmap for scaling"; } return( bmhds ); } struct MyBitMap { struct BitMap bm; long mflags; USHORT xsize, ysize; }; struct BitMap * MyAllocBitMap( int xsize, int ysize, int depth, long mflags ) { int j; struct MyBitMap *bm; bm = (struct MyBitMap *)alloc( sizeof( *bm ) ); if( !bm ) return( NULL ); bm->xsize = xsize; bm->ysize = ysize; InitBitMap( &bm->bm, depth, xsize, ysize ); for( j = 0; j < depth; ++j ) { if( mflags & MEMF_CHIP ) bm->bm.Planes[ j ] = AllocRaster( xsize, ysize ); else bm->bm.Planes[ j ] = AllocMem( RASSIZE( xsize, ysize ), mflags ); if( bm->bm.Planes[ j ] == 0 ) { MyFreeBitMap( &bm->bm ); return( NULL ); } if( mflags & MEMF_CLEAR ) memset( bm->bm.Planes[ j ], 0, RASSIZE( xsize, ysize ) ); } return( &bm->bm ); } void MyFreeBitMap( struct BitMap *bmp ) { int j; struct MyBitMap *bm = (struct MyBitMap *)bmp; for( j = 0; j < bm->bm.Depth; ++j ) { if( bm->bm.Planes[j] ) { if( bm->mflags & MEMF_CHIP ) FreeRaster( bm->bm.Planes[j], bm->xsize, bm->ysize ); else FreeMem( bm->bm.Planes[j], RASSIZE( bm->xsize, bm->ysize ) ); } } free( bm ); } #ifdef TESTING void panic(s,a1,a2,a3,a4) char *s; { printf( s, a1, a2, a3, a4 ); putchar('\n'); } long * alloc(unsigned int x){ long *p = (long *)malloc(x); if(!p){panic("malloc failed"); exit(1);} return p; } #endif void FreeTileImageFiles(){ FreeImageFiles(tileimages,ifftimg); } void FreeImageFiles(char **filenames, struct BitMap **img ) { register int i; for( i = 0; filenames[i]; ++i ) { if( img[ i ] ) MyFreeBitMap( img[ i ] ); } /* REALLY ugly hack alert! */ if( tile && img==ifftimg) MyFreeBitMap( tile ); } #ifndef TESTING /* * Define some stuff for our special glyph drawing routines */ unsigned short glyph_node_index, glyph_buffer_index; #define NUMBER_GLYPH_NODES 80 #define GLYPH_BUFFER_SIZE 512 struct amiv_glyph_node { short odstx, odsty; short srcx, srcy, dstx, dsty; struct BitMap *bitmap; }; struct amiv_glyph_node amiv_g_nodes[NUMBER_GLYPH_NODES]; static char amiv_glyph_buffer[GLYPH_BUFFER_SIZE]; void flush_glyph_buffer( vw ) struct Window *vw; { if( WINVERS_AMIV ) amiv_flush_glyph_buffer ( vw ); else amii_flush_glyph_buffer ( vw ); } /* * Routine to flush whatever is buffered */ void amiv_flush_glyph_buffer( vw ) struct Window *vw; { #if !defined(DISPMAP) || defined(OPT_DISPMAP) int xsize, ysize, x, y; struct BitScaleArgs bsa; struct BitScaleArgs bsm; struct RastPort rast; struct Window *w = NULL; struct BitMap *imgbm = 0, *bm = 0; int i, k; int scaling_needed; register struct RastPort *rp = vw->RPort; #endif /* If nothing is buffered, return before we do anything */ if(glyph_node_index == 0) return; cursor_off( WIN_MAP ); amiv_start_glyphout( WIN_MAP ); #ifdef OPT_DISPMAP if(flags.fast_map){ #endif #ifdef DISPMAP display_map( vw ); #endif #ifdef OPT_DISPMAP } else { #endif #if !defined(DISPMAP) || defined(OPT_DISPMAP) /* XXX fix indent */ /* This is a dynamic value based on this relationship. */ scaling_needed = ( pictdata.xsize != mxsize || pictdata.ysize != mysize ); /* If overview window is up, set up to render the correct scale there */ if( WIN_OVER != WIN_ERR && ( w = amii_wins[ WIN_OVER ]->win ) != NULL ) { InitRastPort( &rast ); /* Calculate the x and y size of each tile for a ROWNO by COLNO map */ xsize = (w->Width - w->BorderLeft - w->BorderRight) / COLNO; ysize = (w->Height - w->BorderTop - w->BorderBottom) / ROWNO; /* Get a chip memory bitmap to blit out of */ bm = MyAllocBitMap( pictdata.xsize, pictdata.ysize, pictdata.nplanes + amii_extraplanes, MEMF_CLEAR|MEMF_CHIP ); if( bm == NULL ) { amii_putstr( WIN_MESSAGE, 0, "Can't allocate bitmap for scaling overview window" ); } rast.BitMap = bm; memset( &bsa, 0, sizeof( bsa ) ); bsa.bsa_SrcX = bsa.bsa_SrcY = 0; bsa.bsa_SrcBitMap = tile; bsa.bsa_SrcWidth = pictdata.xsize; bsa.bsa_SrcHeight = pictdata.ysize; bsa.bsa_XSrcFactor = pictdata.xsize; bsa.bsa_YSrcFactor = pictdata.ysize; bsa.bsa_DestX = 0; bsa.bsa_DestY = 0; bsa.bsa_DestWidth = xsize; bsa.bsa_DestHeight = ysize; bsa.bsa_XDestFactor = xsize; bsa.bsa_YDestFactor = ysize; bsa.bsa_DestBitMap = bm; } if( scaling_needed ) { /* Fill in scaling data for map rendering */ memset( &bsm, 0, sizeof( bsm ) ); bsm.bsa_SrcX = bsm.bsa_SrcY = 0; bsm.bsa_SrcBitMap = tile; bsm.bsa_SrcWidth = pictdata.xsize; bsm.bsa_SrcHeight = pictdata.ysize; bsm.bsa_XSrcFactor = pictdata.xsize; bsm.bsa_YSrcFactor = pictdata.ysize; bsm.bsa_DestWidth = mxsize; bsm.bsa_DestHeight = mysize; bsm.bsa_XDestFactor = mxsize; bsm.bsa_YDestFactor = mysize; bsm.bsa_DestBitMap = rp->BitMap; bsm.bsa_DestY = bsm.bsa_DestX = 0; imgbm = MyAllocBitMap( mxsize, mysize, pictdata.nplanes + amii_extraplanes, MEMF_CLEAR|MEMF_CHIP ); if( imgbm == NULL ) { amii_putstr( WIN_MESSAGE, 0, "Can't allocate scaling bitmap for map window" ); } else bsm.bsa_DestBitMap = imgbm; } /* Go ahead and start dumping the stuff */ for( i=0; iBytesPerRow; for( j = 0; j < pictdata.nplanes + amii_extraplanes; ++j ) { for( k = 0; k < pictdata.ysize; ++k ) { /* For a 16x16 tile, this could just be short assignments, but * this code is generalized to handle any size tile image... */ memcpy( tile->Planes[ j ] + ( ( k * pictdata.ysize ) / 8 ), nodebm->Planes[ j ] + offx + offy + ( nodebm->BytesPerRow * k ), pictdata.ysize/8 ); } } if( !clipping || ( x >= clipx && y >= clipy && x < clipxmax && y < clipymax ) ) { /* scaling is needed, do it */ if( scaling_needed ) { BitMapScale( &bsm ); BltBitMapRastPort( imgbm, 0, 0, rp, amiv_g_nodes[ i ].dstx, amiv_g_nodes[ i ].dsty, mxsize, mysize, 0xc0 ); } else { BltBitMapRastPort( tile, 0, 0, rp, amiv_g_nodes[ i ].dstx, amiv_g_nodes[ i ].dsty, pictdata.xsize, pictdata.ysize, 0xc0 ); } } /* Draw the overview window unless we are scrolling the map raster around */ if( bm && w && reclip != 2 ) { BitMapScale( &bsa ); BltBitMapRastPort( rast.BitMap, 0, 0, w->RPort, w->BorderLeft + amiv_g_nodes[ i ].odstx*xsize, w->BorderTop + amiv_g_nodes[ i ].odsty*ysize, xsize, ysize, 0xc0 ); } } if( imgbm ) MyFreeBitMap( imgbm ); if( bm ) MyFreeBitMap( bm ); #endif /* DISPMAP */ #ifdef OPT_DISPMAP } #endif amii_end_glyphout( WIN_MAP ); /* Clean up */ glyph_node_index = glyph_buffer_index = 0; } /* * Glyph buffering routine. Called instead of WindowPuts(). */ void amiv_lprint_glyph(window,color_index, glyph) winid window; int color_index, glyph; { int base; struct amii_WinDesc *cw; struct Window *w; int curx; int cury; int tbl, icon; register int xoff, yoff; /* Get the real icon index */ if( glyph != NO_GLYPH ) icon = GlyphToIcon( glyph ); if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) panic("bad winid in amiv_lprint_glyph: %d", window ); w = cw->win; if( glyph != NO_GLYPH && glyph < 10000) { /* decide on which image has the needed picture */ if( icon <= MAXMONTILE ) { tbl = TBLMONTILE; base = 0; } else if( icon <= MAXOBJTILE ) { tbl = TBLOBJTILE; base = MAXMONTILE+1; } else if( icon <= MAXOTHTILE ) { tbl = TBLOTHTILE; base = MAXOBJTILE+1; } else panic( "Bad icon #%d, glyph #%d, only %d icons known\n", icon, glyph, MAXOTHTILE ); /* Get the relative offset in the page */ /* How many pixels to account for y distance down */ yoff = ((icon-base) / pictdata.across) * pictdata.ysize; /* How many pixels to account for x distance across */ xoff = ((icon-base) % pictdata.across) * pictdata.xsize; } if(glyph >= 10000){ /* Run a single ASCII character out to the rastport right now */ char c= glyph-10000; int xxx,xxy; struct RastPort *rp = w->RPort; Move(rp, xxx=(((cw->curx-clipx)*rp->TxWidth) + w->BorderLeft), xxy=(w->BorderTop + (((cw->cury-clipy)+1)* rp->TxHeight)+1)); Text(rp,&c,1); /* XXX this shouldn't be necessary: */ if(cw->cursx == xxx && cw->cursy == xxy){ cw->wflags &= ~FLMAP_CURSUP; } cw->curx += rp->TxWidth; /* keep things in sync */ return; } if( cw->type == NHW_MAP ) { curx = cw->curx - clipx; cury = cw->cury - clipy; /* See if we're out of glyph nodes */ if(glyph_node_index >= NUMBER_GLYPH_NODES) amiv_flush_glyph_buffer( w ); /* Fill in the node. */ amiv_g_nodes[glyph_node_index].dsty = min( w->BorderTop + (cury * mysize), w->Height - 1 ); #ifdef OPT_DISPMAP if(flags.fast_map){ #endif /* keni */ #ifdef DISPMAP /* display_map() needs byte-aligned destinations, and we don't want to * overwrite the window border. */ amiv_g_nodes[glyph_node_index].dstx = (w->BorderLeft + 8 + (curx * mxsize)) & -8; #endif #ifdef OPT_DISPMAP } else { #endif #if !defined(DISPMAP) || defined(OPT_DISPMAP) amiv_g_nodes[glyph_node_index].dstx = min( w->BorderLeft + (curx * mxsize), w->Width - 1 ); #endif #ifdef OPT_DISPMAP } #endif amiv_g_nodes[glyph_node_index].odsty = cw->cury; amiv_g_nodes[glyph_node_index].odstx = cw->curx; amiv_g_nodes[glyph_node_index].srcx = xoff; amiv_g_nodes[glyph_node_index].srcy = yoff; amiv_g_nodes[glyph_node_index].bitmap = ifftimg[ tbl ]; ++glyph_node_index; } else { /* Do it */ register int j, k, x, y, apen; struct RastPort *rp = w->RPort; x = rp->cp_x - pictdata.xsize - 3; #ifdef OPT_DISPMAP if(flags.fast_map){ #endif #ifdef DISPMAP x &= -8; if(x==0) x = 8; #endif #ifdef OPT_DISPMAP } #endif y = rp->cp_y - pictdata.ysize + 1; if( glyph != NO_GLYPH ) { struct BitMap *bm = ifftimg[ tbl ]; /* 8 bits per byte */ xoff /= 8; yoff *= bm->BytesPerRow; for( j = 0; j < pictdata.nplanes; ++j ) { for( k = 0; k < pictdata.ysize; ++k ) { memcpy( tile->Planes[ j ] + ( ( k * pictdata.ysize ) / 8 ), bm->Planes[ j ] + xoff + yoff + ( bm->BytesPerRow * k ), pictdata.ysize/8 ); } } BltBitMapRastPort( tile, 0, 0, rp, x, y, pictdata.xsize, pictdata.ysize, 0xc0 ); apen = rp->FgPen; SetAPen( rp, flags.amii_dripens[ SHINEPEN ] ); Move( rp, x-1, y + pictdata.ysize ); Draw( rp, x-1, y - 1 ); Draw( rp, x + pictdata.xsize, y - 1 ); SetAPen( rp, flags.amii_dripens[ SHADOWPEN ] ); Move( rp, x + pictdata.xsize, y ); Draw( rp, x + pictdata.xsize, y + pictdata.ysize ); Draw( rp, x, y + pictdata.ysize ); SetAPen( rp, apen ); } else if( x > w->BorderLeft ) { int apen, bpen; apen = rp->FgPen; bpen = rp->BgPen; SetAPen( rp, amii_menuBPen ); SetBPen( rp, amii_menuBPen ); RectFill( rp, x-1, y-1, x + pictdata.xsize, y + pictdata.ysize ); SetAPen( rp, apen ); SetBPen( rp, bpen ); } } } /* * Define some variables which will be used to save context when toggling * back and forth between low level text and console I/O. */ static long xsave, ysave, modesave, apensave, bpensave; static int usecolor; /* * The function is called before any glyphs are driven to the screen. It * removes the cursor, saves internal state of the window, then returns. */ void amiv_start_glyphout(window) winid window; { struct amii_WinDesc *cw; struct Window *w; if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) panic( "bad winid %d in start_glyphout()", window ); if( cw->wflags & FLMAP_INGLYPH ) return; if( !(w = cw->win ) ) panic( "bad winid %d, no window ptr set", window ); /* * Save the context of the window */ xsave = w->RPort->cp_x; ysave = w->RPort->cp_y; modesave = w->RPort->DrawMode; apensave = w->RPort->FgPen; bpensave = w->RPort->BgPen; /* * Set the mode, and be done with it */ usecolor = iflags.use_color; iflags.use_color = FALSE; cw->wflags |= FLMAP_INGLYPH; } /* * General cleanup routine -- flushes and restores cursor */ void amii_end_glyphout(window) winid window; { struct amii_WinDesc *cw; struct Window *w; if( ( cw = amii_wins[ window ] ) == (struct amii_WinDesc *)NULL ) panic("bad window id %d in amii_end_glyphout()", window ); if( ( cw->wflags & FLMAP_INGLYPH ) == 0 ) return; cw->wflags &= ~(FLMAP_INGLYPH); if( !(w = cw->win ) ) panic( "bad winid %d, no window ptr set", window ); /* * Clean up whatever is left in the buffer */ iflags.use_color = usecolor; /* * Reset internal data structs */ SetAPen(w->RPort, apensave); SetBPen(w->RPort, bpensave); SetDrMd(w->RPort, modesave); Move(w->RPort, xsave, ysave); } static maze_type=COL_MAZE_BRICK; void SetMazeType(MazeType t) { maze_type=t; } int GlyphToIcon(int glyph) { if(glyph>10000)return glyph; return( glyph2tile[glyph] ); } #endif #ifdef AMII_GRAPHICS # ifdef TESTING /* * Define some stuff for our special glyph drawing routines */ static unsigned short glyph_node_index, glyph_buffer_index; # define NUMBER_GLYPH_NODES 80 # define GLYPH_BUFFER_SIZE 512 # endif /* TESTING */ struct amii_glyph_node { short x; short y; short len; unsigned char bg_color; unsigned char fg_color; char *buffer; }; static struct amii_glyph_node amii_g_nodes[NUMBER_GLYPH_NODES]; static char amii_glyph_buffer[GLYPH_BUFFER_SIZE]; #ifdef TEXTCOLOR /* * Map our amiga-specific colormap into the colormap specified in color.h. * See amiwind.c for the amiga specific colormap. */ int foreg[16] = { 0, 7, 4, 2, 6, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; int backg[16] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 1, 6, 5, 3, 1 }; #if 0 #define CLR_BLACK 0 #define CLR_RED 1 #define CLR_GREEN 2 #define CLR_BROWN 3 /* on IBM, low-intensity yellow is brown */ #define CLR_BLUE 4 #define CLR_MAGENTA 5 #define CLR_CYAN 6 #define CLR_GRAY 7 /* low-intensity white */ #define NO_COLOR 8 #define CLR_ORANGE 9 #define CLR_BRIGHT_GREEN 10 #define CLR_YELLOW 11 #define CLR_BRIGHT_BLUE 12 #define CLR_BRIGHT_MAGENTA 13 #define CLR_BRIGHT_CYAN 14 #define CLR_WHITE 15 #define CLR_MAX 16 #endif #endif #ifndef TESTING /* * Begin Revamped Text display routines * * Up until version 3.1, the only method for displaying text on the playing * field was by using the console.device. This was nice for a number of * reasons, the most signifigant of which was a lot of the nuts and bolts was * done for you via escape sequences interpreted by said device. This did * not come without a price however. And that price was speed. It has now * come to a point where the speed has now been deemed unacceptable. * * The following series of routines are designed to drop into the current * nethack display code, using hooks provided for such a measure. It works * on similar principals as the WindowPuts(), buffering I/O internally * until either an explicit flush or internal buffering is exceeded, thereby * forcing the flush. The output (or glyphs) does not go to the * console.device, however. It is driven directly to the rasterport of the * nethack window via the low-level Text() calls, increasing the speed by * a very signifigant factor. */ /* * Routine to simply flush whatever is buffered */ void amii_flush_glyph_buffer( w ) struct Window *w; { short i, x, y; register struct RastPort *rp = w->RPort; /* If nothing is buffered, return before we do anything */ if(glyph_node_index == 0) return; cursor_off( WIN_MAP ); amii_start_glyphout( WIN_MAP ); /* Set up the drawing mode */ SetDrMd( rp, JAM2); /* Go ahead and start dumping the stuff */ for(i=0; iBorderTop + (amii_g_nodes[i].y-2) * rp->TxHeight + rp->TxBaseline + 1; x = amii_g_nodes[i].x * rp->TxWidth + w->BorderLeft; /* Move pens to correct location */ Move( rp, (long)x, (long)y); /* Setup the colors */ SetAPen( rp, (long)amii_g_nodes[i].fg_color); SetBPen( rp, (long)amii_g_nodes[i].bg_color); /* Do it */ Text( rp, amii_g_nodes[i].buffer, amii_g_nodes[i].len); } amii_end_glyphout( WIN_MAP ); /* Clean up */ glyph_node_index = glyph_buffer_index = 0; } void amiga_print_glyph(window,color_index, glyph) winid window; int color_index, glyph; { if( WINVERS_AMIV ) amiv_lprint_glyph(window,color_index, glyph); else amii_lprint_glyph(window,color_index, glyph); } /* * Glyph buffering routine. Called instead of WindowPuts(). */ void amii_lprint_glyph(window,color_index, glyph) winid window; int color_index, glyph; { int fg_color, bg_color; struct amii_WinDesc *cw; struct Window *w; int curx; int cury; if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) panic("bad winid in amii_lprint_glyph: %d", window ); w = cw->win; curx=cw->curx; cury=cw->cury; #ifdef TEXTCOLOR fg_color = foreg[color_index]; bg_color = backg[color_index]; #else fg_color = 1; bg_color = 0; #endif /* TEXTCOLOR */ /* See if we have enough character buffer space... */ if(glyph_buffer_index >= GLYPH_BUFFER_SIZE) amii_flush_glyph_buffer( w ); /* * See if we can append it to the current active node of glyph buffer. It * must satisfy the following conditions: * * * background colors are the same, AND * * foreground colors are the same, AND * * they are precisely side by side */ if((glyph_buffer_index != 0) && (fg_color == amii_g_nodes[glyph_node_index-1].fg_color) && (bg_color == amii_g_nodes[glyph_node_index-1].bg_color) && (amii_g_nodes[glyph_node_index-1].x+ amii_g_nodes[glyph_node_index-1].len == curx) && (amii_g_nodes[glyph_node_index-1].y == cury)) { /* * Add it to the end of the buffer */ amii_glyph_buffer[glyph_buffer_index++] = glyph; amii_g_nodes[glyph_node_index-1].len ++; } else { /* See if we're out of glyph nodes */ if(glyph_node_index >= NUMBER_GLYPH_NODES) amii_flush_glyph_buffer( w ); amii_g_nodes[glyph_node_index].len = 1; amii_g_nodes[glyph_node_index].x = curx; amii_g_nodes[glyph_node_index].y = cury; amii_g_nodes[glyph_node_index].fg_color = fg_color; amii_g_nodes[glyph_node_index].bg_color = bg_color; amii_g_nodes[glyph_node_index].buffer = &amii_glyph_buffer[glyph_buffer_index]; amii_glyph_buffer[glyph_buffer_index] = glyph; ++glyph_buffer_index; ++glyph_node_index; } } #endif /* !TESTING */ #ifdef TESTING /* * Define some variables which will be used to save context when toggling * back and forth between low level text and console I/O. */ static long xsave, ysave, modesave, apensave, bpensave; static int usecolor; #endif /* TESTING */ #ifndef TESTING /* * The function is called before any glyphs are driven to the screen. It * removes the cursor, saves internal state of the window, then returns. */ void amii_start_glyphout(window) winid window; { struct amii_WinDesc *cw; struct Window *w; if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) panic( "bad winid %d in start_glyphout()", window ); if( cw->wflags & FLMAP_INGLYPH ) return; if( !(w = cw->win ) ) panic( "bad winid %d, no window ptr set", window ); /* * Save the context of the window */ xsave = w->RPort->cp_x; ysave = w->RPort->cp_y; modesave = w->RPort->DrawMode; apensave = w->RPort->FgPen; bpensave = w->RPort->BgPen; /* * Set the mode, and be done with it */ usecolor = iflags.use_color; iflags.use_color = FALSE; cw->wflags |= FLMAP_INGLYPH; } #endif /* !TESTING */ # if 0 /* * General cleanup routine -- flushes and restores cursor */ void amii_end_glyphout(window) winid window; { struct amii_WinDesc *cw; struct Window *w; if( ( cw = amii_wins[ window ] ) == (struct amii_WinDesc *)NULL ) panic("bad window id %d in amii_end_glyphout()", window ); if( ( cw->wflags & FLMAP_INGLYPH ) == 0 ) return; cw->wflags &= ~(FLMAP_INGLYPH); if( !(w = cw->win ) ) panic( "bad winid %d, no window ptr set", window ); /* * Clean up whatever is left in the buffer */ iflags.use_color = usecolor; /* * Reset internal data structs */ SetAPen(w->RPort, apensave); SetBPen(w->RPort, bpensave); SetDrMd(w->RPort, modesave); Move(w->RPort, xsave, ysave); } # endif #endif #ifndef TESTING # ifdef OPT_DISPMAP /* don't use dispmap unless x & y are 8,16,24,32,48 and equal */ void dispmap_sanity(){ if( mxsize != mysize || dispmap_sanity1(mxsize) || dispmap_sanity1(mysize)){ flags.fast_map = 0; } } int dispmap_sanity1(x) int x; { static unsigned char valid[] = {8,16,24,32,48,0}; return !!strchr(valid,x); } # endif /* OPT_DISPMAP */ #endif /* TESTING */