From 15ce2689d489cfd6167c52b4ba85c3f42a6ab858 Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:54 +0000 Subject: [PATCH] *** empty log message *** --- sys/amiga/winchar.c | 1246 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1246 insertions(+) create mode 100644 sys/amiga/winchar.c diff --git a/sys/amiga/winchar.c b/sys/amiga/winchar.c new file mode 100644 index 000000000..2f6e72177 --- /dev/null +++ b/sys/amiga/winchar.c @@ -0,0 +1,1246 @@ +/* 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 + +#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 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_CHIP|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 winami.c for the amiga specific colormap. + */ + +int foreg[AMII_MAXCOLORS] = { 0, 7, 4, 2, 6, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +int backg[AMII_MAXCOLORS] = { 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 */