pax_global_header00006660000000000000000000000064121771723750014526gustar00rootroot0000000000000052 comment=bde6da6d58b73f1ce589669be2c5b961a773b8ec dxx-rebirth-0.58.1-d2x/000077500000000000000000000000001217717237500145545ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/.gitignore000066400000000000000000000011071217717237500165430ustar00rootroot00000000000000# Compiled source # ################### *.com *.class *.dll *.exe *.app *.o *.so *.pyc build # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods *.7z *.dmg *.gz *.iso *.jar *.rar *.tar *.zip # Logs and databases # ###################### *.log *.sql *.sqlite *.dblite # OS generated files # ###################### .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes Icon? ehthumbs.db Thumbs.db # Xcode generated files # ###################### # Note: committing these is optional *.mode1v3 *.pbxuserdxx-rebirth-0.58.1-d2x/2d/000077500000000000000000000000001217717237500150615ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/2d/2dsline.c000066400000000000000000000043441217717237500165720ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for drawing solid scanlines. * */ #include #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "dxxerror.h" void gr_linear_darken(ubyte * dest, int darkening_level, int count, ubyte * fade_table) { register int i; for (i=0;icv_fade_level >= GR_FADE_OFF) { switch(TYPE) { case BM_LINEAR: #ifdef OGL case BM_OGL: #endif gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1); break; } } else { switch(TYPE) { case BM_LINEAR: #ifdef OGL case BM_OGL: #endif gr_linear_darken( DATA + ROWSIZE*y + x1, grd_curcanv->cv_fade_level, x2-x1+1, gr_fade_table); break; } } } void gr_scanline( int x1, int x2, int y ) { if ((y<0)||(y>MAXY)) return; if (x2 < x1 ) x2 ^= x1 ^= x2; if (x1 > MAXX) return; if (x2 < MINX) return; if (x1 < MINX) x1 = MINX; if (x2 > MAXX) x2 = MAXX; if (grd_curcanv->cv_fade_level >= GR_FADE_OFF) { switch(TYPE) { case BM_LINEAR: #ifdef OGL case BM_OGL: #endif gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1); break; } } else { switch(TYPE) { case BM_LINEAR: #ifdef OGL case BM_OGL: #endif gr_linear_darken( DATA + ROWSIZE*y + x1, grd_curcanv->cv_fade_level, x2-x1+1, gr_fade_table); break; } } } dxx-rebirth-0.58.1-d2x/2d/bitblt.c000066400000000000000000000405051217717237500165110ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines for bitblt's. * */ #include #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "rle.h" #include "dxxerror.h" #include "byteswap.h" #ifdef OGL #include "ogl_init.h" #endif static int gr_bitblt_dest_step_shift = 0; static int gr_bitblt_double = 0; static ubyte *gr_bitblt_fade_table=NULL; static void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); static void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); static void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); static void gr_linear_movsd( ubyte * source, ubyte * dest, unsigned int nbytes) { memcpy(dest,source,nbytes); } static void gr_linear_rep_movsdm(ubyte *src, ubyte *dest, int num_pixels) { register ubyte c; while (num_pixels--) if ((c=*src++)!=255) *dest++=c; else dest++; } static void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, int num_pixels, ubyte fade_value ) { register ubyte c; while (num_pixels--) if ((c=*src++)!=255) *dest++=gr_fade_table[((int)fade_value<<8)|(int)c]; else dest++; } static void gr_linear_rep_movsd_2x(ubyte * source, ubyte * dest, uint nbytes ) { register ubyte c; while (nbytes--) { if (nbytes&1) *dest++=*source++; else { unsigned short *sp=(unsigned short *)dest; c=*source++; *sp=((short)c<<8)|(short)c; dest+=2; } } } static void gr_ubitmap00( int x, int y, grs_bitmap *bm ) { register int y1; int dest_rowsize; unsigned char * dest; unsigned char * src; dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift; dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]); src = bm->bm_data; for (y1=0; y1 < bm->bm_h; y1++ ) { if (gr_bitblt_double) gr_linear_rep_movsd_2x( src, dest, bm->bm_w ); else gr_linear_movsd( src, dest, bm->bm_w ); src += bm->bm_rowsize; dest+= (int)(dest_rowsize); } } static void gr_ubitmap00m( int x, int y, grs_bitmap *bm ) { register int y1; int dest_rowsize; unsigned char * dest; unsigned char * src; dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift; dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]); src = bm->bm_data; if (gr_bitblt_fade_table==NULL) { for (y1=0; y1 < bm->bm_h; y1++ ) { gr_linear_rep_movsdm( src, dest, bm->bm_w ); src += bm->bm_rowsize; dest+= (int)(dest_rowsize); } } else { for (y1=0; y1 < bm->bm_h; y1++ ) { gr_linear_rep_movsdm_faded( src, dest, bm->bm_w, gr_bitblt_fade_table[y1+y] ); src += bm->bm_rowsize; dest+= (int)(dest_rowsize); } } } static void gr_ubitmap012( int x, int y, grs_bitmap *bm ) { register int x1, y1; unsigned char * src; src = bm->bm_data; for (y1=y; y1 < (y+bm->bm_h); y1++ ) { for (x1=x; x1 < (x+bm->bm_w); x1++ ) { gr_setcolor( *src++ ); gr_upixel( x1, y1 ); } } } static void gr_ubitmap012m( int x, int y, grs_bitmap *bm ) { register int x1, y1; unsigned char * src; src = bm->bm_data; for (y1=y; y1 < (y+bm->bm_h); y1++ ) { for (x1=x; x1 < (x+bm->bm_w); x1++ ) { if ( *src != 255 ) { gr_setcolor( *src ); gr_upixel( x1, y1 ); } src++; } } } static void gr_ubitmapGENERIC(int x, int y, grs_bitmap * bm) { register int x1, y1; for (y1=0; y1 < bm->bm_h; y1++ ) { for (x1=0; x1 < bm->bm_w; x1++ ) { gr_setcolor( gr_gpixel(bm,x1,y1) ); gr_upixel( x+x1, y+y1 ); } } } static void gr_ubitmapGENERICm(int x, int y, grs_bitmap * bm) { register int x1, y1; ubyte c; for (y1=0; y1 < bm->bm_h; y1++ ) { for (x1=0; x1 < bm->bm_w; x1++ ) { c = gr_gpixel(bm,x1,y1); if ( c != 255 ) { gr_setcolor( c ); gr_upixel( x+x1, y+y1 ); } } } } void gr_ubitmap( int x, int y, grs_bitmap *bm ) { int source, dest; source = bm->bm_type; dest = TYPE; if (source==BM_LINEAR) { switch( dest ) { case BM_LINEAR: if ( bm->bm_flags & BM_FLAG_RLE ) gr_bm_ubitblt00_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap ); else gr_ubitmap00( x, y, bm ); return; #ifdef OGL case BM_OGL: ogl_ubitmapm_cs(x,y,-1,-1,bm,-1,F1_0); return; #endif default: gr_ubitmap012( x, y, bm ); return; } } else { gr_ubitmapGENERIC(x, y, bm); } } void gr_ubitmapm( int x, int y, grs_bitmap *bm ) { int source, dest; source = bm->bm_type; dest = TYPE; if (source==BM_LINEAR) { switch( dest ) { case BM_LINEAR: if ( bm->bm_flags & BM_FLAG_RLE ) gr_bm_ubitblt00m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap ); else gr_ubitmap00m( x, y, bm ); return; #ifdef OGL case BM_OGL: ogl_ubitmapm_cs(x,y,-1,-1,bm,-1,F1_0); return; #endif default: gr_ubitmap012m( x, y, bm ); return; } } else { gr_ubitmapGENERICm(x, y, bm); } } // From Linear to Linear static void gr_bm_ubitblt00(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { unsigned char * dbits; unsigned char * sbits; //int src_bm_rowsize_2, dest_bm_rowsize_2; int dstep; int i; sbits = src->bm_data + (src->bm_rowsize * sy) + sx; dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift; // No interlacing, copy the whole buffer. if (gr_bitblt_double) for (i=0; i < h; i++ ) { gr_linear_rep_movsd_2x( sbits, dbits, w ); sbits += src->bm_rowsize; dbits += dstep; } else for (i=0; i < h; i++ ) { gr_linear_movsd( sbits, dbits, w ); //memcpy(dbits, sbits, w); sbits += src->bm_rowsize; dbits += dstep; } } // From Linear to Linear Masked static void gr_bm_ubitblt00m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { unsigned char * dbits; unsigned char * sbits; //int src_bm_rowsize_2, dest_bm_rowsize_2; int i; sbits = src->bm_data + (src->bm_rowsize * sy) + sx; dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; // No interlacing, copy the whole buffer. if (gr_bitblt_fade_table==NULL) { for (i=0; i < h; i++ ) { gr_linear_rep_movsdm( sbits, dbits, w ); sbits += src->bm_rowsize; dbits += dest->bm_rowsize; } } else { for (i=0; i < h; i++ ) { gr_linear_rep_movsdm_faded( sbits, dbits, w, gr_bitblt_fade_table[dy+i] ); sbits += src->bm_rowsize; dbits += dest->bm_rowsize; } } } void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { int dx1=dx, dx2=dx+dest->bm_w-1; int dy1=dy, dy2=dy+dest->bm_h-1; int sx1=sx, sx2=sx+src->bm_w-1; int sy1=sy, sy2=sy+src->bm_h-1; if ((dx1 >= dest->bm_w ) || (dx2 < 0)) return; if ((dy1 >= dest->bm_h ) || (dy2 < 0)) return; if ( dx1 < 0 ) { sx1 += -dx1; dx1 = 0; } if ( dy1 < 0 ) { sy1 += -dy1; dy1 = 0; } if ( dx2 >= dest->bm_w ) { dx2 = dest->bm_w-1; } if ( dy2 >= dest->bm_h ) { dy2 = dest->bm_h-1; } if ((sx1 >= src->bm_w ) || (sx2 < 0)) return; if ((sy1 >= src->bm_h ) || (sy2 < 0)) return; if ( sx1 < 0 ) { dx1 += -sx1; sx1 = 0; } if ( sy1 < 0 ) { dy1 += -sy1; sy1 = 0; } if ( sx2 >= src->bm_w ) { sx2 = src->bm_w-1; } if ( sy2 >= src->bm_h ) { sy2 = src->bm_h-1; } // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) if ( dx2-dx1+1 < w ) w = dx2-dx1+1; if ( dy2-dy1+1 < h ) h = dy2-dy1+1; if ( sx2-sx1+1 < w ) w = sx2-sx1+1; if ( sy2-sy1+1 < h ) h = sy2-sy1+1; gr_bm_ubitblt(w,h, dx1, dy1, sx1, sy1, src, dest ); } void gr_bm_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { register int x1, y1; if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR )) { if ( src->bm_flags & BM_FLAG_RLE ) gr_bm_ubitblt00_rle( w, h, dx, dy, sx, sy, src, dest ); else gr_bm_ubitblt00( w, h, dx, dy, sx, sy, src, dest ); return; } #ifdef OGL if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL )) { ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest); return; } if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR )) { return; } if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL )) { return; } #endif if ( (src->bm_flags & BM_FLAG_RLE ) && (src->bm_type == BM_LINEAR) ) { gr_bm_ubitblt0x_rle(w, h, dx, dy, sx, sy, src, dest); return; } for (y1=0; y1 < h; y1++ ) { for (x1=0; x1 < w; x1++ ) { gr_bm_pixel( dest, dx+x1, dy+y1, gr_gpixel(src,sx+x1,sy+y1) ); } } } // Clipped bitmap ... void gr_bitmap( int x, int y, grs_bitmap *bm ) { int dx1=x, dx2=x+bm->bm_w-1; int dy1=y, dy2=y+bm->bm_h-1; #ifndef OGL int sx=0, sy=0; #endif if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return; if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return; if ( dx1 < 0 ) { #ifndef OGL sx = -dx1; #endif dx1 = 0; } if ( dy1 < 0 ) { #ifndef OGL sy = -dy1; #endif dy1 = 0; } if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; } if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; } // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) #ifdef OGL ogl_ubitmapm_cs(x, y, 0, 0, bm, -1, F1_0); #else gr_bm_ubitblt(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); #endif } void gr_bitmapm( int x, int y, grs_bitmap *bm ) { int dx1=x, dx2=x+bm->bm_w-1; int dy1=y, dy2=y+bm->bm_h-1; int sx=0, sy=0; if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return; if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return; if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; } if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; } if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; } if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; } // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2) if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_LINEAR )) { if ( bm->bm_flags & BM_FLAG_RLE ) gr_bm_ubitblt00m_rle(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); else gr_bm_ubitblt00m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); return; } gr_bm_ubitbltm(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap ); } void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { register int x1, y1; ubyte c; #ifdef OGL if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL )) { ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest); return; } if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR )) { return; } if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL )) { return; } #endif for (y1=0; y1 < h; y1++ ) { for (x1=0; x1 < w; x1++ ) { if ((c=gr_gpixel(src,sx+x1,sy+y1))!=255) gr_bm_pixel( dest, dx+x1, dy+y1,c ); } } } static void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { unsigned char * dbits; unsigned char * sbits; int i, data_offset; data_offset = 1; if (src->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &src->bm_data[4 + (src->bm_h*data_offset)]; for (i=0; ibm_data[4+(i*data_offset)])); dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; // No interlacing, copy the whole buffer. for (i=0; i < h; i++ ) { gr_rle_expand_scanline( dbits, sbits, sx, sx+w-1 ); if ( src->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)]))); else sbits += (int)(src->bm_data[4+i+sy]); dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift; } } static void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { unsigned char * dbits; unsigned char * sbits; int i, data_offset; data_offset = 1; if (src->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &src->bm_data[4 + (src->bm_h*data_offset)]; for (i=0; ibm_data[4+(i*data_offset)])); dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx; // No interlacing, copy the whole buffer. for (i=0; i < h; i++ ) { gr_rle_expand_scanline_masked( dbits, sbits, sx, sx+w-1 ); if ( src->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)]))); else sbits += (int)(src->bm_data[4+i+sy]); dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift; } } // in rle.c static void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest) { int i, data_offset; register int y1; unsigned char * sbits; data_offset = 1; if (src->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &src->bm_data[4 + (src->bm_h*data_offset)]; for (i=0; ibm_data[4+(i*data_offset)])); for (y1=0; y1 < h; y1++ ) { gr_rle_expand_scanline_generic( dest, dx, dy+y1, sbits, sx, sx+w-1); if ( src->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)]))); else sbits += (int)src->bm_data[4+y1+sy]; } } // rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl static inline void scale_line(unsigned char *in, unsigned char *out, int ilen, int olen) { int a = olen/ilen, b = olen%ilen; int c = 0, i; unsigned char *end = out + olen; while(out= ilen) { c -= ilen; goto inside; } while(--i>=0) { inside: *out++ = *in; } in++; } } void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst) { unsigned char *s = src->bm_data; unsigned char *d = dst->bm_data; int h = src->bm_h; int a = dst->bm_h/h, b = dst->bm_h%h; int c = 0, i, y; for(y=0; y= h) { c -= h; goto inside; } while(--i>=0) { inside: scale_line(s, d, src->bm_w, dst->bm_w); d += dst->bm_rowsize; } s += src->bm_rowsize; } } void show_fullscr(grs_bitmap *bm) { grs_bitmap * const scr = &grd_curcanv->cv_bitmap; #ifdef OGL if(bm->bm_type == BM_LINEAR && scr->bm_type == BM_OGL && bm->bm_w <= grd_curscreen->sc_w && bm->bm_h <= grd_curscreen->sc_h) // only scale with OGL if bitmap is not bigger than screen size { ogl_ubitmapm_cs(0,0,-1,-1,bm,-1,F1_0);//use opengl to scale, faster and saves ram. -MPM return; } #endif if(scr->bm_type != BM_LINEAR) { grs_bitmap *tmp = gr_create_bitmap(scr->bm_w, scr->bm_h); gr_bitmap_scale_to(bm, tmp); gr_bitmap(0, 0, tmp); gr_free_bitmap(tmp); return; } gr_bitmap_scale_to(bm, scr); } // Find transparent area in bitmap void gr_bitblt_find_transparent_area(grs_bitmap *bm, int *minx, int *miny, int *maxx, int *maxy) { ubyte c; int i = 0, x = 0, y = 0, count = 0; static unsigned char buf[1024*1024]; if (!(bm->bm_flags&BM_FLAG_TRANSPARENT)) return; memset(buf,0,1024*1024); *minx = bm->bm_w - 1; *maxx = 0; *miny = bm->bm_h - 1; *maxy = 0; // decode the bitmap if (bm->bm_flags & BM_FLAG_RLE){ unsigned char * dbits; unsigned char * sbits; int i, data_offset; data_offset = 1; if (bm->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)]; dbits = buf; for (i=0; i < bm->bm_h; i++ ) { gr_rle_decode(sbits,dbits); if ( bm->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)]))); else sbits += (int)bm->bm_data[4+i]; dbits += bm->bm_w; } } else { memcpy(&buf, bm->bm_data, sizeof(unsigned char)*(bm->bm_w*bm->bm_h)); } for (y = 0; y < bm->bm_h; y++) { for (x = 0; x < bm->bm_w; x++) { c = buf[i++]; if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here. count++; if (x < *minx) *minx = x; if (y < *miny) *miny = y; if (x > *maxx) *maxx = x; if (y > *maxy) *maxy = y; } } } Assert (count); } dxx-rebirth-0.58.1-d2x/2d/bitmap.c000066400000000000000000000144751217717237500165140ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for manipulating grs_bitmaps. * */ #include #include #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "dxxerror.h" #ifdef OGL #include "ogl_init.h" #endif #include "bitmap.h" void gr_set_bitmap_data (grs_bitmap *bm, unsigned char *data) { #ifdef OGL ogl_freebmtexture(bm); #endif bm->bm_data = data; } grs_bitmap *gr_create_bitmap(int w, int h ) { unsigned char *d; MALLOC(d, unsigned char, MAX_BMP_SIZE(w, h)); return gr_create_bitmap_raw (w, h, d); } grs_bitmap *gr_create_bitmap_raw(int w, int h, unsigned char * raw_data ) { grs_bitmap *n; MALLOC(n, grs_bitmap, 1); gr_init_bitmap (n, 0, 0, 0, w, h, w, raw_data); return n; } void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ) // TODO: virtualize { bm->bm_x = x; bm->bm_y = y; bm->bm_w = w; bm->bm_h = h; bm->bm_flags = 0; bm->bm_type = mode; bm->bm_rowsize = bytesperline; bm->bm_data = NULL; #ifdef OGL bm->bm_parent=NULL;bm->gltexture=NULL; #endif gr_set_bitmap_data (bm, data); } void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline) { gr_init_bitmap(bm, mode, x, y, w, h, bytesperline, 0); unsigned char *d; MALLOC(d, unsigned char, MAX_BMP_SIZE(w, h)); gr_set_bitmap_data(bm, d); } void gr_init_bitmap_data (grs_bitmap *bm) // TODO: virtulize { bm->bm_data = NULL; bm->bm_parent=NULL; #ifdef OGL bm->gltexture=NULL; #endif } grs_bitmap *gr_create_sub_bitmap(grs_bitmap *bm, int x, int y, int w, int h ) { grs_bitmap *n; MALLOC(n, grs_bitmap, 1); gr_init_sub_bitmap (n, bm, x, y, w, h); return n; } void gr_free_bitmap(grs_bitmap *bm ) { gr_free_bitmap_data (bm); if (bm!=NULL) d_free(bm); } void gr_free_sub_bitmap(grs_bitmap *bm ) { if (bm!=NULL) { d_free(bm); } } void gr_free_bitmap_data (grs_bitmap *bm) // TODO: virtulize { #ifdef OGL ogl_freebmtexture(bm); #endif if (bm->bm_data != NULL) d_free (bm->bm_data); bm->bm_data = NULL; } void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h ) // TODO: virtualize { bm->bm_x = x + bmParent->bm_x; bm->bm_y = y + bmParent->bm_y; bm->bm_w = w; bm->bm_h = h; bm->bm_flags = bmParent->bm_flags; bm->bm_type = bmParent->bm_type; bm->bm_rowsize = bmParent->bm_rowsize; #ifdef OGL bm->gltexture=bmParent->gltexture; #endif bm->bm_parent=bmParent; bm->bm_data = bmParent->bm_data+(unsigned int)((y*bmParent->bm_rowsize)+x); } void decode_data(ubyte *data, int num_pixels, ubyte *colormap, int *count) { int i; ubyte mapped; for (i = 0; i < num_pixels; i++) { count[*data]++; mapped = *data; *data = colormap[mapped]; data++; } } void gr_set_bitmap_flags (grs_bitmap *pbm, int flags) { pbm->bm_flags = flags; } void gr_set_transparent (grs_bitmap *pbm, int bTransparent) { if (bTransparent) { gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_TRANSPARENT); } else { gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_TRANSPARENT); } } void gr_set_super_transparent (grs_bitmap *pbm, int bTransparent) { if (bTransparent) { gr_set_bitmap_flags (pbm, pbm->bm_flags & ~BM_FLAG_SUPER_TRANSPARENT); } else { gr_set_bitmap_flags (pbm, pbm->bm_flags | BM_FLAG_SUPER_TRANSPARENT); } } void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ) { int i, r, g, b; for (i=0; i<256; i++ ) { r = *palette++; g = *palette++; b = *palette++; *colormap++ = gr_find_closest_color( r, g, b ); *freq++ = 0; } } void gr_remap_bitmap( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ) { ubyte colormap[256]; int freq[256]; if (bmp->bm_type != BM_LINEAR) return; //can't do it // This should be build_colormap_asm, but we're not using invert table, so... build_colormap_good( palette, colormap, freq ); if ( (super_transparent_color>=0) && (super_transparent_color<=255)) colormap[super_transparent_color] = 254; if ( (transparent_color>=0) && (transparent_color<=255)) colormap[transparent_color] = TRANSPARENCY_COLOR; decode_data(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq ); if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) ) gr_set_transparent (bmp, 1); if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) ) gr_set_super_transparent (bmp, 0); } void gr_remap_bitmap_good( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ) { ubyte colormap[256]; int freq[256]; build_colormap_good( palette, colormap, freq ); if ( (super_transparent_color>=0) && (super_transparent_color<=255)) colormap[super_transparent_color] = 254; if ( (transparent_color>=0) && (transparent_color<=255)) colormap[transparent_color] = TRANSPARENCY_COLOR; if (bmp->bm_w == bmp->bm_rowsize) decode_data(bmp->bm_data, bmp->bm_w * bmp->bm_h, colormap, freq ); else { int y; ubyte *p = bmp->bm_data; for (y=0;ybm_h;y++,p+=bmp->bm_rowsize) decode_data(p, bmp->bm_w, colormap, freq ); } if ( (transparent_color>=0) && (transparent_color<=255) && (freq[transparent_color]>0) ) gr_set_transparent (bmp, 1); if ( (super_transparent_color>=0) && (super_transparent_color<=255) && (freq[super_transparent_color]>0) ) gr_set_super_transparent (bmp, 1); } void gr_bitmap_check_transparency( grs_bitmap * bmp ) { int x, y; ubyte * data; data = bmp->bm_data; for (y=0; ybm_h; y++ ) { for (x=0; xbm_w; x++ ) { if (*data++ == TRANSPARENCY_COLOR ) { gr_set_transparent (bmp, 1); return; } } data += bmp->bm_rowsize - bmp->bm_w; } bmp->bm_flags = 0; } dxx-rebirth-0.58.1-d2x/2d/bitmap.h000066400000000000000000000003071217717237500165060ustar00rootroot00000000000000#ifndef _BITMAP_H #define _BITMAP_H void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ); void decode_data(ubyte *data, int num_pixels, ubyte * colormap, int * count ); #endif dxx-rebirth-0.58.1-d2x/2d/box.c000066400000000000000000000053241217717237500160210ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include "u_mem.h" #include "gr.h" #include "grdef.h" void gr_ubox0(int left,int top,int right,int bot) { int i, d; unsigned char * ptr1; unsigned char * ptr2; ptr1 = DATA + ROWSIZE *top+left; ptr2 = ptr1; d = right - left; for (i=top; i<=bot; i++ ) { ptr2[0] = (unsigned char) COLOR; ptr2[d] = (unsigned char) COLOR; ptr2 += ROWSIZE; } ptr2 = ptr1; d = (bot - top)*ROWSIZE; for (i=1; i<(right-left); i++ ) { ptr2[i+0] = (unsigned char) COLOR; ptr2[i+d] = (unsigned char) COLOR; } } void gr_box0(int left,int top,int right,int bot) { if (top > MAXY ) return; if (bot < MINY ) return; if (left > MAXX ) return; if (right < MINX ) return; if (top < MINY) top = MINY; if (bot > MAXY ) bot = MAXY; if (left < MINX) left = MINX; if (right > MAXX ) right = MAXX; gr_ubox0(left,top,right,bot); } void gr_ubox12(int left,int top,int right,int bot) { #if 0 // the following shifts the box up 1 unit in OpenGL int i; for (i=top; i<=bot; i++ ) { gr_upixel( left, i ); gr_upixel( right, i ); } for (i=left; i<=right; i++ ) { gr_upixel( i, top ); gr_upixel( i, bot ); } #endif gr_uline(i2f(left), i2f(top), i2f(right), i2f(top)); gr_uline(i2f(right), i2f(top), i2f(right), i2f(bot)); gr_uline(i2f(left), i2f(top), i2f(left), i2f(bot)); gr_uline(i2f(left), i2f(bot), i2f(right), i2f(bot)); } void gr_box12(int left,int top,int right,int bot) { if (top > MAXY ) return; if (bot < MINY ) return; if (left > MAXX ) return; if (right < MINX ) return; if (top < MINY) top = MINY; if (bot > MAXY ) bot = MAXY; if (left < MINX) left = MINX; if (right > MAXX ) right = MAXX; gr_ubox12(left, top, right, bot ); } void gr_ubox(int left,int top,int right,int bot) { if (TYPE==BM_LINEAR) gr_ubox0( left, top, right, bot ); else gr_ubox12( left, top, right, bot ); } void gr_box(int left,int top,int right,int bot) { if (TYPE==BM_LINEAR) gr_box0( left, top, right, bot ); else gr_box12( left, top, right, bot ); } dxx-rebirth-0.58.1-d2x/2d/canvas.c000066400000000000000000000062521217717237500165050ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifdef OGL #include "ogl_init.h" #endif grs_canvas * grd_curcanv; //active canvas grs_screen * grd_curscreen; //active screen grs_canvas *gr_create_canvas(int w, int h) { grs_canvas *n; MALLOC(n, grs_canvas, 1); gr_init_bitmap_alloc (&n->cv_bitmap, BM_LINEAR, 0, 0, w, h, w); n->cv_color = 0; n->cv_fade_level = GR_FADE_OFF; n->cv_blend_func = GR_BLEND_NORMAL; n->cv_drawmode = 0; n->cv_font = NULL; n->cv_font_fg_color = 0; n->cv_font_bg_color = 0; return n; } grs_canvas *gr_create_sub_canvas(grs_canvas *canv, int x, int y, int w, int h) { grs_canvas *n; MALLOC(n, grs_canvas, 1); gr_init_sub_bitmap (&n->cv_bitmap, &canv->cv_bitmap, x, y, w, h); n->cv_color = canv->cv_color; n->cv_fade_level = canv->cv_fade_level; n->cv_blend_func = canv->cv_blend_func; n->cv_drawmode = canv->cv_drawmode; n->cv_font = canv->cv_font; n->cv_font_fg_color = canv->cv_font_fg_color; n->cv_font_bg_color = canv->cv_font_bg_color; return n; } void gr_init_canvas(grs_canvas *canv, unsigned char * pixdata, int pixtype, int w, int h) { int wreal; canv->cv_color = 0; canv->cv_fade_level = GR_FADE_OFF; canv->cv_blend_func = GR_BLEND_NORMAL; canv->cv_drawmode = 0; canv->cv_font = NULL; canv->cv_font_fg_color = 0; canv->cv_font_bg_color = 0; wreal = w; gr_init_bitmap (&canv->cv_bitmap, pixtype, 0, 0, w, h, wreal, pixdata); } void gr_init_sub_canvas(grs_canvas *n, grs_canvas *src, int x, int y, int w, int h) { n->cv_color = src->cv_color; n->cv_fade_level = src->cv_fade_level; n->cv_blend_func = src->cv_blend_func; n->cv_drawmode = src->cv_drawmode; n->cv_font = src->cv_font; n->cv_font_fg_color = src->cv_font_fg_color; n->cv_font_bg_color = src->cv_font_bg_color; gr_init_sub_bitmap (&n->cv_bitmap, &src->cv_bitmap, x, y, w, h); } void gr_free_canvas(grs_canvas *canv) { gr_free_bitmap_data(&canv->cv_bitmap); d_free(canv); } void gr_free_sub_canvas(grs_canvas *canv) { d_free(canv); } void gr_set_current_canvas( grs_canvas *canv ) { if (canv==NULL) grd_curcanv = &(grd_curscreen->sc_canvas); else grd_curcanv = canv; } void gr_clear_canvas(int color) { gr_setcolor(color); gr_rect(0,0,GWIDTH-1,GHEIGHT-1); } void gr_setcolor(int color) { grd_curcanv->cv_color=color; } void gr_settransblend(int fade_level, ubyte blend_func) { grd_curcanv->cv_fade_level=fade_level; grd_curcanv->cv_blend_func=blend_func; #ifdef OGL ogl_set_blending(); #endif } dxx-rebirth-0.58.1-d2x/2d/circle.c000066400000000000000000000042771217717237500165000ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifndef OGL int gr_circle(fix xc1,fix yc1,fix r1) { int p,x, y, xc, yc, r; r = f2i(r1); xc = f2i(xc1); yc = f2i(yc1); p=3-(r*2); x=0; y=r; // Big clip if ( (xc+r) < 0 ) return 1; if ( (xc-r) > GWIDTH ) return 1; if ( (yc+r) < 0 ) return 1; if ( (yc-r) > GHEIGHT ) return 1; while(x (b)) ? (a) : (b)) */ #define IABS(x) (((x) < 0) ? -(x) : (x)) #define EXCHG(a,b) do { \ int __temp__ = (a); \ (a) = (b); \ (b) = __temp__; \ } while(0) // sort two values #define SORT2(a,b) do { \ if((a) > (b)) EXCHG(a,b); \ } while(0) # define SCALE(var,arg,num,den) \ ((var) = ((arg) * (num)) / (den)) # define USCALE(var,arg,num,den) \ ((var) = ((unsigned)(arg) * (unsigned)(num)) / (unsigned)(den)) # define FIXSCALE(var,arg,num,den) ((var) = fixmuldiv((arg),(num),(den))) #define CLIPDOT(xx,yy,WHEN_OUTSIDE,WHEN_CLIPPED) { \ if((xx > XMAX) || (xx < XMIN)) { WHEN_OUTSIDE; } \ if((yy > YMAX) || (yy < YMIN)) { WHEN_OUTSIDE; } \ } #define CLIPHLINE(x1,x2,yy,WHEN_OUTSIDE,WHEN_CLIPPED) { \ if(x1 > x2) EXCHG(x1,x2); \ if((x1 > XMAX) || (x2 < XMIN)) { WHEN_OUTSIDE; } \ if((yy > YMAX) || (yy < YMIN)) { WHEN_OUTSIDE; } \ if(x1 < XMIN) { x1 = XMIN; WHEN_CLIPPED; } \ if(x2 > XMAX) { x2 = XMAX; WHEN_CLIPPED; } \ } #define CLIPVLINE(xx,y1,y2,WHEN_OUTSIDE,WHEN_CLIPPED) { \ if(y1 > y2) EXCHG(y1,y2); \ if((xx > XMAX) || (xx < XMIN)) { WHEN_OUTSIDE; } \ if((y1 > YMAX) || (y2 < YMIN)) { WHEN_OUTSIDE; } \ if(y1 < YMIN) { y1 = YMIN; WHEN_CLIPPED; } \ if(y2 > YMAX) { y2 = YMAX; WHEN_CLIPPED; } \ } #define CLIPBOX(x1,y1,x2,y2,WHEN_OUTSIDE,WHEN_CLIPPED) { \ if(x1 > x2) EXCHG(x1,x2); \ if(y1 > y2) EXCHG(y1,y2); \ if((x1 > XMAX) || (x2 < 0)) { WHEN_OUTSIDE; } \ if((y1 > YMAX) || (y2 < 0)) { WHEN_OUTSIDE; } \ if(x1 < 0) { x1 = 0; WHEN_CLIPPED; } \ if(y1 < 0) { y1 = 0; WHEN_CLIPPED; } \ if(x2 > XMAX) { x2 = XMAX; WHEN_CLIPPED; } \ if(y2 > YMAX) { y2 = YMAX; WHEN_CLIPPED; } \ } #define CLIPLINE(x1,y1,x2,y2,XMIN,YMIN,XMAX,YMAX,WHEN_OUTSIDE,WHEN_CLIPPED,MY_SCALE) do { \ register int temp; \ if(y1 > y2) \ { EXCHG(y1,y2); EXCHG(x1,x2); } \ if((y2 < YMIN) || (y1 > YMAX)) \ { WHEN_OUTSIDE; } \ if(x1 < x2) { \ if((x2 < XMIN) || (x1 > XMAX)) { \ WHEN_OUTSIDE; \ } \ if(x1 < XMIN) { \ MY_SCALE(temp,(y2 - y1),(XMIN - x1),(x2 - x1)); \ if((y1 += temp) > YMAX) { WHEN_OUTSIDE; } \ x1 = XMIN; \ WHEN_CLIPPED; \ } \ if(x2 > XMAX) { \ MY_SCALE(temp,(y2 - y1),(x2 - XMAX),(x2 - x1)); \ if((y2 -= temp) < YMIN) { WHEN_OUTSIDE; } \ x2 = XMAX; \ WHEN_CLIPPED; \ } \ if(y1 < YMIN) { \ MY_SCALE(temp,(x2 - x1),(YMIN - y1),(y2 - y1)); \ x1 += temp; \ y1 = YMIN; \ WHEN_CLIPPED; \ } \ if(y2 > YMAX) { \ MY_SCALE(temp,(x2 - x1),(y2 - YMAX),(y2 - y1)); \ x2 -= temp; \ y2 = YMAX; \ WHEN_CLIPPED; \ } \ } \ else { \ if((x1 < XMIN) || (x2 > XMAX)) { \ WHEN_OUTSIDE; \ } \ if(x1 > XMAX) { \ MY_SCALE(temp,(y2 - y1),(x1 - XMAX),(x1 - x2)); \ if((y1 += temp) > YMAX) { WHEN_OUTSIDE; } \ x1 = XMAX; \ WHEN_CLIPPED; \ } \ if(x2 < XMIN) { \ MY_SCALE(temp,(y2 - y1),(XMIN - x2),(x1 - x2)); \ if((y2 -= temp) < YMIN) { WHEN_OUTSIDE; } \ x2 = XMIN; \ WHEN_CLIPPED; \ } \ if(y1 < YMIN) { \ MY_SCALE(temp,(x1 - x2),(YMIN - y1),(y2 - y1)); \ x1 -= temp; \ y1 = YMIN; \ WHEN_CLIPPED; \ } \ if(y2 > YMAX) { \ MY_SCALE(temp,(x1 - x2),(y2 - YMAX),(y2 - y1)); \ x2 += temp; \ y2 = YMAX; \ WHEN_CLIPPED; \ } \ } \ } while(0) dxx-rebirth-0.58.1-d2x/2d/disc.c000066400000000000000000000014401217717237500161460ustar00rootroot00000000000000/* * * Graphical routines for drawing a disk. * */ #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifndef OGL int gr_disk(fix xc1,fix yc1,fix r1) { int p,x, y, xc, yc, r; r = f2i(r1); xc = f2i(xc1); yc = f2i(yc1); p=3-(r*2); x=0; y=r; // Big clip if ( (xc+r) < 0 ) return 1; if ( (xc-r) > GWIDTH ) return 1; if ( (yc+r) < 0 ) return 1; if ( (yc-r) > GHEIGHT ) return 1; while(x #include #include #include #ifndef macintosh #include #endif #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "dxxerror.h" #include "byteswap.h" #include "bitmap.h" #include "makesig.h" #include "gamefont.h" #include "console.h" #include "config.h" #include "inferno.h" #ifdef OGL #include "ogl_init.h" #endif #define FONTSCALE_X(x) ((float)(x)*(FNTScaleX)) #define FONTSCALE_Y(x) ((float)(x)*(FNTScaleY)) #define MAX_OPEN_FONTS 50 typedef struct openfont { char filename[FILENAME_LEN]; grs_font *ptr; char *dataptr; } openfont; //list of open fonts, for use (for now) for palette remapping openfont open_font[MAX_OPEN_FONTS]; #define BITS_TO_BYTES(x) (((x)+7)>>3) int gr_internal_string_clipped(int x, int y, const char *s ); int gr_internal_string_clipped_m(int x, int y, const char *s ); ubyte *find_kern_entry(grs_font *font,ubyte first,ubyte second) { ubyte *p=font->ft_kerndata; while (*p!=255) if (p[0]==first && p[1]==second) return p; else p+=3; return NULL; } //takes the character AFTER being offset into font #define INFONT(_c) ((_c >= 0) && (_c <= grd_curcanv->cv_font->ft_maxchar-grd_curcanv->cv_font->ft_minchar)) //takes the character BEFORE being offset into current font void get_char_width(ubyte c,ubyte c2,int *width,int *spacing) { int letter; letter = c-grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter)) { //not in font, draw as space *width=0; if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) *spacing = FONTSCALE_X(grd_curcanv->cv_font->ft_w)/2; else *spacing = grd_curcanv->cv_font->ft_w; return; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) *width = FONTSCALE_X(grd_curcanv->cv_font->ft_widths[letter]); else *width = grd_curcanv->cv_font->ft_w; *spacing = *width; if (grd_curcanv->cv_font->ft_flags & FT_KERNED) { ubyte *p; if (!(c2==0 || c2=='\n')) { int letter2 = c2-grd_curcanv->cv_font->ft_minchar; if (INFONT(letter2)) { p = find_kern_entry(grd_curcanv->cv_font,(ubyte)letter,letter2); if (p) *spacing = FONTSCALE_X(p[2]); } } } } // Same as above but works with floats, which is better for string-size measurement while being bad for string composition of course void get_char_width_f(ubyte c,ubyte c2,float *width,float *spacing) { int letter; letter = c-grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter)) { //not in font, draw as space *width=0; if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) *spacing = FONTSCALE_X(grd_curcanv->cv_font->ft_w)/2; else *spacing = grd_curcanv->cv_font->ft_w; return; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) *width = FONTSCALE_X(grd_curcanv->cv_font->ft_widths[letter]); else *width = grd_curcanv->cv_font->ft_w; *spacing = *width; if (grd_curcanv->cv_font->ft_flags & FT_KERNED) { ubyte *p; if (!(c2==0 || c2=='\n')) { int letter2 = c2-grd_curcanv->cv_font->ft_minchar; if (INFONT(letter2)) { p = find_kern_entry(grd_curcanv->cv_font,(ubyte)letter,letter2); if (p) *spacing = FONTSCALE_X(p[2]); } } } } int get_centered_x(const char *s) { float w,w2,s2; for (w=0;*s!=0 && *s!='\n';s++) { if (*s<=0x06) { if (*s<=0x03) s++; continue;//skip color codes. } get_char_width_f(s[0],s[1],&w2,&s2); w += s2; } return ((grd_curcanv->cv_bitmap.bm_w - w) / 2); } //hack to allow color codes to be embedded in strings -MPM //note we subtract one from color, since 255 is "transparent" so it'll never be used, and 0 would otherwise end the string. //function must already have orig_color var set (or they could be passed as args...) //perhaps some sort of recursive orig_color type thing would be better, but that would be way too much trouble for little gain int gr_message_color_level=1; #define CHECK_EMBEDDED_COLORS() if ((*text_ptr >= 0x01) && (*text_ptr <= 0x02)) { \ text_ptr++; \ if (*text_ptr){ \ if (gr_message_color_level >= *(text_ptr-1)) \ grd_curcanv->cv_font_fg_color = (unsigned char)*text_ptr; \ text_ptr++; \ } \ } \ else if (*text_ptr == 0x03) \ { \ underline = 1; \ text_ptr++; \ } \ else if ((*text_ptr >= 0x04) && (*text_ptr <= 0x06)){ \ if (gr_message_color_level >= *text_ptr - 3) \ grd_curcanv->cv_font_fg_color=(unsigned char)orig_color; \ text_ptr++; \ } int gr_internal_string0(int x, int y, const char *s ) { unsigned char * fp; const char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int skip_lines = 0; unsigned int VideoOffset, VideoOffset1; bits=0; VideoOffset1 = y * ROWSIZE + x; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; if (x==0x8000) { //centered int xx = get_centered_x(text_ptr1); VideoOffset1 = y * ROWSIZE + xx; } for (r=0; rcv_font->ft_h; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } if (*text_ptr == CC_COLOR) { grd_curcanv->cv_font_fg_color = (unsigned char)*(text_ptr+1); text_ptr += 2; continue; } if (*text_ptr == CC_LSPACING) { skip_lines = *(text_ptr+1) - '0'; text_ptr += 2; continue; } underline = 0; if (*text_ptr == CC_UNDERLINE ) { if ((r==grd_curcanv->cv_font->ft_baseline+2) || (r==grd_curcanv->cv_font->ft_baseline+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); letter = (unsigned char)*text_ptr - grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter)) { //not in font, draw as space VideoOffset += spacing; text_ptr++; continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) fp = grd_curcanv->cv_font->ft_chars[letter]; else fp = grd_curcanv->cv_font->ft_data + letter * BITS_TO_BYTES(width)*grd_curcanv->cv_font->ft_h; if (underline) for (i=0; i< width; i++ ) DATA[VideoOffset++] = (unsigned char) grd_curcanv->cv_font_fg_color; else { fp += BITS_TO_BYTES(width)*r; BitMask = 0; for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) DATA[VideoOffset++] = (unsigned char) grd_curcanv->cv_font_fg_color; else DATA[VideoOffset++] = (unsigned char) grd_curcanv->cv_font_bg_color; BitMask >>= 1; } } VideoOffset += spacing-width; //for kerning text_ptr++; } VideoOffset1 += ROWSIZE; y++; } y += skip_lines; VideoOffset1 += ROWSIZE * skip_lines; skip_lines = 0; } return 0; } int gr_internal_string0m(int x, int y, const char *s ) { unsigned char * fp; const char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int skip_lines = 0; unsigned int VideoOffset, VideoOffset1; int orig_color=grd_curcanv->cv_font_fg_color;//to allow easy reseting to default string color with colored strings -MPM bits = 0; VideoOffset1 = y * ROWSIZE + x; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; if (x==0x8000) { //centered int xx = get_centered_x(text_ptr1); VideoOffset1 = y * ROWSIZE + xx; } for (r=0; rcv_font->ft_h; r++) { text_ptr = text_ptr1; VideoOffset = VideoOffset1; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } if (*text_ptr == CC_COLOR) { grd_curcanv->cv_font_fg_color = (unsigned char)*(text_ptr+1); text_ptr += 2; continue; } if (*text_ptr == CC_LSPACING) { skip_lines = *(text_ptr+1) - '0'; text_ptr += 2; continue; } underline = 0; if (*text_ptr == CC_UNDERLINE ) { if ((r==grd_curcanv->cv_font->ft_baseline+2) || (r==grd_curcanv->cv_font->ft_baseline+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); letter = (unsigned char)*text_ptr-grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter) || (unsigned char) *text_ptr <= 0x06) //not in font, draw as space { CHECK_EMBEDDED_COLORS() else{ VideoOffset += spacing; text_ptr++; } continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) fp = grd_curcanv->cv_font->ft_chars[letter]; else fp = grd_curcanv->cv_font->ft_data + letter * BITS_TO_BYTES(width)*grd_curcanv->cv_font->ft_h; if (underline) for (i=0; i< width; i++ ) DATA[VideoOffset++] = (unsigned char) grd_curcanv->cv_font_fg_color; else { fp += BITS_TO_BYTES(width)*r; BitMask = 0; for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) DATA[VideoOffset++] = (unsigned char) grd_curcanv->cv_font_fg_color; else VideoOffset++; BitMask >>= 1; } } text_ptr++; VideoOffset += spacing-width; } VideoOffset1 += ROWSIZE; y++; } y += skip_lines; VideoOffset1 += ROWSIZE * skip_lines; skip_lines = 0; } return 0; } #ifndef OGL //a bitmap for the character grs_bitmap char_bm = { 0,0,0,0, //x,y,w,h BM_LINEAR, //type BM_FLAG_TRANSPARENT, //flags 0, //rowsize NULL, //data 0, //avg_color 0 //unused }; int gr_internal_color_string(int x, int y, const char *s ) { unsigned char * fp; const char *text_ptr, *next_row, *text_ptr1; int width, spacing,letter; int xx,yy; char_bm.bm_h = grd_curcanv->cv_font->ft_h; //set height for chars of this font next_row = s; yy = y; while (next_row != NULL) { text_ptr1 = next_row; next_row = NULL; text_ptr = text_ptr1; xx = x; if (xx==0x8000) //centered xx = get_centered_x(text_ptr); while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; yy += grd_curcanv->cv_font->ft_h+FSPACY(1); break; } letter = (unsigned char)*text_ptr - grd_curcanv->cv_font->ft_minchar; get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); if (!INFONT(letter)) { //not in font, draw as space xx += spacing; text_ptr++; continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) fp = grd_curcanv->cv_font->ft_chars[letter]; else fp = grd_curcanv->cv_font->ft_data + letter * BITS_TO_BYTES(width)*grd_curcanv->cv_font->ft_h; gr_init_bitmap (&char_bm, BM_LINEAR, 0, 0, width, grd_curcanv->cv_font->ft_h, width, fp); gr_bitmapm(xx,yy,&char_bm); xx += spacing; text_ptr++; } } return 0; } #else //OGL int get_font_total_width(grs_font * font){ if (font->ft_flags & FT_PROPORTIONAL){ int i,w=0,c=font->ft_minchar; for (i=0;c<=font->ft_maxchar;i++,c++){ if (font->ft_widths[i]<0) Error("heh?\n"); w+=font->ft_widths[i]; } return w; }else{ return font->ft_w*(font->ft_maxchar-font->ft_minchar+1); } } void ogl_font_choose_size(grs_font * font,int gap,int *rw,int *rh){ int nchars = font->ft_maxchar-font->ft_minchar+1; int r,x,y,nc=0,smallest=999999,smallr=-1,tries; int smallprop=10000; int h,w; for (h=32;h<=256;h*=2){ // h=pow2ize(font->ft_h*rows+gap*(rows-1)); if (font->ft_h>h)continue; r=(h/(font->ft_h+gap)); w=pow2ize((get_font_total_width(font)+(nchars-r)*gap)/r); tries=0; do { if (tries) w=pow2ize(w+1); if(tries>3){ break; } nc=0; y=0; while(y+font->ft_h<=h){ x=0; while (xft_flags & FT_PROPORTIONAL){ if (x+font->ft_widths[nc]+gap>w)break; x+=font->ft_widths[nc++]+gap; }else{ if (x+font->ft_w+gap>w)break; x+=font->ft_w+gap; nc++; } } if (nc==nchars) break; y+=font->ft_h+gap; } tries++; }while(nc!=nchars); if (nc!=nchars) continue; if (w*h==smallest){//this gives squarer sizes priority (ie, 128x128 would be better than 512*32) if (w>=h){ if (w/hft_maxchar-font->ft_minchar+1; int i,w,h,tw,th,x,y,curx=0,cury=0; unsigned char *fp; ubyte *data; int gap=1; // x/y offset between the chars so we can filter ogl_font_choose_size(font,gap,&tw,&th); MALLOC(data, ubyte, tw*th); memset(data, TRANSPARENCY_COLOR, tw * th); // map the whole data with transparency so we won't have borders if using gap gr_init_bitmap(&font->ft_parent_bitmap,BM_LINEAR,0,0,tw,th,tw,data); gr_set_transparent(&font->ft_parent_bitmap, 1); if (!(font->ft_flags & FT_COLOR)) oglflags |= OGL_FLAG_NOCOLOR; ogl_init_texture(font->ft_parent_bitmap.gltexture = ogl_get_free_texture(), tw, th, oglflags); // have to init the gltexture here so the subbitmaps will find it. font->ft_bitmaps=(grs_bitmap*)d_malloc( nchars * sizeof(grs_bitmap)); h=font->ft_h; for(i=0;ift_flags & FT_PROPORTIONAL) w=font->ft_widths[i]; else w=font->ft_w; if (w<1 || w>256) continue; if (curx+w+gap>tw) { cury+=h+gap; curx=0; } if (cury+h>th) Error("font doesn't really fit (%i/%i)?\n",i,nchars); if (font->ft_flags & FT_COLOR) { if (font->ft_flags & FT_PROPORTIONAL) fp = font->ft_chars[i]; else fp = font->ft_data + i * w*h; for (y=0;yft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=fp[x+y*w]; // Let's call this a HACK: // If we filter the fonts, the sliders will be messed up as the border pixels will have an // alpha value while filtering. So the slider bitmaps will not look "connected". // To prevent this, duplicate the first/last pixel-row with a 1-pixel offset. if (gap && i >= 99 && i <= 102) { // See which bitmaps need left/right shifts: // 99 = SLIDER_LEFT - shift RIGHT // 100 = SLIDER_RIGHT - shift LEFT // 101 = SLIDER_MIDDLE - shift LEFT+RIGHT // 102 = SLIDER_MARKER - shift RIGHT // shift left border if (x==0 && i != 99 && i != 102) font->ft_parent_bitmap.bm_data[(curx+x+(cury+y)*tw)-1]=fp[x+y*w]; // shift right border if (x==w-1 && i != 100) font->ft_parent_bitmap.bm_data[(curx+x+(cury+y)*tw)+1]=fp[x+y*w]; } } } } else { int BitMask,bits=0,white=gr_find_closest_color(63,63,63); if (font->ft_flags & FT_PROPORTIONAL) fp = font->ft_chars[i]; else fp = font->ft_data + i * BITS_TO_BYTES(w)*h; for (y=0;yft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=white; else font->ft_parent_bitmap.bm_data[curx+x+(cury+y)*tw]=255; BitMask >>= 1; } } } gr_init_sub_bitmap(&font->ft_bitmaps[i],&font->ft_parent_bitmap,curx,cury,w,h); curx+=w+gap; } ogl_loadbmtexture_f(&font->ft_parent_bitmap, GameCfg.TexFilt); } int ogl_internal_string(int x, int y, const char *s ) { const char * text_ptr, * next_row, * text_ptr1; int width, spacing,letter; int xx,yy; int orig_color=grd_curcanv->cv_font_fg_color;//to allow easy reseting to default string color with colored strings -MPM int underline; next_row = s; yy = y; if (grd_curscreen->sc_canvas.cv_bitmap.bm_type != BM_OGL) Error("carp.\n"); while (next_row != NULL) { text_ptr1 = next_row; next_row = NULL; text_ptr = text_ptr1; xx = x; if (xx==0x8000) //centered xx = get_centered_x(text_ptr); while (*text_ptr) { int ft_w; if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; yy += FONTSCALE_Y(grd_curcanv->cv_font->ft_h)+FSPACY(1); break; } letter = (unsigned char)*text_ptr - grd_curcanv->cv_font->ft_minchar; get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); underline = 0; if (!INFONT(letter) || (unsigned char)*text_ptr <= 0x06) //not in font, draw as space { CHECK_EMBEDDED_COLORS() else{ xx += spacing; text_ptr++; } if (underline) { ubyte save_c = (unsigned char) COLOR; gr_setcolor(grd_curcanv->cv_font_fg_color); gr_rect(xx, yy + grd_curcanv->cv_font->ft_baseline + 2, xx + grd_curcanv->cv_font->ft_w, yy + grd_curcanv->cv_font->ft_baseline + 3); gr_setcolor(save_c); } continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) ft_w = grd_curcanv->cv_font->ft_widths[letter]; else ft_w = grd_curcanv->cv_font->ft_w; if (grd_curcanv->cv_font->ft_flags&FT_COLOR) ogl_ubitmapm_cs(xx,yy,FONTSCALE_X(ft_w),FONTSCALE_Y(grd_curcanv->cv_font->ft_h),&grd_curcanv->cv_font->ft_bitmaps[letter],-1,F1_0); else{ if (grd_curcanv->cv_bitmap.bm_type==BM_OGL) ogl_ubitmapm_cs(xx,yy,ft_w*(FONTSCALE_X(grd_curcanv->cv_font->ft_w)/grd_curcanv->cv_font->ft_w),FONTSCALE_Y(grd_curcanv->cv_font->ft_h),&grd_curcanv->cv_font->ft_bitmaps[letter],grd_curcanv->cv_font_fg_color,F1_0); else Error("ogl_internal_string: non-color string to non-ogl dest\n"); } xx += spacing; text_ptr++; } } return 0; } int gr_internal_color_string(int x, int y, const char *s ){ return ogl_internal_string(x,y,s); } #endif //OGL int gr_string(int x, int y, const char *s ) { int w, h, aw; int clipped=0; Assert(grd_curcanv->cv_font != NULL); if ( x == 0x8000 ) { if ( y<0 ) clipped |= 1; gr_get_string_size(s, &w, &h, &aw ); // for x, since this will be centered, only look at // width. if ( w > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1; if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1; if ( (y+h) < 0 ) clipped |= 2; if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2; } else { if ( (x<0) || (y<0) ) clipped |= 1; gr_get_string_size(s, &w, &h, &aw ); if ( (x+w) > grd_curcanv->cv_bitmap.bm_w ) clipped |= 1; if ( (y+h) > grd_curcanv->cv_bitmap.bm_h ) clipped |= 1; if ( (x+w) < 0 ) clipped |= 2; if ( (y+h) < 0 ) clipped |= 2; if ( x > grd_curcanv->cv_bitmap.bm_w ) clipped |= 2; if ( y > grd_curcanv->cv_bitmap.bm_h ) clipped |= 2; } if ( !clipped ) return gr_ustring(x, y, s ); if ( clipped & 2 ) { // Completely clipped... return 0; } // Partially clipped... #ifdef OGL if (TYPE==BM_OGL) return ogl_internal_string(x,y,s); #endif if (grd_curcanv->cv_font->ft_flags & FT_COLOR) return gr_internal_color_string( x, y, s); if ( grd_curcanv->cv_font_bg_color == -1) return gr_internal_string_clipped_m( x, y, s ); return gr_internal_string_clipped( x, y, s ); } int gr_ustring(int x, int y, const char *s ) { #ifdef OGL if (TYPE==BM_OGL) return ogl_internal_string(x,y,s); #endif if (grd_curcanv->cv_font->ft_flags & FT_COLOR) { return gr_internal_color_string(x,y,s); } else switch( TYPE ) { case BM_LINEAR: if ( grd_curcanv->cv_font_bg_color == -1) return gr_internal_string0m(x,y,s); else return gr_internal_string0(x,y,s); } return 0; } void gr_get_string_size(const char *s, int *string_width, int *string_height, int *average_width ) { int i = 0; float width=0.0,spacing=0.0,longest_width=0.0,string_width_f=0.0,string_height_f=0.0; string_height_f = FONTSCALE_Y(grd_curcanv->cv_font->ft_h); string_width_f = 0; *average_width = grd_curcanv->cv_font->ft_w; if (s != NULL ) { string_width_f = 0; while (*s) { // if (*s == '&') // s++; while (*s == '\n') { s++; string_height_f += FONTSCALE_Y(grd_curcanv->cv_font->ft_h)+FSPACY(1); string_width_f = 0; } if (*s == 0) break; get_char_width_f(s[0],s[1],&width,&spacing); string_width_f += spacing; if (string_width_f > longest_width) longest_width = string_width_f; i++; s++; } } string_width_f = longest_width; *string_width = string_width_f; *string_height = string_height_f; } int gr_uprintf( int x, int y, const char * format, ... ) { char buffer[1000]; va_list args; va_start(args, format ); vsnprintf(buffer,sizeof(buffer),format,args); return gr_ustring( x, y, buffer ); } int gr_printf( int x, int y, const char * format, ... ) { char buffer[1000]; va_list args; va_start(args, format ); vsnprintf(buffer,sizeof(buffer),format,args); return gr_string( x, y, buffer ); } void gr_close_font( grs_font * font ) { if (font) { int fontnum; char * font_data; //find font in list for (fontnum=0;fontnumft_chars ) d_free( font->ft_chars ); #ifdef OGL if (font->ft_bitmaps) d_free( font->ft_bitmaps ); gr_free_bitmap_data(&font->ft_parent_bitmap); #endif d_free( font ); } } //remap (by re-reading) all the color fonts void gr_remap_color_fonts() { int fontnum; for (fontnum=0;fontnumft_flags & FT_COLOR)) gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr); } } void gr_remap_mono_fonts() { int fontnum; con_printf (CON_DEBUG, "gr_remap_mono_fonts ()\n"); for (fontnum=0;fontnumft_flags & FT_COLOR)) gr_remap_font(font, open_font[fontnum].filename, open_font[fontnum].dataptr); } } /* * reads a grs_font structure from a PHYSFS_file */ static void grs_font_read(grs_font *gf, PHYSFS_file *fp) { gf->ft_w = PHYSFSX_readShort(fp); gf->ft_h = PHYSFSX_readShort(fp); gf->ft_flags = PHYSFSX_readShort(fp); gf->ft_baseline = PHYSFSX_readShort(fp); gf->ft_minchar = PHYSFSX_readByte(fp); gf->ft_maxchar = PHYSFSX_readByte(fp); gf->ft_bytewidth = PHYSFSX_readShort(fp); gf->ft_data = (ubyte *)((size_t)PHYSFSX_readInt(fp) - GRS_FONT_SIZE); gf->ft_chars = (ubyte **)(size_t)PHYSFSX_readInt(fp); gf->ft_widths = (short *)((size_t)PHYSFSX_readInt(fp) - GRS_FONT_SIZE); gf->ft_kerndata = (ubyte *)((size_t)PHYSFSX_readInt(fp) - GRS_FONT_SIZE); } grs_font * gr_init_font( const char * fontname ) { static int first_time=1; grs_font *font; char *font_data; int i,fontnum; unsigned char * ptr; int nchars; PHYSFS_file *fontfile; char file_id[4]; int datasize; //size up to (but not including) palette if (first_time) { int i; for (i=0;ift_maxchar - font->ft_minchar + 1; if (font->ft_flags & FT_PROPORTIONAL) { font->ft_widths = (short *) &font_data[(size_t)font->ft_widths]; font->ft_data = (unsigned char *) &font_data[(size_t)font->ft_data]; font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *)); ptr = font->ft_data; for (i=0; i< nchars; i++ ) { font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]); font->ft_chars[i] = ptr; if (font->ft_flags & FT_COLOR) ptr += font->ft_widths[i] * font->ft_h; else ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h; } } else { font->ft_data = (unsigned char *) font_data; font->ft_chars = NULL; font->ft_widths = NULL; ptr = font->ft_data + (nchars * font->ft_w * font->ft_h); } if (font->ft_flags & FT_KERNED) font->ft_kerndata = (unsigned char *) &font_data[(size_t)font->ft_kerndata]; if (font->ft_flags & FT_COLOR) { //remap palette ubyte palette[256*3]; ubyte colormap[256]; int freq[256]; PHYSFS_read(fontfile,palette,3,256); //read the palette build_colormap_good( (ubyte *)&palette, colormap, freq ); colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh decode_data(font->ft_data, ptr - font->ft_data, colormap, freq ); } PHYSFS_close(fontfile); //set curcanv vars grd_curcanv->cv_font = font; grd_curcanv->cv_font_fg_color = 0; grd_curcanv->cv_font_bg_color = 0; #ifdef OGL ogl_init_font(font); #endif return font; } //remap a font by re-reading its data & palette void gr_remap_font( grs_font *font, char * fontname, char *font_data ) { int i; int nchars; PHYSFS_file *fontfile; char file_id[4]; int datasize; //size up to (but not including) palette unsigned char *ptr; if (! (font->ft_flags & FT_COLOR)) return; fontfile = PHYSFSX_openReadBuffered(fontname); if (!fontfile) Error( "Can't open font file %s", fontname ); PHYSFS_read(fontfile, file_id, 4, 1); if ( !strncmp( file_id, "NFSP", 4 ) ) Error( "File %s is not a font file", fontname ); datasize = PHYSFSX_readInt(fontfile); datasize -= GRS_FONT_SIZE; // subtract the size of the header. d_free(font->ft_chars); grs_font_read(font, fontfile); // have to reread in case mission hogfile overrides font. PHYSFS_read(fontfile, font_data, 1, datasize); //read raw data nchars = font->ft_maxchar - font->ft_minchar + 1; if (font->ft_flags & FT_PROPORTIONAL) { font->ft_widths = (short *) &font_data[(size_t)font->ft_widths]; font->ft_data = (unsigned char *) &font_data[(size_t)font->ft_data]; font->ft_chars = (unsigned char **)d_malloc( nchars * sizeof(unsigned char *)); ptr = font->ft_data; for (i=0; i< nchars; i++ ) { font->ft_widths[i] = INTEL_SHORT(font->ft_widths[i]); font->ft_chars[i] = ptr; if (font->ft_flags & FT_COLOR) ptr += font->ft_widths[i] * font->ft_h; else ptr += BITS_TO_BYTES(font->ft_widths[i]) * font->ft_h; } } else { font->ft_data = (unsigned char *) font_data; font->ft_chars = NULL; font->ft_widths = NULL; ptr = font->ft_data + (nchars * font->ft_w * font->ft_h); } if (font->ft_flags & FT_KERNED) font->ft_kerndata = (unsigned char *) &font_data[(size_t)font->ft_kerndata]; if (font->ft_flags & FT_COLOR) { //remap palette ubyte palette[256*3]; ubyte colormap[256]; int freq[256]; PHYSFS_read(fontfile,palette,3,256); //read the palette build_colormap_good( (ubyte *)&palette, colormap, freq ); colormap[TRANSPARENCY_COLOR] = TRANSPARENCY_COLOR; // changed from colormap[255] = 255 to this for macintosh decode_data(font->ft_data, ptr - font->ft_data, colormap, freq ); } PHYSFS_close(fontfile); #ifdef OGL if (font->ft_bitmaps) d_free( font->ft_bitmaps ); gr_free_bitmap_data(&font->ft_parent_bitmap); ogl_init_font(font); #endif } void gr_set_curfont( grs_font * n) { grd_curcanv->cv_font = n; } void gr_set_fontcolor( int fg_color, int bg_color ) { grd_curcanv->cv_font_fg_color = fg_color; grd_curcanv->cv_font_bg_color = bg_color; } int gr_internal_string_clipped(int x, int y, const char *s ) { unsigned char * fp; const char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int x1 = x, last_x; bits = 0; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; x = x1; if (x==0x8000) //centered x = get_centered_x(text_ptr1); last_x = x; for (r=0; rcv_font->ft_h; r++) { text_ptr = text_ptr1; x = last_x; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } if (*text_ptr == CC_COLOR) { grd_curcanv->cv_font_fg_color = (unsigned char)*(text_ptr+1); text_ptr += 2; continue; } if (*text_ptr == CC_LSPACING) { Int3(); // Warning: skip lines not supported for clipped strings. text_ptr += 2; continue; } underline = 0; if (*text_ptr == CC_UNDERLINE ) { if ((r==grd_curcanv->cv_font->ft_baseline+2) || (r==grd_curcanv->cv_font->ft_baseline+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); letter = (unsigned char)*text_ptr-grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter)) { //not in font, draw as space x += spacing; text_ptr++; continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) fp = grd_curcanv->cv_font->ft_chars[letter]; else fp = grd_curcanv->cv_font->ft_data + letter * BITS_TO_BYTES(width)*grd_curcanv->cv_font->ft_h; if (underline) { for (i=0; i< width; i++ ) { gr_setcolor(grd_curcanv->cv_font_fg_color); gr_pixel( x++, y ); } } else { fp += BITS_TO_BYTES(width)*r; BitMask = 0; for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) gr_setcolor(grd_curcanv->cv_font_fg_color); else gr_setcolor(grd_curcanv->cv_font_bg_color); gr_pixel( x++, y ); BitMask >>= 1; } } x += spacing-width; //for kerning text_ptr++; } y++; } } return 0; } int gr_internal_string_clipped_m(int x, int y, const char *s ) { unsigned char * fp; const char * text_ptr, * next_row, * text_ptr1; int r, BitMask, i, bits, width, spacing, letter, underline; int x1 = x, last_x; bits = 0; next_row = s; while (next_row != NULL ) { text_ptr1 = next_row; next_row = NULL; x = x1; if (x==0x8000) //centered x = get_centered_x(text_ptr1); last_x = x; for (r=0; rcv_font->ft_h; r++) { x = last_x; text_ptr = text_ptr1; while (*text_ptr) { if (*text_ptr == '\n' ) { next_row = &text_ptr[1]; break; } if (*text_ptr == CC_COLOR) { grd_curcanv->cv_font_fg_color = (unsigned char)*(text_ptr+1); text_ptr += 2; continue; } if (*text_ptr == CC_LSPACING) { Int3(); // Warning: skip lines not supported for clipped strings. text_ptr += 2; continue; } underline = 0; if (*text_ptr == CC_UNDERLINE ) { if ((r==grd_curcanv->cv_font->ft_baseline+2) || (r==grd_curcanv->cv_font->ft_baseline+3)) underline = 1; text_ptr++; } get_char_width(text_ptr[0],text_ptr[1],&width,&spacing); letter = (unsigned char)*text_ptr-grd_curcanv->cv_font->ft_minchar; if (!INFONT(letter)) { //not in font, draw as space x += spacing; text_ptr++; continue; } if (grd_curcanv->cv_font->ft_flags & FT_PROPORTIONAL) fp = grd_curcanv->cv_font->ft_chars[letter]; else fp = grd_curcanv->cv_font->ft_data + letter * BITS_TO_BYTES(width)*grd_curcanv->cv_font->ft_h; if (underline) { for (i=0; i< width; i++ ) { gr_setcolor(grd_curcanv->cv_font_fg_color); gr_pixel( x++, y ); } } else { fp += BITS_TO_BYTES(width)*r; BitMask = 0; for (i=0; i< width; i++ ) { if (BitMask==0) { bits = *fp++; BitMask = 0x80; } if (bits & BitMask) { gr_setcolor(grd_curcanv->cv_font_fg_color); gr_pixel( x++, y ); } else { x++; } BitMask >>= 1; } } x += spacing-width; //for kerning text_ptr++; } y++; } } return 0; } dxx-rebirth-0.58.1-d2x/2d/gpixel.c000066400000000000000000000023521217717237500165170ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifdef OGL #include "ogl_init.h" #endif unsigned char gr_ugpixel( grs_bitmap * bitmap, int x, int y ) { switch (bitmap->bm_type) { case BM_LINEAR: return bitmap->bm_data[ bitmap->bm_rowsize*y + x ]; #ifdef OGL case BM_OGL: return ogl_ugpixel(bitmap, x, y); #endif } return 0; } unsigned char gr_gpixel( grs_bitmap * bitmap, int x, int y ) { if ((x<0) || (y<0) || (x>=bitmap->bm_w) || (y>=bitmap->bm_h)) return 0; return gr_ugpixel(bitmap, x, y); } dxx-rebirth-0.58.1-d2x/2d/line.c000066400000000000000000000147741217717237500161710ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for drawing lines. * */ #include #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "fix.h" #include "clip.h" #ifdef OGL #include "ogl_init.h" #endif /* Symmetric Double Step Line Algorithm by Brian Wyvill from "Graphics Gems", Academic Press, 1990 */ /* non-zero flag indicates the pixels needing EXCHG back. */ void plot(int x,int y,int flag) { if (flag) gr_upixel(y, x); else gr_upixel(x, y); } int gr_hline(int x1, int x2, int y) { int i; if (x1 > x2) EXCHG(x1,x2); for (i=x1; i<=x2; i++ ) gr_upixel( i, y ); return 0; } int gr_vline(int y1, int y2, int x) { int i; if (y1 > y2) EXCHG(y1,y2); for (i=y1; i<=y2; i++ ) gr_upixel( x, i ); return 0; } void gr_universal_uline(int a1, int b1, int a2, int b2) { int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; int x1, y1; int sign_x = 1, sign_y = 1, step, reverse, i; if (a1==a2) { gr_vline(b1,b2,a1); return; } if (b1==b2) { gr_hline(a1,a2,b1); return; } dx = a2 - a1; dy = b2 - b1; if (dx < 0) { sign_x = -1; dx *= -1; } if (dy < 0) { sign_y = -1; dy *= -1; } /* decide increment sign by the slope sign */ if (sign_x == sign_y) step = 1; else step = -1; if (dy > dx) { /* chooses axis of greatest movement (make * dx) */ EXCHG(a1, b1); EXCHG(a2, b2); EXCHG(dx, dy); reverse = 1; } else reverse = 0; /* note error check for dx==0 should be included here */ if (a1 > a2) { /* start from the smaller coordinate */ x = a2; y = b2; x1 = a1; y1 = b1; } else { x = a1; y = b1; x1 = a2; y1 = b2; } /* Note dx=n implies 0 - n or (dx+1) pixels to be set */ /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */ /* In fact (dx-1)/4 as 2 pixels are already plottted */ xend = (dx - 1) / 4; pixels_left = (dx - 1) % 4; /* number of pixels left over at the * end */ plot(x, y, reverse); plot(x1, y1, reverse); /* plot first two points */ incr2 = 4 * dy - 2 * dx; if (incr2 < 0) { /* slope less than 1/2 */ c = 2 * dy; incr1 = 2 * c; D = incr1 - dx; for (i = 0; i < xend; i++) { /* plotting loop */ ++x; --x1; if (D < 0) { /* pattern 1 forwards */ plot(x, y, reverse); plot(++x, y, reverse); /* pattern 1 backwards */ plot(x1, y1, reverse); plot(--x1, y1, reverse); D += incr1; } else { if (D < c) { /* pattern 2 forwards */ plot(x, y, reverse); plot(++x, y += step, reverse); /* pattern 2 backwards */ plot(x1, y1, reverse); plot(--x1, y1 -= step, reverse); } else { /* pattern 3 forwards */ plot(x, y += step, reverse); plot(++x, y, reverse); /* pattern 3 backwards */ plot(x1, y1 -= step, reverse); plot(--x1, y1, reverse); } D += incr2; } } /* end for */ /* plot last pattern */ if (pixels_left) { if (D < 0) { plot(++x, y, reverse); /* pattern 1 */ if (pixels_left > 1) plot(++x, y, reverse); if (pixels_left > 2) plot(--x1, y1, reverse); } else { if (D < c) { plot(++x, y, reverse); /* pattern 2 */ if (pixels_left > 1) plot(++x, y += step, reverse); if (pixels_left > 2) plot(--x1, y1, reverse); } else { /* pattern 3 */ plot(++x, y += step, reverse); if (pixels_left > 1) plot(++x, y, reverse); if (pixels_left > 2) plot(--x1, y1 -= step, reverse); } } } /* end if pixels_left */ } /* end slope < 1/2 */ else { /* slope greater than 1/2 */ c = 2 * (dy - dx); incr1 = 2 * c; D = incr1 + dx; for (i = 0; i < xend; i++) { ++x; --x1; if (D > 0) { /* pattern 4 forwards */ plot(x, y += step, reverse); plot(++x, y += step, reverse); /* pattern 4 backwards */ plot(x1, y1 -= step, reverse); plot(--x1, y1 -= step, reverse); D += incr1; } else { if (D < c) { /* pattern 2 forwards */ plot(x, y, reverse); plot(++x, y += step, reverse); /* pattern 2 backwards */ plot(x1, y1, reverse); plot(--x1, y1 -= step, reverse); } else { /* pattern 3 forwards */ plot(x, y += step, reverse); plot(++x, y, reverse); /* pattern 3 backwards */ plot(x1, y1 -= step, reverse); plot(--x1, y1, reverse); } D += incr2; } } /* end for */ /* plot last pattern */ if (pixels_left) { if (D > 0) { plot(++x, y += step, reverse); /* pattern 4 */ if (pixels_left > 1) plot(++x, y += step, reverse); if (pixels_left > 2) plot(--x1, y1 -= step, reverse); } else { if (D < c) { plot(++x, y, reverse); /* pattern 2 */ if (pixels_left > 1) plot(++x, y += step, reverse); if (pixels_left > 2) plot(--x1, y1, reverse); } else { /* pattern 3 */ plot(++x, y += step, reverse); if (pixels_left > 1) plot(++x, y, reverse); if (pixels_left > 2) { if (D > c) /* step 3 */ plot(--x1, y1 -= step, reverse); else /* step 2 */ plot(--x1, y1, reverse); } } } } } } //unclipped version just calls clipping version for now int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2) { int a1,b1,a2,b2; a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2); switch(TYPE) { #ifdef OGL case BM_OGL: ogl_ulinec(a1,b1,a2,b2,COLOR); return 0; #endif case BM_LINEAR: gr_universal_uline( a1,b1,a2,b2); return 0; } return 2; } // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and // 2 if not drawn at all. int gr_line(fix a1, fix b1, fix a2, fix b2) { int x1, y1, x2, y2; int clipped=0; x1 = i2f(MINX); y1 = i2f(MINY); x2 = i2f(MAXX); y2 = i2f(MAXY); CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FIXSCALE ); gr_uline( a1, b1, a2, b2 ); return clipped; } dxx-rebirth-0.58.1-d2x/2d/palette.c000066400000000000000000000155351217717237500166740ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for setting the palette * */ #include #include #include #include "physfsx.h" #include "pstypes.h" #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "dxxerror.h" #include "fix.h" #include "palette.h" extern int gr_installed; #define SQUARE(x) ((x)*(x)) #define MAX_COMPUTED_COLORS 32 int Num_computed_colors=0; typedef struct { ubyte r,g,b,color_num; } color_record; color_record Computed_colors[MAX_COMPUTED_COLORS]; ubyte gr_palette[256*3]; ubyte gr_current_pal[256*3]; ubyte gr_fade_table[256*34]; ubyte gr_palette_gamma = 0; int gr_palette_gamma_param = 0; void gr_palette_set_gamma( int gamma ) { if ( gamma < 0 ) gamma = 0; if ( gamma > 16 ) gamma = 16; //was 8 if (gr_palette_gamma_param != gamma ) { gr_palette_gamma_param = gamma; gr_palette_gamma = gamma; gr_palette_load( gr_palette ); } } int gr_palette_get_gamma() { return gr_palette_gamma_param; } void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size) { memcpy(gr_palette, pal, size); Num_computed_colors = 0; } void gr_use_palette_table( char * filename ) { PHYSFS_file *fp; int i,fsize; #ifdef SWAP_0_255 ubyte c; #endif fp = PHYSFSX_openReadBuffered( filename ); // the following is a hack to enable the loading of d2 levels // even if only the d2 mac shareware datafiles are present. // However, if the pig file is present but the palette file isn't, // the textures in the level will look wierd... if ( fp==NULL) fp = PHYSFSX_openReadBuffered( DEFAULT_LEVEL_PALETTE ); if ( fp==NULL) Error("Can open neither palette file <%s> " "nor default palette file <" DEFAULT_LEVEL_PALETTE ">.\n", filename); fsize = PHYSFS_fileLength( fp ); Assert( fsize == 9472 ); (void)fsize; PHYSFS_read( fp, gr_palette, 256*3, 1 ); PHYSFS_read( fp, gr_fade_table, 256*34, 1 ); PHYSFS_close(fp); // This is the TRANSPARENCY COLOR for (i=0; i> 15; Computed_colors[add_index].r = r; Computed_colors[add_index].g = g; Computed_colors[add_index].b = b; Computed_colors[add_index].color_num = color_num; } void init_computed_colors(void) { int i; for (i=0; i 4) { color_record trec; trec = Computed_colors[i-1]; Computed_colors[i-1] = Computed_colors[i]; Computed_colors[i] = trec; return Computed_colors[i-1].color_num; } return Computed_colors[i].color_num; } // r &= 63; // g &= 63; // b &= 63; best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]); best_index = 0; if (best_value==0) { add_computed_color(r, g, b, best_index); return best_index; } j=0; // only go to 255, 'cause we dont want to check the transparent color. for (i=1; i<254; i++ ) { j += 3; value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]); if ( value < best_value ) { if (value==0) { add_computed_color(r, g, b, i); return i; } best_value = value; best_index = i; } } add_computed_color(r, g, b, best_index); return best_index; } int gr_find_closest_color_15bpp( int rgb ) { return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 ); } int gr_find_closest_color_current( int r, int g, int b ) { int i, j; int best_value, best_index, value; // r &= 63; // g &= 63; // b &= 63; best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]); best_index = 0; if (best_value==0) return best_index; j=0; // only go to 255, 'cause we dont want to check the transparent color. for (i=1; i<254; i++ ) { j += 3; value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]); if ( value < best_value ) { if (value==0) return i; best_value = value; best_index = i; } } return best_index; } void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b ) { int i; ubyte r1, g1, b1; for (i=0; i<256; i++ ) { r1 = gr_palette[i*3+0] + r; if ( r1 > 63 ) r1 = 63; g1 = gr_palette[i*3+1] + g; if ( g1 > 63 ) g1 = 63; b1 = gr_palette[i*3+2] + b; if ( b1 > 63 ) b1 = 63; table[i] = gr_find_closest_color( r1, g1, b1 ); } } void gr_make_blend_table(ubyte *blend_table, ubyte r, ubyte g, ubyte b) { int i, j; float alpha; ubyte r1, g1, b1; for (j = 0; j < GR_FADE_LEVELS; j++) { alpha = 1.0 - (float)j / ((float)GR_FADE_LEVELS - 1); for (i = 0; i < 255; i++) { r1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 0] + (alpha * (float)r)); g1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 1] + (alpha * (float)g)); b1 = (ubyte)((1.0 - alpha) * (float)gr_palette[i * 3 + 2] + (alpha * (float)b)); blend_table[i + j * 256] = gr_find_closest_color(r1, g1, b1); } blend_table[i + j * 256] = 255; // leave white alone } } dxx-rebirth-0.58.1-d2x/2d/pcx.c000066400000000000000000000202361217717237500160220ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to read/write pcx images. * */ #include #include #include #include "gr.h" #include "grdef.h" #include "u_mem.h" #include "pcx.h" #include "physfsx.h" #ifdef OGL #include "palette.h" #endif int pcx_encode_byte(ubyte byt, ubyte cnt, PHYSFS_file *fid); int pcx_encode_line(ubyte *inBuff, int inLen, PHYSFS_file *fp); /* PCX Header data type */ typedef struct { ubyte Manufacturer; ubyte Version; ubyte Encoding; ubyte BitsPerPixel; short Xmin; short Ymin; short Xmax; short Ymax; short Hdpi; short Vdpi; ubyte ColorMap[16][3]; ubyte Reserved; ubyte Nplanes; short BytesPerLine; ubyte filler[60]; } __pack__ PCXHeader; #define PCXHEADER_SIZE 128 /* * reads n PCXHeader structs from a PHYSFS_file */ int PCXHeader_read_n(PCXHeader *ph, int n, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++) { ph->Manufacturer = PHYSFSX_readByte(fp); ph->Version = PHYSFSX_readByte(fp); ph->Encoding = PHYSFSX_readByte(fp); ph->BitsPerPixel = PHYSFSX_readByte(fp); ph->Xmin = PHYSFSX_readShort(fp); ph->Ymin = PHYSFSX_readShort(fp); ph->Xmax = PHYSFSX_readShort(fp); ph->Ymax = PHYSFSX_readShort(fp); ph->Hdpi = PHYSFSX_readShort(fp); ph->Vdpi = PHYSFSX_readShort(fp); PHYSFS_read(fp, &ph->ColorMap, 16*3, 1); ph->Reserved = PHYSFSX_readByte(fp); ph->Nplanes = PHYSFSX_readByte(fp); ph->BytesPerLine = PHYSFSX_readShort(fp); PHYSFS_read(fp, &ph->filler, 60, 1); } return i; } struct PCX_PHYSFS_file { PHYSFS_file *PCXfile; }; static int pcx_read_bitmap_file(struct PCX_PHYSFS_file *const pcxphysfs, grs_bitmap * bmp,int bitmap_type ,ubyte * palette); int pcx_read_bitmap( char * filename, grs_bitmap * bmp,int bitmap_type ,ubyte * palette ) { struct PCX_PHYSFS_file pcxphysfs; int result; pcxphysfs.PCXfile = PHYSFSX_openReadBuffered( filename ); if (!pcxphysfs.PCXfile) return PCX_ERROR_OPENING; result = pcx_read_bitmap_file(&pcxphysfs, bmp, bitmap_type, palette); PHYSFS_close(pcxphysfs.PCXfile); return result; } static int PCX_PHYSFS_read(struct PCX_PHYSFS_file *pcxphysfs, ubyte *data, unsigned size) { return PHYSFS_read(pcxphysfs->PCXfile, data, size, sizeof(*data)); } static int pcx_read_bitmap_file(struct PCX_PHYSFS_file *const pcxphysfs, grs_bitmap * bmp,int bitmap_type ,ubyte * palette) { PCXHeader header; int i, row, col, count, xsize, ysize; ubyte data, *pixdata; // read 128 char PCX header if (PCXHeader_read_n( &header, 1, pcxphysfs->PCXfile )!=1) { return PCX_ERROR_NO_HEADER; } // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { return PCX_ERROR_WRONG_VERSION; } // Find the size of the image xsize = header.Xmax - header.Xmin + 1; ysize = header.Ymax - header.Ymin + 1; if ( bitmap_type == BM_LINEAR ) { if ( bmp->bm_data == NULL ) { gr_init_bitmap_alloc (bmp, bitmap_type, 0, 0, xsize, ysize, xsize); } } if ( bmp->bm_type == BM_LINEAR ) { for (row=0; row< ysize ; row++) { pixdata = &bmp->bm_data[bmp->bm_rowsize*row]; for (col=0; col< xsize ; ) { if (PCX_PHYSFS_read(pcxphysfs, &data, 1) != 1) { return PCX_ERROR_READING; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; if (PCX_PHYSFS_read(pcxphysfs, &data, 1) != 1) { return PCX_ERROR_READING; } memset( pixdata, data, count ); pixdata += count; col += count; } else { *pixdata++ = data; col++; } } } } else { for (row=0; row< ysize ; row++) { for (col=0; col< xsize ; ) { if (PCX_PHYSFS_read(pcxphysfs, &data, 1) != 1) { return PCX_ERROR_READING; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; if (PCX_PHYSFS_read(pcxphysfs, &data, 1) != 1) { return PCX_ERROR_READING; } for (i=0;i>= 2; } } else { return PCX_ERROR_NO_PALETTE; } } return PCX_ERROR_NONE; } int pcx_write_bitmap( char * filename, grs_bitmap * bmp, ubyte * palette ) { int retval; int i; ubyte data; PCXHeader header; PHYSFS_file *PCXfile; memset( &header, 0, PCXHEADER_SIZE ); header.Manufacturer = 10; header.Encoding = 1; header.Nplanes = 1; header.BitsPerPixel = 8; header.Version = 5; header.Xmax = bmp->bm_w-1; header.Ymax = bmp->bm_h-1; header.BytesPerLine = bmp->bm_w; PCXfile = PHYSFSX_openWriteBuffered(filename); if ( !PCXfile ) return PCX_ERROR_OPENING; if (PHYSFS_write(PCXfile, &header, PCXHEADER_SIZE, 1) != 1) { PHYSFS_close(PCXfile); return PCX_ERROR_WRITING; } for (i=0; ibm_h; i++ ) { if (!pcx_encode_line( &bmp->bm_data[bmp->bm_rowsize*i], bmp->bm_w, PCXfile )) { PHYSFS_close(PCXfile); return PCX_ERROR_WRITING; } } // Mark an extended palette data = 12; if (PHYSFS_write(PCXfile, &data, 1, 1) != 1) { PHYSFS_close(PCXfile); return PCX_ERROR_WRITING; } // Write the extended palette for (i=0; i<768; i++ ) palette[i] <<= 2; retval = PHYSFS_write(PCXfile, palette, 768, 1); for (i=0; i<768; i++ ) palette[i] >>= 2; if (retval !=1) { PHYSFS_close(PCXfile); return PCX_ERROR_WRITING; } PHYSFS_close(PCXfile); return PCX_ERROR_NONE; } // returns number of bytes written into outBuff, 0 if failed int pcx_encode_line(ubyte *inBuff, int inLen, PHYSFS_file *fp) { ubyte ub, last; int srcIndex, i; register int total; register ubyte runCount; // max single runlength is 63 total = 0; last = *(inBuff); runCount = 1; for (srcIndex = 1; srcIndex < inLen; srcIndex++) { ub = *(++inBuff); if (ub == last) { runCount++; // it encodes if (runCount == 63) { if (!(i=pcx_encode_byte(last, runCount, fp))) return(0); total += i; runCount = 0; } } else { // this != last if (runCount) { if (!(i=pcx_encode_byte(last, runCount, fp))) return(0); total += i; } last = ub; runCount = 1; } } if (runCount) { // finish up if (!(i=pcx_encode_byte(last, runCount, fp))) return 0; return total + i; } return total; } // subroutine for writing an encoded byte pair // returns count of bytes written, 0 if error int pcx_encode_byte(ubyte byt, ubyte cnt, PHYSFS_file *fid) { if (cnt) { if ( (cnt==1) && (0xc0 != (0xc0 & byt)) ) { if(EOF == PHYSFSX_putc(fid, (int)byt)) return 0; // disk write error (probably full) return 1; } else { if(EOF == PHYSFSX_putc(fid, (int)0xC0 | cnt)) return 0; // disk write error if(EOF == PHYSFSX_putc(fid, (int)byt)) return 0; // disk write error return 2; } } return 0; } //text for error messges static const char pcx_error_messages[] = { "No error.\0" "Error opening file.\0" "Couldn't read PCX header.\0" "Unsupported PCX version.\0" "Error reading data.\0" "Couldn't find palette information.\0" "Error writing data.\0" }; //function to return pointer to error message const char *pcx_errormsg(int error_number) { const char *p = pcx_error_messages; while (error_number--) { if (!p) return NULL; p += strlen(p)+1; } return p; } dxx-rebirth-0.58.1-d2x/2d/pixel.c000066400000000000000000000031371217717237500163520ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for setting a pixel. * */ #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifdef OGL #include "ogl_init.h" #endif void gr_upixel( int x, int y ) { switch (TYPE) { #ifdef OGL case BM_OGL: ogl_upixelc(x,y,COLOR); return; #endif case BM_LINEAR: DATA[ ROWSIZE*y+x ] = COLOR; return; } } void gr_pixel( int x, int y ) { if ((x<0) || (y<0) || (x>=GWIDTH) || (y>=GHEIGHT)) return; gr_upixel (x, y); } static inline void gr_bm_upixel( grs_bitmap * bm, int x, int y, unsigned char color ) { switch (bm->bm_type) { #ifdef OGL case BM_OGL: ogl_upixelc(bm->bm_x+x,bm->bm_y+y,color); return; #endif case BM_LINEAR: bm->bm_data[ bm->bm_rowsize*y+x ] = color; return; } } void gr_bm_pixel( grs_bitmap * bm, int x, int y, unsigned char color ) { if ((x<0) || (y<0) || (x>=bm->bm_w) || (y>=bm->bm_h)) return; gr_bm_upixel (bm, x, y, color); } dxx-rebirth-0.58.1-d2x/2d/rect.c000066400000000000000000000024471217717237500161710ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Graphical routines for drawing rectangles. * */ #include "u_mem.h" #include "gr.h" #include "grdef.h" #ifdef OGL #include "ogl_init.h" #endif void gr_urect(int left,int top,int right,int bot) { #ifdef OGL if (TYPE == BM_OGL) { ogl_urect(left,top,right,bot); return; } #else int i; for ( i=top; i<=bot; i++ ) gr_uscanline( left, right, i ); #endif } void gr_rect(int left,int top,int right,int bot) { int i; #ifdef OGL if (TYPE == BM_OGL) { ogl_urect(left,top,right,bot); return; } #endif for ( i=top; i<=bot; i++ ) gr_scanline( left, right, i ); } dxx-rebirth-0.58.1-d2x/2d/rle.c000066400000000000000000000344551217717237500160220ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to do run length encoding/decoding * on bitmaps. * */ #include #include #include #include "pstypes.h" #include "u_mem.h" #include "gr.h" #include "grdef.h" #include "dxxerror.h" #include "rle.h" #include "byteswap.h" #define RLE_CODE 0xE0 #define NOT_RLE_CODE 31 #define IS_RLE_CODE(x) (((x) & RLE_CODE) == RLE_CODE) #define rle_stosb(_dest, _len, _color) memset(_dest,_color,_len) void gr_rle_decode( ubyte * src, ubyte * dest ) { int i; ubyte data, count = 0; while(1) { data = *src++; if ( ! IS_RLE_CODE(data) ) { *dest++ = data; } else { count = data & NOT_RLE_CODE; if (count == 0) return; data = *src++; for (i = 0; i < count; i++) *dest++ = data; } } } // Given pointer to start of one scanline of rle data, uncompress it to // dest, from source pixels x1 to x2. void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 ) { int i = 0; ubyte count; ubyte color=0; if ( x2 < x1 ) return; count = 0; while ( i < x1 ) { color = *src++; if ( color == RLE_CODE ) return; if ( IS_RLE_CODE(color) ) { count = color & (~RLE_CODE); color = *src++; } else { // unique count = 1; } i += count; } count = i - x1; i = x1; // we know have '*count' pixels of 'color'. if ( x1+count > x2 ) { count = x2-x1+1; if ( color != TRANSPARENCY_COLOR ) rle_stosb( dest, count, color ); return; } if ( color != TRANSPARENCY_COLOR ) rle_stosb( dest, count, color ); dest += count; i += count; while( i <= x2 ) { color = *src++; if ( color == RLE_CODE ) return; if ( IS_RLE_CODE(color) ) { count = color & (~RLE_CODE); color = *src++; } else { // unique count = 1; } // we know have '*count' pixels of 'color'. if ( i+count <= x2 ) { if ( color != 255 )rle_stosb( dest, count, color ); i += count; dest += count; } else { count = x2-i+1; if ( color != 255 )rle_stosb( dest, count, color ); i += count; dest += count; } } } void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 ) { int i = 0; ubyte count; ubyte color=0; if ( x2 < x1 ) return; count = 0; while ( i < x1 ) { color = *src++; if ( color == RLE_CODE ) return; if ( IS_RLE_CODE(color) ) { count = color & (~RLE_CODE); color = *src++; } else { // unique count = 1; } i += count; } count = i - x1; i = x1; // we know have '*count' pixels of 'color'. if ( x1+count > x2 ) { count = x2-x1+1; rle_stosb( dest, count, color ); return; } rle_stosb( dest, count, color ); dest += count; i += count; while( i <= x2 ) { color = *src++; if ( color == RLE_CODE ) return; if ( IS_RLE_CODE(color) ) { count = color & (~RLE_CODE); color = *src++; } else { // unique count = 1; } // we know have '*count' pixels of 'color'. if ( i+count <= x2 ) { rle_stosb( dest, count, color ); i += count; dest += count; } else { count = x2-i+1; rle_stosb( dest, count, color ); i += count; dest += count; } } } int gr_rle_encode( int org_size, ubyte *src, ubyte *dest ) { int i; ubyte c, oc; ubyte count; ubyte *dest_start; dest_start = dest; oc = *src++; count = 1; for (i=1; ibm_h; y++ ) { d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] ); if (d1 > 255) { large_rle = 1; break; } } MALLOC(rle_data, ubyte, MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h)); if (rle_data==NULL) return 0; if (!large_rle) doffset = 4 + bmp->bm_h; else doffset = 4 + (2 * bmp->bm_h); // each row of rle'd bitmap has short instead of byte offset now for (y=0; ybm_h; y++ ) { d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] ); if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > (large_rle?32767:255) ) ) { d_free(rle_data); return 0; } d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] ); Assert( d==d1 ); doffset += d; if (large_rle) *((short *)&(rle_data[(y*2)+4])) = (short)d; else rle_data[y+4] = d; } memcpy( rle_data, &doffset, 4 ); memcpy( bmp->bm_data, rle_data, doffset ); d_free(rle_data); bmp->bm_flags |= BM_FLAG_RLE; if (large_rle) bmp->bm_flags |= BM_FLAG_RLE_BIG; return 1; } #define MAX_CACHE_BITMAPS 32 typedef struct rle_cache_element { grs_bitmap * rle_bitmap; ubyte * rle_data; grs_bitmap * expanded_bitmap; int last_used; } rle_cache_element; int rle_cache_initialized = 0; int rle_counter = 0; int rle_next = 0; rle_cache_element rle_cache[MAX_CACHE_BITMAPS]; int rle_hits = 0; int rle_misses = 0; void rle_cache_close(void) { if (rle_cache_initialized) { int i; rle_cache_initialized = 0; for (i=0; ibm_data[4 + bmp->bm_h]; dbits = rle_temp_bitmap_1->bm_data; rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE); for (i=0; i < bmp->bm_h; i++ ) { gr_rle_decode( sbits, dbits ); sbits += (int)bmp->bm_data[4+i]; dbits += bmp->bm_w; } } grs_bitmap * rle_expand_texture( grs_bitmap * bmp ) { int i; int lowest_count, lc; int least_recently_used; if (!rle_cache_initialized) rle_cache_init(); Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) ); lc = rle_counter; rle_counter++; if (rle_counter < 0) rle_counter = 0; if ( rle_counter < lc ) { for (i=0; i= MAX_CACHE_BITMAPS ) rle_next = 0; for (i=0; ibm_w, bmp->bm_h); rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap ); rle_cache[least_recently_used].rle_bitmap = bmp; rle_cache[least_recently_used].last_used = rle_counter; return rle_cache[least_recently_used].expanded_bitmap; } void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2 ) { int i = 0, j; int count; ubyte color=0; if ( x2 < x1 ) return; count = 0; while ( i < x1 ) { color = *src++; if ( color == RLE_CODE ) return; if ( IS_RLE_CODE(color) ) { count = color & NOT_RLE_CODE; color = *src++; } else { // unique count = 1; } i += count; } count = i - x1; i = x1; // we know have '*count' pixels of 'color'. if ( x1+count > x2 ) { count = x2-x1+1; for ( j=0; j x2 ) { count = x2-x1+1; if (color != TRANSPARENCY_COLOR) { for ( j=0; jbm_flags & BM_FLAG_RLE_BIG; MALLOC(temp, unsigned char, MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h)); if (rle_big) { // set ptrs to first lines ptr = bmp->bm_data + 4 + 2 * bmp->bm_h; ptr2 = temp + 4 + 2 * bmp->bm_h; } else { ptr = bmp->bm_data + 4 + bmp->bm_h; ptr2 = temp + 4 + bmp->bm_h; } for (i = 0; i < bmp->bm_h; i++) { start = ptr2; if (rle_big) line_size = INTEL_SHORT(*((unsigned short *)&bmp->bm_data[4 + 2 * i])); else line_size = bmp->bm_data[4 + i]; for (j = 0; j < line_size; j++) { if ( ! IS_RLE_CODE(ptr[j]) ) { if (ptr[j] == 0) { *ptr2++ = RLE_CODE | 1; *ptr2++ = 255; } else *ptr2++ = ptr[j]; } else { *ptr2++ = ptr[j]; if ((ptr[j] & NOT_RLE_CODE) == 0) break; j++; if (ptr[j] == 0) *ptr2++ = 255; else if (ptr[j] == 255) *ptr2++ = 0; else *ptr2++ = ptr[j]; } } if (rle_big) // set line size *((unsigned short *)&temp[4 + 2 * i]) = INTEL_SHORT(ptr2 - start); else temp[4 + i] = ptr2 - start; ptr += line_size; // go to next line } len = ptr2 - temp; *((int *)temp) = len; // set total size memcpy(bmp->bm_data, temp, len); d_free(temp); } /* * remaps all entries using colormap in an RLE bitmap without uncompressing it */ void rle_remap(grs_bitmap *bmp, ubyte *colormap) { int i, j, len, rle_big; unsigned char *ptr, *ptr2, *temp, *start; unsigned short line_size; rle_big = bmp->bm_flags & BM_FLAG_RLE_BIG; MALLOC(temp, unsigned char, MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h) + 30000); if (rle_big) { // set ptrs to first lines ptr = bmp->bm_data + 4 + 2 * bmp->bm_h; ptr2 = temp + 4 + 2 * bmp->bm_h; } else { ptr = bmp->bm_data + 4 + bmp->bm_h; ptr2 = temp + 4 + bmp->bm_h; } for (i = 0; i < bmp->bm_h; i++) { start = ptr2; if (rle_big) line_size = INTEL_SHORT(*((unsigned short *)&bmp->bm_data[4 + 2 * i])); else line_size = bmp->bm_data[4 + i]; for (j = 0; j < line_size; j++) { if ( ! IS_RLE_CODE(ptr[j])) { if (IS_RLE_CODE(colormap[ptr[j]])) *ptr2++ = RLE_CODE | 1; // add "escape sequence" *ptr2++ = colormap[ptr[j]]; // translate } else { *ptr2++ = ptr[j]; // just copy current rle code if ((ptr[j] & NOT_RLE_CODE) == 0) break; j++; *ptr2++ = colormap[ptr[j]]; // translate } } if (rle_big) // set line size *((unsigned short *)&temp[4 + 2 * i]) = INTEL_SHORT(ptr2 - start); else temp[4 + i] = ptr2 - start; ptr += line_size; // go to next line } len = ptr2 - temp; *((int *)temp) = len; // set total size memcpy(bmp->bm_data, temp, len); d_free(temp); } dxx-rebirth-0.58.1-d2x/2d/scalec.c000066400000000000000000000257671217717237500165000ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include "gr.h" #include "grdef.h" #include "rle.h" // John's new stuff below here.... int scale_error_term; int scale_initial_pixel_count; int scale_adj_up; int scale_adj_down; int scale_final_pixel_count; int scale_ydelta_minus_1; int scale_whole_step; ubyte * scale_source_ptr; ubyte * scale_dest_ptr; ubyte scale_rle_data[640]; void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1, int orientation ); void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1, int orientation ); void rls_stretch_scanline_setup( int XDelta, int YDelta ); void rls_stretch_scanline(void); void decode_row( grs_bitmap * bmp, int y ) { int i, offset=4+bmp->bm_h; for (i=0; ibm_data[4+i]; gr_rle_decode( &bmp->bm_data[offset], scale_rle_data ); } void scale_up_bitmap(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1, int orientation ) { fix dv, v; int y; if (orientation & 1) { int t; t = u0; u0 = u1; u1 = t; } if (orientation & 2) { int t; t = v0; v0 = v1; v1 = t; if (v1 < v0) v0--; } v = v0; dv = (v1-v0) / (y1-y0); rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); if ( scale_ydelta_minus_1 < 1 ) return; v = v0; for (y=y0; y<=y1; y++ ) { scale_source_ptr = &source_bmp->bm_data[source_bmp->bm_rowsize*f2i(v)+f2i(u0)]; scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; rls_stretch_scanline(); v += dv; } } void scale_up_bitmap_rle(grs_bitmap *source_bmp, grs_bitmap *dest_bmp, int x0, int y0, int x1, int y1, fix u0, fix v0, fix u1, fix v1, int orientation ) { fix dv, v; int y, last_row = -1; if (orientation & 1) { int t; t = u0; u0 = u1; u1 = t; } if (orientation & 2) { int t; t = v0; v0 = v1; v1 = t; if (v1 < v0) v0--; } dv = (v1-v0) / (y1-y0); rls_stretch_scanline_setup( (int)(x1-x0), f2i(u1)-f2i(u0) ); if ( scale_ydelta_minus_1 < 1 ) return; v = v0; for (y=y0; y<=y1; y++ ) { if ( f2i(v) != last_row ) { last_row = f2i(v); decode_row( source_bmp, last_row ); } scale_source_ptr = &scale_rle_data[f2i(u0)]; scale_dest_ptr = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; rls_stretch_scanline( ); v += dv; } } void rls_stretch_scanline_setup( int XDelta, int YDelta ) { scale_ydelta_minus_1 = YDelta - 1; /* X major line */ /* Minimum # of pixels in a run in this line */ scale_whole_step = XDelta / YDelta; /* Error term adjust each time Y steps by 1; used to tell when one extra pixel should be drawn as part of a run, to account for fractional steps along the X axis per 1-pixel steps along Y */ scale_adj_up = (XDelta % YDelta) * 2; /* Error term adjust when the error term turns over, used to factor out the X step made at that time */ scale_adj_down = YDelta * 2; /* Initial error term; reflects an initial step of 0.5 along the Y axis */ scale_error_term = (XDelta % YDelta) - (YDelta * 2); /* The initial and last runs are partial, because Y advances only 0.5 for these runs, rather than 1. Divide one full run, plus the initial pixel, between the initial and last runs */ scale_initial_pixel_count = (scale_whole_step / 2) + 1; scale_final_pixel_count = scale_initial_pixel_count; /* If the basic run length is even and there's no fractional advance, we have one pixel that could go to either the initial or last partial run, which we'll arbitrarily allocate to the last run */ if ((scale_adj_up == 0) && ((scale_whole_step & 0x01) == 0)) { scale_initial_pixel_count--; } /* If there're an odd number of pixels per run, we have 1 pixel that can't be allocated to either the initial or last partial run, so we'll add 0.5 to error term so this pixel will be handled by the normal full-run loop */ if ((scale_whole_step & 0x01) != 0) { scale_error_term += YDelta; } } void rls_stretch_scanline( ) { ubyte c, *src_ptr, *dest_ptr; int i, j, len, ErrorTerm, initial_count, final_count; // Draw the first, partial run of pixels src_ptr = scale_source_ptr; dest_ptr = scale_dest_ptr; ErrorTerm = scale_error_term; initial_count = scale_initial_pixel_count; final_count = scale_final_pixel_count; c = *src_ptr++; if ( c != TRANSPARENCY_COLOR ) { for (i=0; i 0) { len++; ErrorTerm -= scale_adj_down; // reset the error term } // Draw this run o' pixels c = *src_ptr++; if ( c != TRANSPARENCY_COLOR ) { for (i=len; i>0; i-- ) *dest_ptr++ = c; } else { dest_ptr += len; } } // Draw the final run of pixels c = *src_ptr++; if ( c != TRANSPARENCY_COLOR ) { for (i=0; ibm_data[source_bmp->bm_rowsize*f2i(v)]; dbits = &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0]; u = u0; v += dv; for (x=x0; x<=x1; x++ ) { c = sbits[u >> 16]; if (c != TRANSPARENCY_COLOR) *dbits = c; dbits++; u += du; } } } void scale_row_transparent( ubyte * sbits, ubyte * dbits, int width, fix u, fix du ) { int i; ubyte c; ubyte *dbits_end = &dbits[width-1]; if ( du < F1_0 ) { // Scaling up. fix next_u; int next_u_int; next_u_int = f2i(u)+1; c = sbits[ next_u_int ]; next_u = i2f(next_u_int); if ( c != TRANSPARENCY_COLOR ) goto NonTransparent; Transparent: while (1) { dbits++; if ( dbits > dbits_end ) return; u += du; if ( u > next_u ) { next_u_int = f2i(u)+1; c = sbits[ next_u_int ]; next_u = i2f(next_u_int); if ( c != TRANSPARENCY_COLOR ) goto NonTransparent; } } return; NonTransparent: while (1) { *dbits++ = c; if ( dbits > dbits_end ) return; u += du; if ( u > next_u ) { next_u_int = f2i(u)+1; c = sbits[ next_u_int ]; next_u = i2f(next_u_int); if ( c == TRANSPARENCY_COLOR ) goto Transparent; } } return; } else { for ( i=0; i= 0); //Int3(); //this should be checked in higher-level routine return; } for (y=y0; y<=y1; y++ ) { if ( f2i(v) != last_row ) { last_row = f2i(v); decode_row( source_bmp, last_row ); } scale_row_transparent( scale_rle_data, &dest_bmp->bm_data[dest_bmp->bm_rowsize*y+x0], x1-x0+1, u0, du ); v += dv; } } #define FIND_SCALED_NUM(x,x0,x1,y0,y1) (fixmuldiv((x)-(x0),(y1)-(y0),(x1)-(x0))+(y0)) // Scales bitmap, bp, into vertbuf[0] to vertbuf[1] void scale_bitmap(grs_bitmap *bp, grs_point *vertbuf, int orientation ) { grs_bitmap * dbp = &grd_curcanv->cv_bitmap; fix x0, y0, x1, y1; fix u0, v0, u1, v1; fix clipped_x0, clipped_y0, clipped_x1, clipped_y1; fix clipped_u0, clipped_v0, clipped_u1, clipped_v1; fix xmin, xmax, ymin, ymax; int dx0, dy0, dx1, dy1; int dtemp; // Set initial variables.... x0 = vertbuf[0].x; y0 = vertbuf[0].y; x1 = vertbuf[2].x; y1 = vertbuf[2].y; xmin = 0; ymin = 0; xmax = i2f(dbp->bm_w)-fl2f(.5); ymax = i2f(dbp->bm_h)-fl2f(.5); u0 = i2f(0); v0 = i2f(0); u1 = i2f(bp->bm_w-1); v1 = i2f(bp->bm_h-1); // Check for obviously offscreen bitmaps... if ( (y1<=y0) || (x1<=x0) ) return; if ( (x1<0 ) || (x0>=xmax) ) return; if ( (y1<0 ) || (y0>=ymax) ) return; clipped_u0 = u0; clipped_v0 = v0; clipped_u1 = u1; clipped_v1 = v1; clipped_x0 = x0; clipped_y0 = y0; clipped_x1 = x1; clipped_y1 = y1; // Clip the left, moving u0 right as necessary if ( x0 < xmin ) { clipped_u0 = FIND_SCALED_NUM(xmin,x0,x1,u0,u1); clipped_x0 = xmin; } // Clip the right, moving u1 left as necessary if ( x1 > xmax ) { clipped_u1 = FIND_SCALED_NUM(xmax,x0,x1,u0,u1); clipped_x1 = xmax; } // Clip the top, moving v0 down as necessary if ( y0 < ymin ) { clipped_v0 = FIND_SCALED_NUM(ymin,y0,y1,v0,v1); clipped_y0 = ymin; } // Clip the bottom, moving v1 up as necessary if ( y1 > ymax ) { clipped_v1 = FIND_SCALED_NUM(ymax,y0,y1,v0,v1); clipped_y1 = ymax; } dx0 = f2i(clipped_x0); dx1 = f2i(clipped_x1); dy0 = f2i(clipped_y0); dy1 = f2i(clipped_y1); if (dx1<=dx0) return; if (dy1<=dy0) return; dtemp = f2i(clipped_u1)-f2i(clipped_u0); if ( bp->bm_flags & BM_FLAG_RLE ) { if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) scale_up_bitmap_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1, orientation ); else scale_bitmap_c_rle(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1, orientation ); } else { if ( (dtemp < (f2i(clipped_x1)-f2i(clipped_x0))) && (dtemp>0) ) scale_up_bitmap(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1, orientation ); else scale_bitmap_c(bp, dbp, dx0, dy0, dx1, dy1, clipped_u0, clipped_v0, clipped_u1, clipped_v1, orientation ); } } dxx-rebirth-0.58.1-d2x/3d/000077500000000000000000000000001217717237500150625ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/3d/clipper.c000066400000000000000000000121741217717237500166710ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include "3d.h" #include "globvars.h" #include "clipper.h" #include "dxxerror.h" int free_point_num=0; g3s_point temp_points[MAX_POINTS_IN_POLY]; g3s_point *free_points[MAX_POINTS_IN_POLY]; void init_free_points(void) { int i; for (i=0;ip3_flags = PF_TEMP_POINT; return p; } void free_temp_point(g3s_point *p) { Assert(p->p3_flags & PF_TEMP_POINT); free_points[--free_point_num] = p; p->p3_flags &= ~PF_TEMP_POINT; } //clips an edge against one plane. g3s_point *clip_edge(int plane_flag,g3s_point *on_pnt,g3s_point *off_pnt) { fix psx_ratio; fix a,b,kn,kd; g3s_point *tmp; //compute clipping value k = (xs-zs) / (xs-xe-zs+ze) //use x or y as appropriate, and negate x/y value as appropriate if (plane_flag & (CC_OFF_RIGHT | CC_OFF_LEFT)) { a = on_pnt->p3_x; b = off_pnt->p3_x; } else { a = on_pnt->p3_y; b = off_pnt->p3_y; } if (plane_flag & (CC_OFF_LEFT | CC_OFF_BOT)) { a = -a; b = -b; } kn = a - on_pnt->p3_z; //xs-zs kd = kn - b + off_pnt->p3_z; //xs-zs-xe+ze tmp = get_temp_point(); psx_ratio = fixdiv( kn, kd ); // PSX_HACK!!!! // tmp->p3_x = on_pnt->p3_x + fixmuldiv(off_pnt->p3_x-on_pnt->p3_x,kn,kd); // tmp->p3_y = on_pnt->p3_y + fixmuldiv(off_pnt->p3_y-on_pnt->p3_y,kn,kd); tmp->p3_x = on_pnt->p3_x + fixmul( (off_pnt->p3_x-on_pnt->p3_x), psx_ratio); tmp->p3_y = on_pnt->p3_y + fixmul( (off_pnt->p3_y-on_pnt->p3_y), psx_ratio); if (plane_flag & (CC_OFF_TOP|CC_OFF_BOT)) tmp->p3_z = tmp->p3_y; else tmp->p3_z = tmp->p3_x; if (plane_flag & (CC_OFF_LEFT|CC_OFF_BOT)) tmp->p3_z = -tmp->p3_z; if (on_pnt->p3_flags & PF_UVS) { // PSX_HACK!!!! // tmp->p3_u = on_pnt->p3_u + fixmuldiv(off_pnt->p3_u-on_pnt->p3_u,kn,kd); // tmp->p3_v = on_pnt->p3_v + fixmuldiv(off_pnt->p3_v-on_pnt->p3_v,kn,kd); tmp->p3_u = on_pnt->p3_u + fixmul((off_pnt->p3_u-on_pnt->p3_u), psx_ratio); tmp->p3_v = on_pnt->p3_v + fixmul((off_pnt->p3_v-on_pnt->p3_v), psx_ratio); tmp->p3_flags |= PF_UVS; } if (on_pnt->p3_flags & PF_LS) { // PSX_HACK // tmp->p3_r = on_pnt->p3_r + fixmuldiv(off_pnt->p3_r-on_pnt->p3_r,kn,kd); // tmp->p3_g = on_pnt->p3_g + fixmuldiv(off_pnt->p3_g-on_pnt->p3_g,kn,kd); // tmp->p3_b = on_pnt->p3_b + fixmuldiv(off_pnt->p3_b-on_pnt->p3_b,kn,kd); tmp->p3_l = on_pnt->p3_l + fixmul((off_pnt->p3_l-on_pnt->p3_l), psx_ratio); tmp->p3_flags |= PF_LS; } g3_code_point(tmp); return tmp; } //clips a line to the viewing pyramid. void clip_line(g3s_point **p0,g3s_point **p1,ubyte codes_or) { int plane_flag; g3s_point *old_p1; //might have these left over (*p0)->p3_flags &= ~(PF_UVS|PF_LS); (*p1)->p3_flags &= ~(PF_UVS|PF_LS); for (plane_flag=1;plane_flag<16;plane_flag<<=1) if (codes_or & plane_flag) { if ((*p0)->p3_codes & plane_flag) {g3s_point *t=*p0; *p0=*p1; *p1=t;} //swap! old_p1 = *p1; *p1 = clip_edge(plane_flag,*p0,*p1); if (old_p1->p3_flags & PF_TEMP_POINT) free_temp_point(old_p1); } } int clip_plane(int plane_flag,g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc) { int i; g3s_point **save_dest=dest; //copy first two verts to end src[*nv] = src[0]; src[*nv+1] = src[1]; cc->uand = 0xff; cc->uor = 0; for (i=1;i<=*nv;i++) { if (src[i]->p3_codes & plane_flag) { //cur point off? if (! (src[i-1]->p3_codes & plane_flag)) { //prev not off? *dest = clip_edge(plane_flag,src[i-1],src[i]); cc->uor |= (*dest)->p3_codes; cc->uand &= (*dest)->p3_codes; dest++; } if (! (src[i+1]->p3_codes & plane_flag)) { *dest = clip_edge(plane_flag,src[i+1],src[i]); cc->uor |= (*dest)->p3_codes; cc->uand &= (*dest)->p3_codes; dest++; } //see if must free discarded point if (src[i]->p3_flags & PF_TEMP_POINT) free_temp_point(src[i]); } else { //cur not off, copy to dest buffer *dest++ = src[i]; cc->uor |= src[i]->p3_codes; cc->uand &= src[i]->p3_codes; } } return (dest-save_dest); } g3s_point **clip_polygon(g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc) { int plane_flag; g3s_point **t; for (plane_flag=1;plane_flag<16;plane_flag<<=1) if (cc->uor & plane_flag) { *nv = clip_plane(plane_flag,src,dest,nv,cc); if (cc->uand) //clipped away return dest; t = src; src = dest; dest = t; } return src; //we swapped after we copied } dxx-rebirth-0.58.1-d2x/3d/clipper.h000066400000000000000000000020401217717237500166650ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for clipper.c * */ #ifndef _CLIPPER_H #define _CLIPPER_H extern void free_temp_point(g3s_point *p); extern g3s_point **clip_polygon(g3s_point **src,g3s_point **dest,int *nv,g3s_codes *cc); extern void init_free_points(void); extern void clip_line(g3s_point **p0,g3s_point **p1,ubyte codes_or); #endif dxx-rebirth-0.58.1-d2x/3d/draw.c000066400000000000000000000176421217717237500161750ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Drawing routines * */ #include "dxxerror.h" #include "3d.h" #include "globvars.h" #include "texmap.h" #include "clipper.h" tmap_drawer_type tmap_drawer_ptr = draw_tmap; flat_drawer_type flat_drawer_ptr = gr_upoly_tmap; line_drawer_type line_drawer_ptr = gr_line; //specifies 2d drawing routines to use instead of defaults. Passing //NULL for either or both restores defaults void g3_set_special_render(tmap_drawer_type tmap_drawer,flat_drawer_type flat_drawer,line_drawer_type line_drawer) { tmap_drawer_ptr = (tmap_drawer)?tmap_drawer:draw_tmap; flat_drawer_ptr = (flat_drawer)?flat_drawer:gr_upoly_tmap; line_drawer_ptr = (line_drawer)?line_drawer:gr_line; } #ifndef OGL //deal with a clipped line bool must_clip_line(g3s_point *p0,g3s_point *p1,ubyte codes_or) { bool ret; if ((p0->p3_flags&PF_TEMP_POINT) || (p1->p3_flags&PF_TEMP_POINT)) ret = 0; //line has already been clipped, so give up else { clip_line(&p0,&p1,codes_or); ret = g3_draw_line(p0,p1); } //free temp points if (p0->p3_flags & PF_TEMP_POINT) free_temp_point(p0); if (p1->p3_flags & PF_TEMP_POINT) free_temp_point(p1); return ret; } //draws a line. takes two points. returns true if drew bool g3_draw_line(g3s_point *p0,g3s_point *p1) { ubyte codes_or; if (p0->p3_codes & p1->p3_codes) return 0; codes_or = p0->p3_codes | p1->p3_codes; if (codes_or & CC_BEHIND) return must_clip_line(p0,p1,codes_or); if (!(p0->p3_flags&PF_PROJECTED)) g3_project_point(p0); if (p0->p3_flags&PF_OVERFLOW) return must_clip_line(p0,p1,codes_or); if (!(p1->p3_flags&PF_PROJECTED)) g3_project_point(p1); if (p1->p3_flags&PF_OVERFLOW) return must_clip_line(p0,p1,codes_or); return (bool) (*line_drawer_ptr)(p0->p3_sx,p0->p3_sy,p1->p3_sx,p1->p3_sy); } #endif //returns true if a plane is facing the viewer. takes the unrotated surface //normal of the plane, and a point on it. The normal need not be normalized bool g3_check_normal_facing(const vms_vector *v,const vms_vector *norm) { vms_vector tempv; vm_vec_sub(&tempv,&View_position,v); return (vm_vec_dot(&tempv,norm) > 0); } bool do_facing_check(vms_vector *norm,const g3s_point **vertlist,vms_vector *p) { if (norm) { //have normal Assert(norm->x || norm->y || norm->z); return g3_check_normal_facing(p,norm); } else { //normal not specified, so must compute vms_vector tempv; //get three points (rotated) and compute normal vm_vec_perp(&tempv,&vertlist[0]->p3_vec,&vertlist[1]->p3_vec,&vertlist[2]->p3_vec); return (vm_vec_dot(&tempv,&vertlist[1]->p3_vec) < 0); } } //like g3_draw_poly(), but checks to see if facing. If surface normal is //NULL, this routine must compute it, which will be slow. It is better to //pre-compute the normal, and pass it to this function. When the normal //is passed, this function works like g3_check_normal_facing() plus //g3_draw_poly(). //returns -1 if not facing, 1 if off screen, 0 if drew bool g3_check_and_draw_poly(int nv,const g3s_point **pointlist,vms_vector *norm,vms_vector *pnt) { if (do_facing_check(norm,pointlist,pnt)) return g3_draw_poly(nv,pointlist); else return 255; } bool g3_check_and_draw_tmap(int nv,const g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm,vms_vector *norm,vms_vector *pnt) { if (do_facing_check(norm,pointlist,pnt)) return g3_draw_tmap(nv,pointlist,uvl_list,light_rgb,bm); else return 255; } //deal with face that must be clipped bool must_clip_flat_face(int nv,g3s_codes cc) { int i; bool ret=0; g3s_point **bufptr; bufptr = clip_polygon(Vbuf0,Vbuf1,&nv,&cc); if (nv>0 && !(cc.uor&CC_BEHIND) && !cc.uand) { for (i=0;ip3_flags&PF_PROJECTED)) g3_project_point(p); if (p->p3_flags&PF_OVERFLOW) { ret = 1; goto free_points; } Vertex_list[i*2] = p->p3_sx; Vertex_list[i*2+1] = p->p3_sy; } (*flat_drawer_ptr)(nv,(int *)Vertex_list); } else ret=1; //free temp points free_points: ; for (i=0;ip3_flags & PF_TEMP_POINT) free_temp_point(Vbuf1[i]); // Assert(free_point_num==0); return ret; } #ifndef OGL //draw a flat-shaded face. //returns 1 if off screen, 0 if drew bool g3_draw_poly(int nv,g3s_point **pointlist) { int i; g3s_point **bufptr; g3s_codes cc; cc.uor = 0; cc.uand = 0xff; bufptr = Vbuf0; for (i=0;ip3_codes; cc.uor |= bufptr[i]->p3_codes; } if (cc.uand) return 1; //all points off screen if (cc.uor) return must_clip_flat_face(nv,cc); //now make list of 2d coords (& check for overflow) for (i=0;ip3_flags&PF_PROJECTED)) g3_project_point(p); if (p->p3_flags&PF_OVERFLOW) return must_clip_flat_face(nv,cc); Vertex_list[i*2] = p->p3_sx; Vertex_list[i*2+1] = p->p3_sy; } (*flat_drawer_ptr)(nv,(int *)Vertex_list); return 0; //say it drew } bool must_clip_tmap_face(int nv,g3s_codes cc,grs_bitmap *bm); //draw a texture-mapped face. //returns 1 if off screen, 0 if drew bool g3_draw_tmap(int nv,g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm) { int i; g3s_point **bufptr; g3s_codes cc; cc.uor = 0; cc.uand = 0xff; bufptr = Vbuf0; for (i=0;ip3_codes; cc.uor |= p->p3_codes; p->p3_u = uvl_list[i].u; p->p3_v = uvl_list[i].v; p->p3_l = (light_rgb[i].r+light_rgb[i].g+light_rgb[i].b)/3; p->p3_flags |= PF_UVS + PF_LS; } if (cc.uand) return 1; //all points off screen if (cc.uor) return must_clip_tmap_face(nv,cc,bm); //now make list of 2d coords (& check for overflow) for (i=0;ip3_flags&PF_PROJECTED)) g3_project_point(p); if (p->p3_flags&PF_OVERFLOW) { Int3(); //should not overflow after clip return 255; } } (*tmap_drawer_ptr)(bm,nv,bufptr); return 0; //say it drew } #endif bool must_clip_tmap_face(int nv,g3s_codes cc,grs_bitmap *bm) { g3s_point **bufptr; int i; bufptr = clip_polygon(Vbuf0,Vbuf1,&nv,&cc); if (nv && !(cc.uor&CC_BEHIND) && !cc.uand) { for (i=0;ip3_flags&PF_PROJECTED)) g3_project_point(p); if (p->p3_flags&PF_OVERFLOW) { Int3(); //should not overflow after clip goto free_points; } } (*tmap_drawer_ptr)(bm,nv,bufptr); } free_points: ; for (i=0;ip3_flags & PF_TEMP_POINT) free_temp_point(bufptr[i]); // Assert(free_point_num==0); return 0; } #ifndef __powerc int checkmuldiv(fix *r,fix a,fix b,fix c); #endif #ifndef OGL //draw a sortof sphere - i.e., the 2d radius is proportional to the 3d //radius, but not to the distance from the eye int g3_draw_sphere(g3s_point *pnt,fix rad) { if (! (pnt->p3_codes & CC_BEHIND)) { if (! (pnt->p3_flags & PF_PROJECTED)) g3_project_point(pnt); if (! (pnt->p3_codes & PF_OVERFLOW)) { fix r2,t; r2 = fixmul(rad,Matrix_scale.x); #ifndef __powerc if (checkmuldiv(&t,r2,Canv_w2,pnt->p3_z)) return gr_disk(pnt->p3_sx,pnt->p3_sy,t); #else if (pnt->p3_z == 0) return 0; return gr_disk(pnt->p3_sx, pnt->p3_sy, fl2f(((f2fl(r2) * fCanv_w2) / f2fl(pnt->p3_z)))); #endif } } return 0; } #endif dxx-rebirth-0.58.1-d2x/3d/globvars.c000066400000000000000000000027011217717237500170450ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Global variables for 3d * */ #include "3d.h" #include "globvars.h" vms_vector View_position; fix View_zoom; vms_matrix Unscaled_matrix; //before scaling vms_matrix View_matrix; vms_vector Window_scale; //scaling for window aspect vms_vector Matrix_scale; //how the matrix is scaled, window_scale * zoom int Canvas_width; //the actual width int Canvas_height; //the actual height fix Canv_w2; //fixed-point width/2 fix Canv_h2; //fixed-point height/2 #ifdef __powerc double fCanv_w2; double fCanv_h2; #endif //vertex buffers for polygon drawing and clipping g3s_point * Vbuf0[MAX_POINTS_IN_POLY]; g3s_point *Vbuf1[MAX_POINTS_IN_POLY]; //list of 2d coords fix Vertex_list[MAX_POINTS_IN_POLY*2]; dxx-rebirth-0.58.1-d2x/3d/globvars.h000066400000000000000000000025531217717237500170570ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Private (internal) header for 3d library * */ #ifndef _GLOBVARS_H #define _GLOBVARS_H #define MAX_POINTS_IN_POLY 100 extern int Canvas_width,Canvas_height; //the actual width & height extern fix Canv_w2,Canv_h2; //fixed-point width,height/2 #ifdef __powerc extern double fCanv_w2, fCanv_h2; #endif extern vms_vector Window_scale; extern int free_point_num; extern fix View_zoom; extern vms_vector View_position,Matrix_scale; extern vms_matrix View_matrix,Unscaled_matrix; //vertex buffers for polygon drawing and clipping extern g3s_point *Vbuf0[]; extern g3s_point *Vbuf1[]; //list of 2d coords extern fix Vertex_list[]; #endif dxx-rebirth-0.58.1-d2x/3d/instance.c000066400000000000000000000045651217717237500170440ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Instancing routines * */ #include #include "dxxerror.h" #include "3d.h" #include "globvars.h" #define MAX_INSTANCE_DEPTH 5 struct instance_context { vms_matrix m; vms_vector p; } instance_stack[MAX_INSTANCE_DEPTH]; int instance_depth = 0; //instance at specified point with specified orientation //if matrix==NULL, don't modify matrix. This will be like doing an offset void g3_start_instance_matrix(const vms_vector *pos,const vms_matrix *orient) { vms_vector tempv; vms_matrix tempm,tempm2; Assert(instance_depth= 0); View_position = instance_stack[instance_depth].p; View_matrix = instance_stack[instance_depth].m; } dxx-rebirth-0.58.1-d2x/3d/interp.c000066400000000000000000000424201217717237500165310ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Polygon object interpreter * */ #include #include "dxxerror.h" #include "interp.h" #include "globvars.h" #include "gr.h" #include "byteswap.h" #include "u_mem.h" #define OP_EOF 0 //eof #define OP_DEFPOINTS 1 //defpoints #define OP_FLATPOLY 2 //flat-shaded polygon #define OP_TMAPPOLY 3 //texture-mapped polygon #define OP_SORTNORM 4 //sort by normal #define OP_RODBM 5 //rod bitmap #define OP_SUBCALL 6 //call a subobject #define OP_DEFP_START 7 //defpoints with start #define OP_GLOW 8 //glow value for next poly //#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table)) #define MAX_POINTS_PER_POLY 25 short highest_texture_num; int g3d_interp_outline; g3s_point *Interp_point_list = NULL; #define MAX_INTERP_COLORS 100 //gives the interpreter an array of points to use void g3_set_interp_points(g3s_point *pointlist) { Interp_point_list = pointlist; } #define w(p) (*((short *) (p))) #define wp(p) ((short *) (p)) #define fp(p) ((fix *) (p)) #define vp(p) ((vms_vector *) (p)) void rotate_point_list(g3s_point *dest,vms_vector *src,int n) { while (n--) g3_rotate_point(dest++,src++); } static const vms_angvec zero_angles = {0,0,0}; static const g3s_point *point_list[MAX_POINTS_PER_POLY]; int glow_num = -1; #ifdef WORDS_BIGENDIAN void short_swap(short *s) { *s = SWAPSHORT(*s); } void fix_swap(fix *f) { *f = (fix)SWAPINT((int)*f); } void vms_vector_swap(vms_vector *v) { fix_swap(fp(&v->x)); fix_swap(fp(&v->y)); fix_swap(fp(&v->z)); } void fixang_swap(fixang *f) { *f = (fixang)SWAPSHORT((short)*f); } void vms_angvec_swap(vms_angvec *v) { fixang_swap(&v->p); fixang_swap(&v->b); fixang_swap(&v->h); } void swap_polygon_model_data(ubyte *data) { int i; short n; g3s_uvl *uvl_val; ubyte *p = data; short_swap(wp(p)); while (w(p) != OP_EOF) { switch (w(p)) { case OP_DEFPOINTS: short_swap(wp(p + 2)); n = w(p+2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 4; break; case OP_DEFP_START: short_swap(wp(p + 2)); short_swap(wp(p + 4)); n = w(p+2); for (i = 0; i < n; i++) vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector)))); p += n*sizeof(struct vms_vector) + 8; break; case OP_FLATPOLY: short_swap(wp(p+2)); n = w(p+2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); short_swap(wp(p+28)); for (i=0; i < n; i++) short_swap(wp(p + 30 + (i * 2))); p += 30 + ((n&~1)+1)*2; break; case OP_TMAPPOLY: short_swap(wp(p+2)); n = w(p+2); vms_vector_swap(vp(p + 4)); vms_vector_swap(vp(p + 16)); for (i=0;iu); fix_swap(&uvl_val->v); } short_swap(wp(p+28)); for (i=0;i 0) { #ifdef FADE_FLATPOLY short c; unsigned char cc; int l; #endif #ifndef FADE_FLATPOLY color = gr_find_closest_color_15bpp(w(p + 28)); #else //l = (32 * model_light) >> 16; l = f2i(fixmul(i2f(32), (model_light.r+model_light.g+model_light.b)/3)); if (l<0) l = 0; else if (l>32) l = 32; cc = gr_find_closest_color_15bpp(w(p+28)); color = gr_fade_table[(l<<8)|cc]; #endif } p += 30 + ((nv&~1)+1)*2; break; } case OP_TMAPPOLY: { int nv = w(p+2); p += 30 + ((nv&~1)+1)*2 + nv*12; break; } case OP_SORTNORM: if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) //facing color = g3_poly_get_color(p+w(p+28)); else //not facing color = g3_poly_get_color(p+w(p+30)); p += 32; break; case OP_RODBM: p+=36; break; case OP_SUBCALL: p += 20; break; case OP_GLOW: p += 4; break; default: Error("invalid polygon model\n"); } return color; } //calls the object interpreter to render an object. The object renderer //is really a seperate pipeline. returns true if drew bool g3_draw_polygon_model(ubyte *p,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,g3s_lrgb model_light,fix *glow_values) { glow_num = -1; //glow off by default while (w(p) != OP_EOF) switch (w(p)) { case OP_DEFPOINTS: { int n = w(p+2); rotate_point_list(Interp_point_list,vp(p+4),n); p += n*sizeof(struct vms_vector) + 4; break; } case OP_DEFP_START: { int n = w(p+2); int s = w(p+4); rotate_point_list(&Interp_point_list[s],vp(p+8),n); p += n*sizeof(struct vms_vector) + 8; break; } case OP_FLATPOLY: { int nv = w(p+2); Assert( nv < MAX_POINTS_PER_POLY ); if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) { int i; #ifdef FADE_FLATPOLY short c; unsigned char cc; int l; #endif // DPH: Now we treat this color as 15bpp // gr_setcolor(w(p+28)); #ifndef FADE_FLATPOLY gr_setcolor(gr_find_closest_color_15bpp(w(p + 28))); #else //l = (32 * model_light) >> 16; l = f2i(fixmul(i2f(32), (model_light.r+model_light.g+model_light.b)/3)); if (l<0) l = 0; else if (l>32) l = 32; cc = gr_find_closest_color_15bpp(w(p+28)); c = gr_fade_table[(l<<8)|cc]; gr_setcolor(c); #endif for (i=0;i 0) { int i; g3s_lrgb light, *lrgb_list; MALLOC(lrgb_list, g3s_lrgb, nv); //calculate light from surface normal if (glow_num < 0) //no glow { light.r = light.g = light.b = -vm_vec_dot(&View_matrix.fvec,vp(p+16)); light.r = f1_0/4 + (light.r*3)/4; light.r = fixmul(light.r,model_light.r); light.g = f1_0/4 + (light.g*3)/4; light.g = fixmul(light.g,model_light.g); light.b = f1_0/4 + (light.b*3)/4; light.b = fixmul(light.b,model_light.b); } else //yes glow { light.r = light.g = light.b = glow_values[glow_num]; glow_num = -1; } //now poke light into l values uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); for (i=0;i 0) { //facing //draw back then front g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); } else { //not facing. draw front then back g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values); g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values); } p += 32; break; case OP_RODBM: { g3s_point rod_bot_p,rod_top_p; g3s_lrgb rodbm_light = { f1_0, f1_0, f1_0 }; g3_rotate_point(&rod_bot_p,vp(p+20)); g3_rotate_point(&rod_top_p,vp(p+4)); g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),rodbm_light); p+=36; break; } case OP_SUBCALL: { const vms_angvec *a; if (anim_angles) a = &anim_angles[w(p+2)]; else a = &zero_angles; g3_start_instance_angles(vp(p+4),a); g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values); g3_done_instance(); p += 20; break; } case OP_GLOW: if (glow_values) glow_num = w(p+2); p += 4; break; default: Error("invalid polygon model\n"); } return 1; } #ifndef NDEBUG int nest_count; #endif //alternate interpreter for morphing object bool g3_draw_morphing_model(ubyte *p,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,g3s_lrgb model_light,vms_vector *new_points) { fix *glow_values = NULL; glow_num = -1; //glow off by default while (w(p) != OP_EOF) switch (w(p)) { case OP_DEFPOINTS: { int n = w(p+2); rotate_point_list(Interp_point_list,new_points,n); p += n*sizeof(struct vms_vector) + 4; break; } case OP_DEFP_START: { int n = w(p+2); int s = w(p+4); rotate_point_list(&Interp_point_list[s],new_points,n); p += n*sizeof(struct vms_vector) + 8; break; } case OP_FLATPOLY: { int nv = w(p+2); int i,ntris; gr_setcolor(w(p+28)); for (i=0;i<2;i++) point_list[i] = Interp_point_list + wp(p+30)[i]; for (ntris=nv-2;ntris;ntris--) { point_list[2] = Interp_point_list + wp(p+30)[i++]; g3_check_and_draw_poly(3,point_list,NULL,NULL); point_list[1] = point_list[2]; } p += 30 + ((nv&~1)+1)*2; break; } case OP_TMAPPOLY: { int nv = w(p+2); g3s_uvl *uvl_list; g3s_lrgb light, *lrgb_list; g3s_uvl morph_uvls[3]; int i,ntris; MALLOC(lrgb_list, g3s_lrgb, nv); //calculate light from surface normal if (glow_num < 0) //no glow { light.r = light.g = light.b = -vm_vec_dot(&View_matrix.fvec,vp(p+16)); light.r = f1_0/4 + (light.r*3)/4; light.r = fixmul(light.r,model_light.r); light.g = f1_0/4 + (light.g*3)/4; light.g = fixmul(light.g,model_light.g); light.b = f1_0/4 + (light.b*3)/4; light.b = fixmul(light.b,model_light.b); } else //yes glow { light.r = light.g = light.b = glow_values[glow_num]; glow_num = -1; } //now poke light into l values uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2); for (i=0;i 0) { //facing //draw back then front g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points); g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points); } else { //not facing. draw front then back g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points); g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points); } p += 32; break; case OP_RODBM: { g3s_point rod_bot_p,rod_top_p; g3s_lrgb rodbm_light = { f1_0, f1_0, f1_0 }; g3_rotate_point(&rod_bot_p,vp(p+20)); g3_rotate_point(&rod_top_p,vp(p+4)); g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),rodbm_light); p+=36; break; } case OP_SUBCALL: { const vms_angvec *a; if (anim_angles) a = &anim_angles[w(p+2)]; else a = &zero_angles; g3_start_instance_angles(vp(p+4),a); g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values); g3_done_instance(); p += 20; break; } case OP_GLOW: if (glow_values) glow_num = w(p+2); p += 4; break; } return 1; } void init_model_sub(ubyte *p) { Assert(++nest_count < 1000); while (w(p) != OP_EOF) { switch (w(p)) { case OP_DEFPOINTS: { int n = w(p+2); p += n*sizeof(struct vms_vector) + 4; break; } case OP_DEFP_START: { int n = w(p+2); p += n*sizeof(struct vms_vector) + 8; break; } case OP_FLATPOLY: { int nv = w(p+2); Assert(nv > 2); //must have 3 or more points // *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28)); p += 30 + ((nv&~1)+1)*2; break; } case OP_TMAPPOLY: { int nv = w(p+2); Assert(nv > 2); //must have 3 or more points if (w(p+28) > highest_texture_num) highest_texture_num = w(p+28); p += 30 + ((nv&~1)+1)*2 + nv*12; break; } case OP_SORTNORM: init_model_sub(p+w(p+28)); init_model_sub(p+w(p+30)); p += 32; break; case OP_RODBM: p += 36; break; case OP_SUBCALL: { init_model_sub(p+w(p+16)); p += 20; break; } case OP_GLOW: p += 4; break; default: Error("invalid polygon model\n"); } } } //init code for bitmap models void g3_init_polygon_model(void *model_ptr) { #ifndef NDEBUG nest_count = 0; #endif highest_texture_num = -1; init_model_sub((ubyte *) model_ptr); } dxx-rebirth-0.58.1-d2x/3d/matrix.c000066400000000000000000000037651217717237500165450ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Matrix setup & manipulation routines * */ #include "3d.h" #include "globvars.h" void scale_matrix(void); //set view from x,y,z & p,b,h, zoom. Must call one of g3_set_view_*() void g3_set_view_angles(const vms_vector *view_pos,const vms_angvec *view_orient,fix zoom) { View_zoom = zoom; View_position = *view_pos; vm_angles_2_matrix(&View_matrix,view_orient); scale_matrix(); } //set view from x,y,z, viewer matrix, and zoom. Must call one of g3_set_view_*() void g3_set_view_matrix(const vms_vector *view_pos,const vms_matrix *view_matrix,fix zoom) { View_zoom = zoom; View_position = *view_pos; View_matrix = *view_matrix; scale_matrix(); } //performs aspect scaling on global view matrix void scale_matrix(void) { Unscaled_matrix = View_matrix; //so we can use unscaled if we want Matrix_scale = Window_scale; if (View_zoom <= f1_0) //zoom in by scaling z Matrix_scale.z = fixmul(Matrix_scale.z,View_zoom); else { //zoom out by scaling x&y fix s = fixdiv(f1_0,View_zoom); Matrix_scale.x = fixmul(Matrix_scale.x,s); Matrix_scale.y = fixmul(Matrix_scale.y,s); } //now scale matrix elements vm_vec_scale(&View_matrix.rvec,Matrix_scale.x); vm_vec_scale(&View_matrix.uvec,Matrix_scale.y); vm_vec_scale(&View_matrix.fvec,Matrix_scale.z); } dxx-rebirth-0.58.1-d2x/3d/points.c000066400000000000000000000105441217717237500165460ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines for point definition, rotation, etc. * */ #include "3d.h" #include "globvars.h" //code a point. fills in the p3_codes field of the point, and returns the codes ubyte g3_code_point(g3s_point *p) { ubyte cc=0; if (p->p3_x > p->p3_z) cc |= CC_OFF_RIGHT; if (p->p3_y > p->p3_z) cc |= CC_OFF_TOP; if (p->p3_x < -p->p3_z) cc |= CC_OFF_LEFT; if (p->p3_y < -p->p3_z) cc |= CC_OFF_BOT; if (p->p3_z < 0) cc |= CC_BEHIND; return p->p3_codes = cc; } //rotates a point. returns codes. does not check if already rotated ubyte g3_rotate_point(g3s_point *dest,const vms_vector *src) { vms_vector tempv; vm_vec_sub(&tempv,src,&View_position); vm_vec_rotate(&dest->p3_vec,&tempv,&View_matrix); dest->p3_flags = 0; //no projected return g3_code_point(dest); } //checks for overflow & divides if ok, fillig in r //returns true if div is ok, else false int checkmuldiv(fix *r,fix a,fix b,fix c) { quadint q,qt; q.low=q.high=0; fixmulaccum(&q,a,b); qt = q; if (qt.high < 0) fixquadnegate(&qt); qt.high *= 2; if (qt.low > 0x7fff) qt.high++; if (qt.high >= c) return 0; else { *r = fixdivquadlong(q.low,q.high,c); return 1; } } //projects a point void g3_project_point(g3s_point *p) { #ifndef __powerc fix tx,ty; if (p->p3_flags & PF_PROJECTED || p->p3_codes & CC_BEHIND) return; if (checkmuldiv(&tx,p->p3_x,Canv_w2,p->p3_z) && checkmuldiv(&ty,p->p3_y,Canv_h2,p->p3_z)) { p->p3_sx = Canv_w2 + tx; p->p3_sy = Canv_h2 - ty; p->p3_flags |= PF_PROJECTED; } else p->p3_flags |= PF_OVERFLOW; #else double fz; if ((p->p3_flags & PF_PROJECTED) || (p->p3_codes & CC_BEHIND)) return; if ( p->p3_z <= 0 ) { p->p3_flags |= PF_OVERFLOW; return; } fz = f2fl(p->p3_z); p->p3_sx = fl2f(fCanv_w2 + (f2fl(p->p3_x)*fCanv_w2 / fz)); p->p3_sy = fl2f(fCanv_h2 - (f2fl(p->p3_y)*fCanv_h2 / fz)); p->p3_flags |= PF_PROJECTED; #endif } //from a 2d point, compute the vector through that point void g3_point_2_vec(vms_vector *v,short sx,short sy) { vms_vector tempv; vms_matrix tempm; tempv.x = fixmuldiv(fixdiv((sx<<16) - Canv_w2,Canv_w2),Matrix_scale.z,Matrix_scale.x); tempv.y = -fixmuldiv(fixdiv((sy<<16) - Canv_h2,Canv_h2),Matrix_scale.z,Matrix_scale.y); tempv.z = f1_0; vm_vec_normalize(&tempv); vm_copy_transpose_matrix(&tempm,&Unscaled_matrix); vm_vec_rotate(v,&tempv,&tempm); } //delta rotation functions vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx) { dest->x = fixmul(View_matrix.rvec.x,dx); dest->y = fixmul(View_matrix.uvec.x,dx); dest->z = fixmul(View_matrix.fvec.x,dx); return dest; } vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy) { dest->x = fixmul(View_matrix.rvec.y,dy); dest->y = fixmul(View_matrix.uvec.y,dy); dest->z = fixmul(View_matrix.fvec.y,dy); return dest; } vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz) { dest->x = fixmul(View_matrix.rvec.z,dz); dest->y = fixmul(View_matrix.uvec.z,dz); dest->z = fixmul(View_matrix.fvec.z,dz); return dest; } vms_vector *g3_rotate_delta_vec(vms_vector *dest,const vms_vector *src) { return vm_vec_rotate(dest,src,&View_matrix); } ubyte g3_add_delta_vec(g3s_point *dest,const g3s_point *src,const vms_vector *deltav) { vm_vec_add(&dest->p3_vec,&src->p3_vec,deltav); dest->p3_flags = 0; //not projected return g3_code_point(dest); } //calculate the depth of a point - returns the z coord of the rotated point fix g3_calc_point_depth(const vms_vector *pnt) { quadint q; q.low=q.high=0; fixmulaccum(&q,(pnt->x - View_position.x),View_matrix.fvec.x); fixmulaccum(&q,(pnt->y - View_position.y),View_matrix.fvec.y); fixmulaccum(&q,(pnt->z - View_position.z),View_matrix.fvec.z); return fixquadadjust(&q); } dxx-rebirth-0.58.1-d2x/3d/rod.c000066400000000000000000000122251217717237500160140ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Rod routines * */ #include "3d.h" #include "globvars.h" #include "fix.h" grs_point blob_vertices[4]; g3s_point rod_points[4]; static const g3s_point *rod_point_list[] = {&rod_points[0],&rod_points[1],&rod_points[2],&rod_points[3]}; g3s_uvl uvl_list[4] = { { 0x0200,0x0200,0 }, { 0xfe00,0x0200,0 }, { 0xfe00,0xfe00,0 }, { 0x0200,0xfe00,0 } }; g3s_lrgb lrgb_list[4] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }; //compute the corners of a rod. fills in vertbuf. int calc_rod_corners(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) { vms_vector delta_vec,top,tempv,rod_norm; ubyte codes_and; int i; //compute vector from one point to other, do cross product with vector //from eye to get perpendiclar vm_vec_sub(&delta_vec,&bot_point->p3_vec,&top_point->p3_vec); //unscale for aspect delta_vec.x = fixdiv(delta_vec.x,Matrix_scale.x); delta_vec.y = fixdiv(delta_vec.y,Matrix_scale.y); //calc perp vector //do lots of normalizing to prevent overflowing. When this code works, //it should be optimized vm_vec_normalize(&delta_vec); vm_vec_copy_normalize(&top,&top_point->p3_vec); vm_vec_cross(&rod_norm,&delta_vec,&top); vm_vec_normalize(&rod_norm); //scale for aspect rod_norm.x = fixmul(rod_norm.x,Matrix_scale.x); rod_norm.y = fixmul(rod_norm.y,Matrix_scale.y); //now we have the usable edge. generate four points //top points vm_vec_copy_scale(&tempv,&rod_norm,top_width); tempv.z = 0; vm_vec_add(&rod_points[0].p3_vec,&top_point->p3_vec,&tempv); vm_vec_sub(&rod_points[1].p3_vec,&top_point->p3_vec,&tempv); vm_vec_copy_scale(&tempv,&rod_norm,bot_width); tempv.z = 0; vm_vec_sub(&rod_points[2].p3_vec,&bot_point->p3_vec,&tempv); vm_vec_add(&rod_points[3].p3_vec,&bot_point->p3_vec,&tempv); //now code the four points for (i=0,codes_and=0xff;i<4;i++) codes_and &= g3_code_point(&rod_points[i]); if (codes_and) return 1; //1 means off screen //clear flags for new points (not projected) for (i=0;i<4;i++) rod_points[i].p3_flags = 0; return 0; } //draw a polygon that is always facing you //returns 1 if off screen, 0 if drew bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width) { if (calc_rod_corners(bot_point,bot_width,top_point,top_width)) return 0; return g3_draw_poly(4,rod_point_list); } //draw a bitmap object that is always facing you //returns 1 if off screen, 0 if drew bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,g3s_lrgb light) { if (calc_rod_corners(bot_point,bot_width,top_point,top_width)) return 0; uvl_list[0].l = uvl_list[1].l = uvl_list[2].l = uvl_list[3].l = (light.r+light.g+light.b)/3; lrgb_list[0].r = lrgb_list[1].r = lrgb_list[2].r = lrgb_list[3].r = light.r; lrgb_list[0].g = lrgb_list[1].g = lrgb_list[2].g = lrgb_list[3].g = light.g; lrgb_list[0].b = lrgb_list[1].b = lrgb_list[2].b = lrgb_list[3].b = light.b; return g3_draw_tmap(4,rod_point_list,uvl_list,lrgb_list,bitmap); } #ifndef __powerc int checkmuldiv(fix *r,fix a,fix b,fix c); #endif #ifndef OGL //draws a bitmap with the specified 3d width & height //returns 1 if off screen, 0 if drew bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm) { #ifndef __powerc g3s_point pnt; fix t,w,h; if (g3_rotate_point(&pnt,pos) & CC_BEHIND) return 1; g3_project_point(&pnt); if (pnt.p3_flags & PF_OVERFLOW) return 1; if (checkmuldiv(&t,width,Canv_w2,pnt.p3_z)) w = fixmul(t,Matrix_scale.x); else return 1; if (checkmuldiv(&t,height,Canv_h2,pnt.p3_z)) h = fixmul(t,Matrix_scale.y); else return 1; blob_vertices[0].x = pnt.p3_sx - w; blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h; blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w; blob_vertices[2].y = pnt.p3_sy + h; scale_bitmap(bm,blob_vertices,0); return 0; #else g3s_point pnt; fix w,h; double fz; if (g3_rotate_point(&pnt,pos) & CC_BEHIND) return 1; g3_project_point(&pnt); if (pnt.p3_flags & PF_OVERFLOW) return 1; if (pnt.p3_z == 0) return 1; fz = f2fl(pnt.p3_z); w = fixmul(fl2f(((f2fl(width)*fCanv_w2) / fz)), Matrix_scale.x); h = fixmul(fl2f(((f2fl(height)*fCanv_h2) / fz)), Matrix_scale.y); blob_vertices[0].x = pnt.p3_sx - w; blob_vertices[0].y = blob_vertices[1].y = pnt.p3_sy - h; blob_vertices[1].x = blob_vertices[2].x = pnt.p3_sx + w; blob_vertices[2].y = pnt.p3_sy + h; scale_bitmap(bm, blob_vertices, 0); return 0; #endif } #endif dxx-rebirth-0.58.1-d2x/3d/setup.c000066400000000000000000000037111217717237500163700ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Setup for 3d library * */ #include #include "dxxerror.h" #include "3d.h" #include "globvars.h" #include "clipper.h" //#include "div0.h" #ifdef OGL #include "ogl_init.h" #else #include "texmap.h" // for init_interface_vars_to_assembler() #endif //start the frame void g3_start_frame(void) { fix s; //set int w,h & fixed-point w,h/2 Canv_w2 = (Canvas_width = grd_curcanv->cv_bitmap.bm_w)<<15; Canv_h2 = (Canvas_height = grd_curcanv->cv_bitmap.bm_h)<<15; #ifdef __powerc fCanv_w2 = f2fl((Canvas_width = grd_curcanv->cv_bitmap.bm_w)<<15); fCanv_h2 = f2fl((Canvas_height = grd_curcanv->cv_bitmap.bm_h)<<15); #endif //compute aspect ratio for this canvas s = fixmuldiv(grd_curscreen->sc_aspect,Canvas_height,Canvas_width); if (s <= f1_0) { //scale x Window_scale.x = s; Window_scale.y = f1_0; } else { Window_scale.y = fixdiv(f1_0,s); Window_scale.x = f1_0; } Window_scale.z = f1_0; //always 1 init_free_points(); #ifdef OGL ogl_start_frame(); #else init_interface_vars_to_assembler(); //for the texture-mapper #endif } //this doesn't do anything, but is here for completeness void g3_end_frame(void) { #ifdef OGL ogl_end_frame(); #endif // Assert(free_point_num==0); free_point_num = 0; } dxx-rebirth-0.58.1-d2x/CHANGELOG.txt000066400000000000000000010171571217717237500166200ustar00rootroot00000000000000D2X-Rebirth Changelog 20130611 -------- main/titles.c: Fixed briefing_screens array for Descent 1 Shareware main/mission.c: Don't try to free Current_mission->alternate_ham_file if not allocated main/menu.c: Changed message regarding VSync and Multisampling indicating not all OSes need a restart to apply (mysteries of SDL) main/gamecntl.c: Fixed case where it wasn't possible to switch to view of a player > X if player X was missing main/laser.c: Consider FrameTime overhead when calculating time to allow next weapon fire. Should work perfectly as long as FPS >= Shots-per-second. Also set Omega firing rate to 20 shots per second for both single- and multiplayer 20130610 -------- misc/hmp.c: Made hmp code actually read tempo. Due to missing documentation of the format I can only guess it's a 4 bit int main/piggy.c: re-init digi system after re-setting sample rate for shareware main/gameseq.c: Removed call of digi_stop_digi_sounds() from DoPlayerDead(). Since it was killing persistent sounds which were only started once a level it would forever mute fans, waterfalls, etc.. Also closing Game_wind kills all sounds anyways so there is no point doing it on player death 20130422 -------- main/net_udp.c: In restricted game mode check for player callsign and sockaddr at the same time; Clear Netgame struct each time player enters a new IP in manual join menu arch/sdl/rbaudio.c: Added a lot of status messages for RBA code shown with -verbose, hopefully making it easier for users to track down problems and made all RBA messages start with RBAudio prefix 20130418 -------- main/lighting.c, main/render.c: Removed light_frame_count due to being unnecessary since lighting is now time-based and messed up deletion of dynamic light main/render.c: Due to additive blending, transparent sprites will become invivible in font of white surfaces (lamps). Fix that with a little desaturation main/net_udp.h: Made UPID_GAME_INFO_SIZE, UPID_GAME_INFO_LITE_SIZE and UPID_SEQUENCE_SIZE change if NETGAME_NAME_LEN, MISSION_NAME_LEN or CALLSIGN_LEN changes 20130408 -------- main/gamecntl.c, main/gamerend.c, main/gauges.c, main/gauges.h: Added 4th alternative HUD mode for no HUD rendering, aka Immersion mode main/menu.c, main/playsave.c, main/playsave.h, main/weapons.c: Added option to ignore cycling weapons that are not on autoselect list 20130407 -------- d2x-rebirth.xcodeproj/project.pbxproj: Updated Xcode project 20130406 -------- .gitignore: Added .gitignore 20130122 -------- d1x-rebirth.xcodeproj/project.pbxproj, editor/ehostage.c, main/custom.c: Updated Xcode project, changed references to error.h to dxxerror.h, since it was renamed 20130405 -------- SConstruct: For the assembler build, make sure platform_settings is accessed from self, likely preventing a compiling error SConstruct: Changes towards building using SCons on Mac OS X 20130117 -------- main/render.c: Fix click-selection in the editor for OpenGL implementations that insist on point blending 20130112 -------- arch/carbon/conf.h: Use new D1XMAJORi / D1XMINORi / D1XMICROi version constants for Mac main/inferno.h, main/mission.c, main/mission.h: Increased the maximum number of levels and secret levels per mission to 127 each, using MALLOC'd arrays; defined 'd_fname' type (mainly for my pointers to arrays of 13 character filenames, but could be convenient elsewhere) arch/carbon/messagebox.c, arch/win32/messagebox.c: If there's a messagebox to show on exit, and we *were* in fullscreen, don't try to toggle fullscreen and crash 20130108 -------- main/gamerend.c, main/multi.c, net_udp.c: Fixed some minor HUD-text related issues: For team assignment messages, joining player name would appear; team color assignment in netgame info screen could be wrong due to wrong syntax handling; when rewrapping text messages to specific player, game would not add space behind colon main/kmatrix.c: Defer free of kmatrix data until window is fully gone - patch by Kp main/inferno.c: Disable fullscreen toggling via ALT+ENTER if Game_wind is on top so toggling cannot be done accidentially ingame arch/sdl/mouse.c, d2x.ini, include/args.h, main/inferno.c, misc/args.c: Added option to hide mouse cursor (without disabling the mouse completely) SConstruct: Patch by A Future Pilot to hopefully fix bug which prevented building source within MinGW if Visual Studio installed main/ai2.c: Corrected ai_fire_laser_at_player() syntax where boss should not fire when Boss_dying_start_time != 0 and boss flag is set - patch by derhass arch/ogl/ogl.c: Changed additive color blending func to GL_ONE, GL_ONE - patch by derhass 20130103 -------- main/net_udp.c: Centralized UDP Broadcast function for IPv4 and IPv6 calls - patch by Kp editor/med.c: Deleted unnecessary drop-to-shell feature; commented out unused ReadLispMacro - patches by Kp 2d/font.c, include/ogl_init.h: Moved pow2ize declaration to ogl_init.h - patch by Kp main/bmread.c, main/piggy.c, main/piggy.h: Moved remove_char declaration to piggy.h - patch by Kp main/multi.h, main/net_udp.c: Moved multi_* declarations to multi.h - patch by Kp maths/rand.c: Included maths.h in rand.c to get d_rand prototype - patch by Kp arch/include/joy.h, arch/sdl/event.c, arch/sdl/joy.c: Moved joy_*_handler declarations to joy.h - patch by Kp editor/group.c, editor/medwall.c, editor/segment.c, main/gameseg.h, main/wall.h: Declared wall_close_door_num in wall.h; Declared validate_segment_side in gameseg.h - patches by Kp include/3d.h, main/gameseq.h, main/weapon.h: Removed redundant/obsolete declarations - patch by Kp main/kconfig.h: Moved large control_info arrays to end - patch by Kp main/switch.c: Avoid -Wformat-nonliteral for trigger message; Reflect plurality in light trigger messages - patches by Kp medrobot.c: medrobot: avoid needless name copy - patch by Kp editor/centers.c, main/gamecntl.c, main/gamerend.c: Fixed argument specifier mismatches flagged by -Wformat - patch by Kp arch/ogl/gr.c, main/game.c: Moved screenshot message formating to HUD_init_message - patch by Kp (and me for non-OGL code ;)) main/automap.c, main/credits.c, main/gamerend.c, main/gauges.c, main/hud.c, main/kmatrix.c, main/menu.c, main/newmenu.c, main/scores.c: Converted gr_printf to gr_string where needed - patch by Kp editor/medrobot.c, main/endlevel.c, main/fireball.c, main/gamecntl.c, main/hostage.c, main/multi.c, main/newdemo.c, main/powerup.c, main/wall.c, main/weapon.c, ui/file.c: Added dummy "%s" to prevent formatting untrusted literals - patch by Kp main/hud.c: Removed obsolete HUD cleaning code - patch by Kp editor/info.c: Use proper width in format specifier - patch by Kp 20121102 -------- arch/include/key.h, arch/sdl/key.c, main/kconfig.c: Made key_properties readable in other files; Eliminated key_text variable; Marked unicode_frame_buffer as extern in header - patches by Kp arch/ogl/gr.c, arch/ogl/ogl.c, include/gr.h: Removed 'new' from prototypes; Declared ogl_do_palfx(), ogl_close_pixel_buffers(), ogl_init_pixel_buffers() in gr.h - patches by Kp include/maths.h, include/texmap.h, include/ui.h, main/object.c, maths/fixc.c, maths/tables.c, texmap/ntmap.c, ui/dialog.c, ui/icon.c: Moved ui_draw_frame(), ui_draw_shad(), draw_tmap_flat(), math tables externs to headers - patches by Kp 3d/clipper.c, 3d/draw.c, editor/meddraw.c, include/3d.h, main/automap.c, main/render.c: in g3s_codes renamed or,and to uor,uand - patch by Kp main/object.h: use struct type explicitly - patch by Kp include/error.h: Renamed __format to __attribute_gcc_format due to possible C++ conflict; allow arguments - patch by Kp include/console.h, main/console.c: Marked con_printf fmt as const, Increased console lines from 512 to 2048; Marked console private entries as static - patches by Kp 2d/font.c: Fixed test for font magic number; Consolidated grs_font_read() - patches by Kp main/menu.c, main/multi.h, main/net_udp.c: Moved vers_id.h inclusion to where it is needed - patch by Kp 2d/bitmap.c: Include bitmap.h - patch by Kp 2d/bitblt.c, include/rle.h: Move declaration of gr_rle_expand_scanline_generic() to rle.h - patch by Kp 20121031 -------- main/hostage.h, include/u_mem.h: Fixed inconsistency in hostage_rescue() definition and revoked recent patch for u_mem.h due to infinite loops in mem.c caused by this 20120903 -------- arch/sdl/jukebox.c, main/gauges.c: Avoid some unnecessary strlen's - (slightly changed) patch by Kp misc/args.c: Made FindArg static - patch by Kp 20120902 -------- include/u_mem.h: Compile out memory checker if not enabled - patch by Kp 20120901 -------- main/vers_id.h: Fixed incorrect patch merge introduced in the last commit main/laser.h, main/object.c, main/object.h, main/powerup.h: Use enum for object types, powerup types, weapon types 20120728 -------- SConstruct, main/vers_id.h: Some Sconstruct lovin': Respect LDFLAGS; Made D2XMAJORi/MINORi/MICROi compile time constants; Do not pass CFLAGS to CXX; Mark some more warnings as errors - patches by Kp 20120724 -------- English.lproj/InfoPlist.strings, d2x-Info.plist, d2xgl-Info.plist: Increment version number for Mac files (should have committed this ages ago) main/bm.c, main/bmread.c: If bitmaps.tbl happens to be available, don't try and re-make the pig if EDITOR is defined because it would cause problems main/collide.c, ui/gadget.c, ui/radio.c: Fix warnings (no checking ubyte 'id' is < 0, include d_strdup prototype for radio.c and make sure that 'text' gets freed) main/polyobj.c: Don't draw objects with a modelnum of -1, improving stability when a third party mission is played with shareware data 20120723 -------- 2d/font.c, 2d/pcx.c, 3d/points.c, arch/include/jukebox.h, arch/sdl/jukebox.c, iff/iff.c, include/3d.h, include/error.h, include/gr.h, include/iff.h, include/pcx.h, include/physfsx.h, include/vecmat.h, main/ai.c, main/ai.h, main/ai2.c, main/automap.c, main/config.c, main/dumpmine.c, main/endlevel.c, main/escort.c, main/gamefont.c, main/gamerend.c, main/gamesave.c, main/gamesave.h, main/gauges.c, main/gauges.h, main/kconfig.c, main/kconfig.h, main/menu.c, main/multi.c, main/multi.h, main/newdemo.c, main/newmenu.c, main/newmenu.h, maths/vecmat.c, misc/error.c, misc/physfsx.c: Redefined lotsa variables, functions and parameters as const and/or static - patch by Kp 20120618 -------- main/gamerend.c, main/multi.c: removed temp_string buffer for ingame message inputs preventing the string from being messed up if containing special characters main/game.c, main/multi.h: cleanup for netgame help menu and incremented multi proto vwersion due to recent code changes (d1x mostly however) 20120610 -------- main/automap.c, main/automap.h, main/multi.c, main/multi.h, main/net_udp.c, main/state.c: removed MarkerOwner; some code cleaning in that regard arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, main/songs.c, main/songs.h: added songs_play_file() to play any song depending on filename-extension as a more streamlined approach to handle all different kinds of formats; also used for jukebox to make it independent from SDL_mixer; cleaned up supported filename extenstions 20120608 -------- main/multi.c, main/object.c: cleanly decide it to drop a hoard orb depending on wether we were killed by ourselves, en enemy or team-mate without any ugly and unreliable hacks main/kconfig.c: Switching keyboard sensitivity function from variable increase to variable offset, making the ship more responsive in higher settings math/vecmat.c: in vms_matrix_from_quaternion put the definition of tmp1 and tmp2 variables at the beginning of the functions because i was a baaaad boy main/multi.c: do not write player file each time lifetime stats change to prevent hickups on killing 20120601 -------- main/kconfig.c, main/kconfig.h, main/menu.c, main/playsave.c, main/playsave.h: Introduced sensitivity sliders for keyboard which cause movement increase the longer the designated key is pressed main/gauges.c, main/menu.c, main/net_udp.c, main/songs.c, misc/physfsx.c: use size of output buffer for snprintf; on the way changed rebirth-specific song file to dxx-r.sng to respect hog 8+3 file convention editor/med.c, misc/physfsx.c: changed extension for archive (addon) content from zip to dxa - still a zip-file but renamed to not accidentially add user generated backups and possibly mess things up 20120527 -------- editor/med.c, main/game.c, main/gamecntl.c, main/gamerend.c, main/gauges.c, main/kconfig.c, main/menu.c, main/screens.h: Removed remnants of the old and obsolete VR implementation main/laser.c: removed weapon_rate_scale() which should be obsolete due to other optimizations in network code; Removed Laser_offset hack 20120526 -------- main/collide.c: Fit player/player collisions to not take damage from bump while remote player has possibly not aligned to the collision, yet; Added FORCE_DAMAGE_THRESHOLD for minimum force damage to receive from object bumps to not simply take damage from touching objects main/net_udp.c: Fixed one more copy/paste issue causeing positional updates relayed to possibly disconnected players include/vecmat.h, main/gameseg.c, main/multi.h, main/net_udp.c, main/net_udp.h, main/object.h, maths/vecmat.c: Optimization for quaternion structure: Stuffed orientation in shorts and removed figure out segnum by position - saving 10 bytes for each positional update in Multiplayer; Also removed render_type from pdata to save yet another byte main/titles.c: fixed possible buffer overflow in load_screen_text() 20120525 -------- main/cntrlcen.c, main/game.c, main/switch.c: Cancel out do_controlcen_dead_frame() when not playing and only check triggers for playing players for further host-authority stuff; Made GameProcessFrame not cause endless loop by closing kmatrix over and over again due to game_leave_menus(); Also only close menus when level ends and when we die only the automap will close - otherwise menus can stay (user request) 20120524 -------- main/gameseq.c, main/gameseq.h: in StartLevel() only call disable_matcens() and clear_transient_objects() in Singleplayer to keep consistency with remote clients 20120521 -------- main/state.c: now properly initialize all other parts of the new/old player object when restoring a coop savestate include/vecmat.h, main/gameseg.c, main/multi.c, main/multi.h, main/net_udp.c, main/net_udp.h, main/object.h, main/playsave.c, maths/vecmat.c: Introduced quaternion functions to replace vector matrix where size matters - created by Florian Feucht; Added option for pdata packets based on quaternion in Multiplayer game; Removed PF_LEVELLING from new player objects to prevent jittering in player banking 20120519 -------- arch/ogl/gr.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, editor/autosave.c, editor/func.c, include/strutil.h, main/bmread.c, main/gamecntl.c, main/gamepal.c, main/gamesave.c, main/hud.c, main/menu.c, main/mission.c, main/multi.c, main/net_udp.c, main/newmenu.c, main/piggy.c, main/playsave.c, main/scores.c, main/songs.c, main/titles.c, misc/args.c, misc/hash.c, misc/physfsx.c, misc/strutil.c, texmap/scanline.c, ui/file.c: using our own functions for stricmp, strnicmp, strlwr, strupr, strrev with a d_ prefix for all platforms for consistency editor/kmine.c, editor/mine.c, include/strutil.h, include/u_mem.h, main/bmread.c, main/gamepal.c, main/gamesave.c, main/piggy.c, mem/mem.c, misc/parsarg.c, misc/strutil.c: using our own functions for strdup and _splitpath with the d_ prefix for all platforms for consistency main/movie.c: solved some potential buffer overflows when initializing movie names 20120518 -------- main/state.c: fixed incorrect canvase for opengl-scaled savestate thumbnail; rebuild free objects after restoring and remapping the coop players 20120516 -------- main/game.c: In Multiplayer when taking damage, the game will only leave menus when shield drop below 5 main/net_udp.c: when updating game info also check for player connected status in case we send to everyone main/gamecntl.c, main/object.c: allow PAUSE key during death sequence to pause or view multiplayer game stats; Also reset hostages_on_board when ship blows up so pause menu during death sequence will show 0 hostages soon as the ship explodes; fixed crash for slew_init by removing old numlock hack 20120515 -------- main/net_udp.c: Do not send endlevel packets to disconnected (but still saved) clients; Do not allow ports below 1024; More verbosity for udp_open_socket() 20120514 -------- 2d/disc.c, SConstruct, editor/medmisc.c, include/gr.h, include/internal.h, main/gauges.c, main/menu.c, main/net_udp.c, main/playsave.c, main/state.c, misc/hmp.c, misc/physfsx.c: Fixed some non-critical compiler warnings; Now compiling with -std=c99 -pedantic and fixed warnings (except for editor build) caused by this 2d/bitblt.c, 2d/pixel.c, arch/sdl/digi_mixer.c, main/gauges.c, main/menu.c: Made inline functions static include/gr.h, main/ai.c, main/ai2.c, main/aipath.c, main/automap.c, main/cntrlcen.c, main/escort.c, main/fuelcen.c, main/game.c, main/game.h, main/gamecntl.c, main/gamerend.c, main/gamesave.c, main/laser.c, main/mglobal.c, main/object.c, main/object.h, main/render.c, main/texmerge.c, main/wall.c, main/weapon.c: Renamed FixedStepCalc() to cald_d_tick() and FixedStep became d_tick_step; Also ther eonly is a 50ms-timer used to d_tick_step as it was the only one used so far; Replaced FrameCount with d_tick_count which only increments by 50ms-timer used in calc_d_tick() - that now scales timed actions for certain functions properly and makes AI work FPS-independent without any hacks in that regard main/multi.c: During kmatrix bring up Game_wind againso the host can still follow the game - becomes necessary later with host-authority functions 20120510 -------- main/multi.h, main/state.c: Reuse pre-defined player objects when loading coop savestate to revent messup when player amount or orders change in a certain way main/menu.c, main/playsave.c, main/playsave.h, main/weapon.c: Wrote seperate function for weapon autocycling that also cycles through non-autoselect weapons and properly respects super laser; Added option to not autoselect weapon when firing; On the way, smoothed the menu text in misc menu a bit net_udp.h: Reduced timeout from 10 to 5 seconds RELEASE-NOTES.txt, SConstruct, arch/carbon/conf.h, main/multi.h: Incremented version to 0.57.3; Added Release notes 20120509 -------- main/laser.c, main/multi.h: Added more versatility in picking targets for the creation of smart blobs - especially for Multiplayer; cleaned that code a bit; made dodging of homing projectiles a little easier 20120430 -------- main/net_udp.c: fixed copy/paste mistake 20120427 -------- main/multi.c, main/multi.h: Similar to Network_new_game introduced imulti_new_game to exclusivly use in multi.c to execute stuff in new level only when starting a new game - for example resetting player ship inventory which is not supposed to happen on each level 20120424 -------- main/gauges.c: little reorganization for draw_hud(): draw multiplayer names first, reticle last to prevent anything being drawn over by floating names and reticle not messed by anything else 20120423 -------- main/multi.c, main/multi.h, main/net_udp.c: fixed improper player disconnecting which might have been caused by endlevel packet 20120422 -------- main/automap.c: Change MarkerScale changing keys from KEY_COMMA and KEY_PERIOD to KEY_F11 and KEY_F12 respectively, so I can use the former as controls in the automap 20120418 -------- main/gameseq.c, main/gameseq.h, main/gauges.c, main/multi.c, main/net_udp.c, main/state.c: Removed usage of 'oldmaxnet' variable when switching between coop and other game modes which would not be correctly set when coop mode is loaded from a netgame profile; Removed 'MaxNumNetPlayers' variable as already replaced by Netgame.max_numplayers 20120417 -------- main/game.c: Make sure Cursegp is initialised if using it to set an object when loading a game (EDITOR build). Thought I already committed this main/gameseq.c: Finish the game cleanly, closing Game_wind, if Current_level_num is 0 editor/med.c: Reset the player object for the editor, since demo playback mucks it up main/render.c: Skip rendering of OBJ_NONE objects to avoid a failed Assert (can happen when playing a demo then going to the editor) main/newdemo.c: Set object lifeleft to IMMORTAL_TIME if the byte read in demo playback is -1. This allows the objects to stay when playing a demo, going to the editor then playing the game from the editor main/newdemo.c: Call free_mission() if a demo is corrupt, so the editor doesn't load a corrupt level editor/group.c, editor/kgame.c, editor/khelp.c, editor/kmine.c, editor/macro.c, editor/med.c, editor/medwall.c, editor/mine.c, include/ui.h, ui/file.c, ui/keypad.c, ui/menubar.c, ui/message.c: Rename MessageBox to ui_messagebox to avoid a conflict with Windows' MessageBox main/newdemo.c, main/object.c, main/object.h: Call new obj_relink_all after playing a demo, so the editor is (hopefully) never faced with poorly linked objects and hence crashes editor/eglobal.c, editor/med.c, main/gamesave.c, main/menu.c, main/mission.c, main/mission.h: Make a new mission when making a new mine to avoid a crash when testing it straight from the editor and winning, only create a new mine if a mission isn't loaded, init Cursegp to NULL, remove key command for ToggleDrawAllSegments since add segment now has ctrl-A 20120416 -------- main/gameseq.c, main/multi.c, main/multi.h: fixed two bugs caused by recent Multiplayer cleanup: Set more player-death-related veriables outside of dead_player_end() when creating new ship as not covered in subfunction is Palyer_is_dead is not true; also init my own inventory properly in multi_prep_level to get our inventory straight after receiving netgame information editor/data/med.mnu, editor/med.c, editor/medmisc.c, main/slew.c, ui/ui.c: Make movement in the editor's game screen use the player controls, make that movement more like the automap and resolve some likely conflicting key commands editor/centers.c, editor/eswitch.c, editor/med.c, editor/medrobot.c, editor/medwall.c, main/game.c, main/gameseq.c: Avoid crashes when clicking on close box with a center, switch, object or wall editing dialog open; also when playing a level, going to the editor, going back to the game then dying 20120415 -------- main/multi.c, main/multi.h, main/net_udp.c: When possibly sending player positions prior to firing, do that before messing multibuf; Added more strict sanity checks for outgoing and incoming multi packets; Moved some general game stuff from net_udp_init() to multi_new_game() editor/meddraw.c: Set edge_list_size to Num_segments*12 to avoid crashes in the editor with certain third party levels 2d/gpixel.c, arch/ogl/gr.c, editor/meddraw.c, include/ogl_init.h, main/multi.c, main/render.c: Clicking on mine elements in the editor now works in ogl editor/centers.c: Create a centers dialog that won't crash main/bmread.c, main/game.c, main/gameseq.c, main/gameseq.h, main/gauges.c, main/kmatrix.c, main/multi.c, main/multi.h, main/net_udp.c, main/state.c: Further Multiplayer cleanup: moved gobal variable resets from multi_new_game() to proper function calls; added pnum variable to init_player_stats_game() and init_player_stats_new_ship() so these can be set for each player when starting match; added multi_new_level() calls when setting up game as well when trying to join game; cleaned multi_reset_stuff() from variable resetting that happen in general game code; when being dumped from game, made sure no packets are sent during messagebox dispaly; replaced MAX_NUM_NET_PLAYERS by MAX_PLAYERS as it's the same definition misc/hmp.c: Addition for last change in hmp_reset(): execute midiOutShortMsg() even if midiOutPrepareHeader() fails as not related to SysEx part 2d/bitblt.c, main/render.c: Fixed set but unused variables in OGL build 20120414 -------- main/gamesave.c: Fix crash when loading a level in the editor editor/segment.c, include/editor/editor.h, main/gamesave.c: Set Gamesave_current_version to correct version when making a new mine, move create_new_mine to gamesave.c main/dumpmine.c: Only do an Int3 in write_game_text_file when PHYSFS_close returns 0, which is an error, not when it returns 1 editor/med.c, main/game.c, main/gamecntl.c: Delete-E while playing a level now works properly - it closes Game_wind and sets Cursegp if necessary when going to the editor main/ai2.c: Fix crash when playing a level straight from the editor (check if Current_mission has actually been loaded, like the other ex-crash) editor/med.c, main/dumpmine.c, main/gamecntl.c, ui/ui.c: Fix bugs switching between game and editor and back: make sure ModeFlag is set to 0 before it has any chance to show an alert message, fixing a crash; allow OBJ_NONE in Assert; make Game_wind invisible when loading editor in case we show an alert; call mouse_flush() in ui_init() to fix mouse issues editor/med.c, main/gamesave.c: Set the correct palette for the editor editor/meddraw.c: Set the correct edge colors for editor wireframe drawing (in LargeView) 20120412 -------- main/collide.c, main/gameseq.c, main/multi.c, main/multi.h, main/net_udp.c: Fixed some Multiplayer bugs: Reactor invulnerable time did not checked for hours spent in level so reactor would become invulnerable again after 60 minutes; Fixed the fix (heh) for misordered explode/reappear packets; Reset Player_eggs_dropped when initializing new ship so eggs are properly dropped when player disconnects two times without respawning; Cleaned player disconnecting a little bit and made code more straightforward main/menu.c, misc/hmp.c: Removed redundant call of songs_stop_all() when starting credits; Added failsafe for loop in case MHDR_DONE flag is not properly set by MIDI device; Added more verbosity for hmp_reset() 20120411 -------- editor/medrobot.c, ui/file.c, ui/inputbox.c, ui/keypress.c, ui/listbox.c, ui/message.c, ui/uidraw.c: Draw the object rotation velocity, file browser and MessageBox dialogs properly ui/file.c: Fix a crash when going into a directory with no files in the editor file browser, clicking on listboxes for same sets inputbox correctly 20120409 -------- main/state.c: in software rendering scale savestate thumbnail to correct size editor/autosave.c, editor/info.c, editor/med.c, editor/objpage.c, editor/texpage.c, include/ui.h, ui/keypad.c, ui/uidraw.c: Get the clock, 'keypad' info, texture choosing page and object choosing page to draw (latter two just show black squares for ogl) arch/sdl/window.c, ui/menubar.c: Fix a nasty bug where pressing 'Alt' to explore the editor menubar would split the window stack in two, rendering the editor unresponsive 2d/bitblt.c, 2d/box.c, 2d/font.c, arch/ogl/gr.c, editor/med.c, ui/dialog.c, ui/uidraw.c, ui/userbox.c: Fix all remaining known editor drawing issues. In ogl: get the texture previews to draw, get userbox borders to draw in the right location, properly underline characters in the menus, draw all the borders properly (i.e. no gap), no scaling fonts. Software render: draw userbox borders again. Both: clear the whole status bar, clear to the right edge of the screen. main/newmenu.c: No setting the screen mode when calling a newmenu function, so if it shows the 'Save Mine' messagebox in the editor, it won't change the screen resolution and trash everything. (If this causes problems, we can make it use the MessageBox if it's still in the editor, nm_messagebox otherwise) 2d/rect.c, editor/info.c, editor/med.c, include/ui.h, main/inferno.c, ui/dialog.c, ui/menubar.c: Editor exits cleanly when clicking the close box, no more redundant gr_uscanline call in gl_urect for ogl (an initial attempt to fix the previous bug) 2d/rect.c: Fix unused variable warning in last commit 20120408 -------- main/mission.c, main/mission.h, main/titles.c: added specification for Descent: Destination Saturn briefing screen to properly show briefings; added different briefing structure for Descent 1 Shareware which has a slightly different order of the usual briefings main/collide.c: plasma fire can ignite bombs which are dropped while firing. to compensate added a timed check where at least one projectile must be older than 200ms to trigger a possible collision. this fixes this issue if the player is moving away from the bomb 20120407 -------- main/fireball.c: in choose_drop_segment let fallback correctly check for reactor segment 2d/font.c, main/piggy.c, misc/strutil.c: removed redundant definitions of FILENAME_LEN main/multi.c, main/multi.h: fixed glitch when reappear and explode packets are misordered, rendering player invisible main/gauges.c: record shields if player is invulnerable to get proper shield display in demo playback if player respawns with invulnerability on 20120405 -------- main/multi.c: variable declarations come first include/maths.h, main/fvi.c, maths/fixc.c: Introduced fixmul64 returning fix64 type to use with check_point_to_face() and prevent fix overflow with very large faces; on the way cleaned up NO_FIX_INLINE remnants and replaced QLONG with fix64 20120331 -------- d2x-rebirth.xcodeproj/project.pbxproj, 2d/font.c: Make sure the ogl font code recognises the editor font is fixed width, fixing a crash; take the plunge and make D2X Rebirth compile with editor for Mac OpenGL build (won't work yet) editor/med.c, editor/meddraw.c, editor/medmisc.c, include/editor/editor.h, main/render.c: Make all drawing in the editor single buffered, since the whole screen is double buffered. Fixes crash - but only shows a black screen and the menu for ogl main/render.c: Complete previous change (whoops) editor/med.c, editor/meddraw.c, editor/medmisc.c, ui/button.c, ui/checkbox.c, ui/dialog.c, ui/file.c, ui/icon.c, ui/inputbox.c, ui/listbox.c, ui/menubar.c, ui/radio.c, ui/scroll.c, ui/userbox.c: Make the main stuff (gadgets, two viewers) draw for the editor in ogl, still more tweaking required ui/dialog.c: Use correct coordinates for dialog border (still doesn't draw fully) editor/medmisc.c, ui/button.c, ui/checkbox.c, ui/icon.c, ui/inputbox.c, ui/listbox.c, ui/radio.c, ui/scroll.c, ui/userbox.c: Make the editor draw the same for the non-ogl build as the ogl build, since I just made it draw the grey background over everything in the last commit. If you want to see what it's *supposed* to look like, go to yesterday's commit :P 20120330 -------- 2d/font.c: Make 2d/font.c more similar between d1x-rebirth and d2x-rebirth arch/include/event.h: Changed declaration of event_get_idle_second() from int32_t to fix since Windows does not know it without pstypes.h. Included maths.h for this but should now work flawlessly on all platforms 20120329 -------- main/multi.c, main/multi.h, main/net_udp.c, main/net_udp.h: Immediately relay pdata packets from clients to others which should reduce artificial delay; allow sending of pdata packet when firing if enough time has passed since last update; only answer full game info requests 2 times per second and lite info 8 times per second main/songs.c: Fixed Redbook playback which was not repeating the CD after finishing 20120328 -------- main/movie.c: Call all necessary MVE functions when initializing robot movies to prevent crashes if a robot movie is the first one the program plays main/slew.c: Fix compile-time error when building without editor arch/sdl/jukebox.c, main/songs.c: Allow .flac to be a filename extension for sng file and jukebox main/state.c: properly disable cheats when loading a saved game so only cheats that were stored are re-enabled main/collide.c, main/physics.c: Fixed double wall-object-damage introduced 20111124 by applying more strict rules to wall-colliding and wall-scraping where latter now is player-exclusive main/gamecntl.c: Fixed unhandled case in key reading when escort hotkeys are disabled main/net_udp.c: Since the kicked message is shown after player is technically removed from the game we do not know hosts name anymore. Message changed accordingly main/multi.c, main/multi.h, main/newdemo.c, main/player.h: Allow a total of 32 different player ship textures and stored N_PLAYER_SHIP_TEXTURES in player.h main/config.c: Dynamically allocate line to read from descent.cfg and ensure a safe length main/weapon.c: Release Fusion charge when changing to another weapon similar to D1X-Rebirth 20120324 -------- arch/ogl/gr.c, arch/sdl/gr.c, ui/menubar.c: Draw the editor menubar properly - by drawing in response to EVENT_WINDOW_DRAW and initialising the screen canvas properly. The latter fixes a lot of other editor drawing issues as well 2d/bitmap.c, arch/include/window.h, arch/sdl/gr.c, arch/sdl/window.c, include/gr.h: Update the canvas data pointers for all windows after changing the screen mode, so the main menu draws properly after leaving the editor arch/include/event.h, editor/centers.c, editor/eswitch.c, editor/med.c, editor/meddraw.c, editor/medrobot.c, editor/medwall.c, ui/dialog.c: Draw in response to EVENT_UI_DIALOG_DRAW, uncomment medlisp_update_screen call. You can now see what you're doing! ui/gadget.c: Fix bug where pad buttons would disappear when clicking on them, after opening then closing a dialog 20120319 -------- editor/med.c, include/editor/editor.h, include/ui.h, main/gamecntl.c, main/gameseq.c, main/inferno.c, main/menu.c: The editor now falls back to the main event loop in inferno.c, File->Exit now works as intended and get closer to making the editor and game work together editor/med.c, main/endlevel.c, main/gamecntl.c, main/gamesave.c, main/inferno.c, main/inferno.h, main/menu.c, main/powerup.c, main/render.c, main/slew.c: Remove all remaining uses of Function_mode, checking for the existence of EditorWindow where necessary instead 20120318 -------- editor/med.c, editor/texpage.c, include/editor/editor.h, main/game.c: Do a bit of a tidy up for the editor, dump code from editor() within the loop into new editor_handler() editor/info.c, editor/med.c, editor/medmisc.c, editor/objpage.c, editor/texpage.c, include/editor/objpage.h, include/editor/texpage.h, include/ui.h, ui/userbox.c: Make editor_handler into a proper callback, iron some problems out. Seems to draw a different bunch of stuff now (still erroneous) SConstruct, arch/include/event.h, arch/include/mouse.h, arch/sdl/event.c, d1x-rebirth.xcodeproj/project.pbxproj, editor/info.c, editor/macro.c, editor/med.c, editor/meddraw.c, editor/medmisc.c, include/ui.h, ui/button.c, ui/checkbox.c, ui/dialog.c, ui/file.c, ui/icon.c, ui/inputbox.c, ui/listbox.c, ui/menubar.c, ui/mouse.c, ui/radio.c, ui/scroll.c, ui/ui.c, ui/userbox.c: Remove redundant ui_event_process and duplicate mouse.c in ui/. All editor input is now event-based. 20120317 -------- editor/eswitch, editor/med.c: Make do_trigger_window into a proper callback editor/med.c, editor/medrobot.c: Make do_robot_window and do_object_window into proper callbacks, doing both in the same commit because of global recycling editor/med.c, editor/medwall.c: Make do_wall_window into a proper callback. Only one dialog left - the main one. 20120312 -------- editor/centers.c, editor/med.c, ui/dialog.c, ui/file.c, ui/gadget.c, ui/radio.c: Make do_centers_window into a proper callback, iron out some problems that have become apparent 20120305 -------- include/ui.h, ui/file.c, ui/gadget.c, ui/keypress.c, ui/listbox.c, ui/menu.c, ui/message.c, ui/popup.c: Use the gadget-sent events in the dialogs in ui 20120303 -------- d2x-Info.plist, d2xgl-Info.plist, English.lproj/InfoPlist.strings, RELEASE-NOTES.txt: Increment version to 0.57.2 for Mac and RELEASE-NOTES d2x-rebirth.xcodeproj/project.pbxproj, editor/data/, editor/data/curve.pad, editor/data/dummy.pad, editor/data/group.pad, editor/data/lighting.pad, editor/data/med.mnu, editor/data/newobj.pad, editor/data/object.pad, editor/data/objmov.pad, editor/data/pc6x8.fnt, editor/data/pc8x16.fnt, editor/data/segmove.pad, editor/data/segsize.pad, editor/data/test.pad, editor/data/texture.pad, editor/med.c, include/physfsx.h, misc/physfsx.c, ui/ui.c: Actually add editor data files and make sure DXX can find them arch/include/event.h, editor/med.c, include/ui.h, ui/button.c, ui/checkbox.c, ui/dialog.c, ui/gadget.c, ui/icon.c, ui/inputbox.c, ui/listbox.c, ui/radio.c, ui/scroll.c, ui/ui.c, ui/userbox.c: All gadgets now send events 20120109 -------- ui/popup.c: Give the last use of a dialog in ui, in PopupMenu, a callback 20120103 -------- ui/keypress.c: Give the dialog in (presently unused) GetKeyCode a callback ui/menu.c: Give the dialog in (also presently unused) MenuX a callback ui/message.c: Give the dialog in MessageBoxN a callback 20120102 -------- ui/dialog.c, ui/file.c: Give ui_get_filename a callback for its dialog. Happy new year! 20111231 -------- editor/med.c, include/ui.h, ui/menu.c, ui/menubar.c, ui/popup.c: Make editor menubar and associated menus into windows; either remove or make event-based all the B1_* macros 20111218 -------- include/ui.h, ui/dialog.c, ui/gadget.c, ui/keypad.c: Remove redundant canvas, next and prev members in the UI_DIALOG struct 20111127 -------- arch/sdl/event.c: break out of loop in event_send() in case window_send_event() closed the window to prevent invalid read on memory 20111124 -------- main/collide.c, main/collide.h, main/fireball.c, main/game.c: Smoothed disabling of friendly fire to re-enable splash damage possible when friendly fire is disabled main/physics.c: calling scrape_object_on_wall in each case of HIT_WALL more reliable to properly do hazard surface damage and prevent weapon objects from possibly sliding against walls 20111114 -------- ui/userbox.c: Make ui_userbox_do fully event-responsive main/newmenu.c: Sliders can now be operated with Numpad arrows if numlock if off 20111112 -------- ui/gadget.c, ui/scroll.c: Make ui_scroll_do fully event-responsive, make sure scrolling actually works by calling all controls' ui_*_do functions (like before) 20111106 -------- include/ui.h, ui/dialog.c, ui/listbox.c: Make ui_listbox_do fully event-responsive ui/radio.c: Make ui_radio_do fully event-responsive 20111105 -------- include/ui.h, ui/button.c, ui/dialog.c, ui/gadget.c, ui/scroll.c, ui/userbox.c: Make B1_JUST_PRESSED event-based, leave ui_dialog_do_gadgets early if a key makes another gadget current, make ui_button_do fully event-responsive (but won't *send* events yet) editor/med.c: Put back use of med_show_warning for Linux, but then clear it properly when leaving the editor ui/checkbox.c: Make ui_checkbox_do fully event-responsive ui/checkbox.c, ui/icon.c: Fix implicit function declaration in last commit, make ui_icon_do fully event-responsive ui/inputbox.c: Say when the event was handled for ui_inputbox_do (was already event-responsive) 20111103 -------- main/net_udp.c, main/net_udp.h: Do not attempt to check for MULTI_PROTO_VERSION when requesting lite_info 20111102 -------- SConstruct, arch/carbon/conf.h, main/gameseq.c, main/inferno.c, main/inferno.h, main/menu.c, main/multi.h, main/net_udp.c, main/net_udp.h, main/vers_id.h: Introduced extra short based on MULTI_PROTO_VERSION for version-independent Multiplayer-compability-check; Changed version to 0.57.2 to make new version checking not cause problems with stable release 0.57.1; Removed old version_major/minor variables from netgame and player structures since DXX handles this independently; Cleaned up old version stuff and copyright messages 20111030 -------- arch/include/mouse.h, arch/sdl/mouse.c, ui/dialog.c: Return 1 (event handled) in ui_dialog_handler for mouse button events if the mouse was in the dialog 20111025 -------- include/ui.h, ui/button.c, ui/checkbox.c, ui/dialog.c, ui/gadget.c, ui/icon.c, ui/inputbox.c, ui/keytrap.c, ui/listbox.c, ui/radio.c, ui/scroll.c, ui/userbox.c: Pass the event to the individual gadgets' 'do' functions, fix compile warnings introduced in last commit 20111023 -------- include/ui.h, ui/dialog.c, ui/gadget.c: Pass the event to ui_dialog_do_gadgets and use it in that immediate function 20111009 -------- main/render.c: Initialise dyn_light using memset, fixing a warning arch/include/event.h, arch/include/window.h, arch/sdl/event.c, arch/sdl/window.c, include/ui.h, ui/dialog.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/message.c, ui/popup.c: Add support for 'modeless' windows - windows that will allow events to be passed on to the underlying window. Intended for the editor main/net_udp.c: Fix comparison is always false warning editor/centers.c, editor/ehostage.c, editor/eswitch.c, editor/info.c, editor/med.c, editor/medrobot.c, editor/medwall.c, ui/dialog.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/message.c, ui/popup.c: Move calls to ui_dialog_do_gadgets to the dialog event handler, making sure ui_event_handler gets called beforehand 20110927 -------- 2d/palette.c, RELEASE-NOTES.txt, editor/eobject.c, editor/group.c, editor/meddraw.c, editor/medrobot.c, editor/mine.c, editor/segment.c, editor/seguvs.c, iff/iff.c, libmve/decoder16.c, libmve/mveplay.c, main/ai2.c, main/aipath.c, main/bmread.c, main/cntrlcen.c, main/dumpmine.c, main/fvi.c, main/gamemine.c, main/gamesave.c, main/gameseq.c, main/gauges.c, main/movie.c, main/multi.c, main/newdemo.c, main/newmenu.c, main/piggy.c, main/polyobj.c, main/render.c, main/titles.c, texmap/ntmap.c, texmap/scanline.c, ui/button.c, ui/inputbox.c, ui/keypad.c, ui/keytrap.c, ui/popup.c, ui/scroll.c: Fixed set but unused variables 20110926 -------- main/collide.c, main/escort.c, main/laser.c, main/fireball.c, main/lighting.c: Code consistency checks by _Tyr_; Fixed set but unused variables d2x-rebirth.desktop, SConstruct, misc/physfsx.c: Patches by Hans de Goede: Made the .desktop file follow the official specifications; Added explicit link to libmath for newer versions of binutils; Fixed crash using PhysFS 1.x in PHYSFSX_addArchiveContent() main/kconfig.c, main/menu.c, main/playsave.c, main/playsave.h: Gave throttle it's own sensitivity and deadzone settings; Added patch by Hans de Goede to let Slide-On and Bank-On settings use invert settings from Slide- and Bank-axes 3d/interp.c, arch/ogl/ogl.c, main/bm.c, main/endlevel.c: Avoided variable array initializations which some compilers do not like; Also made sure declarations happen first inside (sub)functions; Fixed set but unused variables 20110925 -------- main/game.c: Fixed misuse of gr_bitblt_find_transparent_area() caused rear view to be shifted on some cockpits 20110924 -------- main/fvi.c, main/gameseg.c, main/object.c: Consistency check for segment number in find_vector_intersection() and obj_create(); Added more debug output for invalid segment numberin get_seg_masks() main/cntrlcen.c, main/newdemo.c, main/switch.c, main/wall.c, main/wall.h: Reworked wall_toggle() to work with index for segnum instead of a pointer, hopefully making the consistency check less error prone 20110923 -------- main/state.c: When restoring Coop players and make turn them into ghosts perform a check if this player is actually a valid player so we do not just blindly use any object number from a possibly uninitialized player structure 20110921 -------- main/net_udp.c: Streamlined joining, rejoining, disconnecting players and timeouts, getting rid of unwanted rejoin messages and let host remove a player for good without rejoining it via pdata packet to really get rid of lossy or unwanted players; Care for rollover of pkt_num of stored mdata packets main/game.c: Fixed overuse of multi_send_sound_function when handling afterburner in case player is dead or escaped main/net_udp.c: Added wrapper functions dxx_sendto and dxx_recvfrom to collect simple statistics about amount and size of packets sent/received per second; Actually fixed packet scheduling in main UDP frame - was sending more than intended - stupid me 20110919 -------- main/multi.h, main/net_udp.c: Reworked Packet Loss Prevention: If an important packet could not be recovered until it timed out, dump player who failed sending/receiving it; Noloss queue can proces spackets until a certain traffic has been reached; In main UDP frame schedule different types of packets depending on PPS to decrease traffic produced in one frame, hopefully preventing too much loss in high-traffic situations; Small code cleanups; Added new dump signal for loss of important packet; When dumping player also disconnect that one in case the dumped player does not accept the signal main/playsave.c: Removed saving/restoring the state of Packet Loss Prevention from Netgame profiles 20110915 -------- main/laser.c, main/laser.h, main/multi.c, main/multi.h, main/multibot.c, main/net_udp.c, main/net_udp.h: Added new priority level for MDATA packets to also send them ASAP without the need for an ACK; Streamlined sending multibot and fire packets and on the way artificially and automatically scaling fire rates, energy/ammo usage and damage of weapons in Multiplayer to decrease traffic easy way without changing the Gameplay 20110914 -------- INSTALL.txt, README.txt, SConstruct, arch/carbon/conf.h, d2x.ini, include/args.h, main/inferno.c, main/kmatrix.c, main/kmatrix.h, main/menu.c, main/multi.c, main/multi.h, misc/args.c: Removed support for IPX protocol and MS-DOS-Multiplayer-compability due to age and lack of real need and to really improve on the Multiplayer without adding too much complexity for backwards-compability 20110913 -------- README.txt: Mention Mac command keys arch/carbon/conf.h, d2x-rebirth.xcodeproj/project.pbxproj: Define USE_TRACKER for Mac OS X, remove reference to deleted cfile.h 20110912 -------- arch/sdl/mouse.c, ui/mouse.c: Move EVENT_MOUSE_DOUBLE_CLICKED support from ui/mouse.c to arch/sdl/mouse.c for tidiness and to possibly use it outside the editor 20110826 -------- main/ai.c: Due to conversion from fix64 to fix Boss_dying_start_time was not 0 when saving even if boss was not dead - fixed; Fixed warning about set but unused variable 20110720 -------- main/menu: Added Polygon model viewer and GameBitmaps viewer in non-Release build for debugging, messing around, DXX-Redrawn, etc. 20110719 -------- main/net_udp.c: Properly call multi_leave_game() when host leaves multi game to let clients exit smoothly English.lproj/InfoPlist.strings, d2x-Info.plist, d2xgl-Info.plist, main/inferno.c: Keep copyright information up to date README.txt, debian/control, debian/copyright, debian/rules: Changed my eMail address 20110716 -------- main/songs.c: Correctly proceed to new Redbook track if songnum != Song_playing (hopefully - to confirm); Using songs_stop_all() in songs_uninit() to clear redundancy; added some notes to functions to shine a bit light on the mess of some functions; Also if there's no escape song, continue level music arch/sdl/rbaudio.c, main/inferno.c: Fixing Redbook hooks: Initialize last_check_time in RBACheckFinishedHook(); Execute RBACheckFinishedHook() during EVENT_WINDOW_DRAW in standard_handler() as EVENT_IDLE rarely happens if you have a shivering Joystick connected for example arch/carbon/conf.h, SConstruct: Changed version to 0.57.1; Updated release notes 20110715 -------- main/net_ipx.c, main/net_udp.c: When updating netgame hoard game flag used for compability reasons must be removed as it can be set - otherwise screwing up game mode display in netlist menu arch/sdl/digi.c, main/digi.h, main/songs.c, misc/hmp.c: Bail out of hmp_reset() if midiOutOpen fails and return error with -debug set; execute hmp_reset() before first song plays; renamed digi_win32_stop_current_song() to digi_win32_stop_midi_song() to keep naming convention; Fixed some compiler warnings main/net_udp.c, main/net_udp.h: Fixed typo in Packets per sec. in GAME_RULES screen; Reduced max amount of games shown on netlist to 900 to reduce RAM usage... as if we'd ever reach this main/automap.c: properly check and fix viewMatrix in free flight auotmap 20110714 -------- main/collide.c: When colliding with robot not controlled by us in Multi-Robot game do not apply force or damage - wait until the robot is under our control - preventing juggeling robots back and forth between players and creating massive damage main/multi.c: Due to descent2.ham reloading, hoard.ham must realod properly as well; cover multi_send_sound_function by plp preventing sound loops get lost/screwed in action 20110713 -------- arch/sdl/event.c, arch/sdl/key.c, main/kconfig.c, main/menu.c: Stability fixes: avoid somfusions with same named variables in one function; Properly sort out players from player list that use too long filenames; Removed call for gr_set_fontcolor in kconfig where no canvas is set, causing crashes when trying to reassign a button, key or axis 20110712 -------- main/wall.c: Readded automatic wall-flag setting for opened doors as PLP cannot protect us from negative side-effects due to how gullible multi_do_door_open() works main/multibot.c: Fixed uninitialized bytes in multi_do_create_robot_powerups() and two set but unused variables 20110710 -------- main/gameseg.c: Added complex error output if illegal segnum passed to get_seg_masks(); Fixed warning about set but unused variables 20110709 -------- main/gamerend.c, main/gauges.h: In Multiplayer games show player names in big guided window as well main/multibot.c: Just like for players do not protect robot firing or positional data (via PLP) to prevent jumpy movement with delayed packets main/lighting.c: Added new dynamic light calculation which works with find_connected_distance() preventing vertecies to be lit up without connection to light source but still maintaining illumination. Still deactivated as it needs more optimization - planned for 0.58. Removed old alternative dynamic lighting which was suppoed to work via fvi but way slower than the new one 20110708 -------- main/net_udp.c: Slight improvement for Packet Loss Prevention: Be able to send to 35 packets per call of net_udp_noloss_process_queue() and also let counter only increase if a packet was actually sent, making sure the queue is not stuck on the first 5 packets in the list arch/sdl/digi.c: Make sure hmp_reset() is only executed if a song was playing 20110704 -------- main/game.c, main/gamerend.c: Only call show_netplayerinfo() if GM_MULTI is set and reset netplayerinfo_on in game_setup() misc/physfsx.c: Fixed typo 20110702 -------- main/ai.c: When initializing ai object correctly initialize Ai_local_info to prevent glitches like random submodel angles main/menu.c: Reset idle timer in main menu correctly even after playing the intro movie; Also got rid of a goto as it's generally bad and not needed since random demo selection picks a correct demo anyways 20110701 -------- d2x.ini, main/inferno.c, main/net_udp.h, misc/args.c: Made formatting for help text more consistent and prettier; Somewhat changed the code for help text so we can use variables in the help text. For example: If we change MAXIMUM_FPS, it will automatically be displayed in the help text without manual editing needed 20110630 -------- editor/group.c, editor/ksegsize.c, editor/meddraw.c, editor/segment.c, editor/seguvs.c, include/editor/editor.h, main/automap.c, main/fireball.c, main/gamecntl.c, main/gameseg.c, main/gameseg.h, main/lighting.c, main/render.c, main/render.h, main/segment.h: changed variables and pointer carrying vertex indexes from short to int to handle levels with over 900 segments properly 20110628 -------- main/state.c: Fixed possible memory corruption when saving Current_mission_filename which is not necessarily a 9 byte long allocated string; Bit safer string handling with snprintf; Fixed set but unused variables like a boss main/net_ipx.c: Correctly disable/initialize Multiplayer features not supported by IPX games for compability; Removed show_games_rules as there isn't much useful to show there; Some more code simplicity; Fixed sending of allowed items; Fixed player selection screen 20110624 -------- main/net_udp.c: Fixed object sync for latecoming clients which was broken due to a very, very, VERY stupid mistake... 20110623 -------- main/hud.c: PlayerCfg.MultiMessages was supposed to only show messages of class HM_MULTI but turned out to only block HM_REDUNDANT, too. Fixed this copy/paste error of mine main/laser.c: For Hotshot and above made homing missiles turn to player a bit less agressive which is hardly noticable but slightly increases the chance to shake off a projective even if dodged without perfect timing. This makes possible to survive in case a player/bot shoots several homing projectiles in spread fashion 20110621 -------- misc/args.c: When GameArg.CtlNoStickyKeys was introduced I forgot to add an actual check if -nostickykeys was supplied - fixed now 20110620 -------- main/lighting.c: in compute_light_emission() handle RT_NONE for delayed explosion fireballs 20110617 -------- main/physics.c: By using fixed distance bumping for fix_illegal_wall_intersection making the whole process much more reliable on sharp edges 20110609 -------- main/render.c: Saturate colored dynamic light just like normal one - makes the hwole thing a bit less colorful but makes for better balanced color mixing (theoretically) and does not reduce static light 20110607 -------- main/switch.c: Correctly disable secret levels for Shareware main/render.c: Definition of dynlight_time should have been static to archive timed light calculations 20110606 -------- main/menu.c, main/playsave.c: For all filename strings use PATH_MAX as size, make sure they are inited correctly and only fill them with snprintf instead of sprintf 20110604 -------- main/lighting.c: Since set_dynamic_light() is not necessarily processed each frame, added own counter for delayed precession of vertex-clight calculation; Added possibility to page in a bitmap in case an object which has never been rendered before is supposed to cast light visible by the player main/digiobj.c, main/piggy.c: Don't force AltSounds on PC-Shareware content but still must bail out on missing sounds using a small hack. Still gives a better sound palette than AltSounds main/titles.c: Play SONG_BRIEFING and SONG_ENDGAME on all non-builtin missions if available main/endlevel.c: Correctly handle PC Shareware for start_endlevel_movie() again without the defines but via is_SHAREWARE main/digiobj.c: Just generally ignore missing sounds in digi_xlat_sound just like D1X-Rebirth - not limit to Shareware main/multi.c: for flexibility in terms of modding, allow player ship textures in Multiplayer be <= N_PLAYER_SHIP_TEXTURES and not hit Assert but pull out Eroor if there are more 20110601 -------- 2d/font.c, 2d/palette.c, 2d/pcx.c, arch/linux/hmiplay.c, arch/ogl/gr.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, editor/group.c, editor/kmine.c, editor/med.c, editor/mine.c, iff/iff.c, include/interp.h, include/physfsx.h, main/ai.c, main/automap.c, main/bm.c, main/bm.h, main/bmread.c, main/cntrlcen.c, main/cntrlcen.h, main/credits.c, main/digiobj.c, main/effects.c, main/effects.h, main/endlevel.c, main/fireball.c, main/fireball.h, main/fuelcen.c, main/fuelcen.h, main/game.c, main/game.h, main/gamefont.c, main/gamemine.c, main/gamemine.h, main/gamesave.c, main/gameseq.c, main/inferno.c, main/menu.c, main/menu.h, main/mission.c, main/movie.c, main/multi.c, main/net_ipx.c, main/net_udp.c, main/newdemo.c, main/newmenu.c, main/piggy.c, main/piggy.h, main/player.c, main/player.h, main/playsave.c, main/polyobj.c, main/polyobj.h, main/powerup.c, main/powerup.h, main/robot.c, main/robot.h, main/segment.c, main/segment.h, main/songs.c, main/state.c, main/switch.c, main/switch.h, main/text.c, main/titles.c, main/vclip.c, main/vclip.h, main/wall.c, main/wall.h, main/weapon.c, main/weapon.h, misc/hmp.c, misc/ignorecase.c, misc/physfsx.c, misc/strio.c, ui/keypad.c, ui/menubar.c: Got rid of cfile code: Renamed cfile-functions to use PHYSFSX-naming convention, Replaced cfile-macros with proper PHYSFS(X) calls; Introduced PHYSFSX_exists() which can check case-sensitive or case-insensitive to give more flexibility with game content main/endlevel.c: When reaching EL_FLYTHROUGH in do_endlevel_frame() do not check for start_endlevel_movie() anymore but rather it's result so this subfunction does not get called again which does not only save us from executing pointless code and code which screws up flythrough sequence main/game.c: Executing timer_update() at the beginning of calc_frame_time in case event_process() taking a significant amount of time to reach the game window and therefor could make FrameTime be inaccurate main/lighting.c: Added proper colored lighting handling for RT_POWERUP which I not noticed was wrong before ... darn dim glowing powerups 20110530 -------- arch/include/digi_audio.h, arch/include/digi_mixer.h, arch/sdl/digi.c, arch/sdl/digi_mixer.c, main/digi.h, main/digiobj.c: Added own channel management to SDL_mixer sound interface since the builtin channel management of this lib cannot handle our needs; Little code cleanup 20110528 -------- main/net_ipx.c, main/net_udp.c: Made netgame setup menu more flexible towards (constant or temporary) changes in available game modes 20110526 -------- arch/sdl/event.c: In event_process() if a window closes while being drawn and there isn't a previous window we can get the next from just finish processing for this frame main/gamerend.c: in game_render_frame_mono() call show_netplayerinfo() last so window views do not overlap 20110525 -------- main/multi.c, main/multi.h, main/net_ipx.h, main/net_udp.c: Added multi_send_data_direct to send multibuf to a specific player (i.e. Host<->Client, not Client<->Client); Overhauled kill sending/receiving and computation to rely in host information about game_mode-related variables (team_vector, Bounty_target) which are vital for consistent kill computation; Added function to send/update game_mode-related variables and solve /move command with this as well instead of workaround via updating lite_info 20110522 -------- editor/med.c, main/game.c, main/gameseg.c, main/gameseq.c, main/menu.c: Like in BigEndian builds do netmisc_calc_checksum() only with expected items of segment/side struct to prevent different checksums in case these structs change; Fixed several issues when building with editor; Fixed compiler warning regarding set but unused variable main/net_udp.c: When restoring Coop setting from netgame profile don't forget to fix max players variable 20110520 -------- INSTALL.txt, RELEASE-NOTES.txt: Updated docs and fixed some typos main/net_ipx.c, main/net_udp.c: Rearranged code to check for netgame-closed flag and refuse-players flag so they are updated correctly if another part of the code changes the menu item without activating it main/automap.c, main/menu.c, main/playsave.c, main/playsave.h: Made Automap Free Flight controls an optional feature which can be set in MISC OPTIONS main/net_udp.c: Let players launch 1-player team-based games in RELEASE build as well main/net_udp.c: Making D1X- and D2X-Rebirth more similar in behavior of which player limit is needed to start team-based game in both RELEASE and DEBUG builds 20110519 -------- main/fvi.c, main/fvi.h, main/physics.c: Improvement for fix_illegal_wall_interesection(): Move away from wall in right angle - not towards center. This improves the bumping in many situations and prevents ship getting stuck in small segments. Simplified and optimized code as well and removed check for degenerated Segments as not needed with this approach; Fixed some compiler warnings regarding set but unused variables main/multi.c: Reset new_Bounty_target after using it and let host add a number on how often Bounty is reassigned. Both additions should help keeping target correct no matter how if multiple packets of the same type are disordered, delayed or both main/physics.c: for fix_illegal_wall_intersection() try using the distance we moved to move out from the wall. Just in case it's a sane value, i.e. > 0 and <= obj->size/2 arch/ogl/gr.c, main/game.c: Removed key_flush() call from save_screen_shot() - not needed anymore due to new input reading and only screws up ingame controls 20110516 -------- main/menu.c: for debug build ignore player Highest_level_index when starting a mission, making *Load Level* entry in main menu obsolete; Fixed two compiler warnings regarding set but unused variables 20110515 -------- main/multi.c: Solved possible issue when setting new Bounty_target via host messing up scores or new target itself - only set if player decided why to unset Bounty_target, keeping code flow and game logic in order; Fixed two compiler warnings regarding set but unused variables RELEASE-NOTES.txt: Added more info: M3U-support, GCC 4.6 warnings, more tracker infos 20110513 -------- main/multi.c: Send player position also when multi_send_player_explode() is called so powerups drop at the right spot in case the respawn packet arrives first 20110507 -------- arch/carbon/conf.h: Enabled Tracker support for Mac OS RELEASE-NOTES.txt, README.txt, SConstruct, arch/carbon/conf.h: Changed version from 0.56 to 0.57; Added first draft for RELEASE-NOTES.txt; updated docs main/endlevel.c: Taken out Render_depth reduction of Endlevel sequence in Software rendering build; Fixed two compiler warnings regarding set but unused variables main/automap.c: Don't call automap_process_input() if autmap_key_command() returns 1 preventing input mess 20110505 -------- main/gauges.c, main/multi.h, main/net_ipx.c, main/net_udp.c, main/net_udp.h, main/playsave.c: Host can now decide (again) if players are allowed to display enemy names on HUD d2x-rebirth.desktop, debian/changelog, debian/control, debian/copyright, debian/rules: Update for Debian packaging stuff main/lighting.c: Correctly handle light computation of objects with render_type RT_LASER 20110504 -------- editor/segment.c, main/fvi.c, main/gameseg.c, main/physics.c, main/segment.h: Since current approach to improve wall collisions prevented the player to enter segments which basically are too small for the player ship, added simple bumping function via object_intersects_wall(); Also when validating segments check for segment degeneration outside the editor build, too and set flag in segment structure for all different purposes but right now helps us to disable bumping when encountering degenerated segments and not break such levels main/endlevel.c: Make sure the big explosion at the end of the escape sequence also uses blending if transparency effects are activated main/multi.c: Fix crash in multi_maybe_disable_friendly_fire() when killer == NULL; Do not let player join game when gamemode is HOARD or TEAM HOARD and hoard.ham is not available 2d/font.c: mipmapping was always on for fonts due to changed filtering code in ogl.c main/physics.c: To compensate fewer FVI runs in lower FPS and wall penetration caused by strong forces allowed fix_illegal_wall_intersection() to move an object out of the wall half it's size improving the collisions once more main/segment.h, main/state.c: Due to increased size of MAX_SEGMENTS old savegames became incompatible. To compensate added MAX_SEGMENTS_ORIGINAL with the original segment amount and read certain savegame info with this info when dealing with standard-sized levels and use Highest_segment_index when dealing with larger levels which are incompatible with older versions of the game anyways. Makes savegame site more efficient and still maintain backwards compability main/render.c: When doing sorted rendering, also take cloaking walls into account to properly draw objects behind it while cloaking process 20110422 -------- 2d/rle.c, SConstruct, main/segment.h, main/texmerge.c: Expanded possibilities for level authors: RLE- and Texture-cache accepts textures bigger than 64x64, only limit being Texture width must be equal height; Increased maximum amount of Segments from 900 to 9000 - not dynamically allocating them, yet arch/sdl/mouse.c, main/kconfig.c, main/menu.c, main/playsave.c, main/playsave.h: When reading ingame controls only flush mouse delta timer-based since reading is event-based already, allowing high precision no matter the game speed; Removed Mouse smoothing/filtering as it's now unnecessary due to event-based motion handling 2d/rle.c, main/texmerge.c: Fixes for RLE- and Texture-cache modifcations: Before freeing now must check if bitmap is already allocated main/menu.c, main/net_udp.c, main/playsave.c, main/playsave.h: Remember previously set up netgame variables in pilot-related file with extension ngp - due to feature consistency for UDP only 20110421 -------- main/net_ipx.c, main/net_udp.c: When leaving game and still sending extras, don't forget to update the timer so we won't get stuck in an infinite loop arch/sdl/key.c: Added SDLK_WORLD_** symbols to keyboard array to enable layout specific keys and make the game more flexible 20110420 -------- main/multi.c, main/state.c: Resolved termination issue when reading and comparing callsigns fro Coop savestates; Added scores sending after Coop savestate loading as unrestored players will send them when loading new level main/gameseq.c, main/misison.c: Moved reloading of main descent2.ham (in case mission brings it's own version) from LoadLevel() to load_mission() so it does not screw missions with ther custom ham-file (like vertigo) 20110418 -------- arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, main/config.c, main/menu.c, main/songs.c, main/songs.h, main/titles.c: Fix broken m3u playlist support (in jukebox_play() path resolving); point to default descent.m3u playlist for Mac OS X (will be included in bundle); better error reporting in mix_play_file(); only make relative Jukebox path in the menu absolute after browsing it - relative paths are more flexible; allow select_file_recursive() to figure out PhysicsFS relative paths passed to it; stop the music if Jukebox is chosen and unavailable (used to just keep playing the last song) 20110416 -------- main/gamecntl.c, main/gauges.c: Due to controls rewrite was not possible anymore to send multiplayer messages while being dead - added specific exception to allow this; Rewrote show_HUD_names to only show names, indicators or typing string for enemy players when they are not cloaked; Small fix for position of Afterburner gauge in CM_FULL_SCREEN misc/hmp.c: Check for hmp before pausing/resuming it main/laser.c: Initialize variables in create_omega_blobs() and give omega_cleanup() a return value to see if we should continue rendering to fix potential crashes 20110414 -------- main/kmatrix.c: Fixing km struct being used after it's being freed by closing the window in EVENT_WINDOW_DRAW main/wall.c: Took out hack to force close doors as not needed anymore and does not take into account linked walls 20110413 -------- main/net_udp.c, main/net_udp.h: Improved security for UDP protocol: Add checks for correct packet size and - if possible - valid sender address (valid player) and making sure Clients only accept packets meant for Clients and Hosts only accept packets meant for Hosts main/fvi.c, main/physics.c: Bit more safeguarding in find_plane_line_intersection() and as a result less agressive but more beautiful back-bumping on illegal wall interesections; Scaling of movement from PhysTime to FrameTime now done with vector math functions main/credits.c: Fixing unfreed buffer when credits_show() was called but there was nothing to show me main/lighting.c: Reset obj_color for colored object lights when object does not return any usable color so the object will cast white light at least 20110412 -------- main/game.c, main/gauges.c, main/multi.h, main/net_ipx.c, main/net_ipx.h, main/net_udp.c, main/net_udp.h: Little fix for typing-indicator in multiplayer - was showing comma even if no player name was displayed; Removed team_vector from UDP lite_info structure - it's not needed; Removed ShowAllNames from Netgame structure as I see no reason why names display should be host-controlled; Increased UDP_NETGAMES_PAGES to actually show 3000 possible games main/laser.c: Stupid me forgot to let Omega use it's charge again after debugging it - fixed... include/gr.h, main/bm.c, main/bm.h, main/gamesave.c, main/lighting.c, main/multi.c, main/object.c, main/object.h, main/piggy.c, main/render.c, main/state.c: Execute set_dynamic_light 60 times per second max since more would just be a waste of CPU time; When executing set_dynamic_light, process ALL lights; Instead of storing light color in objects, do it on-thy-fly but store bitmap-based color in grs_bitmap - vastly speeds up colored dynamic lights; Improved saturation for vertex lighting to make light color a bit more subtile main/playsave.c: kconfig weapon cycling fields changed after 0.56 release will automatically fix if version number changes on next release 20110411 -------- main/game.c, main/gamecntl.c, main/gamerend.c, main/gauges.c, main/multi.c, main/multi.h: Improved syntax for Multi messages/commands: Commands starting with '/' and those accepting arguments as well as Player/Team messages require space after ':' ; Added indicator on HUD to show if a player is typing a message to prevent accidential kills main/collide.c, main/hud.c, main/hudmsg.h, main/powerup.c, main/weapon.c: Introduced HUD message class HM_MAYDUPL for messages that may appear once per frame but the player might not able to supress via option 20110410 -------- main/collide.c, main/laser.c, main/laser.h, main/object.c, main/object.h, main/vclip.c: Reworked Omega cannon: Instead of firing every frame, fire in 33.33ms intervals instead which will improve performance, decrease network traffic and make damage in Multiplayer not a totally random factor; To compensate inaccuracy due high velocity of leading omega blob, check for it's distance from parent and delete if distance > MAX main/gamerend.c, main/gauges.c, main/titles.c: Fixed text-related annoyances: Fixed positions of strings TXT_CLOAKED and TXT_CRUISE in CM_FULL_SCREEN; Fixed scaling of tab_stop in briefings (again) INSTALL.txt: Tell people about The Unarchiver for installing from the Mac game CD (thanks, Jonathan!) arch/ogl/gr.c: Smash texture list when switching between window mode and fullscreen prevent invalid textures; Made code to capture Screenshots more similar between OpenGL and OpenGL ES 3d/interp.c, main/automap.c: Allow completely free movement in the automap. It will rotate relative to the viewer. Also fix an unused variable warning. 20110408 -------- main/net_udp.c: Allow multi_send_fire when necessary and not crop to PPS so fix weapons with high firing rate 20110407 -------- 3d/draw.c, 3d/interp.c, 3d/rod.c, arch/ogl/ogl.c, include/3d.h, include/interp.h, include/ogl_init.h, main/endlevel.c, main/gamesave.c, main/lighting.c, main/lighting.h, main/menu.c, main/morph.c, main/multi.c, main/object.c, main/object.h, main/playsave.c, main/playsave.h, main/polyobj.c, main/polyobj.h, main/render.c, main/state.c, main/terrain.c: Made lighting code work with actual RGB values and added feature to let certain objects emit colored dynamic light as well as let mine flash red when control center destroyed (OpenGL-only at the moment) main/physics.c: When sliding along a wall keep wall_part sane to ensure good velocity for slide 20110405 -------- SConstruct, arch/win32/ipx.c, d2x.ini, include/args.h, main/inferno.c, main/menu.c, main/multi.h, main/net_ipx.h, main/net_udp.c, main/net_udp.h, misc/args.c: Client-side implementation for Tracker support by Matt "1360" Vandermeulen including improvements in udp_dns_filladdr and IPv4/IPv6 compability; Very little adjustments by me, too including IPv6 support for Windows (untested); Actual tracker code will follow later as seperate branch when it's done 20110329 -------- main/cntrlcen.c, main/cntrlcen.h, main/state.c: Dead_controlcen_object_num should be set when a new level starts in debug build, too; Setting Total_countdown_time when loading a savestate so SEF-DESTRUCT SEQUENCE ACTIVATED sample will not play soon as timer reaches 0 20110328 -------- main/endlevel.c, main/newdemo.c: Properly record the event of reset_rear_view() while switching levels to make it work right when rewinding as well; Properly record Countdown seconds for each newdemo frame instead of second change to get display showing up right while playback and still preserving backwards compability; Suspend Game_wind when playing endlevel movie while demo playback arch/ogl/gr.c: Fixes for OpenGL ES implementation 20110327 -------- main/physics.c: Another rework for anti-stuck-bumping: Execute after calculation of velocity and add fvi check to make sure we deal with an actual wall collision main/gamesave.c: Added hack to fix illegal segment (104) in D2 Level 12 which should be fixed in the level itself but impossible due to copyright of original game content... 20110314 -------- main/fvi.c, main/physics.c: Again reworked new bump hack to only apply when fate == HIT_WALL (to not break level SKYBOX) and made bumping by distance between object position and wall hit point; Removed/handled some safety checks in find_plane_line_intersection() to make sliding along joining edges smoother again while bad values *should* be handled in pyhsics.c and not make object warp-crashing tru the whole level or stuck in walls (fvi code should still be rewritten tho) 20110310 -------- main/kconfig.c: Due to lazy copy&paste sliding up/down speed was divided by 2 - fixed 20110306 -------- main/songs.c: Be safer not interrupting other ports of descent or the original MS-DOS game when it comes to reading song files: Try reading from MISSION_NAME.sngdxx to have a way reading a song file for a specific mission outside the mission's HOG, next try reading from descent.sngdxx which shall serve as an alternative song file specifically for DXX and then try descent.sng. This should give authors enough possibilities to add OSTs for all different versions of the game without the need to publish different versions of their missions 20110224 -------- 2d/canvas.c: Fix for last revision: Correctly initialize cv_fade_level and cv_blend_func when creating initializing a canvas main/multi.c, main/piggy.c: Using gr_init_bitmap for hoard data initialization; Correctly free hoard data before the program closes; When reloading the main HAM files, made sure it does not try to reload main game sounds from shareware/demo HAM 20110223 -------- 2d/2dsline.c, 2d/canvas.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/sdl/gr.c, include/3d.h, include/gr.h, include/ogl_init.h, main/ai.c, main/ai.h, main/console.c, main/effects.h, main/gamerend.c, main/gauges.c, main/hud.c, main/menu.c, main/multibot.c, main/newmenu.c, main/object.c, main/playsave.c, main/playsave.h, main/render.c, texmap/tmapflat.c: Added cv_fade_level to canvas structure to replace Gr_scanline_darkening_level; Added cv_blend_func to canvas structure to set blending; Introduced gr_settransblend to set cv_fade_level and cv_blend_func; Added function to set normal blending, additive alpha blending and additive color blending; Moved Special transparency effects from g3_draw_bitmap to render_object to set individual transparency and/or blending for each object outside of OpenGL-specific code; Added special blending for fuelcenter and force field effects as well; Removed unused LASER_HACK code; Renamed OglAlphaEffects variable of PalyerCfg to AlphaEffects as I plan to implement this kind of effects for Software renderer, too 20110221 -------- misc/strutil.c: Fix a critical bug in string_array_add - when d_reallocing the buffer containing the string data, update all the pointers in '*list' as well as next_str, preventing ugly crashes 20110219 -------- main/gameseq.c: Added another call for read_hamfile right after a level loads in case a third party mission brings it's own version of the main game HAM file 20110218 -------- arch/ogl/ogl.c, include/ogl_init.h, main/endlevel.c, main/object.c: Draw laser effects with special blending instead of disabled DepthMask; Added special blending for transparency effects as well to let them kick more ass; Corrections while rendering outside part of endlevel sequence with disabled depth testing and dynamically changing Render_depth to make the mine exit visible again while not rendering the exit tunnel tru the planet terrain arch/ogl/ogl.c: Set zNear for gluPerspective to 0.1 to prevent ugly clipping while passing illusory walls; Set zFar to 5000.0 to prevent disappearing automap in large distance - all still sane enough for Intel chips so my eeePC is safe nyahahaha 20110217 -------- main/wall.c: When recording cloaking or unclocking wall to demo, make sure the very first frame is recorded, too so wall will correctly transform back when rewinding the demo 20110215 -------- main/gamecntl.c: Fixed PRShot feature which was accidentially broken while implementation of OpenGL ES support 20110214 -------- SConstruct, d2x.ini, include/args.h, main/ai.c, main/ai.h, main/ai2.c, main/automap.c, main/cntrlcen.c, main/collide.c, main/config.c, main/config.h, main/escort.c, main/escort.h, main/fvi.c, main/game.c, main/game.h, main/gamecntl.c, main/gamerend.c, main/gameseq.c, main/gameseq.h, main/gauges.c, main/inferno.c, main/kconfig.c, main/laser.c, main/menu.c, main/multi.c, main/net_ipx.c, main/net_udp.c, main/physics.c, main/player.h, main/render.c, main/state.c, misc/args.c: Moved all these unsorted global cheat variables to a handy structure; Simplified reading of the cheats without trying to make it complicated so no one finds them (everyone can get the source); Removed one or two cheats which carry more garbage than they are worth; Added replacement for the bittersweet cheat; Made FPS Counter an option of Graphics menu main/credits.c, main/titles.c: For credits and briefings moved all code happened in EVENT_IDLE to EVENT_WINDOW_DRAW since a jitterish Joystick could slow down text rendering 20110212 -------- arch/inlcude/window.h, arch/sdl/event.c, arch/sdl/window.c, main/game.c: New approach to handle a bunch of closing windows - removed window_do_close() again, reworked game_leave_menus by checking window_get_front() and closing this window until it's Game_wind, while event_process checking if window still exists after drawing and if not, take next window from previous which should be updated by then 20110211 -------- main/gamecntl.c, main/kconfig.c, main/newmenu.c: Controls.select_weapon_count needs to be incremented differently to get non-0 when we want to select the laser type weapon; Readded jumping from first to last item in newmenu and vice versa 20110210 -------- main/automap.c, main/gauges.c, main/gauges.h, main/kconfig.c, main/newmenu.c, main/newmenu.h: Fixed broken FlightSim indicator on Automap; Fixed Assert for using mouse buttons in kconfig (which can react to UP and DOWN states); Added scrolling support for menus flagged tiny_mode and all_text arch/ogl/gr.c, arch/sdl/gr.c, d2x.ini, include/args.h, main/inferno.c, misc/args.c: Simplified ogl version of gr.c in terms of SDL video flags and fullscreen toggle; Added command-line/INI option to remove borders from windowed program main/multi.c: Fixed compiler warning related to generation of game_id for Coop Savegames arch/ogl/ogl.c, main/gamerend.c, main/gauges.c, main/gauges.h: Added secondary weapon indicators to new reticle types; Fixed disks being drawn as circles - whoops 20110209 -------- main/ai.c, main/game.c, main/gamecntl.c, main/gameseq.c, main/menu.c, main/multi.c, main/multi.h, main/state.c, main/state.h: Reintroduced Savegames for Coop games using the original Descent2 implementation but correctly handling player slots in their pre-loading state preventing accidential player shifting which never really worked in the original game and we do not want with UDP anyways - was all tested but still might need a fix or two; Added some missing initializations for saving players and AI stuff; Completely ripped out remnants of saving between levels code main/movie.c: Fixed little memory issue while playing movies introduced by overhaul of window closing arch/ogl/ogl.c: Fixed memory leak produced by drawing circles and disks 20110206 -------- arch/include/key.h, main/automap.c: Increased key repeat values to react a little more like the MS-DOS version of the game but a little slower so I can still stop at the correct item; In automap reorganized control_info swapping as well as wiggle state handling to properly work in connection with the new input handling and Multiplayer where game is not paused 20110203 -------- main/automap.c, main/gamecntl.c: Little fixes for recent kconfig/event overhaul: Automap inputs read by kconfig should be processed by input rather than idle and automap frame calculations should be done while drawing; Fixed drop_bomb_count which could roll over to 255 dropping bombs without end main/gauges: Corrected values for gr_ubox while drawing a window_view to not mess up at some widescreen resolutions arch/include/window.h, arch/sdl/event.c, arch/sdl/window.c: Included new window structure flag w_closing_state and let window_close() set this flag - after drawing all windows, check them again and call window_do_close() which then actually closes the window(s) marked to. Solving all sorts of problems when windows close while being drawn (network error messageboxes, game_leave_menus(), etc.) 20110202 -------- arch/include/event.h, arch/include/joy.h, arch/include/key.h, arch/include/mouse.h, arch/sdl/event.c, arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c, main/automap.c, main/endlevel.c, main/game.c, main/gamecntl.c, main/inferno.c, main/kconfig.c, main/kconfig.h, main/movie.c, main/multi.c, main/newmenu.c, main/slew.c: Added event types for all input actions; Rewrote kconfig code to work with events; static defined inputs will not trigger kconfig-mapped inputs anymore; Simplified keyboard, mouse and joystick code a lot due to event-based handling; Added function to toggle SDL key repeats on and off; Put timer_update() to event_process; Removed return when event_poll() is idle to get cursor hiding to work again; Added a small delay between cursoe hiding and re-enabling to cursor will not accidentially enable by SDL event centering cursor while hiding arch/ogl/ogl.c: After rendering Reboot reticle, reset glLineWidth to default value again main/fireball.c, main/gameseq.c, main/net_ipx.c, main/net_udp.c: Little more smoothness for Multiplayer: Before dropping Powerups in random segment, make sure it's accessible by the player who drops it; Got rid of goto in InitPlayerPositions() and made code more D2-ish; Allow host to send 50 object/extra packets per second which does not overload network stack, yet but speeds up joining 20110126 -------- arc/sdl/event.c: In event_process() check for wind->next before sending EVENT_WINDOW_DRAW in case drawing will free wind 20110124 -------- main/physics.c: Revamped what previously was the BUMP_HACK by checking if an object is actually intersecting a segment and move it out towards segment center just after the initial object movement composed by fvi and before velocity is made - should make inaccurate wall collisions a bit smoother and prevent objects from goind inside or through walls, too main/physics.c: Added some new conditions to the bumping code: Only bump objects which can slide (alive robots and players) and added a count making sure this function can never get stuck in an infinite loop main/collide.c, main/fireball.c: Some improvements and cleanups for Persistent Debris: Let them bounce, added drag and let them explode on hazardous walls 20110123 -------- main/ai2.c: Taking out one Int3 in init_boss_segments() stopping the program if there is more than one boss in level - taking out because it's not fatal or unsafe to do that; Also removed one conditional size_check which was meant for one mprintf we removed long ago main/physics.c: Increasing the collision count for objects so there can be 8 for all objects; also do not increase count when colliding with a powerup as it should not change our movement main/playsave.c: For new player, set ReticleSize to 0 which is the smallest size 20110122 -------- main/console.c, main/game.c, main/gamerend.c, main/gauges.c: Added timer_update() to stop/start/reset_time() functions so resumed last_timer_value will be precise; Added new FPS counter which actually does count the frames rendered per second and is less irritating; Added timer_dleay2 call to console to not stress CPU too much; Imporoved placement for show_time(), multi messages, marker messages and orb counts main/multi.c: Fixed small issue parsing killreactor command in Multiplayer include/byteswap.h: Added swapping for 64Bit sized integers in case we want to store/read them some day (i.e. new Savegame version storing object instead of object_rw) main/gamerend.c: in show_framerate do not use gr_get_string_size at all but rather use hardcoded coordinates - less CPU-intense main/fvi.c: Removed fvi_a.h and added the asm code from it as comment to fvi.c in case we need it again some day 20110121 -------- main/render.c: Protection for negative array index in find_seg_side was accidentially checking for vv1 != -1 - fixed that 20110120 -------- arch/sdl/jukebox.c, main/digi.h, main/menu.c, main/songs.c: Added a simple random function for the Jukebox; Removed one small printf I once added for debugging 20110119 -------- main/game.h, main/gamerend.c, main/gauges.c, main/multi.c, main/multi.h, main/net_udp.c: Introducing new BOUNTY Multiplayer game mode by Matt "1360" Vandermeulen main/gauges.c, main/multi.c: Fix for showing bounty target in kill list - was not actually checking if player_num == Bounty_target; When Bounty_target player leaves game host must select a new target so the game can proceed main/gamerend.c, main/multi.c, main/multi.h, main/net_ipx.c, main/net_udp.c, main/text.h: On NETGAMES list Bounty mode was not shown since MODE_NAMES define was not adjusted - so in the end introduced GMNames and GMNamesShrt Arrays in multi.c for globally displaying full or short Multiplayer game mode names 2d/bitmap.c, 2d/bitmap.h, 2d/canvas.c, 2d/font.c, 2d/scale.c, 2d/scalec.c, 2d/tmerge.c, SConstruct, arch/linux/alsadigi.c, arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, include/error.h, include/maths.h, main/fvi_a.h, main/inferno.c, maths/fixc.c, maths/vecmat.c, texmap/scanline.c: Retired most of the Assembler code except the generic i386 scanline renderer; Removed all leftovers of Direct3D implementation; On the way make a some code more similar between D1X-Rebirth and D2X-Rebirth 20110118 -------- main/net_udp.c: Fixed small bug in net_udp_list_join_poll() which was introduced when I reorganized the events for making console render global main/gamecntl.c, main/gameseq.c: Allowing loading a savestate while being in death sequence and resetting Dead_player_camera correctly in init_player_stats_level() so forther death sequences won't screw up main/net_udp.c: In net_udp_send_objects() player_num byte was not considered for mode 1 resulting on incorrect object count for this mode main/net_ipx.c, main/net_udp.c: Instead of calling object/extras sending every frame, use a delay of 100ms between packet send to not overload the network stack 20110117 -------- arch/sdl/event.c: Still send idle events when receiving SDL joystick events, fixing possible joystick issues main/menu.c: No referring to non-existent ogl_maxanisotropy for non-OGL build main/kconfig.c, main/newmenu.c, ui/mouse.c: Fix cursor recentering issues - comment out redundant event_toggle_focus(1) calls in kconfig.c and newmenu.c and use event_toggle_focus(0) in ui_mouse_show() arch/ogl/ogl.c, main/gauges.c: Before duplicating last pixel column or row in ogl_filltexbuf, make sure we are still in actual bitmap boundaries; Incrementing defines SHIELD_GAUGE_Y, SHIP_GAUGE_Y for HIRESMODE to fit these gauges pixel-correct in Cockpit mode SConstruct, d2x-rebirth.xcodeproj/project.pbxproj, editor/centers.c, editor/eswitch.c, editor/med.c, editor/medrobot.c, editor/medwall.c, editor/mine.c, editor/objpage.c, editor/texpage.c, include/editor/editor.h, include/editor/objpage.h, include/editor/texpage.h, include/ui.h, ui/button.c, ui/checkbox.c, ui/dialog.c, ui/file.c, ui/gadget.c, ui/icon.c, ui/inputbox.c, ui/keypad.c, ui/keypress.c, ui/keytrap.c, ui/listbox.c, ui/menu.c, ui/message.c, ui/popup.c, ui/radio.c, ui/scroll.c, ui/userbox.c: Rename ui/window.c to ui/dialog.c to avoid confusion with arch/sdl/window.c, also rename UI_WINDOW to UI_DIALOG, rename all associated functions, constants, parameters, local variables etc too; make a window when making a UI_DIALOG (does nothing yet) SConstruct: opengles variable in SConstruct could be activated by command-line argument opengl main/terrain.c texmap/ntmap.c, texmap/scanline.c: Fixing memory corruptions produced by the scanline renderer; Dynamically allocate y_pointers to free scanline renderer from resolution limits 20110116 -------- 2d/bitblt.c, arch/ogl/gr.c, arch/ogl/ogl.c, include/ogl_init.h, main/menu.c: Added feature to enable Anisotropic filtering is supported by hardware or driver; Reworked way of handling texture filtering information so ingame switching is possible again main/menu.c: When changing resolutions and Game_wind is present, send EVENT_WINDOW_ACTIVATE shortly so it's canvase will align to the new resolution seamlessly main/titles.c: For more consistency to original game, show descent(b).pcx before pilot selection if available; Generally use PATH_MAX for filename arrays in titles code main/console.c, main/inferno.c: Toggle console by KEY_SHIFTED+KEY_ESC again - as it should be arch/ogl/ogl.c: in ogl_filltexbuf add pixel row matching color of bitmap edge to get a clean border when filtering cockpit overlay bitmaps 20110115 -------- arch/linux/ipx.c, main/net_ipx.c: Fixed some compiler warnings main/game.c: Due to recent changes in event_poll() game_handler() must call ReadControls() for EVENT_MOUSE_MOVED, too; Little fix for FixedStepCalc() arch/ogl/gr.c, arch/ogl/ogl.c: Fixed alpha limit for ogl_ulinec(), gr_uricle(), gr_disk() 20110114 -------- arch/include/event.h, arch/include/key.h, arch/include/mouse.h, arch/sdl/event.c, arch/sdl/key.c, arch/sdl/mouse.c, editor/med.c, include/ui.h, main/automap.c, main/credits.c, main/escort.c, main/gamecntl.c, main/inferno.c, main/inferno.h, main/kconfig.c, main/kmatrix.c, main/menu.c, main/movie.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/scores.c, main/titles.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/menubar.c, ui/message.c, ui/mouse.c, ui/popup.c, ui/window.c: For editor, replace use of ui_mega_process() with event_process(), with the editor's own default event handler; add EVENT_MOUSE_MOVED event with event_mouse_get_delta() accessor; add event_key_get() to replace ugly casting; rename mouse_get_button() with event_mouse_get_button() to keep with name convention; only send idle events when there are no input events so editor still works properly (or the same anyway); add and use event_send() function for input events (including idle) main/fireball.c, main/gamesave.c, main/multi.c, main/multi.h, main/net_ipx.c, main/net_udp.c, main/object.c, main/object.h: Fixing code used for capping powerups in multiplayer - it was not correctly conting 4pack powerups; Cleaned up this code a bit and added more consistent naming convention for functions to maybe make it more understandable; Removed MULTI_PROTO_D2X_VER define as it's not needed main/gamesave.c, main/multi.c, main/object.h: In multi_leave_game check for Player_eggs_Dropped before actually dropping to prevent multiple drops in case player quits game after being killed; put console output level of multiplayer powerup cap messagers to CON_VERBOSE main/gameseq.c: Using timer_query() instead of clock() in InitPlayerPositions(); Also decreasing check value for closest_dist to D1-level to actually make it less likely to start at total random unchecked location where another player could be main/net_ipx.c, main/net_udp.c: When displaying kill goals in game rules, value must be multiplied by 5 to show the correct limit main/collide.c, main/multi.c, main/multi.h, main/net_udp.c: Added feature to optionally disable friendly fire in Team and Coop games main/newmenu.c: Moved scroll arrow one unit to the left to be not pixel-aligned to possible checkbox; Made newmenu sliders only react to spacebar, backspace, left and right since pageup/down is already taken for menu scrolling and all other previous key assignments will not work on most spread keyboard layouts include/console.h, main/console.c, main/gamecntl.c, main/gamerend.c, main/inferno.c, main/kmatrix.c, main/movie.c, main/net_ipx.c, main/net_udp.c: Converted console into a window and allow it to show in every part of the game; Fit several poll functions and kmatrix so they won't get interrupted by the console 20110111 -------- main/net_ipx.c, main/net_udp.c: Fixed Menu setting for AllowedItems which was broken due to changed return value of newmenu_do1 20110110 -------- 2d/disc.c, arch/ogl/gr.c, arch/ogl/ogl.c, include/gr.h, include/ogl_init.h, main/automap.c, main/gamerend.c, main/gauges.c, main/gauges.h, main/menu.c, main/playsave.c, main/playsave.h: Added different reticle types with RGBA and size settings; Apply RGBA and size to FlightSim Indicator and Guided Crosshair; Added Brightness Slider to Graphics options menu; Added OpenGL usage for gr_disk main/credits.c, main/songs.c, misc/hmp.c: Let credits track fade out at the end of text sequence; Fixed usage for RBAPlayTracks - when playing only one track last must be equal first, not 0; In hmp_open changed data from long to int, preventing memory explosion depending on optimisation of the code arch/sdl/timer.c: In timer_update() convert cur_tv to fix scale before substracting from last_tv to get more accurate values to F64_RunTime (insignificant tho); Added rollover check for SDL_GetTicks() to timer_delay2() 20110109 -------- main/net_udp.h: Set max UDP packet size to 1024 again (seems some configuration DO have problems with larger packets after all) main/net_udp.c: Fix for rev968: my_pnum must be defined static arch/sdl/digi.c, inlcude/hmp.h, misc/hmp.c: Improvement on the HMP track loop feature by TURRICAN; Added small template fix for descent.hmp which is supposed to be activated soon as we have some kind or Checksum function main/kconfig.c: Mousebutton assigned to CYCLE SECONADARY was actually calling CYCLE PRIMARY 20110106 -------- main/multi.c, main/state.c: Fixed but in object to object_rw conversion - if a bot is not dead, leave dying_start_time at 0 as anything else would kill it 3d/rod.c, SConstruct, arch/ogl/gr.c, arch/ogl/ogl.c, include/3d.h, include/ogl_init.h, main/gamecntl.c, main/object.c, main/state.c, misc/args.c: Added OpenGL ES support - contributed by Florian Feucht and Oliver Haag main/automap.c, main/gauges.c, main/gauges.h: Draw FlightSim Reticle on Automap display, too; Fixed small glitch showing Vulcan/Gauss ammo in alt hud mode on all cockpit modes instead of CM_FULL_SCREEN only arch/ogl/ogl.c: Fix small bug in vertex_array for ogl_ubitblt_i 20110104 -------- d2x.ini, include/args.h, main/gauges.c, main/inferno.c, main/kconfig.c, main/kconfig.h, main/menu.c, main/playsave.c, main/playsave.h, misc/args.c: Introduced FlightSim control scheme for mouse which adds delta values to absolute position to behave like a Joystick; Added Deadzone slider for FlightSim as well as an optional Reticle display to show the positional data on screen; Removed old Mouselook hack in favor of this new feature 20110103 -------- arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c, include/args.h, main/kconfig.c, main/kconfig.h, main/playsave.c, misc/args.c: Saving weapon keys in PLX like in D1X-Rebirth; Added Cycle Primary/Secondary for Mouse which makes wheel axis cycling unnecessary and also let Weapon Keys be assigned to a Mouse button; If GameArg.NoStickyKeys do flush these keys so they can be used as normal game keys - otherwise ban them; Fixed crash when reassigning mouse button greater than 3; Joystick/Mouse function taking button as argument now check for sanity of this value so they can safely be used in kconfig code and deal with unassigned key values d2x.ini, include/args.h, main/gamerend.c, main/hud.c, main/inferno.c, main/menu.c, main/multi.c, main/net_ipx.c, main/net_udp.c, main/playsave.c, main/playsave.h, misc/args.c: Moved NoRedundancy, MultiMessages and NoRankings toggles from GameArg to PlayerCfg to be set via Misc Options SConstruct, INSTALL.txt: More consistency in SConstruct command-line variables; Added automatic Endianess-checker; Set target to 'd2x-rebirth' no matter if OpenGL or not 20110102 -------- main/credits.c, main/kconfig.c, main/menu.c, main/net_udp.c, main/newmenu.c, main/scores.c: Increasing general mouse functionality all over the game: Mouse wheel now can scroll through menu/listbox items; Right mouse button closes a menu (without the need of these ugly close boxes); Also added mouse-closing capabilities to credits, scores and kconfig menus; While being in UDP Netgames list, override keycode at PAGEUP/DOWN keypress to only flip pages without modifying citem also added messagebox showing TXT_INVALID_CHOICE when invalid netgame was chosen arch/include/key.h, arch/sdl/key.c, main/newmenu.c, main/credits.c: Introduced function key_ismodlck to get the status of modifier keys or sticky keys; Let sticky keys survive flush so we can accurately use their real states; Added key repeating via SDL; Depending on status of KEY_NUMLOCK keypad will either be used as numerical or arrow input in menus; Fixed small typo for mouse.h include in credits.c 20101230 -------- main/newmenu.c, main/menu.c: Fixed glitch in scroll arrow position; Added newmenu_scroll which can scroll through all kind is menu structures including automatically handling NM_TYPE_TEXT items as well as automatically updating scroll_offset; PageUp/Down now scrolls by 10 items, Home/end will select first/last/items of menu creating consistency to listbox behaviour; Fit text for GrabInput to be more understandable 20101228 -------- d2x-rebirth.xcodeproj/project.pbxproj, editor, include/editor, main/editor, SConstruct: Move main/editor to editor and move headers to include/editor, like d1x editor/info.c, editor/med.c, include/editor/editor.h, include/editor/info.h: Make the keypad info display into a window arch/include/event.h, arch/include/joy.h, arch/include/mouse.h, arch/sdl/event.c, arch/sdl/joy.c, arch/sdl/mouse.c, d2x.ini, include/args.h, main/automap.c, main/config.c, main/config.h, main/game.c, main/gamecntl.c, main/inferno.c, main/kconfig.c, main/menu.c, main/newmenu.c, main/playsave.c, main/playsave.h, misc/args.c: Added Sensitivity/Deadzone menu with sliders for each movement based action seperated for joystick and mouse to support all kinds of configuration - regardless the amount of joystick axes and whatnot; SDL_WM_GrabInput does not only capture mouse but also focus keyboard input - changed code to respect this fact and made grabbing a menu option which is enabled by default 20101224 -------- d2x-rebirth.xcodeproj/project.pbxproj, include/ui.h, main/editor/centers.c, main/editor/editor.h, main/editor/group.c, main/editor/medrobot.c, main/editor/medwall.c, main/editor/mine.c, main/editor/texpage.h, main/gamesave.c, main/gamesave.h, main/switch.c, main/switch.h, ui/button.c, ui/checkbox.c, ui/func.c, ui/harderr.c, ui/keytrap.c, ui/medfunc.c, ui/menubar.c, ui/mouse.c, ui/radio.c, ui/ui.c, ui/window.c: Copy some editor stuff from d1x-rebirth to d2x-rebirth, like use of the OS native cursor arch/carbon/conf.h: Disabling IPv6 support for OS X since in Snow Leopard it's buggy, making all Multiplayer pretty much impossible - re-activating soon as proper patches from Apple are in sight 20101223 -------- main/net_udp.c, main/net_udp.h: Reworked object sending/receiving to work without unnecessary type casting and a bit less error prone; Also increased UDP max packet size to 2048 so we can send 7 objects per frame; Fixded joinign games - GameID was sent for full game info, not lite info main/credits.c: Align timer_delay for credits so the song (midi or redbook) should at least be heard once 20101222 -------- arch/sdl/window.c: In window_close() prev window did not get EVENT_WINDOW_ACTIVATED but the recent closed window got it causing previous window not being activated anymore and a bunch of memory errors arch/ogl/ogl.c, include/ogl_init.h, main/ai.c, main/ai.h, main/ai2.c, main/aipath.c, main/aistruct.h, main/cntrlcen.c, main/collide.c, main/controls.c, main/escort.c, main/fuelcen.c, main/game.c, main/game.h, main/gamecntl.c, main/gameseg.c, main/gameseq.c, main/gauges.c, main/laser.c, main/lighting.c, main/mglobal.c, main/multi.c, main/multi.h, main/multibot.c, main/net_ipx.c, main/net_udp.c, main/newdemo.c, main/object.c, main/object.h, main/player.c, main/player.h, main/powerup.c, main/state.c, main/weapon.c: Made GameTime to GameTime64 using fix64; Changed all structures saving GameTime64 for internal timer purposes to store fix64 and added converting functions to save such times in fix; For Savegames/Demos always reset GameTime64 to 0 while saving and putting all timer values to safe limits, Multiplayer objects are sent in similar fashion d2x-rebirth.xcodeproj/project.pbxproj, main/menu.c, main/editor/med.c, ui/file.c: Activate EDITOR for Mac OS X in Xcode, d2x target; fix some warnings and errors main/collide.c, main/object.c, main/object.h, main/state.c: added hitobj_list to struct laser_info to get a bit cleaner code main/gamecntl.c, main/gamesave.c: Fix warning for deliberate GameTime64 wrap; change GameTime to GameTime64 for editor main/multi.h, main/net_udp.c, main/net_udp.h: in IPv6 builds also send regular broadcast packets to get games found via LAN between IPv4 clients/systems and IPv6 clients/systems; rather than identifying (lite_info) games via IP use randomly generated GameID and game name to prevent duplicated coming from IPv6 builds ui/window.c: Put event_process() in ui_mega_process(), getting editor to (mostly) work 20101211 -------- arch/include/key.h, arch/include/mouse.h, arch/sdl/event.c, arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c, arch/sdl/rbaudio.c, arch/sdl/timer.c, include/maths.h, include/timer.h, include/ui.h, main/automap.c, main/console.c, main/digiobj.c, main/editor/medrobot.c, main/editor/medwall.c, main/fireball.c, main/game.c, main/inferno.c, main/kmatrix.c, main/laser.c, main/laser.h, main/lighting.c, main/menu.c, main/multi.c, main/multi.h, main/multibot.c, main/net_ipx.c, main/net_ipx.h, main/net_udp.c, main/net_udp.h, main/newmenu.c, main/scores.c, main/titles.c, ui/listbox.c, ui/mouse.c, ui/scroll.c, ui/window.c: Introduced new data type fix64 to be used for new timers which can last 4462756 years instead of 9 hours; Introduced new timer functions to update and query program time; Used new timer all over the program except GameTime (which comes next) 20101205 -------- arch/carbon/messagebox.c, arch/include/window.h, arch/linux/messagebox.c, arch/sdl/key.c, arch/sdl/mouse.c, arch/sdl/window.c, arch/win32/messagebox.c: Add CON_DEBUG level con_printf's for basic events (not EVENT_IDLE or EVENT_DRAW though) 20101204 -------- main/bmread.c, main/piggy.c: Set a bogus sound when a sound is skipped in gamedata_read_tbl and don't let piggy_close free it main/gamecntl.c: When calling do_game_pause do not allocate msg in Game mod GM_MULTI as it's not used nor freed include/pstypes.h: Changed another WIN32 to _WIN32 to avoid accidentially compiling with WORDS_BIGENDIAN when using VisualC 20101203 -------- main/net_udp.c: Made resent_delay for net_udp_noloss_process_queue() a bit longer depending on the player's ping 20101130 -------- include/hmp.h, misc/hmp.c: Little fixes for rev950 - changed definition from WIN32 to _WIN32, added little hack for incorrectly set HMP loop in Descent2-version of descent.hmp SConstruct, arch/include/messagebox.h, arch/win32/messagebox.c, main/inferno.c, misc/error.c: Add support for Windows native error/warning boxes; Only print to stdout on Linux/other *nix; Fixed redundant printing of Error and Warning via stdout arch/carbon/messagebox.c, d2x-rebirth.xcodeproj/project.pbxproj: Add missing stuff to get it to build on Mac OS X; turn fullscreen off when showing a messagebox for Mac main/inferno.c: When Quitting is called in standard_handler disable Autodemo if active 20101128 -------- main/multi.c: In multi_new_game when initializing Players structures, also correctly init connected variable which is highly important for spreading pdata to clients and should be set correctly anyways (Thanks to Gold Leader and Flip for help with debugging/testing recent Multiplayer bugs) main/powerup.c: in do_powerup added check for distance of other players to powerup object to make redundant pickups less likely arch/carbon/messagebox.c, arch/include/messagebox.h, arch/linux/messagebox.c, arch/sdl/rbaudio.c, arch/win32/messagebox.c, d2x-rebirth.xcodeproj/project.pbxproj, main/editor/med.c, main/game.c, main/inferno.c, SConstruct: Add support for OS native error/warning boxes, only implemented for Mac for now SConstruct: Added missing brackets gone missing in r936 arch/sdl/digi.c, arch/sdl/digi_mixer_music.c, include/hmp.h, main/digi.h, main/songs.c, misc/args.c, misc/hmp.c: Large improvement for _WIN32 native MIDI code by TURRICAN: supprt for HMP track loop, seamless song looping, GS reset, pausing/resuming midi, volume control for each MIDI channel; Set GameArg.SndDisableSdlMixer automatically if compiled without SDL_mixer support; On _WIN32 play HMP natively again 20101126 -------- include/physfsx.h, main/inferno.c, misc/physfsx.c: Implemented PHYSFSX_checkSupportedArchiveTypes to check if essential archive types are supported. Print warnings if not and stop program if necessary. Also added PHYSFSX_listSearchPAthContent to print out search path contents (figures) each time the function is called. Doing this before main HOG inits as well after sucessfully adding archives. Made PHYSFSX_addArchiveContent a bit more verbose as well. main/console.c, main/inferno.c: If -verbose or -debug is set, write gamelog.txt unbuffered for a higher chance to get messages there in case of a crash; Totally supress messages in stdout/err.txt on _WIN32 20101125 -------- main/net_udp.c: When adding data from net_udp_send_mdata_direct to noloss queue, use data_len as length of data stream - not len which is longer and would then cause storing garbage 20101123 -------- main/net_udp.h: reducing max buffer size of an UDP packet from 1024 to 576 bytes - should prevent possible turncating, especially when sending obejcts where max size is actually used main/net_ipx.c, main/net_udp.c: When verifying objects, do not necessarily check for controlcen as it's not necessarily there in some anarchy missions 20101122 -------- arch/sdl/jukebox.c: Make sure read_m3u won't read past the end of the buffer, causing a crash main/inferno.c: If it can't find descent2.hog/d2demo.hog, still print some useful info main/multi.c, main/multi.h, main/net_ipx.c, main/net_udp.c: Took over variable VerifyPlayerJoined for UDP protocol usage as well to get object and extra packet sending in order as well as regulary resending UPID_SYNC for latecoming players. Should resolve problems when joining already running UDP games 20101120 -------- arch/sdl/jukebox.c, include/physfsx.h, main/menu.c, misc/physfsx.c: Created function PHYSFSX_isNewPath to check wether given path has already been added to Searchpath or not; Used PHYSFSX_isNewPath for menu browsing code instead it's own implementation; Using PHYSFSX_isNewPath for Jukebox directory, too to make sure Jukebox will not accidentially remove Game content depending on user selection; Also only keep Jukebox directory added until files are stored to prevent any other file present in this path can override or add anything to the game main/config.c: For fresh configuration set Redbook music as default for Mac, Builtin music for all others main/hud.c: When checking for redundant messages in HUD display, compare new message to most recent one for locking and check whole list only for messages marked with HM_REDUNDANT. This will show all messages in correct order while keeping redundancy-prone messages from looping infinitely 20101109 -------- main/multi.c: In DropOrb PLAYER_FLAGS_FLAG-bit was not removed before calling multi_send_flags which would draw the HUD-box even if player ejected all Hoard orbs main/multi.c: In multi_consistency_error check for Game_wind before trying to set it in/visible - just for safety mem/mem.c: When running out of memory slots, do not try to print detailed info as it will only call a negative array index 20101108 -------- arch/ogl/ogl.c: Apply transparency to Hoard Orb if effect activated 20101101 -------- main/newmenu.c: In case listbox strings are too long for screen, fit box width to screen width, shorten strings and add a scroll effect to selected item 20101030 -------- main/titles: Make songs playing at end briefings loop, like they used to in the original game main/menu.c: Text string for level music was made smaller some time ago so BROWSE_TXT_SHRT basically became obsolete - removed it now and show BROWSE_TXT instead 20101029 -------- arch/sdl/digi_mixer_music, include/hmp.h, misc/hmp.c: Instead of writing converted MIDI to file, write to buffer so it can be played directly 20101016 -------- D2X.make, arch/sdl/jukebox.c, d2x-rebirth.xcodeproj/project.pbxproj, include/pstypes.h, main/game.c, main/hud.c, main/menu.c, main/newdemo.c, main/titles.c, misc/args.c, misc/physfsx.c: Fix errors for Mac OS 9, Mac OS X 'd2x' target builds again 20101014 -------- main/menu.c: Fixed compilation of menu.c when USE_SDLMIXER is not defined arch/sdl/jukebox.c, include/cfile.h, main/console.c, main/hud.c, main/menu.c, main/mission.c, main/net_ipx.c, main/net_udp.c, main/scores.c, misc/physfsx.c: Added format arguments to all printf, sprintf and snprintf calls missing them to prevent warnings/errors with some distributions of gcc 20101010 -------- d2x-rebirth.xcodeproj/project.pbxproj, INSTALL.txt: Use dynamic PhysicsFS library again to fix linking errors 20100926 -------- arch/sdl/jukebox.c, include/strutil.h, main/menu.c, misc/strutil.c: Add support for M3U playlists, tweak 'Jukebox playing' message so it shows the end of the path when truncating main/config.c, main/endlevel.c, main/menu.c, main/songs.c: Enable exit sequence song for D2X (not available via Redbook) 20100925 -------- include/cfile.h, include/physfsx.h, main/bm.c, main/bmread.c, main/multi.c, main/piggy.c, misc/physfsx.c: Add 'Data' subdir as a searchpath, so D2X will find descent.pig and to simplify a lot of file opening/checking/closing code misc/physfsx.c: fullpath variable was missing for _WIN32 20100919 -------- main/state.c: Pass -1 instead of 255 as the colour to ogl_ubitmapm_cs when drawing savegame previews, to make sure a black rectangle isn't drawn instead iff/iff.c, main/titles.c: To fix Dravis's head in endgame debriefing, don't remap the colours and read compressed .bbm bitmaps properly (both my bad) 20100917 -------- arch/carbon/conf.h: Enable IPv6 for Mac OS X main/config.c: Set default Jukebox music paths to original Redbook music in iTunes for Mac OS X d2x-rebirth.xcodeproj/project.pbxproj, include/cfile.h, include/hmp.h, include/physfsrwops.h, include/physfsx.h, INSTALL.txt, main/config.c, main/inferno.c, main/newdemo.c, main/newmenu.c, main/playsave.c, misc/hmp.c, misc/ignorecase.c: Link to PhysicsFS static library and use header from source for Mac OS X main/menu.c: Put in a note that a restart is required when changing the texture filter level (remove later when it isn't) main/gameseq.c, main/switch.c: Don't let the teleport sound get cut out by Game_wind being hidden when going to a secret level d2x-Info.plist, d2xgl-Info.plist, English.lproj/InfoPlist.strings: Increment version to 0.56.0 for Mac OS X, marking release point 20100904 -------- main/titles.c: In briefing_init() init robot angles properly because in show_spinning_robot_frame() robot_angles.h is incremented only but not initialized main/game.c, main/game.h, main/gameseq.c, main/state.c: Removed Fusion_last_sound_time and made Fusion_next_sound_time static inside FireLaser() with it's own fallback function for bogus timer values - should make this code insusceptible against errors - last but not least: minus two globals 20100903 -------- main/game.h, main/gameseq.c, main/state.c: Reset Fusion_next_sound_time in init_player_stats_level() to hopefully fix Fusion not doing damage or playing sounds 20100902 -------- arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, d2x-rebirth.xcodeproj/project.pbxproj, main/multi.h, main/mveplay.c: On Mac OS X - no longer have to copy SDL_mixer.h to SDL framework; frameworks can now be in /Library/Frameworks; fix for obscure compile error involving u_int32_t include/args.h, include/ogl_init.h, main/inferno.c, main/menu.c, main/movie.c, main/config.c, main/config.h, misc/args.c, 2d/font.c, d2x.ini, arch/ogl/ogl.c, arch/ogl/gr.c: Rewrote code to control Texture Filtering a little so it's easier to apply Mipmaps for different parts of the game independently; Made Movie Filtering a menu option which must be enabled seperately; Added Movie Subtitles toggle to misc game options main/gamecntl.c, main/menu.c, main/newdemo.c, main/newdemo.h: Using PHYSFSX_findFiles to make sure random demo playback will only find actual demo files and not quit autodemo; added DEMO_EXT for an universal definition of demo file extension arch/sdl/digi_mixer_music.c: When opening music file via filehandle, made sure buffer is freed after playing to prevent major memory leakage 20100901 -------- main/net_ipx.c, main/net_udp.c: in pdata communication swap_bytes was set for create_shortpos causing problems on PPC architecture; in multiplayer host menu set citem to START GAME by default 20100831 -------- include/u_mem.h, main/menu.c, main/newmenu.c, main/newmenu.h: Added feature to let select_file_reursive() change drive on _WIN32 via CTRL-D; Removed second definition of MEM_K accidentially happened due to bad communication 20100828 -------- main/menu.c: In list_dir_el make sure PHYSFS_getRealDir won't give NULL to strcmp which will happen for files located in a Windows root directory include/u_mem.h: Make define of MEM_K apply to non-debug builds as well (whoops) main/menu.c: In select_file_recursive handle paths relative to the current write directory correctly 20100827 -------- arch/include/jukebox.h, arch/sdl/jukebox.c, include/u_mem.h, main/menu.c: Add path browsing feature to make song file/directory selection easier include/u_mem.h, main/menu.c: Moving upwards definition of MEM_K so it's not restricted to !NDEBUG; Initialized **i in list_dir_el properly to silence gcc when compiling main/menu.c: In select_file_handler properly initialize newpath preventing memory errors and crashes 20100825 -------- main/menu.c, main/songs.c: When 'force descent ][ cd track order' is chosen, play and loop the credits track after the title track for Jukebox too 20100824 -------- main/mission.c, main/mission.h, main/titles.c: Overhauled detection of TEX/TXB files for Briefings and Endings 20100823 -------- main/songs.c: For Redbook, play the credits track after the title track like original Descent 2 did 20100822 -------- main/net_ipx.c, main/net_udp.c: Moved levelnum-sanity-check in game_param_handler so it will be checked when screen is changed to allow entry of secret levels (which does not work in D2X-Rebirth - it's only done for code similarity); added menu item START GAME for consistency and added proper subtitle for game setup page arch/sdl/digi_mixer_music.c: Use more reliable Mix_LoadMUS for music in directory searchpaths, so WAVE's and MP3's are correctly loaded (probably others) 20100821 -------- d2x-rebirth.ico, d2x-rebirth.xpm, arch/sdl/gr.c, arch/ogl/gr.c: Bind WM-Icon to application SConstruct, d2x-rebirth.bmp, d2x-rebirth.xpm, arch/sdl/gr.c, arch/ogl/gr.c, arch/win32/d2xr.res: Added res-file to be linked in Windows build to show icon in Filemanager; converted icon file to be smaller 20100819 -------- d2x-rebirth/main/multi.c, d2x-rebirth/main/bmread.c, d2x-rebirth/main/bmread.h, d2x-rebirth/main/paging.c, d2x-rebirth/main/piggy.c, d2x-rebirth/main/render.c, d2x-rebirth/main/net_ipx.c, d2x-rebirth/main/dumpmine.c, d2x-rebirth/main/editor/kmine.c, d2x-rebirth/main/editor/mine.c, d2x-rebirth/main/editor/group.c, d2x-rebirth/main/editor/med.c, d2x-rebirth/main/editor/eswitch.c, d2x-rebirth/main/editor/medwall.c, d2x-rebirth/main/kconfig.c, d2x-rebirth/main/gamecntl.c, d2x-rebirth/ui/window.c, d2x-rebirth/ui/keypad.c, d2x-rebirth/mem/mem.c: Patching together editor so it compiles again (while still not running); Implemented PhysFS for file accessing for editor- and debugging-related code main/gamecntl.c: Removed processing of HandleVRKey() as this code is not usable anymore and blocks some system keys (removal of general VR-code will follow later) main/songs.c, arch/sdl/digi_mixer_music.c, arch/sdl/rbaudio.c, arch/sdl/digi.c: For each Music playback system defining own volume scaling definition which was wrong for SDL_mixer 20100817 -------- main/digi.h, main/menu.c, main/songs.c, main/songs.h: Renamed MUSIC TYPE options BUILT-IN MUSIC to BUILT-IN/ADDON MUSIC and CUSTOM MUSIC to JUKEBOX; Removed LEVEL-DEPENDENT play order for Jukebox as this is now mainly covered by AddOn packs and future M3U-support 20100816 -------- main/net_ipx.c, main/net_udp.c: When switching from COOP to any other game mode, make sure Netgame.max_numplayers, MaxNumNetPlayers as well as the menu text showing the player limit is updated correctly INSTALL.txt: Updated docs to add new OGG Soundtrack created by Brandon Blume main/inferno.c: Moved up PHYSFSX_addArchiveContent() a little inside main() so -debug and -verbose will show us this content which will be helpful for debugging possible problems with AddOn Zips 20100815 -------- INSTALL.txt, include/physfsx.h, main/inferno.c, misc/physfsx.c: Added support to automatically load/mount ZIP files at startup, giving option to dynamically override or replace game content; Updated docs 20100814 -------- main/game.c: Tidy up for EVENT_IDLE case in game_handler, hopefully fixing obscure 'optimise threads' bug 20100811 -------- main/laser.c: The inital vector scaling to compensate previous frame-skipped tracking was not aligned to FrameTime. Removed that code and just divided homer_turn_base values to compensate this offset properly. Thanks to zif for hinting me to that; Added comment about the how and why of the homing missile scaling issue 20100809 -------- d2x-rebirth.xcodeproj/project.pbxproj, include/physfsx.h, include/pstypes.h, misc/physfsx.c, SConstruct: Add 'Resources' in .app bundle to searchpath for Mac; move bigger functions from physfsx.h to physfsx.c; resolve conflict with definition of 'bool' include/pstypes.h: Cleaned and simplified includes to fix possible and actual problems with PATH_MAX 20100806 -------- arch/sdl/event.c: Between event sending, exit event_process if front window is different, fixing netgame joining problem introduced with commit on 20100731 20100803 -------- main/hud.c: When updating redundant HUD messages check the for-loop not the start with a negative number - causes too long message display and negative array index 20100801 -------- main/menu.c, main/songs.c, main/songs.h, main/gameseq.c, main/digi.h, arch/sdl/digi.c: Builtin music list now dynamically allocated and not limited to 30 songs; Instead of never loading new level when loading savestate ingame, only do this for Redbook and Custom Music playing order 'continously'; if no endlevel song is specified in Custom Music continue with level music arch/sdl/mouse.c: If mouse_toggle_cursor is set to activate, do not toggle ursor visibility as mouse_update_cursor_and_grab might decide it should be hidden main/automap.c, main/text.h: Fixed automap marker info as well as misleading text defines 20100731 -------- main/gamepal.c, main/gamerend.c, main/inferno.c, main/kmatrix.c, main/menu.c, main/newmenu.c, main/newmenu.h, main/scores.c: For polling newmenus, set rval using a pointer and don't delay closing the window, hopefully fixing bad memory access when clicking in level scores screen; change newmenu_close to newmenu_free_background to avoid confusion 20100730 -------- main/game.c: Removed leftover of mouse grabbing from set_screen_mode - forgot to do this in rev1192 SConstruct: restricted parsing of sdl-config to *NIX and Mac builds as it's static on Win32 anyways; added verbosebuild as SCons option to print out all compiler/linker messages main/state.c, main/game.c, arch/sdl/event.c, arch/sdl/mouse.c, arch/include/event.h: Added event_flush to take place in game_flush_inputs which will clean SDL events which may be buffered while event_process was suspended; suspend Game_Wind while loading restoring save state while playing a level to properly flush controls and reset timer; when toggeling cursor, also directly modify the mouse to wanted behaviour instead of waiting for mouse_update_cursor_and_grab 20100729 -------- main/automap.c, main/cntrlcen.c, main/game.c, main/gamecntl.c, main/gameseq.c, main/menu.c, main/movie.c, main/newmenu.c: Tidy up use of set_screen_mode arch/ogl/gr.c, arch/ogl/ogl.c: Using rather sane values for gluPerspective - fixing Z-Fighting bugs on Intel chips; in Fullscreen toggle, always apply new viewing values independent of Screen_mode 20100728 -------- main/automap.c, main/game.c, main/gamecntl.c, arch/sdl/init.c, arch/sdl/mouse.c, arch/include/mouse.h: One more take on Mouse cursor friendliness: Merged mouse_toggle_cursor and mouse_toggle_grab; instead of trying to use SDL_GetAppState (which does not work as expected on Windows) to release mouse, use strict calls of mouse_toggle_cursor so we at least have a free mouse outside of Game_wind and Automap; decreased time to automatically hide cursor; added mouse_close to release mouse in case of emergency 20100727 -------- 2d/pcx.c, include/pcx.h, main/cntrlcen.h, main/fuelcen.h, main/gameseq.c, main/kmatrix.c: Show stars background for died in mine and secret level messageboxes; equalise fuelcen.h and cntrlcen.h arch/sdl/mouse.c: Fixing automatic mouse release function - still this does not seem to work in every case misc/hmp.c: Fixing bug in MIDI header - format was written in size of int instead of short arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, main/config.c: Moved digi_set_digi_volume call from config loading to designated audio subsystem init function so it will be correctly set after the sound system is auctionlly initialized 20100726 -------- arch/sdl/event.c, arch/sdl/mouse.c: Overhauling showing/grabbing cursor and also taking care of case if program looses focus; store old_delta_x/y in mouse info structure 20100725 -------- arch/sdl/event.c, arch/ogl/gr.c, arch/sdl/gr.c: Exit SDL_PollEvent early if window changes, to avoid menu problems when pressing keys fast; fix 'condition is always false' warning main/inferno.c, main/inferno.h, main/movie.c: Rewrite quit system, fixing *many* bugs with it :P main/newmenu: For menus, only call the user function for closing immediately before closing, fixing memory errors when the user function frees memory main/newmenu.c: Fix crash caused by last commit (whoops) 20100721 -------- main/net_udp.c: Fixing crash when joinging game over UDP Netlist: when exiting the menu for any reason, return 0 instead of following the code and possibly lead to drawing text from a newly free'd pointer - D'OH! 20100720 -------- main/net_udp.c: Thanks to Marix for hinting me I should not init a pointer with quotes if I plan to allocate/free it... my stupid-level officially broke the record 20100719 -------- misc/hmp.c: Did not close hmp after MIDI conversion which caused some unfree memory - fixed main/gameseq.c, main/state.c, main/state.h: Introduced state_quick_item so we can safly check if there is a valid quicksave slot wihtout messing around with state_Default_item which is supposed to always show a valid slot in the first place main/titles.c: In briefings make sure Current_color cannot exceed possible array bounds include/strutil.h, main/newdemo.c: Fixing some harmless compiler warnings caused by missing includes, missing newlines at end of file; cleaned up strutil.h arch/win32/ipx.c: Removed redundant Winsock calls from Windows-specific IPX code - it's already in net_ipx.c 20100718 -------- SCsonstruct, d1x-rebirth.xcodeproj, arch/sdl/digi.c, arch/sdl/digi_mixer_music.c, include/cfile.h, include/hmp.h, include/hmp.c: Merged all HMP-related code into hmp.c/h; Also introduced new HMP to MIDI conversion functions based on JJFFE which use former Win32-related HMP-code - fixes some bugs in MIDI conversion and cleaner 20100717 -------- main/render.c: Fix overlapping room in D1 lvl19 by moving vertex a little. Still a hack main/gameseg.c, main/render.c: Instead of screwing by possibly using negative array indicies in find_seg_side() return -1. In ordering segments make this result in unimportant order; Taking in some Asserts which were disabled years ago by me. Let's fix this for real when we get to it arch/sdl/digi_audio.c: For normal digital audio (11/22Khz) use buffer of 1024 for all platforms to prevent delay 20100716 -------- main/gamecntl.c: Fixing showing options menu in demos - was still called (or rather not) by obsolete variable main/newmenu.c, main/newmenu.h, main/automap.c, main/game.c, main/kconfig.c, arch/sdl/event.c, arch/sdl/joy.c, arch/sdl/init.c, arch/sdl/key.c, arch/sdl/mouse.c, arch/include/mouse.h: Only use one single call of timer_get_fixed_seconds() for whole SDL event loop; Abstracted grabbing mouse and mouse cursor toogle to mouse functions instead of calling SDL functions inside of non-arch code; Automatically hide mouse cursor if it's not used for more than 3 seconds; Reworked placement of mouse grabbing toggle; Do not read any mouse input if -nomouse is given main/newdemo.c: If newdemo_start_playback fails if random file is given set -autodemo to 0 to prevent endless loop 20100715 -------- main/object.c, main/wall.c, main/newdemo.c, main/newdemo.h, main/gauges.c: Cleaned the variables used for newdemo code; Instead of giving both old and new values to special recording functions, added new variables to demo code serving this purpose and also checking for redundant record calls which only would waste bytes; Removed duplicated-object-id-hack which did not work as expected and caused jittering on playback; In that process, found a bug where Num_open_doors might nor be set correctly - cleaned that up a little and got also rid of one aweful goto; Made sure cloaked walls are recorded FPS-independent but rather fade-value-dependent main/titles.c: Scale tab stops in briefings to font-size correctly main/titles.c: Make sure the right canvas is set for titles and briefings, fixing bug where briefing is shown in the cockpit when using 'freespace' cheat 20100713 -------- include/args.h, main/net_udp.c, main/collide.c, main/multi.c, main/inferno.c, main/object.c, main/gamepal.c, main/wall.c, main/state.c, main/hud.c, main/weapon.c, main/hostage.c, main/hudmsg.h, main/newdemo.c, main/switch.c, main/net_ipx.c, main/gameseq.c, main/escort.c, main/fuelcen.c, main/endlevel.c, main/powerup.c, main/automap.c, main/game.c, main/gauges.c, main/kconfig.c, main/gauges.h, main/gamecntl.c, misc/args.c, d2x.ini, arch/ogl/gr.c, arch/sdl/jukebox.c: Added expandable classes for HUD messages (like D1X but slacked) to better handle Multi messages or redundant messages; Rewrote HUD code completely; Changes -playermessages to -multimessages since this is more appropriate; Removed remnants of -mprofile 20100709 -------- main/mission.c, main/titles.c: When reading mission file, check for sanity of possible breifing or ending to make sure author did not just screw up the file; Fixed slight bug when playing ending briefings from secret levels main/laser.c: Trying to improve reliability to find appropriate homing object by using vm_vec_mag/normalize instead of their *quick equivalents 20100708 -------- main/net_udp.c, main/net_udp.h: Reworked handling of Netlist now also showing full game info; Prevent Clients from sending lite_info; Make lite_info show numconnected instead of numplayers as this would show disconnected ones as well; Removed reusing ports on different instances in Windows build - only screws up several games running on one machine main/game.c, main/gameseq.c, main/multi.c, main/net_udp.c, main/net_ipx.c: Improved hanlding for closing sockets - doing via closing of Game_wind when available or in specific multi menus; Also handling GM_GAME_OVER setting over Game_wind closing as well if apprpriate - cleaner and helps to cleanup multi when mission is over arch/sdl/key.c: Also send event KEY_COMMAND if there's somethig in our Unicode buffer since not every Unicode key corresponds to a keysym on every layout README.txt: Fixing typo 20100705 -------- main/kconfig.c: Fixing issue when assigning mouse button if a citem is still pointed out; Fixing still processing key commands even if we want to assign a key; After setting mouse button, reset mouse state properly arch/sdl/digi_mixer_music.c: Fixing issue introduced in rev1139: Game could of course not open music files which are not inside Searchpath or added to it - re-added playing over absolute path main/net_ipx.c, main/net_udp.c: When selecting coop game mode, make sure that besides max players menu values also actual player number is set and menu text is updated properly main/net_udp.h: Reducing sending objects per frame from 20 to 1 again to reduce possibility of timeout on stressed systems main/songs.c: Fixing building on Windows if SDL_Mixer is not a target 20100704 -------- SConstruct: Fixing Windows build which was not linking against SDL main/net_udp.c: Fixed Compiler-warning on Windows main/net_ipx.c, main/net_udp.c: Implemented Winsock functions for UDP which I totally forgot about; Now when leaving game in any way, close sockets and Winsock stuff main/gameseq.c, main/multi.c: Since time is not suspended between levels in Multiplayer, call reset_time after level change. Apply this in Singleplayer, too since it should always be safe - and appropriate - to reset timer_value soon as a new level begins main/net_udp.c: Fixes for rev1148: Was too hasty with calling net_udp_close; Fixing typo in WSACleanup() 20100701 -------- 2d/font.c: For gr_get_string_size introduced get_char_width_f to calculate with floats to measure non-integer font scalings; Cleanup main/net_udp.c, main/newmenu.c: Renamed manual_join to direct_join; Aligned letlist tabs a little bit 20100630 -------- main/gameseq.c: If multi_level_sync() fails, restart menu music since level music is playing already main/game.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/newmenu.h, main/weapon.c: Removed SurfingNet global and made tabs a parameter of newmenu_dotiny; Same procedure with MenuReordering which is replaced with newmenu_doreorder to set reordering flag specifically main/net_udp.c: Always try to open UDP default port when discovering Netgames and give warning if that fails; If entered IP address cannot be resoled, do not warn me twice 20100629 -------- main/net_ipx.c, main/net_udp.c: Aligned default width for IPX-Netlist menu to fit possible items a bit better; Fixed two small bugs when sending and receiving lite_info in UDP; Allowed broadcast on UDP sockets (for later use) main/menu.c, main/new_udp.c, main/net_udp.h: Added UDP Netlist to join LAN games discovered/announced via broadcast main/net_ipx.c, main/net_udp.c: Improved handling of multi level sync and exit smoothly back to the menus; Fixed another small bug in lite_info broadcasting which was sending full info; By broadcasting full info, host could cripple Netgame so a new security measure is implemented to protect host from letting his game be overwritten from outside 20100627 -------- main/game.c, main/game.h, main/gameseq.c: When starting, leaving or changing a level in any way, use more ordered approach to set Game_wind visible or invisible. Fixing timer-issues after level-change and makes hiding of Game_wind obsolete for certain messageboxes; Moved GameTime and weapon timer variables out of reset_time since this function is not appropriate for this and is not needed between levels anymore due to window management handling start/stop_time properly arch/sdl/digi_mixer_music.c, main/jukebox.c: For playing music over SDL_mixer always use handle over PhysFS to save the path building mess; When building Jukebox path, only try to build full path if given path is actually a child of Searchpath 20100625 -------- main/titles.c: Made Briefing printing sound apply everytime there is chattering enabled. Even if it would be logical to have it only with flashing cursor, most briefings - even Counterstrike - forget to toggle it correctly 20100624 -------- arch/ogl/gr.c, arch/sdl/gr.c, include/gr.h, main/menu.c: Added function to list valid resolutions and build resolutions menu dynamically with the resulting list main/gamecntl.c: When inregulary exiting a level by warp cheat, suspend Game_wind and reactivate again after the switch 20100623 -------- main/menu.c, main/newmenu.c, main/newmenu.h, main/net_ipx.c: Making menus recreated on the fly in case resolution or font-size changes; Removing arguments to pass width and height to menu which was not used except on one IPX menu; Fixing measurement of menu strings of type NM_TYPE_INPUT_MENU; Fixing slight bug in freeing IPX netlist main/menu.c: If no player exists and GameCfg.LasterPlayer is unset, give user a nice default for convenience and - more important - let menu stop to nag about missing callsign and thereby showing the player creation dialogue over and over again main/newmenu.c: Fix for last rev1130 - store resolution and font-size in matching data type 20100622 -------- main/titles.c: Make sure GAME_FONT is set when reading out briefing text so char dimensions will always be stored correctly 20100620 -------- main/newdemo.c: For starting demo, seperate hide_menus() and game_setup() since between this, demo must load the actual level and it's palette; Fixed small bug in interpolate_frame() causing interpolation happening in very first frame causing file read corruption 20100619 -------- main/titles.c: For briefings, keep elementes of show_briefing_bitmap and show_animated_bitmap in correct aspect d2x.ini, include/args.h, include/libmve.h, main/inferno.c, main/movie.c, libmve/mve_main.c, main/mveplay.c, misc/args.c: Show movies in correct aspect; Added mipmap generation to movie texture if Texture filtering enabled - can also be disabled seperately main/laser.c: Re-balanced homing-device turn values introduced in rev1118 based on comparisons to many levels played 20100618 -------- 2d/bitblt.c, include/gr.h, main/game.c, main/gauges.c: Introducing gr_bitblt_find_transparent_area to dynamically detect boundaries of sub canvas used for CM_REAR_VIEW; On the way also allowing to create weapon box sub bitmaps from uncompressed cockpit bitmaps include/physfsx.h, main/newdemo.c: Removed PHYSFSX_getFreeDiskSpace and relying on success of buffered writing to see if demo recording must be stopped 20100617 -------- main/weapons.c: If picking up one missile out of a four-pack, use singular description instead of plural 20100615 -------- main/game.c, main/gameseq.c: Resetting GameTime, Next/Last_flare/laser/missile_time in reset_time() together so GameTime-rollover-fallbacks will not create a massive delay when starting a new level main/laser.c: Removed the previously used homers code and instead used old one to keep good ol' Gameplay; Removed FrameCount steps from track_track_goal() and scaled homing vector accordingly to this change, including properly scaling it to FrameTime; Made code more similar between D1X and D2X; Introduced different turn rates for different difficulty levels main/game.c: Fixing typo in Netgame help screen arch/sdl/digi.c, arch/sdl/digi_audio.c, main/songs.c: Fixing digi_win32_ functions I broke yesterday. THANKS ZIF! 20100614 -------- include/args.h, include/physfsx.h, main/inferno.c, main/menu.c, main/movie.c, main/songs.c, main/songs.h, main/switch.c, main/config.c, main/config.h, main/gameseq.c, main/digiobj.c, main/digi.h, main/game.c, main/gamecntl.c, misc/args.c, CHANGELOG.txt, d2x.ini, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/init.c, arch/sdl/jukebox.c, arch/sdl/digi.c, arch/sdl/digi_audio.c, arch/include/digi_audio.h, arch/include/digi_mixer.h, arch/include/digi_mixer_music.h, arch/include/jukebox.h: Increased SDL_mixer music abilities to play non-hmp from HOGs, having Level-music path to play, options to specify non-level tracks and added various playing order methods; Abstracted SDL_mixer- and Redbook-interfaces; Simplified program flow through all music functions arch/sdl/jukebox.c: Small fix and improvement for Jukebox path detection arch/sdl/digi_mixer_music.c, main/songs.c: Use strrchr instead of strchr for music filename extension in case there are dots in the filename main/collide.c: Made reactor damage with persistent weapons FPS-independent but still a bit stronger than normal arch/sdl/jukebox.c: rev1112 contd: Killed juggling around with adding Jukebox paths - must always be removed correctly if Jukebox loading fails arch/linux/hmiplay.c, arch/sdl/digi.c, main/songs.c: Process -nomusic argument again 20100503 -------- main/menu.c: Properly specify number of items for do_options_menu, so the options menu actually shows arch/include/event.h, main/newmenu.h: Merge d_event and newmenu_event enum's, hopefully fixing compiler warnings in GCC 4.5.0 arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c: Comment out redundant calls to event_poll, fixing rapid bomb dropping bug (and probably others) 20100405 -------- arch/include/digi_audio.h, arch/include/digi_mixer.h, arch/include/digi_mixer_music.h, arch/linux/hmiplay.c, arch/linux/hmistub.c, arch/sdl/digi.c, arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, arch/sdl/rbaudio.c, include/strutil.h, main/digi.h, main/gamecntl.c, main/songs.c, main/songs.h, main/titles.c, misc/strutil.c: Actually play endgame music when game is finished, play briefing music instead of hum if appropriate main/gameseq.c, main/titles.c: Actually fix endgame music, make briefing beep only play when flashing_cursor is on, no restarting music when reloading a saved game 20100404 -------- arch/include/event.h, arch/sdl/event.c, main/automap.c, main/game.c, main/gamecntl.c, main/gamepal.c, main/gameseq.c, main/inferno.c, main/inferno.h, main/menu.c, main/multi.c, main/net_ipx.c, main/net_udp.c, main/newdemo.c, main/state.c, misc/error.c: Get rid of a heap of uses of Function_mode, quit properly (freeing all windows and asking for confirmation for game) when clicking close box arch/include/window.h, arch/sdl/window.c, main/inferno.c, main/menu.c, main/mission.c, main/net_ipx.c, main/net_ipx.h, main/net_udp.c, main/net_udp.h, main/newmenu.c: Make menus for hosting a netgame stack, make quitting work with newmenu_do2 and simpler 20100403 -------- arch/sdl/mouse.c, main/game.c, main/net_ipx.c, main/newmenu.c, main/newmenu.h, main/state.c: Make newmenu_do3 and newmenu_dotiny return as soon as the newmenu is created, which will allow the main menu (and others) to persist main/menu.c: Make main menu persist to streamline redrawing (later) main/kconfig.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/scores.c: Remove calls to nm_draw_background1 to show newmenus stacked main/menu.c, main/newmenu.c, main/scores.c: Move copyright drawing to main menu's event handler for tidiness 20100402 -------- arch/include/event.h, arch/sdl/event.c, arch/sdl/key.c, arch/sdl/mouse.c, main/automap.c, main/credits.c, main/escort.c, main/game.c, main/gamecntl.c, main/inferno.c, main/kconfig.c, main/kmatrix.c, main/movie.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/scores.c, main/titles.c: Add a default event handler for screenshots, entering debugger, Redbook repeating etc main/menu.c, main/newmenu.c: Keep demo selector just after playing one, for convenience 20100331 -------- main/gamecntl.c, main/laser.c, main/laser.h: Make gamecntl.c more similar between D1X and D2X main/automap.c, main/game.c, main/gamecntl.c, main/multi.c, main/multi.h: Make game respond to EVENT_KEY_COMMAND for key commands, allowing default key handler (later) main/gamecntl.c: Fix bug introduced in last commit where the player can't escape from the death sequence (whoops) main/endlevel.c: Hide the game window so the exit movie has a black background 20100330 -------- main/titles.c: For Descent 1 briefings, only change the palette to groupa.256 for brief03.pcx - the robot screen. Improves palette use for sdl build main/menu.c, main/menu.h, main/movie.c: Don't reshow the mission menu after playing a level intro movie 20100328 -------- main/lighting.c: For casting light from Player-object, smooth out thrust to prevent flickering on high FPS 20100327 -------- main/kmatrix.c, main/net_udp.c: Initialise 'playing' to 0 for UDP kmatrix, making sure player progresses to next level; always return 1 when starting to join a UDP game so it doesn't immediately return to the main menu main/gameseq.c, main/menu.c: Hide mission dialog before the level intro screens are shown, make sure it doesn't try to show it again after it was closed - fixing bad memory access main/game.c: Finally fix bug where if you start a single player game then a multiplayer game, time is stopped. Always start time if it's stopped and the game window is activated main/menu.c: Check menus[0], not menus[i] in hide_menus - fixing possible crash 20100326 -------- main/endlevel.c, main/gameseq.c, main/mission.c, main/mission.h, main/titles.c, main/titles.h: In Endlevel sequence, re-align big explosion to draw in front of exit model, relative to viewer; Re-organized tex files for Briefings and Endings and created more general code to play them; Re-aligned Dravis' head main/automap.c, main/escort.c, main/gamecntl.c, main/kconfig.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/scores.c: Make all windows except game and editor use EVENT_KEY_COMMAND, returning 1 if handled; pass NULL instead of userdata for the PCX filename, for newmenu_do1 include/cfile.h, include/physfsx.h, main/piggy.c: Ignore case-sensitivity for cfile_init/close/size and PHYSFSX_openReadBuffered; Give error message if default sound file cannot be opened so user knows what's going on main/titles.c: Fixing uninitialized angles for robots in briefings 20100325 -------- main/titles.c: Make sure got_z is not reset to 0 for Descent 1 missions - fixing crash, also make sure briefing hum is not played through more than one channel 20100324 -------- arch/include/event.h, arch/include/mouse.h, arch/sdl/mouse.c, main/kconfig.c, main/movie.c, main/newmenu.c, main/titles.c: Add EVENT_MOUSE_BUTTON_DOWN and EVENT_MOUSE_BUTTON_UP, use for all windows except game and editor. Fixes crash on iMac G5 when pressing keys to progress through briefing main/titles.c: Only show briefing background if we have one, fixing arithmetic crash with SDL Video build 20100322 -------- main/credits.c: Make credits screen a window main/credits.c, main/titles.c: Fix error introduced with credits, make title screen a window. Only the editor left now... 20100321 -------- main/gameseq.c, main/multi.c: Hide game window between levels, fixing bug where many textures are loaded with the wrong palette when advancing to the next multiplayer level main/multi.c: Fix bug introduced in last commit - when the last level is finished, hide the game window - making sure the cockpit isn't drawn over the kmatrix screen 20100320 -------- main/kmatrix.c, main/multi.c, main/multi.h: Make kmatrixs into windows (failed attempt at fixing a bug) main/game.c: Fix bug - make sure time isn't stopped for multiplayer when aborting, so starting a second game doesn't result in a frozen game 20100318 -------- main/menu.c, main/menu.h, main/movie.c: Show intro movie properly when idle in main menu, including subtitles if on main/titles.c: Make briefing into a window, allowing more flexibility with other windows and tidying code up main/game.c, main/menu.c, main/mission.c, main/mission.h, main/net_ipx.c, main/net_ipx.h, main/net_udp.c, main/net_udp.h, main/newmenu.c, main/newmenu.h: Make all listboxes fall back to main event loop for flexibility 20100317 -------- arch/include/window.h, arch/sdl/window.c, libmve/mveplay.c, main/movie.c, main/titles.c: Make fullscreen movies into windows, maintain performance of robot briefing movies with necessary move of gr_flip 20100313 -------- main/newmenu.c: Fix memory error for listbox when clicking in the region where there are no items 20100310 -------- main/titles.c: Put most local variables in show_briefing in 'briefing' struct, to make briefing a window in future 20100309 -------- main/titles.c: Put briefing globals in 'briefing' struct, pass this by parameter arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c: Change audio buffer size back to 1024 for Mac only - fixing crackly music main/titles.c, main/titles.h: Put parameters in functions from do_briefing_screens to show_briefing in 'briefing' struct, to make briefing a window in future 20100303 -------- arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c: Changed default Audio-buffer size to 2048 bytes. Should prevent crackly playback on some systems debian/control: Adding scons to depends-list for Debian packaging main/mission.c: Init variables/strings at the beginning of load_mission() to prevent errors if demo content is used 20100301 -------- main/titles.c, main/titles.h: Make titles.c more similar between D1X and D2X 20100227 -------- main/menu.c: Actually change to MIDI if Jukebox was selected arch/sdl/jukebox.c: No more crashing if an invalid Jukebox path is entered - default to MIDI 20100226 -------- main/menu.c, main/newmenu.c: Handle all user input in callback for sounds menu, being more judicious about when to restart the music. Also make the jukebox path input a NM_TYPE_INPUT_MENU, allowing the user to abort changes 20100225 -------- main/game.c, main/gamecntl.c, main/gameseq.c, main/state.c, main/state.h: Put fast save back, using Alt-F1 instead of F6 arch/sdl/key.c: Move call to callback outside of loop in key_handler, now deleting a second demo using CTRL-D actually works main/automap.c, main/escort.c, main/game.c, main/gamecntl.c, main/gauges.c, main/kconfig.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/scores.c: Call game_flush_inputs for all windows' EVENT_WINDOW_ACTIVATED, so clicking on a pilot doesn't bring up the multiplayer screen for example main/kconfig.c: Resetting menu->mouse_state after changing a key in kconfig so you will not accidentially activate a new field when left mouse button is assigned 20100224 -------- main/kconfig.c: Due to the change of GameCfg.ControlType, Mouselook was broken - fixed 20100223 -------- SConstruct: Removing svnmicro as micro numbering option since SVN-revisions will not really represent logical numbering; Some cleaning for libs usage; Small cleanup SConstruct, main/multi.h, main/net_udp.c, main/net_udp.h, main/vers_id.h: Make Version-check for UDP also cover Micro-versions; Making sure versioning will act same way as conf.h for MacOS main/game.c, main/multi.c: Add to help how to send a message to a specific player in Multiplayer; Removed NoBombs command as this is covered by the weapons selection in Multiplayer game creation main/songs.c: Adding a Failsafe to Songs-reading so it will not accidentially read over current Array-boundaries INSTALL.TXT, README.TXT: Updated docs and hopefully made them more user-friendly 20100221 -------- main/config.h, main/kconfig.c, main/kconfig.h, main/menu.c, main/playsave.c, main/playsave.h, main/text.h: Overhaul for CONTROLS menu; Cleaned kconfig-code a little and slacked out keymap arrays 20100219 -------- main/gauges.c: The little light bulb showing homing warning in Cockpit was broken and I replaced it; Rewritten code to show weapon text in Cockpit and Statusbar slightly main/songs.c, main/songs.h: Making reading of descent.sng a bit more flexible; Not dynamically allocated, yet, since missions are not as well 20100215 -------- libmve/mveplay.c: Added another bunch of macros to fix sound initialisation for Movies when program is compiled without SDL_mixer 20100214 -------- d2x.ini, arch/include/joy.h, arch/sdl/joy.c, main/endlevel.c, main/inferno.c, main/kconfig.c, main/slew.c, misc/args.c: Cleaning up Joystick code and on the way supporting more axes and buttons; Also fixed bug with channel_mask byte causing trouble using some axes ingame; Added argument to set environment variable which disables sticky keys (for SDL >= 1.2.14) 20100208 -------- main/menu.c, main/scores.c, main/scores.h: Move all globals in scores.c into struct members/local variables main/game.c, main/newdemo.c: Don't make another Game_wind when advancing a level, fixing failed asserts / slow turning arch/sdl/window.c: Don't send an EVENT_WINDOW_DEACTIVATED when closing a window if it wasn't the front window, now the game works properly after you're shown on the high scores main/collide.c, main/object.c, main/object.h, main/state.c: Introduced hitobj_list for persistent weapon objects to keep track of multiple objects the weapon is in contect with to prevent it from doing FPS-based damage; Made persistent weapon objects not die on debris but just decrease their shields like when an ordinary player/robot is hit - makes more sense main/console.c: Write gamelog.txt buffered so it will not stress the medium it's saved on 20100207 -------- main/game.c, main/gameseq.c, main/inferno.c, main/inferno.h, main/menu.c, main/newdemo.c: Create the main event loop and use it for the game and main menu main/scores.c: Make the scores menu into a window d2x-rebirth.xcodeproj/project.pbxproj, main/aistruct.h, main/game.h, main/gameseq.h, main/inferno.h, main/laser.h, main/polyobj.h, main/robot.h, main/weapon.h: Move MAX_SUBMODELS from inferno.h to polyobj.h, fixing #include loop by removing some (mainly object.h) and instead using explicit 'struct' declarations; compile net_ipx.c for Mac SDL Video build main/gameseq.c, main/gameseq.h, main/menu.c, main/menu.h: Split select_filename into [existing] RegisterPlayer and select_demo for better clarity 20100206 -------- main/newmenu.c: Reset last_palette_loaded in nm_draw_background1 as before, it's needed for using the right palette when advancing a level main/newmenu.c: Set the correct scroll position for the listbox when it's shown main/gameseq.c, main/gameseq.h, main/menu.c, main/menu.h: Handle player selection and demo playing in filename_menu_handler, fixing bug where it won't leave the player listbox if there's no LastPlayer; close do_options dialog when changing resolution 20100205 -------- main/automap.c, main/escort.c, main/game.c, main/game.h, main/gamecntl.c, main/gameseq.c, main/newdemo.c, main/newmenu.c: Put the full_palette_save and palette_restore calls in the game handler for tidiness; remove leftover redundant digi_resume_digi_sounds calls main/newmenu.c: No showing the main menu background between loading a level and playing it, fixing palette issue when autoplaying a demo main/window.c: Send EVENT_WINDOW_DEACTIVATE before EVENT_WINDOW_ACTIVATE, ensuring cursor remains shown when appropriate main/physics.c: In do_physics_sim() only set velocity from movement for certain objects which actually do collisions like Player or Robots - otherwise we might be able to shoot down projectiles or produce other unfortunate glitches 20100202 -------- arch/include/event.h, arch/sdl/window.c, main/automap.c, main/dumpmine.c, main/editor/med.c, main/escort.c, main/game.c, main/gamecntl.c, main/gamesave.c, main/gameseq.c, main/kconfig.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c: Add EVENT_WINDOW_DEACTIVATED; move many game_flush_inputs, start_time and stop_time calls to game_handler as well as digi_pause_digi_sounds and digi_resume_digi_sounds main/inferno.c: Hide all other windows before showing error dialog, hopefully so errors don't happen while the error dialog is there arch/include/event.h, arch/sdl/window.c, main/game.c, main/inferno.c, main/newmenu.c: Put LeaveGame longjmp back, but in response to new EVENT_WINDOW_CLOSED, fixing demo issues; fix compiler error in last commit 20100201 -------- arch/carbon/conf.h, d1x-rebirth.xcodeproj/project.pbxproj, main/kconfig.c, main/menu.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/newmenu.h: Leave kconfig_idle early if exiting kconfig to avoid erroneous memory access; initialise menu's citem properly; add EVENT_NEWMENU_CHANGED; activate USE_IPX in Xcode while I'm still changing net_ipx.c 20100131 -------- main/newmenu.c: Fix memory errors, but still dynamically allocate menu and lb so it doesn't have to stay in newmenu_do4 and newmenu_listbox1 respectively main/automap.c, main/game.c, main/game.h, main/multi.c, main/multi.h, main/net_ipx.c, main/net_udp.c, main/newmenu.c: Fix crashing when doing menus in multiplayer, don't let player move when in automap main/automap.c, main/kconfig.c, main/newmenu.c: Adding a bunch of memset's to menu/automap creations so we won't run into uninitialized variables 20100130 -------- arch/sdl/event.c, arch/sdl/key.c, main/menu.c, main/newmenu.c, main/newmenu.h, main/state.c: Send EVENT_KEY_COMMAND from key.c; add EVENT_NEWMENU_DRAW for state restore; place newmenu and listbox calls to callback so they can override ALL newmenu behaviour main/newdemo.c: Fix warning in newdemo_stop_recording where it should set the last char of filename to 0, not the next variable main/menu.c, main/newmenu.c: Fixed two memory errors inside menu GUI 20100129 -------- main/automap.c, main/automap.h, main/game.c, main/gamecntl.c, main/kconfig.c, main/multi.c, main/multi.h, main/net_ipx.c, main/net_udp.c, main/newmenu.c: For multiplayer, close menus from game_handler by doing frame processing in response to EVENT_WINDOW_DRAW, replacing multi_menu_poll system with single multi_menu_check call main/newmenu.c: Initialise lb->first_item to 0, not -1, preventing crash if you make a listbox selection very quickly d2x.ini, arch/ogl/gr.c, arch/sdl/gr.c, include/args.h, main/inferno.c, main/movie.c, main/newmenu.c, misc/args.c: Added real Doublebuffering to SDL-build; While on the way, making Bpp selection available for SDL-build, too 20100128 -------- main/playsave.c, main/playsave.h, main/object.c, main/render.c, main/hostage.c, main/newdemo.c, main/gamerend.c, main/endlevel.c, main/game.c, main/gauges.c: Made PlayerCfg.CockpitMode an array to hold two values: 0 to store the actual "cockpit", 1 to also store Letterbox, Rear, etc. Greatly helps to switch and restore views - especially in Demo playback which now properly selects modes main/newdemo.c: Added a new code to properly re-record view/cockpit-events at beginning and end of Demo recording so views will be fine if switched before recording started; Also added lost sequence to record Rear-view reset between levels; Everything done without breaking the Demo format! arch/sdl/window.c, main/automap.c, main/escort.c, main/game.c, main/gamecntl.c, main/kconfig.c, main/menu.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c: Make response to EVENT_WINDOW_CLOSE conform to 'handling' system - returning 1 means abort closing main/kconfig.c, main/newmenu.c: Tidy up newmenu_show/hide_cursor calls main/newmenu.c: Allow user to abort close, for whatever reason (helps with my next commit) main/gamesave.c, main/newdemo.c, main/object.c, main/object.h, main/state.c: Improved Object signature assignment and made sure there will be no duplicates; Also used short-ranged values only so Demo system won't screw up main/newdemo.c: Resetting DemoDoLeft/Right correctly at start of each demo 20100127 -------- main/game.c, main/game.h, main/gamecntl.c, main/gameseq.c, main/kmatrix.c, main/multi.c, main/net_ipx.c, main/net_udp.c, main/newdemo.c, main/render.c: Remove all uses of LeaveGame jmpbuf to allow more changing of main loop main/gameseq.c, main/inferno.c, main/menu.c, main/newmenu.c: Allow escape from player listbox if appropriate; call RegisterPlayer only from main menu for more flexibility; actually use file_list block so deleting players/demos doesn't crash it 20100126 -------- main/newdemo.c: Once again improving Demo Interpolation code, regarding changes from rev993, reducing Viewport flicker and jitter 20100124 -------- main/gamerend.c, main/gauges.c: Rewrote code for showing Cloak-effect on Cockpit and Statusbar, because it became bugged with changed order of function calls do_cloaked_stuff() and render_gauges(); Fixed cockpit switches for Guided missile when Player is in Rear-View - the original code never considered that 20100123 -------- main/gamecntl.c, main/inferno.c, main/menu.c: Move the editor call out of the Function_mode loop, for later overhaul 20100121 -------- main/newdemo.c: Removed the new Demo Interpolating code and added the improvements to the old one 20100120 -------- arch/include/event.h, arch/sdl/event.c, arch/sdl/window.c, main/automap.c, main/escort.c, main/game.c, main/gamecntl.c, main/kconfig.c, main/menu.c, main/net_ipx.c, main/net_udp.c, main/newmenu.c, main/state.c: Add EVENT_WINDOW_ACTIVATED, change EVENT_DRAW to EVENT_WINDOW_DRAW and EVENT_CLOSE to EVENT_WINDOW_CLOSE main/automap.c, main/escort.c, main/game.c, main/gamecntl.c, main/kconfig.c, main/newmenu.c: Fix major issues with last commit - tidy up window callbacks to dodge EVENT_WINDOW_ACTIVATED where it's unnecessary or erroneous to respond to, fix compiling error 20100119 -------- main/net_ipx.c, main/net_udp.c: Make net_ipx_show_game_rules and net_udp_show_game_rules into windows 20100118 -------- main/kconfig.c: Make kconfig menus into windows - allowing drawing of the game screen behind, changing of item to change while question mark flashing and clicking out of item change 20100117 -------- main/menu.c: Respond to EVENT_NEWMENU_SELECTED for options_menuset and input_menuset, so the input menu will have THE event loop for kconfig 20100115 -------- main/menu.c: For get_filename, put mode and find variables in a structure - fixing 64-bit problem and allowing freeing of PHYSFS file list in callback in future, respectively 20100109 -------- main/escort.c: Make escort menu a window, now the game is drawn behind it arch/include/window.h, main/game.c, main/gamecntl.c, main/gamerend.c: Make pause box a window 20100108 -------- arch/sdl/event.h, main/newmenu.c, main/newmenu.h: Add EVENT_NEWMENU_SELECTED, allowing a newmenu/listbox selection to be handled in the callback 20100107 -------- main/gamecntl.c, main/newdemo.c: New Interpolation method for demos and a small hack to fix this Interpolation if duplicate object signatures appear (mostly) arch/carbon/conf.h, arch/include/event.h, arch/include/key.h, arch/sdl/event.c, main/game.c, main/gamecntl.c, main/gamesave.c, main/gameseq.c, main/kmatrix.c, main/menu.c, main/mission.c, main/multi.c, main/multi.h, main/net_ipx.c, main/net_ipx.h, main/net_udp.c, main/net_udp.h, main/newdemo.c, main/newmenu.c, main/newmenu.h, main/scores.c, main/state.c, main/weapon.c: Change newmenu and listbox callback systems, adding use of d_event, for greater flexibility 20091227 -------- main/newmenu.c: Make listboxes into windows main/automap.c, main/automap.h: Put most of the remaining globals in automap.c in the 'automap' struct 20091226 -------- arch/include/key.h, arch/sdl/event.c, arch/sdl/key.c, main/automap.c, main/editor/med.c, main/game.c, main/gamerend.c, main/kconfig.c, main/newmenu.c: Make newmenus into windows, allowing redrawing of automap and game to take place outside of newmenu.c; remove redundant keyd_repeat 20091213 -------- main/game.c: Make sure the Game_wind only gets freed once when escaping demo playback 20091212 -------- main/game.c: Make sure the Game_wind always gets freed when exiting the game screen, fixing flashing automap and framerate reduction after playing demos 20091211 -------- arch/linux/ukali.c: Fixing possible string overflow while using KALI_PROCESS_NAME 20091208 -------- main/gameseq.c, main/menu.c, main/menu.h, main/newdemo.c, main/newmenu.c, main/newmenu.h: Move newmenu_get_filename to menu.c, call it get_filename and have it use newmenu_listbox1; support long demo filenames 20091207 -------- main/net_ipx.c: Removing old use of variable already_showing_info which was removed from newmenu code 20091205 -------- main/gamecntl.c, main/newmenu.c: Make newmenu.c nearly identical between D1X and D2X 20091202 -------- arch/include/event.h, arch/include/window.h, arch/sdl/window.c, d2x-rebirth.xcodeproj/project.pbxproj, main/automap.c, main/game.c, main/game.h, main/gamecntl.c, main/kconfig.c, main/kconfig.h: Make the automap into a 'window', make kconfig.c more similar between D1X and D2X 20091201 -------- main/gauges.c, main/weapon.c: Squishing string-related bugs in Bomb display and Weapon reordering 2d/clip.h, 2d/line.c: Renaming FSCALE to FIXSCALE preventing possible naming conflicts 20091130 -------- d2x-rebirth.xcodeproj/project.pbxproj: Update to not compile redundant net_ipx.c for Mac OS X main/newdemo.c, main/newdemo.h, main/gamerend.c, main/game.c, main/gauges.c, main/gamecntl.c: Reintroduced Newdemo_game_mode to prevent demo playback from entering code parts it should not and fixing a bug with Multiplayer demos along the way, introduced in rev. 953 arch/ogl.c, main/endlevel.c: Draw Endlevel sequence with correct DepthFunc main/newmenu.c, main/terrain.c, iff/archive/ifftestv.c, 2d/2dsline.c, 2d/bitblt.c, 2d/pixel.c, 2d/rle.c, 2d/line.c, 2d/gpixel.c, SConstruct: Making files in 2d directory more similar and removed unused and broken code; Fixing a bunch of memory errors; Removed stack protecting flag for gcc in debug mode 20091129 -------- d1x-Info.plist, d1x-rebirth.xcodeproj/project.pbxproj, d1xgl-Info.plist, English.lproj/InfoPlist.strings: Make Mac version numbers consistent, Xcode build settings tidy up main/net_udp.c, main/multi.c, main/multi.h, main/menu.c, SConstruct, arch/linux/ipx.c, arch/carbon/conf.h: Adding macros for the compiler to compile with either UDP- and/or IPX-support and removed the older IPX macros 20091128 -------- main/net_udp.c, d2x-rebirth.xcodeproj, D2X.make, arch/carbon/conf.h: Fixed building error on Windows caused by false socket variable; Fixed compiler Warnings on Mac; Updated Mac build files; Unification in version numbering 20091124 -------- include/args.h, INSTALL.txt, main/net_udp.c, main/net_udp.h, main/fireball.c, main/multi.c, main/multibot.c, main/multi.h, main/inferno.c, main/menu.c, main/object.c, main/kmatrix.c, main/kmatrix.h, main/newdemo.c, main/config.c, main/net_ipx.c, main/config.h, main/net_ipx.h, main/gamerend.c, main/gameseq.c, main/endlevel.c, main/vers_id.h, main/game.c, main/gauges.c, misc/args.c, SConstruct, d2x.ini, README.txt, arch/linux/ipx.c, arch/linux/ipx_kali.c, arch/win32/ipx.c: Abstracting networking protocols - Step 4: Implemented new UDP layer with Client/Server communication, Packet Loss Prevention and strict Version checking. Netgames list will follow later. main/net_udp.c: Remove the IP check when processing game info or version deny as the IP might be translated (IPv6 especially) main/net_udp.c, main/net_ipx.c, SConstruct: Improved Disconnect-handling between levels; Improved Kick-handling; Do not say that IPv4 and IPv6 builds are not compatible in scons -h anymore include/timer.h, main/net_udp.c, main/newmenu.c, main/multibot.c, main/menu.c, main/titles.c, main/kmatrix.c, main/net_ipx.c, main/digiobj.c, arch/sdl/timer.c: Removed timer_get_approx_seconds() and replaced with timer_get_fixed seconds since it was too inaccurate and created significant offset main/net_udp.c: Again making the joining safer 20091117 -------- arch/ogl/gr.c, arch/sdl/gr.c, include/gr.h, main/menu.c, main/piggy.c: Only list resolutions that can actually be used, using new gr_check_mode 20091115 -------- main/gamecntl.c, main/gameseq.c, main/gameseq.h, main/menu.c, main/newdemo.c, main/newdemo.h, main/newmenu.c, main/text.c: Add endian converter for demos, read shareware demos, various bugfixes to demo system 20091005 -------- include/physfsx.h, main/ai.c, main/ai.h, main/cntrlcen.c, main/cntrlcen.h, main/fireball.c, main/fireball.h, main/fuelcen.c, main/fuelcen.h, main/object.c, main/object.h, main/player.c, main/player.h, main/state.c, main/switch.c, main/switch.h, main/wall.c, main/wall.h: Read big endian savegames on little endian computers and vice versa 20090911 -------- main/state.c: Include necessary ogl_init.h in state.c (whoops) 20090822 -------- main/state.c, main/state.h: Make state.c more similar between D1X and D2X 20090810 -------- arch/sdl/window.c, main/automap.c, main/game.c, main/inferno.c, main/multi.c: Make the game screen into a 'window', handling events through event_process 20090701 -------- main/game.c, main/game.h, main/gamecntl.c, main/kconfig.c, main/kconfig.h, main/menu.c, main/net_ipx.c, main/newmenu.c, main/newmenu.h, main/scores.c, main/screens.h, main/songs.c, main/titles.c: Make game.c more similar between D1X and D2X, making related changes to other files (!) 20090607 -------- main/game.c, main/gamecntl.c: Small cleanup 20090531 -------- include/args.h, include/u_mem.h, main/gamecntl.c, main/inferno.c: Make inferno.c more similar between D1X and D2X 20090522 -------- arch/sdl/window.c, main/inferno.c: Add include directives for last commit (whoops) 20090521 -------- arch/include/event.h, arch/include/window.h, arch/sdl/event.c, arch/sdl/mouse.c, arch/sdl/window.c, d1x-rebirth.xcodeproj/project.pbxproj, main/inferno.c, SConstruct: Add new window system, not used yet 20090506 -------- main/config.c, main/config.h, main/menu.c, main/songs.c: Add option to force either Redbook or Jukebox to use the playing order for the game CD 220090503 -------- main/net_ipx.c: Make sure HoardEquipped returns 1 if hoard.ham is in the Data folder, hence properly allowing hoard.ham to be in the Data folder main/config.c, main/menu.c: Make some files more similar between D1X and D2X 20090430 -------- arch/carbon/conf.h, d2x-rebirth.xcodeproj/project.pbxproj: Disable network support for Mac OS X for now 2d/2dsline.c, 2d/bitblt.c, 2d/bitmap.c, 2d/box.c, 2d/canvas.c, 2d/circle.c, 2d/disc.c, 2d/font.c, 2d/gpixel.c, 2d/line.c, 2d/palette.c, 2d/pcx.c, 2d/pixel.c, 2d/poly.c, 2d/rect.c, 2d/rle.c, 2d/scalec.c, 2d/tmerge.c, 3d/clipper.c, 3d/draw.c, 3d/globvars.c, 3d/instance.c, 3d/interp.c, 3d/matrix.c, 3d/points.c, 3d/rod.c, 3d/setup.c, arch/carbon/findfile.c, arch/carbon/gui.c, arch/carbon/SDL_main.c, arch/linux/ukali.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, arch/sdl/digi.c, arch/sdl/event.c, arch/sdl/gr.c, arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c, arch/sdl/rbaudio.c, arch/sdl/timer.c, iff/iff.c, include/physfsx.h, libmve/mvelib.c, libmve/mveplay.c, main/ai.c, main/ai2.c, main/aipath.c, main/automap.c, main/bm.c, main/bmread.c, main/cntrlcen.c, main/collide.c, main/config.c, main/console.c, main/controls.c, main/credits.c, main/crypt.c, main/digiobj.c, main/dumpmine.c, main/editor/autosave.c, main/editor/centers.c, main/editor/curves.c, main/editor/eglobal.c, main/editor/ehostage.c, main/editor/elight.c, main/editor/eobject.c, main/editor/eswitch.c, main/editor/fixseg.c, main/editor/func.c, main/editor/group.c, main/editor/info.c, main/editor/kbuild.c, main/editor/kcurve.c, main/editor/kfuncs.c, main/editor/kgame.c, main/editor/khelp.c, main/editor/kmine.c, main/editor/ksegmove.c, main/editor/ksegsel.c, main/editor/ksegsize.c, main/editor/ktmap.c, main/editor/kview.c, main/editor/macro.c, main/editor/med.c, main/editor/meddraw.c, main/editor/medmisc.c, main/editor/medrobot.c, main/editor/medsel.c, main/editor/medwall.c, main/editor/mine.c, main/editor/objpage.c, main/editor/segment.c, main/editor/seguvs.c, main/editor/texpage.c, main/editor/texture.c, main/effects.c, main/endlevel.c, main/escort.c, main/fireball.c, main/fuelcen.c, main/fvi.c, main/game.c, main/gamecntl.c, main/gamemine.c, main/gamepal.c, main/gamerend.c, main/gamesave.c, main/gameseg.c, main/gameseq.c, main/gauges.c, main/hostage.c, main/hud.c, main/inferno.c, main/kconfig.c, main/kmatrix.c, main/laser.c, main/lighting.c, main/menu.c, main/mglobal.c, main/mission.c, main/morph.c, main/movie.c, main/multi.c, main/multibot.c, main/newdemo.c, main/newmenu.c, main/object.c, main/paging.c, main/physics.c, main/piggy.c, main/player.c, main/playsave.c, main/polyobj.c, main/powerup.c, main/render.c, main/robot.c, main/scores.c, main/segment.c, main/slew.c, main/state.c, main/switch.c, main/terrain.c, main/texmerge.c, main/text.c, main/titles.c, main/vclip.c, main/wall.c, main/weapon.c, maths/fixc.c, maths/rand.c, maths/tables.c, maths/vecmat.c, mem/mem.c, misc/args.c, misc/error.c, misc/hash.c, misc/strio.c, misc/strutil.c, texmap/ntmap.c, texmap/scanline.c, texmap/tmapflat.c, ui/barbox.c, ui/button.c, ui/checkbox.c, ui/func.c, ui/gadget.c, ui/icon.c, ui/inputbox.c, ui/keypad.c, ui/keypress.c, ui/keytrap.c, ui/listbox.c, ui/menu.c, ui/menubar.c, ui/message.c, ui/mouse.c, ui/number.c, ui/popup.c, ui/radio.c, ui/scroll.c, ui/ui.c, ui/uidraw.c, ui/userbox.c, ui/window.c: Remove redundant conf.h directives 20090409 -------- main/multi.c, main/multi.h, main/multibot.c, main/menu.c, main/kmatrix.c, main/net_ipx.c, main/net_ipx.h, main/gameseq.c, main/fuelcen.c, main/gamerend.c: Abstracting networking protocols - Step 3: Renaming network_* functions to net_ipx_*, writing wrappers for protocol dependend functions in multi.c, Implementing protocol selection and Cleanup - Next up: Implementing new UDP layer 20090320 -------- include/ipxdrv.h, main/collide.c, main/ipxdrv.c, main/fireball.c, main/multi.c, main/multi.h, main/menu.c, main/state.c, main/newdemo.c, main/switch.c, main/net_ipx.c, main/net_ipx.h, main/gameseq.c, main/endlevel.c, main/powerup.c, main/automap.c, SConstruct, arch/linux/ipx.c, arch/linux/ipx_kali.c, arch/win32/ipx.c: Abstracting networking protocols - Step 2: Introducing new structure to hold protocol-dependend and -independend information about Netgame and it's Players; Further isolation of the IPX code and renaming the netdrv_* code to ipxdrv_* as this is now actually IPX-only; Next up: Renaming network_* functions to net_ipx_*, writing wrappers for protocol dependend functions in multi.c, Implementing protocol selection and Cleanup 20090304 -------- various: Abstracting networking protocols - Step 1: Renaming network-related files; Removing net_ipx.h (former network.h) includes from as much files as possible to make isolation of IPX-related functions easier in Step 2; Version defines Cleanup - needed later for good Version-Checking 20090303 -------- arch/include/digi_mixer_music.h, arch/include/jukebox.h, arch/sdl/digi_mixer_music.c, arch/sdl/digi_mixer.c, arch/sdl/digi.c, arch/sdl/init.c, arch/sdl/jukebox.c, arch/sdl/rbaudio.c, include/rbaudio.h, main/automap.c, main/config.h, main/credits.c, main/digi.h, main/game.c, main/gamecntl.c, main/kconfig.c, main/kmatrix.c, main/menu.c, main/network.c, main/newmenu.c, main/scores.c, main/songs.c, main/songs.h: Associate the jukebox with Redbook Audio via new 'extmusic' layer - separating from MIDI and making it handle ALL music (not just game music) 20090223 -------- main/gamerend.c, main/gauges.c, main/menu.c: Made our Cockpit-Transparency decoding function a bit safer for current and possibly new code flow main/gauges.c: Small positional correction for homing-warning bitmap 20090222 -------- main/fireball.c: Fixed param handling of expl_obj in do_explosion_sequence for the case that free_object_slots might have it set to OF_SHOULD_BE_DEAD before it's actually attached to another object 20090217 -------- main/object.c, main/object.h, main/weapon.c: Made Max_used_objects an absolute defined value; Made num_objects globally available; Restricted Weapon drops to MAX_USED_OBJECTS; When dropping Secondary weapon, drop 4-pack if possible 20090215 -------- main/network.c, main/noloss.c, main/noloss.h: Added list to keep trace of received PDATA packets so receiver won't interpret them several times main/kmatrix.c: Made connect-state handling in kmatrix flow even more failsafe 20090209 -------- main/kconfig.c: Removed PH_SCALE on Keyboard readings as caps movement not in sync to FrameTime; Removed scaled Joystick reading as it's not necessary anymore main/gameseq.c: When creating new player, make sure string is long enough for use with players dir 20090208 -------- main/multi.c, main/network.h, main/kmatrix.c, main/kmatrix.h: Fixed connect-state mess in order of kmatrix flow main/menu.c: Make sure HostAddr buffer is directly saved as soon as we confirm it in the entry field 20090206 -------- INSTALL.txt, main/network.c, main/network.h, main/noloss.c: Small docs update; Noloss thinking flaw correccted: Add a special type for PDATA packets that need to be ACK'd so other clients won't ACK everything 20090203 -------- main/network.c, main/noloss.c: Close out fire from queue list as this is not necessarily needed to keep games in sync; While processing the noloss queue, only process 5 packets max 20090202 -------- main/newdemo.c, main/gameseq.c, main/gamerend.c, main/ai.c, main/game.c, main/gauges.c, main/game.h, main/gamecntl.c: Defined some default cockpit modes in Demo mode so we do not get invalid values when demo starts in non-default-view mode (as new HUD modes are only triggered at beginning and end of event); Removed Newdemo_flying_guided global; Init seismic disturbances in demo mode just to make sure tey are switched off when coming from game mode; Made initialisation for Missile_viewer signature saving global so we can reset it for each new level and make sure we get a correct missile view; Fixed regression in Ai_last_missile_camera main/gamerend.c: Made FPS string statically right-justified - unrelated to actual FPS string width preventing jumps 20090201 -------- main/netdrv_udp.c: Fixing bug with incorrect/missing UDP port termination main/network.c, main/network.h, main/multi.h, main/netdrv_udp.c, main/netdrv_udp.h, main/noloss.c, main/noloss.h, SConstruct: Added Packet-loss prevention code for Netgames 20090130 -------- arch/ogl/ogl.c, main/render.c: New level render order for better seperation and blending between transculent level geometry and sprites 20090129 -------- main/netdrv_udp.c: Decreasing delay from timer_delay2 to timer_delay for sending/receiving packets when connecting to UDP host due to FPS-dependent inconsistencies in timer_delay2 causing packets possibly not received or sent frequently 20090126 -------- include/netdrv.h, main/network.c, main/menu.c, main/netdrv_udp.c, main/netdrv_udp.h, main/netpkt.c, main/netpkt.h, main/netdrv.c, arch/linux/netdrv_ipx.c, arch/linux/netdrv_kali.c, arch/win32/netdrv_ipx.c: Changed function naming convention in netdrv and below to general Descent code convention arch/carbon/conf.h, d2x-Info.plist, d2xgl-Info.plist, English.lproj/InfoPlist.strings: Update version to 0.55.1 20090124 -------- main/game.c: Removed some old code to smooth FrameTime we don't need anymore 20090122 -------- main/newdemo.c: New condition to switch to Interpolated demo playback - the old one did NOT make ANY sense at all 20090117 -------- arch/sdl/mouse.c, main/menu.c, main/playsave.c, main/playsave.h: Made MouseFilter selectable over Controls menu while defaulting to OFF - Saved in PLX d2x.ini, inlcude/args.h, main/inferno.c, main/laser.c, misc/args.c: Took out old missile tracking code to be selectable over command-line to preserve consistency 20090116 -------- arch/ogl/ogl.c, main/gamefont.c, main/menu.c: Reduced size of vectorial reticle to match the size of the original one; Only scale fonts by float if Texture filtering is on - otherwise scale by int arch/ogl/gr.c: Error handling while dumping TGA file - (partially) Patch by v66r 20090115 -------- include/cfile.h, main/network.c, main/inferno.h, main/netdrv_udp.c, main/netdrv_udp.h, main/netdrv.c, main/gamecntl.c, arch/sdl/digi_mixer_music.c, include/ogl_init.h: Patch from Damjan Cvetko for better support building with a non-free compiler... arch/sdl/mouse.c, main/automap.c, main/game.h, main/kconfig.c: Fixed typo in mouse delta reading cleaning not up Z-Axis; Giving automap a nicer Frameloop; 20090113 -------- main/physics.c: Actually set velocity from movement when colliding with objects arch/sdl/jukebox.c: Use a 2D array to allow playing of songs by track number in future main/collide.c: Added some randomness to collision sound delays and synced robot-player collision sprites to same steps 20090108 -------- main/network.c: Fixed condition for protocol version checking when joining a game - must be allowed for both original and D2X version 20081230 -------- SConstruct: prefix is now an argument (useful for auto-builds) debian/*: created the debian packaging files 20081227 -------- arch/carbon/conf.h, d2x-Info.plist, d2x-rebirth.xcodeproj/project.pbxproj, d2xgl-Info.plist, English.lproj/InfoPlist.strings: Increment Mac version number, update project for latest Xcode 20081226 -------- main/netdrv_udp.c: Fixed segfault via buffer overflow when attempting to start or join a UDP/IP netgame. 20081223 -------- main/config.c: Make Redbook the default for Mac, because MIDI is buggy 20081221 -------- d2x-rebirth.xcodeproj/project.pbxproj, D2X.make, main/gamecntl.c, main/playsave.c: Fix Mac OS 9 compile issues, update Xcode project arch/carbon/conf.h: Set SHAREPATH to "." for Mac OS X so reading data from DXX's directory ACTUALLY WORKS 20081213 -------- main/game.c, main/game.h, main/gamecntl.c, main/menu.c: Seperated help screens for game, netgame and demo; Also show them in Controls menu; Small Menu UI fix for ScrollOffset when calling menus in a scrolled area of a menu 20081212 -------- main/multi.c: Added /KillReactor command to blow up the reactor in Multiplayer games 20081207 -------- 2d/pcx.c, 3d/interp.c, arch/include/key.h, arch/sdl/key.c, d2x-rebirth.xcodeproj/project.pbxproj, iff/iff.c, include/gr.h, include/pcx.h, include/u_mem.h, main/automap.c, main/escort.c, main/game.c, main/gamecntl.c, main/gauges.h, main/inferno.c, main/inferno.h, main/kconfig.c, main/mglobal.c, main/newdemo.c, main/newdemo.h, main/newmenu.c, main/piggy.c, main/render.c, main/songs.c, main/titles.c: Get Mac command keys working, MACINTOSH code cleanup, update Xcode project 20081201 -------- main/kconfig.c: Restored vertical_thrust_time behaviour combined with slide_on to be inverted - respecting user's wishes 20081129 -------- main/state.c: Fixed the Birthday Bug: Correctly re-compute static_light when restoring a game - finally 20081126 -------- main/gameseq.c: Fixed logical code flow error when player dies in a secret level entered after base level destroyed which is also the last level arch/ogl/ogl.c: Deactivated depth writing fo g3_draw_bitmap() sprites to prevent rendering errors when clipped in some cases 20081122 -------- main/kconfig.c: Completly forgot to make mouse axis values static so they can be used in intervals - shame on me! main/fvi.c, main/pysics.c: Took out the "disable_new_fvi"-hack. After all we do not need that specific optimisation anymore and also without it we can have more accurate collisions with non-player objects. After playtesting for a while let's just do this. 20081121 -------- main/gamecntl.c, main/gauges.c: Do not allow to restore games while player is dead... again - to much trouble right now; Solving small display issue when fading out weapons which ran out of ammo main/render.c: Increasing Render_depth to max. if OGL build (we probably should get rid of these variables, but may still be handy for non-3D-accellerated build optimisations) 20081120 -------- main/ai2.c: When we reached MAX_BOSS_TELEPORT_SEGS in init_boss_segments, make sure we also escape out of the for-loop - otherwise we still might overflow main/piggy.c: Corrected a small logical mistake in Shareware-HAM recognition arch/ogl/ogl.c, main/ai2.c, main/object.c: Small transparency fix for robot weapons; Some timer-Failsafe in robot/boss dying frames; Fixed logical flaw in create_small_fireball_on_object() closing out sound effects on robots 20081119 -------- main/gamecntl.c: Actually demand ANY valid key to abort the Death sequence main/songs.c: Do a songs_init() each time a song is played and try to read a new descent.sng - supporting descent.sng files in hog archives 20081118 -------- main/console.c: When printing Gamelog, make sure canvas is NULL main/newmenu.c, main/multi.c, main/automap.c, main/gamecntl.c, ui/inputbox.c, ui/menubar.c, arch/sdl/event.c, arch/sdl/key.c, arch/include/key.h: Yet another UNICODE overhaul - Using seperate buffer for UNICODE chars and only use it in key_ascii() while still using keysyms for the rest of the program so we do not screw up readings by key values altered by modifers - possibly still room to optimize main/gamecntl.c: Fixed cheats! main/automap.c: Changed keys for Automap Viewing Distance to F9/F10 - Minus/Equal is not Layout independent 20081115 -------- arch/sdl/digi_audio.c: include/error.h, main/console.c, main/inferno.c: Added other SDL_(Un)LockAudio statements to protect the audio_mixcallback function - making that hopefully stable on multicores; Resetting warn_func at quit_request so we do not accidently show any menu; Open gamelog.txt unbuffered 20081114 -------- include/args.h, include/3d.h, include/rle.h, include/rbaudio.h, main/text.c, main/text.h, main/bm.c, main/gamefont.c, main/inferno.c, main/bm.c, main/bmread.c, main/piggy.c, main/render.c, main/render.h, main/songs.c, main/gameseq.c, main/gamerend.c, main/netdrv.c, main/endlevel.c, main/endlevel.h, main/terrain.c, main/terrain.h, main/polyobj.c, main/polyobj.h, main/game.c, main/gauges.c, main/texmerge.c, main/mission.c, main/mission.h, main/gamecntl.c, misc/args.c, 2d/rle.c, 3d/setup.c, SConstruct, D2X.make, arch/linux/alsadigi.c, arch/ogl/gr.c, arch/sdl/digi_mixer.c, arch/sdl/joy.c, arch/sdl/init.c, arch/sdl/rbaudio.c, arch/sdl/gr.c, arch/sdl/key.c, arch/sdl/digi_audio.c, arch/include/mouse.h: Using a clean flow for closing game data at the end of main() instead of using atexit; Now only use atexit for SDL stuff, error, mem, console (and editor which we do later); Small Cleanup 20081110 -------- main/credits.c, main/inferno.c, main/menu.c, main/newmenu.c: Small Cleanup: Using timer_delay for credits timer as timer_delay2 would respect VSync and change speed of the Credits scrolling; Cleaned that Start/Join Netgame cases up a bit; Removed the excessive use of atexit in newmenu... more to come misc/error.c: When Error() is called, set Function_mode to FMODE_EXIT... basically to prevent the messagebox would try to render the game in background if the Error would happen while mission loading 20081109 -------- include/args.h, include/gr.h, main/gamefont.c, main/inferno.c, main/menu.c, main/gamerend.c, main/gauges.c, main/gauges.h, misc/args.c, d2x.ini, arch/ogl/ogl.c, arch/ogl/gr.c: Always keep aspect scaling (lowest scalar of width and height) for fonts, lines, dots, spheres, reticle and non-Cockpit-/Statusbar-related HUD-elements; Moved the Cockpit alpha decoding to gauges.c and created a seperate bitmap for the alpha fields and create subbitmaps from this one - more memory but this way we do not modify the cockpit bitmap itself 20081107 -------- arch/sdl/key.c: Only read UNICODE values from 31 to 254 to make sure we do not read any non-printable characters and prefer the keysym that way; Added left and right Command Key for MAC Keyboards 20081103 -------- misc/args.c: Fixed Typo main/ai2.c, main/collide.c: Made move_towards_segment_center() use move_towards_vector() instead of just changing object position suddenly - smoother; Changed back the robot:controlcen collision back to original - the AI just relies to often on no-damage collisions, especially when our segment suddenly is a controlcen 20081101 -------- main/config.c, main/menu.c, main/newmenu.c, main/piggy.c: Fixed possible overflows in Jukebox Path; Menu GUI improvements: Correct inputbox scaling for font widths, a little performance boost when determinating string-part to show in inputbox, make it possible to flip over from first/last menu entry to last/first even if it's a ScrollBox, Scrolling via Maousebutton now works with delay; Made reading for Piggy data always break up in loops when reached end of file instead of provoking possible error if *data-count < max-data-count* arch/sdl/key.c: Make sure that if we use UNICODE, we always take non-control type chars and - as we only want lowercase letters - convert chars if shift is pressed arch/ogl/ogl.c. main/game.c: I always forget glLineWidth takes previous setting if arg is <1; Made the decodebuffer for cockpit static as the bitmap data pointer points to it 20081031 -------- main/bm.c, main/inferno.c, main/piggy.c: Allow hires Mac demo graphics, fix endian issue with reading GameBitmapXlat (fixing crash on PowerPC Macs using PC demo), put a return on the end of an error message arch/include/key.h, arch/sdl/key.c, main/game.c, main/kmatrix.c, main/multi.c, main/multi.h, main/newmenu.c, main/scores.c, ui/inputbox.c, main/menubar.c: Always use printable UNICODE characters for the key_handler and included routine to assign key symbols to UNICODE so we get an equivalent of a Key-Released state which we need for the Keyboard buffer; Removed the shifted_ascii_value field from key_props and stored all usable characters in seperate rows; Improves Text input and makes keyboard mapping independent from keyboard layout without breaking any compability arch/ogl/ogl.c: Make glLinewidth depend on screen height, not width (for Widescreen monitors) (commit came with last revision, sorry) 20081030 -------- INSTALL.txt, README.txt: Docs update: Infos about Jukebox over SDL_mixer, SDL_mixer is not experimental anymore, yet another .de->.com change d2x.ini, main/inferno.c: Show debug help screen options in release build as well as some might be actually useful for players main/menu.c: Add a messagebox informing to restart the game if either VSync or 4x Multisampling has been (de)selected 20081029 -------- 2d/font.c, main/gamefont.c, main/gamefont.h, main/menu.c: Scale fonts by float values and filter them if texture filtering is on; Another fix for the code flow in change_res() as the check for minimal custom resolution always failed main/collide.c: Yet another check for collide sounds as FixedStep is not necessarily true if the actual collision happens main/newmenu.c: Cast LINE_SPACING to integer for menu Scrollbox usages - fixing scrolling issues with non-integer-scaled font sizes 20081028 -------- arch/ogl.c, include/gr.h, main/game.c, main/gamerend.c, main/gauges.c, main/gauges.h, main/newmenu.c: Removed hack for Cockpit-window transparencies and added function to decode and add alpha to the bitmap directly (now works in non-OGL as well); Using sub-bitmaps for Cockpit-windows and menu backgrounds; Cleaned old bkg stuff from menu GUI main/gamerend.c, main/manu.c, main/newmenu.c: Fixes for my last revisions: More reliable check for cockpit_decode_alpha, more reliable check is newmenu sub-bitmap needs to be re-created, call gr_set_mode() in change_res() with correct Game_screen_mode INSTALL.txt, README.txt: Docs update: We moved from www.dxx-rebirth.de to www.dxx-rebirth.com! arch/sdl/gr.c, arch/ogl/gr.c, arch/ogl/ogl.c, include/args.h, main/game.c, main/gamecntl.c, main/inferno.c, main/menu.c, main/playsave.c, main/playsave.h, misc/args.c: Cleanup: Renderstats; Made PRShot a non-OpenGL-related feature and added to Misc Options; Added command for SDL_ASYNCBLIT to command-line args SConstruct, include/dl_list.h, main/config.c, main/console.c, main/menu.c, main/robot.h, misc/dl_list.c: Revisited Kip's non-Tracker changes and implemented to D2X: Prettier SConstruct output, Forgotten newlines at end of files, Improvement in dl_list code, Revamped menu GUI defines; I am NOT HAPPY I have to do these changes seperately!!! 20081023 -------- main/network.c: Fixed handling for multi_quit_game; Always keep setting -1 for ping table entry of current player so just not to use any previous entry 20081022 -------- main/menu.c, main/netdrv_udp.c, main/netdrv_udp.h: Removing reset of Game_screen_mode while change_res Fullscreen toggle (wtf is the point?); Adding a third valid state for UDP peers so we can get more order in handshaking process - should fix problem when two clients join (and shake) simultaniously 20081021 -------- iff/iff.c, main/wall.c: Fix some gcc 4.0 warnings (-wall flag) 20081020 -------- main/menu.c: resolution 1440x960 to 1440x900 - typo d1x.ini, include/args.h, main/inferno.c, main/menu.c, main/netdrv_udp.c, misc/args.c: Readded -ip_hostaddr optional to the value stored in descent.cfg for automated program starts or whatever; Fix by Locate: Correctly close UDP sockets on Win32; Fix by Locate: Ability to select Secret levels on Multiplayer in D1X again which was broken in r619 20081019 -------- arch/sdl/gr.c, arch/ogl/gr.c, main/gamecntl.c, main/menu.c, main/movie.c, main/titles.c: Setting Fullscreen toggle setting the GameCfg value at each change, not only in change_res(); Do not allow the toggle while playing since ALT-GR+ENTER could be used as game-keys; Reorganized Resolutions menu to automatically calculate aspect ratio for preset resolutions and making custom fields exclusive 20081016 -------- main/credits.h, main/collide.c, main/newmenu.c, main/menu.c, main/playsave.c, main/playsave.h, main/titles.c, main/wall.c, main/render.c, main/newdemo.c, main/newdemo.h, main/config.c, main/gameseq.c, main/gamerend.c, main/endlevel.c, main/scores.c, main/game.c, main/kconfig.c, main/gamecntl.c, main/credits.c, 2d/ibitblt.c, arch/sdl/mouse.c, arch/win32/hmpfile.c, arch/include/joy.h: Giving credits function ability to use custom creditfile (again); Made laser-offset for laser exclusive so Prox mines won't go tru doors; Preventing cycling tru cockpit modes while dead, but allowing to load a state; Implemented D2X' lighting code to D1X (faster, better, sexier - weeee); Try to hop over some errors regarding walls/doors in levels instead of using -1 indexes for arrays; Made the briefing text ptr a bit more failsafe in case the file is corrupt/non-standard; Made scores use the menu screen even in GAME OVER; Fixed bug in neighbour fields of Weapon Keys table; Added the Weapon Keys stuff to TABLE_CREATION; Fixed bug where D2X did not recall applied resolution in the resolutions menu; Simpler check to create DEMO_DIR; Seperated X/Y sensitivity for mouse and joystick; Flush controls when Automap toggles so keypress won't deactivate it again; Made FrameCount in Demos aligned to the Dropframe condition; Added KEy to ttoggle playback text off; Gracefully exit demo code if demo is corrupt; Removed that new percent counter because many old demos seem to have corrupted last frames; Closing endlevel data file if IFF error so the mission still can be freed; Fixed Cruising for keyboard which was not aligned to FPS correctly; Used mouse delta scaling in kconfig.c instead of mouse.c to not screw up when delta is requested in non-ingame situations - it actually belongs to the controls IMHO; Now support up to 8 joysticks; Changed some leftover malloc's to d_malloc and free to d_free 20081001 -------- main/physics.c: Update object segment after object position interpolation. This is always done in DEBUG, but not in RELEASE, where further movement would break at segment check 20080903 -------- main/console.c, main/collide.c, main/mglobal.c, main/inferno.c, main/menu.c, main/physics.c, main/aipath.c, main/cntrlcen.c, main/weapon.c, main/netpkt.h, main/gamerend.c, main/ai2.c, main/laser.c, main/game.c, main/gauges.c, main/game.h, main/gamecntl.c, SConstruct, d2x.ini, maths/vecmat.c, arch/sdl/timer.c, arch/sdl/mouse.c, arch/sdl/digi.c, arch/sdl/digi_audio.c, arch/include/mouse.h: Added new function to calculate common timesteps; Increased MAXIMUM_FPS to 200 for release and 1000 for debug; Used fixed sim_time for do_physics_sim and Interpolating to ensure collisions stay accurate at high FPS; New code and faster code for dot products by The_Lion; Disabled Nice-FPS and common Frame-Loop if VSync is active; More accurate delta timer for mouse (consider overhead); Added SDL_(Un)LockAudio for old SDL Audio interface; General support for up to 16 mouse buttons; Code cleanup; Made some AI movement and Player shaking FPS-independent 20080726 -------- d2x-rebirth.xcodeproj, main/multi.c, main/netpkt.c, main/netpkt.h, main/network.c: Make network endian code more consistent with D1X, use PUT/GET_INTEL macros more, remove redundant no_cpp_precomp macro 20080720 -------- include/netdrv.h, main/netdrv_udp.c, main/netdrv_udp.h, main/netdrv.c, arch/linux/netdrv_ipx.c, arch/linux/netdrv_kali.c, arch/win32/netdrv_ipx.c: Fixed IPX default socket (typo); Using function pointer for IPX-based sockets instead of globals 20080701 -------- arch/carbon/conf.h, d2x-Info.plist, d2xgl-Info.plist, d2x-rebirth.xcodeproj, English.lproj/InfoPlist.strings: Increment version number for Mac, ensure Get Info strings copy to bundle, use correct Mac OS X SDKs include/strutil.h, misc/strutil.c: Add snprintf for Mac OS 9 main/songs.c: Make sure the right audio CD track is played when starting a level include/physfsx.h, main/config.c: No using chdir for Mac OS 9 - it doesn't have it 20080628 -------- main/collide.c: Do not apply new bump_two_objects() when companion object colliding with controlcen due to inability of companion to find alternatives 20080617 -------- main/songs.c: make sure it knows whether an audio CD just inserted is the official one 20080615 -------- main/newdemo.c: Better call for DoJasonInterpolate in demo code (hopefully) arch/sdl/rbaudio.c, include/inferno.h, include/rbaudio.h, main/game.c, main/gamecntl.c, main/songs.c: tidy up music keys, ALT-SHIFT-F9 ejects audio CDs main/gamecnt.c: add necessary #includes for last commit (whoops) 20080612 -------- README.txt, main/collide.c, main/multi.c, main/netdrv_udp.c, main/network.c, main/state.c: Improved Player relay for Endlevel status; Fixed leaving when UDP hosts leaves; Fixed multi_frame_calling while demos since demos can be Game_mode & GM_MULTI; Re-added lost collision fix between robots and reactor; Made state_defaut_item static so selected state slot stays selected arch/sdl/digi_mixer.c: Setting GameArg.SndNoSound to true if SDL_mixer init fails 20080605 -------- INSTALL.txt, arch/sdl/digi_mixer.c, arch/sdl/jukebox.c: Small doc update; Improved SDL_mixer / Jukebox handling if no resource (sound) is available 20080604 -------- main/newmenu.c, main/network.c, main/menu.c, main/netdrv_udp.c, main/playsave.c, main/titles.c, main/object.c, main/kmatrix.c, main/scores.c, main/game.c, main/gauges.c, main/kconfig.c, main/gamecntl.c, main/credits.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, arch/include/jukebox.h: Generally increasing Menu rendering from 20 to 50 FPS; Allowed Fullscreen toggle in Pause menu and correctly releasing mouse; Fixed broken Death sequence timer; Fixed incorrect data offset for UDP player relay; Fixed crash in Multiplayer summary; Reworked player loading a little bit, making sure kconfig controls are all set; Some small Status bar correction; Implemented real Pause/Reume for Jukebox via SDL_mixer 20080602 -------- arch/sdl/jukebox.c: Only stop music at jukebox_stop() if MIDI jukebox_loaded - otherwise user can stop Jukebox with keys but not start it again 20080601 -------- include/args.h, main/inferno.c, main/hud.c, main/game.c, main/gamecntl.c, misc/args.c, d2x.ini, README.txt, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/digi_audio.c, arch/win32/include/hmpfile.h, arch/win32/hmpfile.c: Using Windows code to play HMP files on Windows build; Fixed Jukebox keys in help screen; Allow -noredundancy in Singleplayer; Fixed processing of Console keys if Console is not active; Added Multiplayer hints to README; Made INI wrapping safer and more accurate 20080528 -------- arch/sdl/rbaudio.c, main/songs.c: allow an audio CD to be played if it's inserted after D2X is launched, hopefully find the first audio CD if multiple CDs are inserted 20080525 -------- arch/sdl/digi_mixer.c, arch/sdl/jukebox.c, main/kconfig.c, main/morph.h: Set sound distance to 0 for HUD sound taunts; Making Jukebox not crash if -nosound is enabled (should stop Jukebox since no digi system enabled); Lowered mouse axis speed a bit again; Increasing MAX_VECS to 5000 20080524 -------- main/gr.c: Give render_frame call both arguments (compiler error) arch/sdl/jukebox.c, arch/sdl/rbaudio.c, d2x.ini, include/args.h, main/config.c, main/config.h, main/gamecntl.c, main/inferno.c, main/menu.c, main/songs.c, misc/args.c: Allow audio CD support to be turned on in the menus, fix associated bugs 20080522 -------- main/menu.c: Added a new set of preset resolutions 20080521 -------- arch/ogl/gr.c, arch/sdl/mouse.c, main/game.h: Implmented filtered mouse delta reading SConstruct, INSTALL.txt, README.txt: Updated docs 20080520 -------- main/kconfig.c: Decreasing divisor for mouse axis reading - making mouse sensitivity practically much higher 20080519 -------- main/gamecntl.c: If a key combo is called which uses key of default wepaon binding, flush inputs main/mission.c, main/mission.h: Added support for another registered D1 HOG with different patching order... damn you PARALLAX! d2x.ini, arch/sdl/digi_mixer.c, include/args.h, main/gamefont.c, main/inferno.c, misc/args.c: Added -nomusic ability for SDL_mixer API; Added -gl_fontfixwidth to scale fonts with fixed aspect on widescreen resolutions, scaled to height 20080518 -------- include/physfsx.h, main/config.c: set "Jukebox" as the default jukebox path, for Mac OS 9 look for d2x.ini outside the app bundle main/game.c, main/gamecntl.c, main/songs.c: Reworked keys for song changing a bit; Added Song control keys to help menu 20080516 -------- d2x.ini, include/args.h, main/config.c, main/config.h, main/inferno.c, main/menu.c, misc/args.c: remember the last IP address entered for UDP instead of parsing -ip_hostaddr 20080510 -------- main/playsave.c: use atoi instead of sscanf for plx reading, so the setting for showing the reticle is read properly on big endian computers 20080508 -------- main/newmenu.c, main/multi.c, main/kconfig.c, main/gamecntl.c, arch/sdl/key.c, arch/include/key.h: Some code improvements and small fixes 20080507 -------- include/args.h, main/newmenu.c, main/multi.c, main/multi.h, main/inferno.c, main/menu.c, main/netdrv_udp.c, main/powerup.c, main/automap.c, main/gamecntl.c, misc/args.c, d2x.ini, ui/inputbox.c, ui/menubar.c, arch/sdl/digi_mixer.c, arch/sdl/jukebox.c, arch/sdl/key.c,arch/include/jukebox.h, arch/include/key.h: Return unicode characters in key_to_ascii for non-EN keyboard layouts; Fixed sound menu issue if not compiled with SDL_mixer; switched -ip_norelay to -ip_relay since it's not tested enough; Renamed jukebox_free() to jukebox_unload() to stay with naming-convention 20080502 -------- include/args.h, main/inferno.c, main/menu.c, main/movie.c, main/songs.c, main/config.c, main/config.h, main/gamecntl.c, misc/dl_list.c, misc/args.c, SConstruct, d2x.ini, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, arch/win32/hmpfile.c, arch/include/jukebox.h, libmve/mveplay.c: Extended Jukebox capabilities for looping and continous playing and added jukebox_free() which allows calling jukebox_load() being able to load a new directory; Added Jukebox options to sound options menu; Removed loop hack for Windows MIDI playback; SDL_mixer implementation can now be used for Windows build as well 20080427 -------- main/console.c: make sure it doesn't try to write to gamelog.txt after it's closed 20080424 -------- D2X.make, d2x-rebirth.xcodeproj, iff/iff.c, include/ogl_init.h, main/config.h, main/newdemo.c, main/newmenu.c, main/playsave.h, main/state.c: get it to build on Mac OS 9 again 20080422 -------- arch/ogl/gr.c, arch/sdl/gr.c, include/gr.h, main/config.c, main/config.h, main/menu.c: Added function gr_set_attributes to change Options like Texture Filtering and SDL_GL attributes while runtime (if supported); Added 4x Multisample support 20080421 -------- main/console.c, main/inferno.c, main/menu.c, main/config.c, main/config.h, main/gamerend.c, main/game.c, main/gamecntl.c, misc/args.c, d2x.ini, arch/ogl/gr.c, arch/sdl/timer.c, arch/win32/netdrv_ipx.c: Reworked timer_delay2() and calc_frame_time() to be more accurate and CPU-friendly; -nicefps replayced by -nonicefps to disable sleeping for calc_frame_time; Implemented VSync via SDL; Fixed compilation issues; Code cleanup main/console.c: Hack to force DOS-style newlines for _WIN32 in gamelog.txt 20080419 -------- include/ogl_init.h, include/gr.h, include/strutil.h, include/internal.h, main/network.c, main/inferno.c, main/menu.c, main/movie.c, main/playsave.c, main/state.c, main/newdemo.c, main/gamecntl.c, d2x-rebirth.xcodeproj/project.pbxproj, misc/strutil.c, SConstruct, arch/ogl/ogl.c, arch/ogl/gr.c, arch/sdl/joy.c, arch/sdl/gr.c, arch/carbon/conf.h, libmve/mve_main.c, libmve/mveplay.c: Made joy_flush also resetting button state; Improved glReticle; Implemented Fallback resolution if SDL may fail; Code cleanup 20080413 -------- include/args.h, main/newmenu.c, main/collide.h, main/network.c, main/multi.c, main/multi.h, main/inferno.c, main/menu.c, main/menu.h, main/playsave.c, main/playsave.h, main/object.c, main/hud.c, main/weapon.c, main/newdemo.c, main/config.c, main/config.h, main/gamerend.c, main/gameseq.c, main/escort.c, main/escort.h, main/endlevel.c, main/powerup.c, main/powerup.h, main/automap.c, main/game.c, main/gauges.c, main/game.h, main/kconfig.c, main/gauges.h, main/kconfig.h, main/gamecntl.c, misc/args.c, d2x.ini, arch/ogl/ogl.c, arch/ogl/gr.c, arch/sdl/joy.c: Added structure for values saved in PLR/PLX files; Added most common command-line options to options menu main/laser.c, main/menu.c, main/playsave.c: Reverted homers turn_radius again to respect higher difficulty levels; Added PRShot to menus; Fixed typo in OglAlphaEffects saving main/cntrlcen.c, main/collide.c, main/hudmsg.h, main/object.c, main/physics.c: Fixing collision bugs; Cleaning hudmsg.h; Solving death sequence timer without GameTime and removed another global 20080408 -------- d2x-rebirth.xcodeproj, include/cfile.h, main/inferno.c, main/newmenu.c, misc/error.c, ui/gadget.c, ui/window.c: show a messagebox if there's an error and graphics are initialised, update Xcode project 20080406 -------- d2x.ini, SConstruct, main/config.c, main/config.h, main/console.c, main/console.h + various: Implemented Console-style game logging system to print graphics, to stdout and gamelog.txt; Added structure to keep values for descent.cfg; Added aspect and Texture Filtering to descent.cfg; Removed mono code - printing important stuff over console; Removed some obsolete or very common defines; Code cleanup and small fixes 20080227 -------- d2x-rebirth.xcodeproj, main/bmread.c, main/piggy.c: allow external sound files to be put in 'Sounds' folder, update Xcode project 20080225 -------- include/loadgl.h, main/newmenu.c, main/titles.c: Added definitions for OpenGL fucntions which might not be included in system headers; Cleaned and declared briefings palette hacks (EMULATING_D1 needs work!); Menu right border shadow was too wide; main/movie.c: Do not actually blit movie frame if palette has been changed 20080323 -------- main/kconfig.c, main/laser.c, main/menu.c, main/newmenu.c, main/playsave.c: Added lock status for mouse axis weapon cycling because of scaled mouse delta; Due to player feedback (any my opinion) making homer turn rate smaller to make them a bit harder to dodge; Preventing write of player data while Demo playback; Small code cleanup and corrections 20080322 -------- INSTALL.txt, SConstruct: make compile instructions clearer for Windows and Mac users, for Mac OS X don't use Sharepath when using SConstruct main/network.c: add prototypes for show_game_stats and network_do_join_game to fix warnings main/multi.c: allow hoard.ham to go in 'Data' subdirectory 20080321 -------- 2d/palette.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/sdl/gr.c, include/gr.h, include/palette.h, main/automap.c, main/automap.h, main/collide.c, main/credits.c, main/editor/med.c, main/endlevel.c, main/escort.c, main/game.c, main/gamecntl.c, main/gamepal.c, main/gamepal.h, main/gamerend.c, main/gameseq.c, main/gauges.c, main/inferno.c, main/kconfig.c, main/kmatrix.c, main/menu.c, main/menu.h, main/network.c, main/newmenu.c, main/newmenu.h, main/paging.c, main/scores.c, main/switch.c, main/titles.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/menubar.c, ui/message.c, ui/number.c, ui/popup.c: Simplification of palette code; Properly screen clearing in SDL-only build when palette changes; Removed obsolete functions like gr_update (replaced by gr_flip), gr_palette_fade_in/out, gr_palette_clear; Added functionality to render Automap while menu display as well; Improved blocking of some controls code while Automap active; Fixed some compiler warnings include/physfsx.h: allow d2x.ini to stay with the binary for *NIX systems, with Mac OS 9 don't put user-created files inside the .app bundle 20080319 -------- d2x-rebirth.xcodeproj: update d2x.xcode to build universal binaries (requires Xcode 2.1 or greater), update source file list 20080308 -------- main/aipath.c, main/collide.c, main/fvi.c, main/game.c, main/gamecntl.c, main/gamerend.c, main/gauges.c, main/mission.c, main/netdrv.c, main/newdemo.c, main/newdemo.h, main/newmenu.c, main/object.c: Fixed some memory issues; Fixed some HUD element alignment; Only send NetDrv packets if NetDrvInstalled is true; Fixed demo glitches; Actually using Game_mode in demos to make Newdemo_game_mode hacking obsolete 20080228 -------- 2d/font.c, arch/ogl/gr.c, arch/ogl/ogl.c, main/escort.c, main/game.h, main/gamecntl.c, main/gamepal.c, main/gamerend.c, main/gameseq.c, main/gauges.c, main/hud.c, main/mission.c, main/network.c, main/newmenu.c, main/state.c, main/titles.c: Fixed wrong font width spacing, -gl_prshot, mission loading, null-terminatinon in several menus, cockpit glitch; Improved gl_reticle, -noredundancy; Some code cleanup 20080224 -------- main/newdemo.c: make sure the right error message is shown if it can't open a demo main/network.c: fix bug where a Mac host crashes on starting a game include/args.h, include/gr.h, main/credits.h, main/console.c, main/screens.h, main/newmenu.c, main/newmenu.h, main/network.c, main/multi.c, main/inferno.c, main/gamefont.c, main/menu.c, main/gamefont.h, main/menu.h, main/netdrv_udp.c, main/movie.c, main/playsave.c, main/titles.c, main/kmatrix.c, main/controls.c, main/hud.c, main/state.c, main/slew.c, main/gamerend.c, main/gameseq.c, main/escort.c, main/scores.c, main/automap.c, main/game.c, main/gauges.c, main/game.h, main/kconfig.c, main/gauges.h, main/gamecntl.c, main/credits.c, misc/args.c, console/CON_console.c, 2d/font.c, SConstruct, d2x.ini, arch/ogl/ogl.c, arch/ogl/gr.c, arch/sdl/gr.c: Reworked fonts routines - makes easier to expand and scale correctly; Reworked menus with better border scaling, improved rendering and cleanups; Improved font priniting ingame, better alignment; Reworked Netgame list; Real Doublebuffering in SDL-mode; Removed old and unused sources 20080217 -------- misc/hmp2mid.c: don't try and free mid_track_buf if it isn't allocated, if midi conversion doesn't work main/netpkt.c, misc/hmp2mid.c: use d_ memory functions in hmp2mid, since I already started to erroneously. Also fixed bug where Mac-hosted games couldn't be started 20080212 -------- main/endlevel.c: make sure a briefing isn't interpreted as an endlevel sequence file, preventing an in-game warning iff/iff.c: remove redundant iff functions 20080211 -------- main/bm.c, main/bm.h, main/bmread.c, main/inferno.c, main/piggy.c, main/piggy.h: support PC shareware files in full version build, make game data loading code easier to follow 20080129 -------- SConstruct, arch/include/mouse.h, arch/ogl/gr.c, arch/ogl/ogl.c, arch/ogl/sdlgl.c, arch/sdl/mouse.c, include/internal.h, main/kconfig.c: Cleanung up arch/ a little bit; Added mouse delta time interval for more more accurate reading at high FPS SConstruct, main/netdrv_udp.c, main/netdrv_udp.h, main/newmenu.c: Renaming udp.* to netdrv_udp.* to fit naming convention; Small menu ui fixes 20080125 -------- arch/sdl/digi_mixer_music.c: allow custom MIDI in add-on hogs to be used without caching everything 20080124 -------- INSTALL.txt, main/gamerend.c, main/network.c, main/udp.c: Updated Docs - Data files must be lowercase; Fixed small Multiplayer issues 20080123 -------- d2x.ini, arch/sdl/joy.c, include/cfile.h, include/physfsx.h, main/config.c, main/gamesave.c, main/mission.c, main/mission.h, main/playsave.c: Fixed memory issue as Joystick freeing; Case-insensitive mission-loading; Added support for non-Hog'ed missions; Improved writing functions for config and player files 20080119 -------- misc/strutil.c: fix potential bad memory access in change_filename_extension main/inferno.c: if descent2.hog / d2demo.hog isn't found, show a more accurate error message than before include/physfsx.h, main/bm.c, main/piggy.c: rename datafile_open to PHYSFSX_openReadBuffered to fit in with naming convention 20080113 -------- main/network.c: fix typo causing compiler error on bigendian computers 2d/font.c: make sure a font header only takes up sizeof(grs_font) memory, not sizeof(grs_font) squared arch/ogl/gr.c, arch/ogl/include/internal.h, arch/ogl/sdlgl.c, include/args.h, main/inferno.c, main/menu.c, main/newdemo.c, main/newmenu.c, misc/args.c: Removed SDL Gammaramp code (obsolete); Improvements on Demo code 20080108 -------- SConstruct, include/args.h, include/netdrv.h, main/gameseq.c, main/netdrv.c, main/netpkt.c, main/netpkt.h, main/network.c, main/network.h, main/udp.c, misc/args.c: Fixing MAC compiling issues (hopefully); Re-Added IPX Socket option to Host menu for IPX games; Renamed netmisc.* to netpkt.*; Handling host disconnect for UDP games in network.c main/menu.c, main/newmenu.c, main/newmenu.h: Safe timer rollover in menu idle-demo function; Reintroduced menu shortcuts; Implemented support for menu scrolling if nitems > 15 20080102 -------- SConstruct, arch/linux/netdrv_ipx.c, arch/linux/netdrv_kali.c, arch/win32/netdrv_ipx.c, main/menu.c, main/netdrv.c, main/netdrv.h, main/netmisc.c main/netmisc.h, main/network.c, main/network.h, main/udp.c, main/udp.h: Cleaned/Rewritten/Renamed lower level network layer to make it (look) less IPX-oriented 20071229 -------- SConstruct, arch/sdl/digi.c, main/ai.c, main/game.h, main/gamepal.c, main/gameseq.c, main/inferno.c, main/kmatrix.c, main/laser.c, main/menu.c, main/mission.c, main/multi.c, main/multibot.c, main/network.c, main/network.h, main/object.c, main/object.h, main/physics.c, main/render.c: Code cleanup - old/unused/obsolete multiplayer code and more 20071223 -------- include/ipx.h, main/credits.c, main/inferno.c, main/multi.c, main/network.c, main/piggy.c: Fixed compiler error because of removed header file; Removed connect state restore in multi_endlevel_score to make sure always state 7 is sent to other players while connect state is obviously restored later; Allocated memory for all sequence_packet's; Moved piggy_close() to main - replacing atexit; Rendering credits with timer_delay2 at constant 25FPS and save CPU 20071217 -------- d2x.ini, SConstruct, arch/linux/include/ipx_drv.h, arch/linux/linuxnet.c, arch/win32/include/ipx_drv.h, arch/win32/ipx_drv.h, arch/win32/winnet.c, include/args.h, main/inferno.c, main/kconfig.c, main/menu.c, main/network.c, main/network.h, main/scores.c, main/udp.c, main/udp.h, misc/args.c: Implemented new UDP/IP interface with Server-Relay (for firewalled users) and IPv6 compability; Fixed memory issues; If arguments -gl_mipmap and -gl_trilinear used both, always select -gl_trilinear 20071124 -------- main/hud.c: Fixed new redundancy HUD messages check - made it more strictly 20071123 -------- main/aipath.c, main/fireball.c, main/titles.c: Fixed some memory problems; Adjusted timer_delay2 for robot briefings 20071121 -------- arch/sdl/key.c, arch/sdl/timer.c, include/timer.h, main/game.c, main/gamecntl.c, main/kconfig.c, main/kmatrix.c, main/network.c, main/newmenu.c, main/scores.c, main/titles.c: Introduced timer_delay2 as replacement for timer_delay to sleep according to given FPS rate considering calc time between frames 20071110 -------- arch/include/digi_mixer_music.h, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, include/physfsx.h: port the jukebox to PhysicsFS for Mac OS 9 compatibility arch/ogl/sdlgl.c: print a more meaningful message when SDL fails to initialise OpenGL D2X.make: re-add Mac OS 9's makefile (SCons not compatible with Mac OS 9) 20071106 -------- main/config.c, main/game.c, main/game.h, main/gamecntl.c, main/gamerend.c, main/menu.c, main/newdemo.c: Correctly saving Reverse Stereo setting; Added Demo playback help keys; aligned Demo recording to 20 frames per second to save lots of hard drive space 20071106 -------- arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, include/args.h, misc/hmp2mid.c: various fixes towards getting it to build for Mac OS 9 again misc/hmp2mid.c: make sure mid_write_error_templ still works 20071105 -------- arch/carbon/conf.h, English.lproj/InfoPlist.strings, d2x-Info.plist, d2xgl-Info.plist: update Mac version info, set SHAREPATH to application folder for Mac OS X arch/sdl/jukebox.c: Fixed crash on absent or invalid jukebox directory 20071103 -------- arch/sdl/jukebox.c: hack to remove warning when compiling on Mac OS X (constant/variable dirent parameter of file selection callback for scandir) include/physfsx.h, INSTALL.txt: hard code userdir to ~/Library/Preferences/D2X Rebirth/ for Mac OS X 20071101 -------- main/collide.c, main/laser.c: Data types correction 20071031 -------- arch/ogl/gr.c, main/multi.c, main/multi.h, main/network.c, main/state.c, main/state.h: Improvements for -gl_prshot; Improved show_netgame_info(); Removed obsolete multisave code texmap/scanline.c: Fixed selection for default Texmapper 20071029 -------- main/object.c: Fixed cockpit_mode_save usage for Death sequence main/credits.c, main/inferno.c, main/menu.c, main/mission.c, main/newmenu.c: Memory stuff 20071028 -------- arch/ogl/ogl.c, include/args.h, main/collide.c, main/fuelcen.c, main/game.c, main/gamecntl.c, main/gameseq.c, main/gauges.c, main/hud.c, main/inferno.c, main/laser.c, main/network.c, main/powerup.c, misc/args.c: Fixed problems with GameTime wraparound - delay sounds, cloak, invulnerability, ping; Added debug key to Reset GameTime for testing; Removed -gl_vidmem; Some HUD message redundancy main/hud.c: For HUD messages redundancy check, compare all messages and check if message already printed and is a typical "ALREADY HAVE" message - waste them if so main/newmenu.c: Using FONTSCALE_X instead of MENSCALE_X to scale netlist tabs 20071018 -------- d2x.ini, 2d/bitblt.c, 2d/box.c, 2d/rle.c, arch/ogl/gr.c, arch/ogl/ogl.c, include/args.h, include/rle.h, main/gauges.c, main/inferno.c, main/menu.c, mist/args.c: Small fixes; Code cleanup; Implemented PR-Screenshot feature 20071015 -------- libmve/mveplay.c: Set defines for USE_SDLMIXER to fix issues while compiling d2x.ini, main/inferno.c: Removed -userdir switches from command-line and INI since it's not available anymore include/physfsx.h: Fixed define mistake in PHYSFSX_init 20071014 -------- d2x.ini, arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/jukebox.c, include/args.h, include/physfsx.h, main/game.h, main/inferno.c, main/args.c: Set SOUND_BUFFER_SIZE for SDL_mixer to 1024 to minimize delay; Removed MIDI-existance check and store all music to Music/ subdirectory of writedir - keeps clean if user has tons of levels; Added SDL_mixer command-line help output; Reworked PHYSFSX_init and removed SysUserDir so we can finally read args without a hassle; Stored MAXIMUM_FPS in game.h - where it belongs to main/game.c, main/game.h, main/gamecntl.c, main/gamerend.c: Reworked Pause-screen 20070112 -------- arch/linux/arch_ip.cpp, main/ip_base.cpp, main/ip_base.h, main/ipclient.cpp: Fixed port deformation while sending handshake d2x.ini, arch/sdl/digi.c, arch/sdl/digi_audio.c, arch/sdl/digi_mixer.c, main/inferno.c, main/menu.c, main/args.c: Fixed some command-line options main/game.c: Increased Rear_view_leave_time to 0x4000 include/physfsx.h, main/args.c: Big code refactoring, fixed issue with userdir d2x.ini SConstruct: micro version now specified as the "micro" scons flag arch/sdl/digi_mixer.c, libmve/mveplay.c: various small fixes 20071011 -------- main/movie.c, arch/sdl/digi_mixer.c, libmve/mveplay.c: enabled SDL_mixer sound backend for movie playback. When using it, audio is no longer closed/re-opened with each movie -- hence does not crash with SDL_mixer 1.2.8. 20071009 -------- main/gauges.c, main/network.c, main/scores.c: Moved show_bomb_count() to work with new transparency cockpit layer; Fixed nm_draw_background() for scores and show_game_rules() 20071008 -------- main/game.c, main/gamerend.c, main/inferno.c, main/object.c, main/playsave.c: Improvements for Cockpit mode save; Fixed -pilot switch 20071007 -------- main/collide.c, main/laser.c: Changed collision handling between robots and controlcen; Aligned constant sounds to GameTime; Using turn radius of 0x0024*F1_0 for all homing objects while not aligning smart blobs to movement vector arch/ogl/ogl.c, main/gauges.h: Changed name for Window Boxes - preventing redundancy in Windows build main/newdemo.c: Reset Rear_view at beginning and end of demo playback 20071006 -------- 2d/box.c, arch/ogl/ogl.c, main/game.c, main/gamerend.c, main/gauges.c, main/gauges.h: Not rendering additional transparency cockpit display anymore to ensure compability with custom cockpits; Improved overlay functions for cockpit elements main/kconfig.c, main/kmatrix.c, main/newmenu.c: Fixed size of kconfig_sub_table background; Fixed problems caused by use of load_stars() 20071001 -------- main/gamerend.c, main/kconfig.c, main/titles.c: Added line_scpacing in netgame info screen for every not-connected player to keep strings below player table in fixed position; Fixed memleak in kconfig code; Fixed show_title_screen function to cycle correctly 3 seconds or until broken by keypress d2x.ini, include/args.h, main/inferno.c, main/movie.c, misc/args.c: Moved -nomovies to System Options 20070930 -------- SConstruct, arch/sdl/digi_audio.c: Moved Windows midi functions to digi_audio_* functions 20070929 -------- INSTALL.txt, README.txt, SConstruct, arch/sdl/digi_audio.c, arch/sdl/event.c, arch/sdl/gr.c, arch/sdl/joy.c, arch/sdl/key.c, include/physfsx.h, main/gamecntl.c, main/kconfig.c, main/menu.c, main/newmenu.c, main/scores.c: Updated docs; Removed GP2X support since I won't support this device anymore include/pstypes.h: Changed define path for SDL_types header for win32 20070928 -------- main/gameseq.c, main/inferno.c, main/playsave.c: Removed some strlwr calls for -use_players_dir since it uses Uppercase letters 20070927 -------- main/gamerend.c: Removed line_spacing for not connected players in Netgame info screen 20070926 -------- main/gamerend.c, main/multi.c, main/network.c, main/network.h: Small fixes for new netgame info screen; Fixed PING routines; Once again fixed some newmenu mouse actions 20070925 -------- main/gamecntl.c: Moved some game keys to not apply if Player_is_dead flag is set 20070924 -------- main/newmenu.c, main/weapons.c: Removed key shortcuts for menus; Correctly aligned ScrollBox arrows; ScrollOffset now increments earlier is scrolling is done with keys; Fixed width for menu mouse selections; Fxied mouse selector for submenus in ScrollBoxes; Using defines for Arrow-chars in Weapon reordering 20070921 -------- most files: executable flag removed main/digi.h: restored previous value of SOUND_MAX_VOLUME 20070920 -------- d2x.ini, SConstruct, include/args.h, main/newmenu.c, main/network.c, main/multi.c, main/network.h, main/multi.h, main/inferno.c, misc/args.c: Code-cleanup; Implemented new multi profile feature main/titles.c: Removed briefing text shadows code 20070918 -------- SConstruct, main/inferno.c, main/digi.h, arch/sdl/include/digi_audio.h, arch/sdl/include/digi_mixer_music.h, arch/sdl/include/digi_mixer.h, arch/sdl/digi.c, arch/sdl/digi_mixer.c, arch/sdl/digi_mixer_music.c, arch/sdl/digi_audio.c : huge refactoring of sound system using function pointers, to allow sound backend selection at runtime and provide a common interface (digi.c) include/args.h, main/args.c : handle SDL_mixer-specific args arch/sdl/jukebox.c, arch/sdl/jukebox.c, include/dl_list.h, misc/dl_list.c : added jukebox functionality 20070913 -------- main/game.c, main/gamecntl.c, main/multi.c, main/network.c: Code Re-formatting; Preventing Redundancy in Restricted-game joining; Dumping refused player back to Join-menu; Expanded Game-help screen 20070908 -------- main/gamecntl.c, main/gamerend.c, main/multi.c, main/network.c, /main/network.h: Added complex netgame information screen (key PAUSE), Removed ping commands because ping handled in new screen 20070905 -------- main/multi.c: Color names in Multi-messages to Player- or Team-color 20070903 -------- 2d/font.c, main/escort.c: Fixed embedded color strings 20070901 -------- main/credits.c, main/game.c, main/gameseq.c, main/titles.c: Moved 'if' for HiresGFX to apply after gr_set_mode call; Fixed problems with HiresGFX=0 in Pilot selection and Briefings; Fixed define for CREDITS_FILE so cfexist checks for txb-, not tex-file 20070831 -------- main/gamerend.c, main/gauges.c: HUD alignment improvements 20070829 -------- main/physics.c: Apply BUMP_HACK on walls only 20070828 -------- d2x.ini, 2d/bitblt.c, include/args.h, main/automap.c, main/credits.c, main/gameseq.c, main/inferno.c, main/newmenu.c, main/piggy.c, main/titles.c, misc/args.c: Fixed some mem-leaks; Made show_fullscr() use ogl_ubitmapm_cs(); Removed use of glScissor for menus - using Blitting; Code cleanup SConstruct, arch/ogl/gr.c: If sdl_only=1 do not use Assembly code by default because of poor portability - switch asm=1 necessary now; Removed final remnants of glScissor 20070826 -------- main/game.c, main/multi.c: Improved CPU cycles sleeping for -nicefps - moved out of main frame calc loop and taking care of 10ms timer inaccuracy main/hud.c: Preventing redundancy of doubled messages correctly 20070824 -------- main/game.c, main/gamecntl.c, main/gamerend.c: allow framerate indicator to be toggled in-game again main/mission.c, main/menu.c: Moved piggy init loading for D1 missions to load_mission_d1 20070822 -------- SConstruct: Removed hardcoded CPPPATH for MinGW environment - obsolete since r487 20070821 -------- arch/linux/linuxnet.c, arch/win32/winnet.c, include/ipx.h, main/network.c: Added ipx_check_ready_to_join for driver element CheckReadyToJoin, making sure communication between UDP/IP clients main/ip_base.h, main/ipclient.h: Fixed some compiler warnings 20070816 -------- main/inferno.c: moved first call of gr_set_mode to before font loading, so OpenGL is initialised before it tries to load textures main/fireball.c: doing pick_connected_segment in D1 way - more reliable 20070809 -------- d2x.ini, include/args.h, main/inferno.c, main/menu.c, misc/args.c: Added -ip_hostaddr argument to specify a host IP address via command-line/INI main/menu.c: Fixes and improvements on -ip_hostaddr main/ipbase.cpp, main/ipbase.h, main/ipclient.cpp, main/ipclient.h, main/multi.c: Some debugging-related cleanups, Fixed memleak 20070808 -------- main/config.c, main/game.c, main/menu.c, main/movie.c, main/piggy.c, main/polyobj.c, main/titles.c, main/titles.h: Set default value for Game_screen_mode which is necessary if there's no config file yet; Made resolution switching more failsafe by not allowing resolutions below 320x200; Cleaned up briefings code (I hope so) main/game.c, main/inferno.c, main/menu.c, main/network.c, main/newmenu.c: Fixed excessive use of set_screen_mode; Menu fixes; Better way to determinate Scollboxes 20070727 -------- 2d/font.c, arch/ogl/ogl.c, include/gr.h, main/automap.c, main/config.c, main/credits.c, main/game.c, main/gamefont.c, main/gamefont.h, main/gamerend.c, main/gameseq.c, main/gauges.c, main/hud.c, main/inferno.c, main/kconfig.c, main/kmatrix.c, main/menu.c, main/menu.h, main/movie.c, main/network.c, main/newmenu.c, main/playsave.c, main/scores.c, main/state.c, main/titles.c: Cleanup in Config- and PLX-code; Saving Resolution in Config file so it will apply directly at game-init; Removed seperated resolution mode for menus, SCREEN_MENU now always uses Game_screen_mode; Last FindArg cleanups; Removed MenuHires(Available) and FontHires(Available) and replaced with HiresGFX(Available) to make a more common way to determinate if Hires data is used or not (interactive Demo); Improved support for Interactive Demo main/gamecntl.c, main/menu.c, main/songs.c, main/songs.h: Control Redbook activity with GameArg.SndEnableRedbook only 20070723 -------- arch/ogl/gr.c, arch/include/internal.h, arch/ogl/ogl.c, arch/sdl/gr.c, include/args.h, include/ogl_init.h, main/inferno.c, main/args.c: FindArg cleanup - GL-Debug and SDL arguments 20070722 -------- include/args.h, include/error.h, main/newmenu.c, main/network.c, main/inferno.c, main/menu.c, main/gamerend.c, main/automap.c, main/game.c, main/game.h, main/gamecntl.c, misc/args.c: Code cleanup and small fixes main/collide.c, main/newmenu.c, main/object.c, main/physics.c, main/weapon.c, main/weapon.h, main/gameseq.c, main/laser.c, main/kconfig.c, main/gamecntl.c: Removed old Tactile-code since ForceFeedback is currently out of question main/multi.h, main/state.c: Deactivated Multisave feature as default (multi.h define) - broken, not sure if it's worth to fix arch/linux/hmiplay.c, arch/ogl/sdlgl.c, include/args.h, include/digi.h, main/digiobj.c, main/inferno.c, main/ipserver.cpp, main/network.c, main/piggy.c, main/polyobj.c, main/slew.c, misc/args.c: Even more FindArg cleanups 20070718 -------- SCsonstruct, 2d/palette.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/sdl/gr.c, include/args.h, include/gr.h, include/ogl_init.h, include/palette.h, main/game.c, main/inferno.c, main/movie.c, main/render.c, main/text.c, misc/args.c: Cleaned up more FindArg's - general Debug Options; Cleanups include/args.h, include/u_mem.h, main/bmread.c, main/inferno.c, mem/mem.c, misc/args.c: Cleanups 20070716 -------- d2x.ini, arch/ogl/gr.c, arch/ogl/ogl.c, arch/ogl/include/internal.h, arch/sdl/gr.c, include/args.h, include/gr.h, include/ogl_init.h, main/automap.c, main/game.c, main/game.h, main/gamecntl.c, main/gamefont.c, main/gauges.c, main/inferno.c, main/menu.c, main/movie.c, main/newmenu.c, main/titles.c, misc/args.c: Cleaned up more FindArg's - (most important) OpenGL Options main/game.c: Fixing duplicated gr_toggle_fullscreen() main/cntrlcen.c, main/game.c, main/game.h, main/gamerend.c, main/laser.c: Removed unused RealFrameTime; Removed FPS-dependent Homing-tracking code d2x.ini, arch/linux/linuxnet.c, arch/win32/winnet.c, include/args.h, main/game.c, main/gamecntl.c, main/hud.c, main/inferno.c, main/ip_base.cpp, main/ipclient.cpp, main/multi.c, main/network.c, misc/args.c: Cleaned up more FindArg's - Networking Options; Some fixes 20070715 -------- Sconstruct, d2x.ini, arch/sdl/mixdigi.c, arch/sdl/rbaudio.c, arch/win32/midi.c, include/args.h, include/physfsx.h, main/ai2.c, main/bmread.c, main/config.c, main/digi.h, main/digiobj.c, main/game.c, main/inferno.c, main/menu.c, main/movie.c, main/multi.c, main/piggy.c, main/songs.c, misc/args.c: Cleaned up more FindArg's - Sound Options main/piggy.c: use EdiMacData, not SysMacData (compiler error) d2x.ini, arch/sdl/gr.c, arch/ogl/gr.c, include/args.h, main/automap.c, main/automap.h, main/collide.c, main/collide.h, main/config.c, main/game.h, main/gamecntl.c, main/gauges.c, main/gauges.h, main/inferno.c, main/movie.c, main/movie.h, main/playsave.c, misc/args.c: Cleaned up more FindArg's - Graphics Options 20070714 -------- SConstruct, d2x.ini, arch/sdl/init.c, arch/sdl/joy.c, include/args.h, include/physfsx.h, main/config.c, main/game.c, main/game.h, main/gamerend.c, main/gameseq.c, main/hud.c, main/inferno.c, main/kconfig.c, main/laser.c, main/menu.c, main/multi.c, main/newdemo.c, main/newmenu.c, main/piggy.c, main/playsave.c, main/playsave.h, main/state.c, main/state.h, main/titles.c, misc/args.c: Placing FindArg calls to seperated function, putting variables to a struct - frist step, not finished, yet; Large code cleanup 20070629 -------- main/playsave.c, main/titles.c: using gr_flip() with title screens 20070628 -------- main/game.c, main/newdemo.c: fixing compiler warning, show up HOARD textures in demo playback 20070616 -------- main/newmenu.c: adjusted size of Inputbox; code cleanup for saving/restoring state; also display savegame thumbnail when saving game 20070615 -------- SConstruct, arch/sdl/digi.c: complete removal of hmiplay-code usage 2d/bitblt.c, arch/ogl/ogl.c, ogl_init.h, main/gamerend.c, main/newmenu.c, main/state.c: small code cleanup; improved texture caching in menus to save RAM 20070614 -------- 2d/font.c, libmve/decoder16.c, main/object.c, main/piggy.c, main/polyobj.c, main/render.c, mem/mem.c: using size_t when it comes to integer to pointer conversions main/game.c, main/gamecntl.c, main/gamepal.c, main/gamerend.c, main/gauges.c, main/hud.c, main/inferno.c, main/kconfig.c, main/menu.c, main/playsave.c: fixed axis direction for vertical and sideways thrust time; fixed y-Offset for mouse selection in kconfig_sub; removed (useless) Shrink/Grow window feature to clean code a bit; improved grabmouse so mouse is always released in non-SCREEN_GAME modes 20070611 -------- 2d/bitblt.c, arch/linux/hmiplay.c, arch/linux/ipx_bsd.c, arch/linux/ukali.c, libmve/decorder16.c, main/fvi.c, main/gameseq.c, main/newdemo.c, main/newmenu.c, main/object.c, main/playsave.c, main/render.c: fixed a bunch of compiler warnings arch/include/mouse.h, arch/sdl/mouse.c, arch/win32/include/mouse.h, arch/ogl/gr.c, include/palette.h, main/bmread.c, main/credits.c, main/desw.h, main/gamepal.h, main/gamesave.c, main/gameseq.c, main/inferno.c: fixed more compiler warnings 20070610 -------- arch/carbon/conf.h, SConstruct: fix Mac errors involving use of 'VERSION' arch/linux/arch_ip.cpp, main/ip_base.cpp, main/ipclient.cpp, main/netmisc.h: fix more Mac errors for new UDP/IP 2d/bitblt.c, 2d/font.c, 2/rle.c, arch/ogl/gr.c, arch/ogl/internal.h, arch/ogl/ogl.c, include/gr.h, include/ogl_init.h, include/rle.h, main/game.c, main/gamerend.c, main/gauges.c, main/render.c, main/titles.c: introduced new bitmap flag to draw cockpit bitmap with transparency; draw transparent cockpit bitmap over gauges to make it more pixel-correct; code cleanups 20070601 -------- main/menu.c, main/netmisc.h, main/network.c, main/newmenu.c: improved pixel-correct (almost) scaling of menus; new Netgame info screen which can show up necessary game rules 20070530 -------- d2x.ini, SConstruct, arch/linux/arch_ip.cpp, arch/linux/linuxnet.c arch/linux/ukali.c, arch/linux/include/ipx_drv.h, arch/win32/arch_ip.cpp, arch/win32/winnet.c, arch/win32/ipx_drv.h, arch/win32/include/ipx_drv.h, main/ip_base.cpp, main/ip_basec.h, main/inferno.c, main/ipbase.h, main/ipclient.cpp, main/ipclienc.c, main/ipclient.h, main/menu.c, main/network.c, main/playsave.c, main/vers_id.h: Removed old UDP/IP and MCAST4 code; Implemented online-capable UDP/IP interface 20070527 -------- include/cfile.h, main/inferno.c, main/mission.c, main/movie.c: add add_to_end parameter to cfile_init, allowing custom MIDI music to be found in an add-on hog arch/sdl/mixmusic.c: look for music files in "Music" dir, store MIDI's in "Music/" to better support custom MIDI music main/mission.c, main/mission.h: close add-on hog when loading another mission, so the add-on hog's custom MIDI music isn't played when playing the built-in mission 20070523 -------- arch/ogl/gr.c: make sure gl functions are not called before OpenGL is initialised, when fullscreen switching 20070522 -------- SConstruct: Added conditions to add compiler/linker flags from user's environemnt if they have any set. main/gameseq.c, main/state.c: make sure the right slot is saved to, and it shows the save screen if appropriate, when using fast save (F6) 20070521 -------- ui/window.c: use new 3 argument mouse_get_delta to avoid compiler errors d2x.ini, main/cntrlcen.c, main/gameseq.c, main/inferno.c, main/multi.c, main/newmenu.c, main/playsave.c, main/playsave.h, main/state.c, main/state.h: add use_players_dir argument, which puts player files and saved games in Players subdirectory, like original Mac D2 folder layout 20070516 -------- include/cfile.h, include/physfsx.h, main/bm.c, main/mission.c, main/piggy.c: allow built-in data files to go in the 'Data' directory, like original Mac D2 folder layout 20070516 -------- main/game.c, main/inferno.c, main/newmenu.c: free grabbed mouse in Demo Playback; improved Player-files deletion 20070514 -------- SConstruct, arch/sdl/init.c, arch/sdl/joydefs.c, arch/sdl/mouse.c, arch/include/mouse.h, include/error.h, main/config.h main/game.c, main/gamecntl.c, main/inferno.c, main/kconfig.c, main/kconfig.h, main/newmenu.c, main/newmenu.h, main/playsave.c, main/text.h: Added config field to map a Mouse Axis/Wheel to cycle Primary and Secondary weapons; lots of controls-related code cleaning main/laser.c: fixed speeding bug in homing system main/game.c: make sure Game_window_w/h is always set to a valid value in every cockpit mode 20070512 -------- main/endlevel.c: Changed RAND_MAX to D_RAND_MAX in vector multipler so that resulting scale equals something logical. Fixes explosions/attached sound when chasing player during endlevel tunnel exit main/switch.c: Added condition so that sounds keep playing through exit sequence when exiting a D1 level 20070511 -------- main/movie.c: if movielib isn't found in requested resolution, do NOT select other version, since the game is unable to determinate to switch correctly - instead skip playback in that case 20070510 -------- main/gameseq.c: moved load_palette() call in StartNewLevelSub() to show HOARD textures and bitmaps correctly in OGL main/inferno.c: read -pilot arg with and without filename extension 20070509 -------- arch/ogl/gr.c, main/gamecntl.c, main/newmenu.c: update viewing values at Fullscreen Toggle; added Fullscreen Toggle to Menus and Demo Playback 2d/tmerge.c, tmerge_a.asm: fixed Assembler Compile Build error 20070506 -------- main/titles.c: removed unnecessary gr_set_mode() call causing annoying resolution change (hopefully) 20070505 -------- main/gameseq.c: fixed broken Textures for Custom levels caused by load_palette() call 20070503 -------- CHANGELOG.txt, COPYING.txt, INSTALL.txt, README.txt: updated docs SConstruct: Version-Tag 0.52 20070502 -------- main/gauges.c: resolved some overlapping HUD elements main/game.c: rev432 revisited - do not send multi De-Cloak packet in Demo Playback 20070427 -------- main/game.c: removed FrameTime limiter since it is only messing if 150FPS or more is reached 20070425 -------- arch/cocoa/tool_bundle.py, SConstruct: add Mac OS X support to SConstruct 20070421 -------- main/hud.c: prevent string placeholders in HUD Messages which may crash the game 20070420 -------- main/laser.c: made smart blobs easier to dodge main/kconfig.c: increased offset to detect movement on Joystick axis for mapping function 20070415 -------- main/newmenu.c: only draw copyright stuff if there is really the menu background (not being changed by draw_stars()) d2x.ini, arch/sdl/rbaudio.c, main/config.c, main/inferno.c, main/menu.c, main/songs.c: removed -nocdrom argument, only use Redbook audio if specified with -redbook main/multi.c: forbid % to read into multi messages to not mess up the string 20070414 -------- main/kconfig.c, main/kmatrix.c, main/newmenu.c, main/scores.c, main/titles.c: introducing kconfig_sub_draw_table() making it possible to redraw configuration tables with OGL swapping and clearing; increased timer_delay for menus and briefings to save more CPU usage main/escort.c: making GuideBot Text color palette independent main/gameseq.c, main/switch.c: fixing D1 Secret Level routines (thanks to xatmes) main/game.c, main/gauges.c: removed use of VR_render_buffer (almost completly) 20070409 -------- arch/carbon/conf.h, include/pstypes.h: move determination of WORDS_BIG_ENDIAN to pstypes.h as SCons can't do it (as far as I know). SCons doesn't make conf.h arch/carbon/SDL_main.c, arch/cocoa/SDLMain.m, arch/dos/digimm.c, arch/include/gp2x.h, arch/ogl/sdlgl.c, arch/sdl/digi.c, arch/sdl/event.c, arch/sdl/gr.c, arch/sdl/init.c, arch/sdl/joy.c, arch/sdl/key.c, arch/sdl/mouse.c, arch/sdl/rbaudio.c, arch/sdl/timer.c, include/cfile.h, include/error.h, include/hmp2mid.h, include/physfsrwops.h, include/physfsx.h, libmve/mve_main.c, libmve/mveplay.c, main/config.c, main/console.c, main/gamecntl.c, main/inferno.c, main/newdemo.c, main/newmenu.c, main/newmenu.h, main/playsave.c, misc/hmp2mid.c, misc/ignorecase.c, ui/file.c: include SDL/SDL.h for all platforms and physfs/physfs.h for Mac OS X to avoid having to add some hard-coded include paths 20070407 -------- main/newmenu.c: hide cursor after newmenu_get_filename() 20070406 -------- SConstruct: some help correction 20070405 -------- arch/dos/gr.c, arch/ogl/gr.c, arch/sdl/gr.c, main/game.c, main/gameseq.c, main/inferno.c, main/menu.c, main/playsave.c, main/screens.h: resolution variable cleanup - remove VGA_current_mode, VR_screen_mode and VR_render_buffer[0].cv_bitmap.bm_w/h (Game_screen_mode is the actual resolution put in an int, not an index) SConstruct: BINARY_SUBDIR should be bin/, not games/ 20070404 -------- main/gauges.c: fixing Alt-HUD Y-Offset for Multi-Games main/newdemo.c, main/newmenu.c: clear HUD-Messages if a Demo starts so old messages do not appear; also set gr_palette_load() in nm_draw_background1 so palette resets if Demo-playback is cancelled arch/linux/ipx_udp.c, arch/win32/ipx_udp.c: fixed typo in default broadcast main/game.c: extend show_help() with some netgame commands main/mission.c: set enhaced-flag a bit earlier so D1 missions do not get messed up after an enhanced mission had been played main/inferno.c, main/menu.c: improved Autodemo-feature - less code, activate AFTER pilot is selected to make sure resolution and player-file operations do not mess up main/gamerend.c, main/gameseq.c, main/newmenu.c: close menu with boxed message; improved palette reloading; fixed selected item for restore game dialog 20070403 -------- main/newdemo.c: fixed seek errors and data types in newdemo_goto_end() 20070402 -------- main/network.c, main/newmenu.c: palette reloading sets at every newmenu_close() 20070401 -------- main/newmenu.c: moved gr_palette_load() in nm_draw_background so it always does apply and resets step-ups properly main/game.c, main/game.h, main/gamecntl.c, main/gameseq.c, main/gauges.c: remove 'extern int last_drawn_cockpit[2]' since it's now a single int (not an array), fixing memory corruption (whoops!!) main/automap.c: merge and move automap border drawing code to draw_automap, so it could be used to draw the automap again just before showing a dialog box 20070331 -------- main/gamecntl.c, main/newmenu.c, main/titles.c: move variable declarations to the top for non-gcc compilers (like MrC for MPW) main/mission.c, main/movie.c: improved HAM support with enhanced-flag detection and fixed Extra-Movie init in load_mission(); close Extra-Movies according to movielib_files d2x.ini, main/game.c, main/game.h, main/inferno.c: a switch to disable timer_delay in calc_frame_time - may be used if game runs a bit choppy 20070329 -------- main/gamerend.c, main/network.c, main/newmenu.c, main/titles.c: palette-related fixes for Doublebuffered menus; fixes for SDL-build 20070326 -------- main/gamecntl.c, main/menu.c: unbind Minus/Equal from Shrink/Grow-window - only use ALT-F9/F10 to get richt with all keyboard layouts; Always allow screen resolution switching, even if selected is not supported to ensure Multi-Monitor support 20070325 -------- main/movie.c, main/network.c, main/titles.c, main/wall.c: do not close movies for now to prevent leaks (PhysFS should do that); fixed crash with malformed N_players if Netgame start is forced in DEBUG; improved briefing screen loading and delay; made wall warning-message not show up in NDEBUG (non-critical) main/gamecntl.c, main/hud.c: allow Quick-Exit with SHIFT+ESC; blocking "SUPER LASER MAXED OUT!" redundancy in stdout 20070324 -------- main/mission.c: remove add_alternate_hogfile because it couldn't close the main hog file (it's normally in use) 20070324 -------- main/game.c, main/gamerend.c, main/gauges.c, main/hud.c, main/inferno.c, main/menu.c, main/newmenu.c, main/screens.h: draw mine view directly to screen with SDL Video, no using an offscreen buffer (will use SDL_Flip later) 20070322 -------- SConstruct, arch/ogl/gr.c, arch/ogl/ogl.c, include/ogl_init.h, main/credits.c, main/escort.c, main/game.c, main/gamecntl.c, main/gamerend.c, main/inferno.c, main/kconfig.c, main/kmatrix.c, main/menu.c, main/movie.c, main/netlist.c, main/newmenu.c, main.polyobj.c, main/scores.c, main/state.c, main/titles.c: Use Doublebuffer in OGL for all parts of the game and properly redraw elements, fixed Profiler build main/inferno.c: must not allow single-buffering for OGL 20070321 -------- 2d/canvas.c, arch/dos/gr.c, arch/ggi/gr.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/sdl/gr.c, arch/svgalib/gr.c, arch/win32/gr.c, arch/win32/win32.c, include/gr.h, include/ogl_init.h, main/automap.c, main/desw.h, main/escort.c, main/game.c, main/game.h, main/gamecntl.c, main/gamerend.c, main/gauges.c, main/hud.c, main/screens.h: add gr_flip, allowing significant cleanup including the moving of gr_show_canvas, Pages and VR_screen_pages to arch/dos/gr.c arch/ogl/gr.c, main/game.c, main/gamerend.c, main/gauges.c, main/hud.c, main/inferno.c, main/screens.h: remove final remnants of VR_current_page and VRF_USE_PAGING, also allowing -nodoublebuffer switch for all platforms. Fix single buffering for d2xgl 20070306 -------- main/kconfig.c, main/kconfig.h, main/newmenu.c, main/scores.c: implemented expanded Joystick configuration panel (Thanks xatmes); corrected draw functions for kconfig_sub() and Scoreboard to show them correct in non 4/3 aspects; corrected Close-boxes for Mouse Menu control 20070304 -------- main/mission.c: improved Error-handling for starting a mission, making the game not crash if Level file is not found main/automap.c, main/guages.c, main/menu.c, main/network.c: improved create_name_canv(); cleaned up hud_show_weapons_mode(); fixed palette loading in RegisterPlayer(); only show newline in network_get_game_params() if MenuHires arch/linux/hmiplay.c, main/hud.c: removed WANT_AWE32 flag - too buggy; scaled space between Hud-messages; block Hudlog output messages beginning with you (your ... maxed out, you already have ...) arch/sdl/joydefs.c, main/config.h, main/playsave.c: make Joystick Deadzone save in PLX file (Thanks xatmes) 20070303 -------- d2x.ini, main/inferno.c, main/newmenu.c: some menu fixes 20070228 -------- main/game.c: newdemo-related fixes 20070226 -------- arch/ogl/ogl.c, main/endlevel.c, main/object.c: improved DepthTest, fixing Clipping bugs 20070220 -------- arch/sdl/key.c: Added ENTER as Game key texmap/scanline.c: removed unreliable gr_fade_table check in c_tmap_scanline_per() 20070219 -------- arch/sdl/gr.c: SDL compile fix main/hud.c: block "You already have"-messages in HudLog output; make 'Press any key ...'- and 'Demo recording' messages not overlap main/ai.c: amd64 fix 20070218 -------- include/3d.h: use generic 'struct object' instead of including object.h, so gcc4.0 with Xcode doesn't complain about FSCALE being passed to CLIPLINE in 2d/line.c (strange indeed) 20070217 -------- d2x.ini, main/inferno.c, main/laser.c: added Alex' patch to add FPS independent and physics homing missiles - also implemented command-line to switch back to legacy homers 20070214 -------- Makefile, SConstruct, arch/sdl/mixdigi.c, arch/sdl/mixmusic.c, include/hmp2mid.h, misc/hmp2mid.c: Going back to PHYSFS_file type (lower-case 'f') for compatibility; Turning off sound debug flags; Optional micro versions (see SConstruct); Makefile emulation for SCons 20070211 -------- d2x.ini, main/collide.c, main/collide.h, main/fireball.c, main/inferno.c, main/object.c: improved debris random stuff, added -persistentdebris feature 20070209 -------- arch/ogl/gr.c, arch/sdl/gr.c, include/gr.h, main/inferno.c: set MENU_SCREEN_MODE at init to set movie according to -menu parameter and also prevent unnecessary screen changes d2x.ini, main/inferno.c: added -gl_voodoo to OpenGL command-line switches and INI SConstruct: added default lflag path for *NIX build 20070208 -------- main/newdemo.c: fixed demo playback Afterburner gauge and Primary weapon ammo info main/game.c, main/game.c, main/movie.c, main/movie.h: since Movies are initiated once in runtime, indroduced SCREEN_MOVIE to set desired movie resolutions seperatly from menu or game resolution main/gauges.c: position alignment for alt-hud2 to prevent overlay with extra views; created offset for LOCK message string if demo record or playback 20070207 -------- main/movie.c: close EXTRA_ROBOT_LIB correctly iff/iff.c: amd64 fixes arch/linux/ipx_udp.c, arch/win32/ipx_udp.c: on-screen network error messages 20070206 -------- 2d/bitblt.c, main/automap.c, main/titles.c: force show_fullscreen to software drawing if image is bigger than screen, showing Automap background in low resolutions via software, removed obsolete robot briefing fix in OGL, code cleanup 20070205 -------- main/menu.h: make sure Menu_pcx_name gets loaded correctly if resolution is lowres main/automap.c: fixed secret level name canvas 20070202 -------- main/gauges.c: corrected Y alignment of hud_show_homing_warning arch/ogl/ogl.c: don't draw bombs with transparency even if -gl_transparency is enabled main/state.c: complete removal of broken Autosave feature 20070131 -------- main/object.c: If bright ships are enabled cast F1_0*2 light instead of F1_0 which is too dark 20070130 -------- d2x.ini, arch/ogl/gr.c, arch/ogl/ogl.c, include/3d.h, main/inferno.c, main/object.c: added transparency effects for some bitmaps like explosions, powerups, weapons, etc. - to enable with -gl_transparency arch/linux/ipx_mcast.c, arch/linux/ipx_udp.c, arch/win32/ipx_mcast.c, arch/win32/ipx_udp.c: corrected UDP/IP error output main/inferno.c: set movie resolution correctly when no parameter is given - referring to rev365 dxx-readme.txt, SConstruct: preparations for v0.51 release 20070129 -------- main/gamecntl.c: fixed energy->shield transfer message output showing 'No transfer: Shields already at max' everytime if there is enough energy 20070127 -------- main/credits: use ogl_ubitmapm_cs instead of show_fullscr in OGL to render faster main/gamerend.c: corrected position of multi-message entry string 20070126 -------- main/credits.c: improved credits scrolling - not that smooth anymore, but less CPU intense dxx-readme.txt, dxx-compile.txt: improvements on dxx-readme's 20070125 -------- arch/ogl/gr.c, include/gr.c, main/game.c: write screenshots to subdirectory main/inferno.c: improved resolution-check method - removed old code main/gauges.c: don't display lives and score if hud message is longer than 40 chars. preventing overlay of message and lives/score 20070122 -------- SConstruct, arch/linux/ipx_udp.c, arch/ogl/gr.c, arch/ogl/ogl.c, arch/win32/init.c, arch/win32/ipx_udp.c, include/pstypes.h: cfile/cfile.c: special WINDOWS fixes and cleanups, corrected automated UDP broadcast arch/include/key.h, main/game.c: fixed PRINTSCREEN key for WINDOWS main/kmatrix.c: fixed multi summary reactor lifetime refresh main/escort.c: made thief messages brighter 20070120 -------- main/automap.c: for OGL don't display background bitmap if screen height < 400 because it won't fit - just draw grey; adjusted level name alignment in secret levels main/render.c: removed inaccurate 4D hack d2x.ini, main/inferno.c: corrected -maxfps switch: MAX_FPS is 80, not 100 d2x.ini, main/inferno.c, main/network.c: made short packets default on. long packets are still available but in general cause more problems than short main/network.c: additional newline line in netgame menu - looks better arch/ogl/ogl.c: in g3_draw_sphere align rad according to canvas so it is always in round shape 20070119 -------- arch/ogl/gr.c: gr_upixelc now able to scale pixels to current resolution 20070118 -------- main/gauges.c: draw bomb count correctly in CM_FULL_SCREEN ... finally main/laser.c: made Omega selectable even if it has no energy left and can't fire main/kconfig.c: prevent changing weapons if automap is active main/inferno.c, main/gameseq.c: only read and write lowercase pilots - prevents mistakes in -pilot option as well as multisaves 20070117 -------- main/endlevel.c: draw spheres instead of pixels in draw_stars to show correctly in OGL 20070114 -------- main/hud.c: moved hudlog printf's so they do not spam stdout with redundant messages 20070113 -------- main/object.c: removing the !dead statement (leftover from WraithX Deathcam) from object_move_one() so the function will return correctly if player dies instead running further and creating invalid code and crashes arch/cocoa/d2x-rebirth.icns: update to Novacron's 128x128-bit icon main/kconfig.c: do not select weapon if guide-bot shortcut has done and weapon key is mapped from 0 to 9 d2x.ini, main/inferno.c, main/movie.c: removed mipmap for movies - makes not a real sense or effect main/gamecntl.c: also use ALT-F9/F10 for demo playback 20070112 -------- main/kmatrix.c: fixed canvas stuff to show summary correctly in OGL, added new strings for CTF and HOARD, code cleanup SConstruct: added NATIVE_IPX and KALINIX to build main/newdemo.c: removed timer_delay from DoJasonInterpolate - caused slowdowns in some demos 20070110 -------- main/kconfig.c, main/newmenu.c: joystick axes can be reassigned; higher offset for axes moving detection; correction for menus that are bigger than screen 20070109 -------- dxx-changelog.txt: added missing changelog entries 20070107 -------- arch/cocoa/d2x-rebirth.icns, d2x-Info.plist: add Mac OS X icon 20061231 -------- main/inferno.c: fix a memory leak that occurs when listing the search paths main/inferno.c: if no Descent 2 hog file is available, generate an error, not a warning main/mission.c: allow an add-on mission to override the built-in hog file, such as the use of custom MIDI tracks 20061230 -------- arch/sdl/mixmusic.c, include/cfile.h, include/hmp2mid.h, misc/hmp2mid.c: use PhysicsFS to write MIDI file, make hmp2mid use PhysicsFS exclusively 20061229 -------- arch/ogl/gr.c, arch/ogl/ogl.c: allocate 'pixels' and 'texbuf' according to current screen resolution, saving over a hundred megabytes of memory 20061228 -------- D2X.make, README: make it easier to build for SDL Video on Mac OS 9, update README dxx-readme.txt: add some useful comments on installation, including specifically for Mac OS 9 D2X.make, texmap/scanline.c, texmap/tmapppc.a: add PowerPC assembly texture mapper (requires PPCAsm, which is for Mac OS 9 only) 20061226 -------- arch/carbon/conf.h, arch/sdl/gr.c, d2x-Info.plist, d2xgl-Info.plist, main/inferno.c, English.lproj/InfoPlist.strings: update version info, use DESCENT_VERSION instead of PACKAGE_NAME D2X.make: disable a heap of warnings that are impractical to fix (eg assignment in an if ()) 20061225 -------- main/titles.c: fix crash where loading screen function is called before video mode is set (when SDL Video is used as well as -notitles) arch/carbon/conf.h, arch/carbon/SDL_main.c: fix compile errors when building on Mac OS 9 using SDL 1.2.10 (conflicting macros, use of putenv) 20061224 -------- arch/ogl/gr.c: use PhysicsFS to check for existing screenshots, previous method may have caused writing over of open screenshots (from D2X CVS) arch/ogl/gr.c: avoid loading OpenGL textures before they have been paged in, bug found by loading Abalyon 5 (from D2X CVS) main/weapon.c: only autoselect a secondary weapon if the player didn't have any of that type before (fix bug #2671) (from D2X CVS) texmap/scanline.c: divide negative light rates of change properly (fix bug #2575) (from D2X CVS) texmap/tmapflat.c: divide negative window x-coordinates properly, fixing random crashes (from D2X CVS) arch/carbon/conf.h: allow universal binaries to be built using Xcode 2.1 or later (from D2X CVS) arch/sdl/digi.c: add MIDI stubs for Mac, it doesn't have the 'real' functions yet arch/sdl/joy.c: use d_strdup instead of strdup to avoid errors when compiling on Mac OS 9, free the joystick button texts when closing main/inferno.c: use strncpy instead of snprintf, MPW on Mac OS 9 doesn't have snprintf main/automap.c, main/gamefont.c, main/newmenu.c, main/state.c, main/titles.c: warning fixes for gcc 4.0 main/playsave.c: make sscanf look for "%i.%i" instead of "v%i.%i" because the 'v' isn't written to file (used to cause D2X for Mac OS 9 to crash), use PHYSFS_delete instead of unlink to be safe include/physfsx.h: chdir to application directory so it uses relative userdir and hogdir paths properly, in Mac OS X it can make the root directory the current one 20061223 -------- main/game.c, main/gamerend.c: small brace tidy up to allow a source code editor to list all the functions (from D2X CVS) 20061219 -------- 2d/rle.c, SConstruct, arch/include/gp2x.h, arch/linux/hmiplay.c, arch/ogl/gr.c, arch/sdl/digi.c, arch/sdl/event.c, arch/sdl/gr.c, arch/sdl/joy.c, arch/sdl/key.c, configure.ac, gp2x/buttonmap.txt, gp2x/dxx-rebirth_buttonmap.pdf, gp2x/notes.txt, include/physfsx.h, main/Makefile.am, main/automap.c, main/config.c, main/game.c, main/gamecntl.c, main/gamerend.c, main/gauges.c, main/inferno.c, main/kconfig.c, main/menu.c, main/movie.c, main/newmenu.c, main/physics.c, main/piggy.c, main/playsave.c, main/scores.c, main/text.c, main/titles.c, maths/fixc.c, texmap/scanline.c: GP2X handheld support; added SConstruct file (MAC support incomplete); code optimisations for software renderer; fixed memleaks 20061212 -------- arch/sdl/mixdigi.c, arch/sdl/mixmusic.c: music volume now properly restored and remembered in D1 and D2, using a static int; removed ugly hack that fixed this bug in D1 (inferno.c, revision 230) 20061123 -------- arch/include/mixmusic.h, arch/sdl/mixdigi.c, arch/sdl/mixmusic.c: SDL_mixer backend implementation files for D2 20061113 -------- include/hmp2mid.h, misc/hmp2mid.c: Providing hmp2mid code, which was previously forgotten when introducing sdl_mixer in r264 20061107 -------- arch/linux/Makefile.am, arch/sdl/Makefile.am, arch/win32/Makefile.am, configure.ac, include/cfile.h, misc/Makefile.am, initial integration of SDL_mixer sound system for Linux 20061102 -------- arch/ogl/gr.c, d2x.ini, include/ogl_init.h, main/gauges.c, main/inferno.c, command-line to set glScissor off if needed arch/include/joy.h, arch/sdl/joy.c: improved joystick code for more buttons 20061101 -------- main/render.c: just turn off detriangulation for OGL 20061031 -------- main/kconfig.c: make sliding use sensitivity main/game.c, main/inferno.c, main/movie.c, misc/args.c, moved some FindArgs to main() so they are not called in the game; added printf for DEBUG to track FindArgs 20061031 -------- d2x.ini, main/inferno.c: removing -cockpit and -hiresfont parameters which actually belong to D1X-Rebirth 20061029 -------- main/render.c: turning detriangulation off by default; not really needed anymore and makes rendering nicer 20061023 -------- /arch/sdl/joy.c: increased "MAX_HATS_PER_JOYSTICK" from 4 to 128 to prevent axes recognition problems /d1x.ini, /main/inferno.c, /main/menu.c: in do_options_menu decreased i by 1 to not show d2x options menu if arg -nod2xmenu is found; added help text; added INI line /arch/ogl/ogl.c: changed ogl_loadtexture to deal with transparent walls /arch/linux/hmiplay.c: added cut_trough(), a clone of stop_all that is called to flush notes while playing a song to improve song switching /arch/ogl/sdlgl.c, /arch/ogl/ogl.c, /main/endlevel.c: added GL functions to fix the portal-bug; added exception boolean value tempNoDepthTest to render d1 endlevel correctly; code reformatting /arch/win32/hmpfile.c, /arch/win32/hmpfile.h, /arch/win32/midi.c, /main/songs.c: midi repeat improvements /arch/ogl/gr.c, /arch/sdl/gr.c, /main/inferno.c, /d2x.ini: added variable aspect function, changed cmd-help, changed ini file /arch/ogl/ogl.c, /main/endlevel.c, /main/gameseg.c, /main/render.c: improved use of Depth Test, added experimental hack for 4D levels; removed two Asserts which fail with 4D levels /main/game.c: added game_flush_input() on automap calls to avaoid control irritations /main/inferno.c: corrected command-line output in inferno.c /dxx-readme.txt: corrected typo /arch/ogl/ogl.c: disabled GL_CULL_FACE at ogl_end_frame to avoid problems with menus after player's death /d1x.ini, /main/inferno.c, /main/menu.c: rejected -nod2xmenu feature /main/gameseg.c: disabled another Assert. commented with FIXME's - debugging if needed /main/inferno.c: made 22k sounds default /arch/ogl/ogl.c, /main/automap.c: show borders in SDL and OGL, optimized and cleaned /2d/font.c, /arch/ogl/ogl.c, /d2x.ini, /include/gr.h, /include/ogl_init.h, /main/automap.c, /main/gamefont.c, /main/inferno.c, /main/kconfig.c, /main/menu.c, /main/newmenu.c, /main/newmenu.h, /main/scores.c, /main/state.c, /main/titles.c: made fonts scalable, added command-line to enable fixed fonts, made savegame thumbs scalable, reworked menu borders, new way to display level info in automap to get right with scaled fonts. additionally layed out special characters to newmenu.h /arch/ogl/ogl.c, /main/credits.c, /main/polyobj.c, /main/titles.c: new code for ogl_offscreen_render, used it to reduce flickering in credits /arch/ogl/gr.c, /arch/sdl/gr.c, /d2x.ini, /main/automap.c, /main/game.c, /main/gamecntl.c, /main/gamerend.c, /main/gameseq.c, /main/gauges.c, /main/inferno.c, /main/kconfig.c, /main/menu.c, /main/movie.c, /main/newmenu.c, /main/playsave.c, /main/scores.c, /main/screens.h: some fixes for menus and automap; new aspect code; improved code to scale window for cockpits; introducing new variable in playsave.c to store game resolution and saving Game_window_h/h again properly - fixes bugs with screwed resolutions; making menus in game-resolution as default and re-activating old command-line arg '-menux' to scale menus /2d/bitblt.c, /arch/ogl/gr.c, /main/game.c, /main/gamerend.c, /main/gameseq.c, /main/gauges.c: scalable HUD, improvements for HUD and cockpits, cleaner code, fixes to get SDL renderer working again /arch/sdl/joy.c, /arch/sdl/joydefs.c: added joystick deadzone feature /main/inferno.c: saving config files in home directory /main/slew.h: fix error when building editor with RELEASE (d2x-cvs takeover) /arch/carbon/descent.r: don't allow MPW build to run in OS X (d2x-cvs takeover) /main/laser.c, /main/object.c: fix crash when a robot's guided missile explodes (d2x-cvs takeover) /d2x.xcode/project.pbxproj: add references to headers in main for SCM and batch find (d2x-cvs takeover) /main/inferno.c, /main/multi.c, /main/multi.h: move hoard data saving from main to save_hoard_data (d2x-cvs takeover) /main/inferno.c, main/titles.c, main/titles.h: move titles, loading screen and order form showing to titles.c (d2x-cvs takeover) /include/physfsx.h, /main/inferno.c: move PhysicsFS initialisation, search path setup and argument reading to physfsx.h (d2x-cvs takeover) /ChangeLog: Update /main/game.c, /main/inferno.c, /main/menu.c, /main/playsave.c: removing unnecessary stuff from game_init_render_buffers; better resolution handling; storing resolution stuff in PLX file (Thanks to Hans de Goede and Chris Taylor)" /arch/sdl/joydefs.c, /main/config.h, /main/gameseq.c, /main/kconfig.c, /main/newmenu.c, /main/playsave.c: added new control type: Joystick & Mouse (Thanks to The_Lion) /main/credits.c: code cleanup /2d/font.c, /arch/ogl/ogl.c, /include/ogl_init.h, /main/automap.c, /main/gamerend.c, /main/gauges.c, /main/newdemo.c, /main/state.c: corrected demo-related font positions; fixed window view glitch in demo playback; merged ogl_ubitmapm_cs and ogl_ubitmapm_cf /2d/font.c, /main/gamecntl.c, /main/menu.c: cleaned up options menu and removed 'd1x options' because not really necessary anymore /arch/ogl/gr.c, /arch/sdl/gr.c, /arch/sdl/joy.c , /main/gamerend.c, /main/gauges.c, /main/hud.c, /main/menu.c: print joystick dialog to stdout; print time with hud messages; fixing some graphical glitches; repaired brightness slider (oops); code cleanup /2d/font.c, /arch/ogl/gr.c, /arch/ogl/internal.h, /arch/ogl/ogl.c, /arch/ogl/sdlgl.c, /main/gamecntl.c, /main/inferno.c: introduced FSAA; fixed fullscreen toggle glitches; adjusted OGL_TEXTURE_LIST_SIZE and OGLTEXBUFSIZE; code cleanup; fixed memleak in game pause; restored font.c (oops) /main/movie.c: made file extension for TXB files lowercase to match filename case itself. makes easier to use external files /arch/ogl/gr.c, /main/inferno.c, /main/menu.c, /main/newmenu.c, /main/vers_id.h: if player is deleted also delete PLX file; removed date strings, not necessary; added Menu_special /configure.ac, /Makefile.am: changed build target to 'rebirth'; changed version string; preparations for v0.50 release /main/gauges.c: corrected position of shield/energy numbers if 200 /main/movie.c: improved code to show scaled movies /arch/ogl/gr.c, /arch/ogl/ogl.c, /arch/ogl/sdlgl.c, /include/gr.h, /main/inferno.c: re-enabled SDL_SetGammaRamp; removed FSAA because no function on all platforms; fixed offscreen render; better restriction to show menus ingame /main/render.c, /main/wall.c: improved 4D room detection /arch/ogl/gr.c: switching SDL gammaramp off by default because uses too much CPU /main/hud.c: aligned 'press any key...' message on hud /main/credits.c: make scrolling smoother by changing time_delay /main/gauges.c: fixes for alt huds /main/gauges.c, /main/titles.c: don't show alt hud while guilded missile view; removed unnbecessary delay in show_char_delay to make robo movies smoother /main/menu.c: print warning if resolution is set too high and don't change after all /arch/ogl/gr.c, /main/lighting.c, /main/state.c: fixing OGL compile bug; fixing calculation of object light before and after restoring a saved game /arch/sdl/joydefs.c, /main/config.h: re-activated Weapon Keys menu - aka D2X keys /arch/sdl/joy.c, /main/inferno.c: fixing mem corruptions while closing joysticks; removed Joystick calibration which should be unnecessary with SDL /arch/ogl/ogl.c: Fix for inherent limitation in pow2ize() and wrong description thereof /d1x.ini, /main/inferno.c: cleaned up command-line help; removed old/redundant/unfunctional options; improved code to read -pilot argument /arch/ogl/gr.c: make write_bmp use PhysFS /main/credits.c: adjusted credits scroll speed with MenuHires /include/loadgl.h, /main/gauges.c: introducing draw_wbu_border to draw rounded weapon boxes with glScissor /main/game.c: removed calibrate joystick line from help menu /arch/ogl/ogl.c: made lines width scale to resolution; fixed compiler warnings /main/object.h: fixed compiler warnings in object header /main/inferno.c, /main/kconfig.c: using global variable for sp-mouselook to save CPU usage 20060416 -------- /main/newmenu.c, /main/gauges.c, /main/gameseg.c, /main/menu.c, /main/gamesave.c, /main/gamerend.c, /include/strutil.h, /main/bm.c, /main/gamepal.c, /main/piggy.c, /misc/strutil.c, /main/object.c, /main/render.c, /main/editor/kfuncs.c, /main/editor/med.c: implementation of current d2x-cvs patches /main/automap.c: FIX: deleting marker dialog in automap causes major graphical issues in automap /main/movie.c: more original look of scalable movies /texmap/tmapppro.S: compile-time bug with ASM /arch/ogl/ogl.c, /arch/ogl/include/ogl_init.h, /2d/bitblt.c, /main/menu.c, /main/game.c, /main/gamerend.c, /main/gauges.c: scalable cockpits /main/gamesave.c: FIX: d2x restores window size wrong after restart /main/gauges.c: FIX: if "you already have 20 concussion missles!" is displayed, lives and score disappeared /main/gauges.c: better alt-huds, alt-huds in cockpit /arch/ogl/ogl.c: fixed renderstats option /main/physics.c: allow asserting objet to none if player is dead - fixes some random crashes /main/credits.c: new credits code /main/gauges.c: no use of fading if alt huds and no alt hugs if missile view /arch/ogl/gr.c: FIX: gamma changes change whole screen /arch/sdl/gr.c, /arch/ogl/gr.c, /main/inferno.c: added widescreen aspect with command-line option for SDL and OGL build /main/newmenu.h: possible menu text sring length incrased to 255 /arch/ogl/ogl.c, /include/ogl_init.h, /2d/bitblt.c, /main/movie.c, /main/inferno.c: added mipmap operator to ogl_bitblt_i, added if to MovieShowFrame to switch off movie mipmap if argument -nomoviesmooth given, added command-line option /arch/ogl/gr.c, /main/menu.c: removed fullok hack for fullscreen changing 20060226 -------- /arch/ogl/include/internal.h fixing "OGL: texture list full"-bug /arch/linux/ipx_udp.c, /arch/win32/ipx_udp.c: full broadcast as default in UPD/IP games /configure, /main/vers_id.h: changes in date, version-number /arch/ogl/gr.c: setting gl_reticle as default (if you don't like it, set -gl_reticle 0) /main/gauges.c: fixed alt-hud text positions for gl_reticle /main/menu.c: removed serial connection functions (not really needed anymore) /main/game.c, /main/inferno.c: implementation of menu in gameres /arch/ogl/ogl.c, /main/movie.c: scalable movies /main/menu.c: removed vertigo say for menu_gameres /main/menu.c: load resolution after player is selected /main/game.c, /main/gamecntl.c: new keys to get shrink and grow window functions working /main/automap.c, /main/inferno.c: automap now always in gameres and eat less cpu power /main/credits.c: credits now working correctly with menu_gameres /main/scores.c: fixing frames in scoretable in menu_gameres /main/kconfig.c: fixing frames in controls-config in menu_gameres /main/menu.c: implementation of custom resolutions /main/game.c, /main/menu.c: new calls to get right fonts with new resolutions menus-menu /main/newdemo.c: smoother demo-playback /arch/sdl/digi.c, /arch/linux/Makefile.am, /arch/linux/Makefile.in: implementation for midi on linux /main/inferno.c: fixing possibility for midi-loops after game was killed 20060122 -------- /main/menu.c: removed second resolutions menu /arch/ogl/gr.c: resolution switches now faster in windows (at least as fast as windows is able to) 20060116 -------- /main/inferno.c, /main/gamerend.c: added -fps switch /arch/ogl/gr.c: fix for screenshot function /main/inferno.c, /main/kconfig.c: new function for optional mouselook style feature /arch/ogl/ogl.c: D2X-CVS update - make super transparent textures have alpha /main/titles.c: D2X-CVS update - for Descent 1 briefings, look for briefings no further than NUM_D1_BRIEFING_SCREENS (fix bug #2270) /main/inferno.c: new definition of config dir for linux because multiplatform release, fix for soundloops after game quit (some onboard soundcards) /arch/ogl/gr.c, /main/game.c, /main/menu.c: fix for fullscreen switching in windows /main/game.c, /main/gamecntl.c /main/gameseq.c: resolution fix after pause, secret level messages and guidebot menu /main/mission.h: fix to hold up to 5000 addon levels /main/game.c: made nicefps standard. better gameplay, lesser cpu usage, a little pause in linux for resolution change at new game /main/gamerend.c: fix for guided missle crosshair /main/menu.c: resolutions up to 1600x1200 /arch/ogl/gr.c, /arch/ogl/sdlgl.c: fix for ingame screenshots /arch/include/key.h, /main/game.c: windows fix for PRINTSCREEN key -> is now ALT+P /main/credits.c: fix for crash while credits in higher game resolutions /main/escort.c: fix for linespacing in guidebot-menu /main/inferno.c, /main/gauges.c: added new hud modes /misc/args.c: fix for crashes while using modified d2x.ini various: code cleaning, fixes and additional includes for windows build, restructuration for new multiplatform release 20051025 -------- /main/inferno.c: cleaned up the command-line help, removed inactive/defected functions /main/kconfig.c: improved turn speed on x and y if mouse is used for better/faster control /main/newmenu.c: fixed messageboxes to prevent chrases in automap, secret leves etc /main/menu.c: fix to prevent toggles menu from crashing game README.TXT: removed/changed some kown issues added gentoo and suse 10 to working ditributions added Maystorm to Thanks section Changelog: file created 20050928 -------- README.TXT d2x-install.sh: Added hint to create $HOME/.d2x manually 20050916 -------- initial release /main/gamerend.c: fix for death-sequence and sdl segfault in 320xXXX /main/lighting.c: fix for dark models after loading a game dxx-rebirth-0.58.1-d2x/COPYING.txt000066400000000000000000000062301217717237500164260ustar00rootroot00000000000000The Descent 2 source code was released by Parallax with this license: --------------------------------------------------------------------------- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. We make no warranties as to the usability or correctness of this code. --------------------------------------------------------------------------- The modifications to Descent 2 which make up D2X-Rebirth are covered by the same license as the d1x project, given below. --------------------------------------------------------------------------- D1x License Preamble -------- This License is designed to allow the Descent programming community to continue to have the Descent source open and available to anyone. Original Parallax License ------------------------- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. We make no warranties as to the usability or correctness of this code. ------------------------- The D1x project is the combination of the original Parallax code and the modifications and additions made to source code. While the original code is only under the Original Parallax License the D1x project contains original code that was not made by Parallax. This ADDED and/or CHANGED code has the following added restrictions: 1) By using this source you are agreeing to these terms. 2) D1x and derived works may only be modified if ONE of the following is done: a) The modified version is placed under this license. The source code used to create the modified version is freely and publicly available under this license. b) The modified version is only used by the developer. 3) D1X IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.dxx-rebirth-0.58.1-d2x/D2X.make000066400000000000000000000346561217717237500160260ustar00rootroot00000000000000# File: D2X.make # Purpose: Compile d2x (descent 2 port to Unix) with MPW for Mac OS 9 # Target: D2X # Created: Saturday, June 12, 2004 04:38:06 PM MAKEFILE = D2X.make ¥MondoBuild¥ = #{MAKEFILE} Make blank to avoid rebuilds when makefile is modified ObjDir = ":obj:" Includes = ¶ -i :include: ¶ -i :arch:include: ¶ -i "{CIncludes}SDL:" ¶ -i :arch:carbon: ¶ -i "{CIncludes}" ¶ -i :main: Sym-PPC = -sym on PPCAOptions = {Includes} {Sym-PPC} # Comment out '-d OGL' to build for SDL Video # More to do further down where the PPCLink call is... PPCCOptions = {Includes} -includes unix -prefix conf.h {Sym-PPC} -d HAVE_CONFIG_H -enum int -noMapCR -w 2,7,30,35 -d OGL -d USE_SDLMIXER -d NDEBUG -d RELEASE ### Source Files ### SrcFiles = ¶ :2d:2dsline.c ¶ :2d:bitblt.c ¶ :2d:bitmap.c ¶ :2d:box.c ¶ :2d:canvas.c ¶ :2d:circle.c ¶ :2d:disc.c ¶ :2d:font.c ¶ :2d:gpixel.c ¶ :2d:line.c ¶ :2d:palette.c ¶ :2d:pcx.c ¶ :2d:pixel.c ¶ :2d:poly.c ¶ :2d:rect.c ¶ :2d:rle.c ¶ :2d:scalec.c ¶ :2d:tmerge.c ¶ :3d:clipper.c ¶ :3d:draw.c ¶ :3d:globvars.c ¶ :3d:instance.c ¶ :3d:interp.c ¶ :3d:matrix.c ¶ :3d:points.c ¶ :3d:rod.c ¶ :3d:setup.c ¶ :arch:carbon:SDL_main.c ¶ :arch:ogl:gr.c ¶ :arch:ogl:ogl.c ¶ :arch:sdl:digi.c ¶ :arch:sdl:digi_audio.c ¶ :arch:sdl:digi_mixer.c ¶ :arch:sdl:digi_mixer_music.c ¶ :arch:sdl:event.c ¶ :arch:sdl:gr.c ¶ :arch:sdl:init.c ¶ :arch:sdl:joy.c ¶ :arch:sdl:jukebox.c ¶ :arch:sdl:key.c ¶ :arch:sdl:mouse.c ¶ :arch:sdl:rbaudio.c ¶ :arch:sdl:timer.c ¶ :arch:sdl:window.c ¶ :iff:iff.c ¶ :libmve:decoder16.c ¶ :libmve:decoder8.c ¶ :libmve:mvelib.c ¶ :libmve:mveplay.c ¶ :libmve:mve_audio.c ¶ :main:ai.c ¶ :main:ai2.c ¶ :main:aipath.c ¶ :main:automap.c ¶ :main:bm.c ¶ :main:cntrlcen.c ¶ :main:collide.c ¶ :main:config.c ¶ :main:console.c ¶ :main:controls.c ¶ :main:credits.c ¶ :main:crypt.c ¶ :main:digiobj.c ¶ :main:effects.c ¶ :main:endlevel.c ¶ :main:escort.c ¶ :main:fireball.c ¶ :main:fuelcen.c ¶ :main:fvi.c ¶ :main:game.c ¶ :main:gamecntl.c ¶ :main:gamefont.c ¶ :main:gamemine.c ¶ :main:gamepal.c ¶ :main:gamerend.c ¶ :main:gamesave.c ¶ :main:gameseg.c ¶ :main:gameseq.c ¶ :main:gauges.c ¶ :main:hostage.c ¶ :main:hud.c ¶ :main:inferno.c ¶ :main:kconfig.c ¶ :main:kmatrix.c ¶ :main:laser.c ¶ :main:lighting.c ¶ :main:menu.c ¶ :main:mglobal.c ¶ :main:mission.c ¶ :main:morph.c ¶ :main:movie.c ¶ :main:multi.c ¶ :main:multibot.c ¶ :main:net_ipx.c ¶ :main:net_udp.c ¶ :main:newdemo.c ¶ :main:newmenu.c ¶ :main:object.c ¶ :main:paging.c ¶ :main:physics.c ¶ :main:piggy.c ¶ :main:player.c ¶ :main:playsave.c ¶ :main:polyobj.c ¶ :main:powerup.c ¶ :main:render.c ¶ :main:robot.c ¶ :main:scores.c ¶ :main:segment.c ¶ :main:slew.c ¶ :main:songs.c ¶ :main:state.c ¶ :main:switch.c ¶ :main:terrain.c ¶ :main:texmerge.c ¶ :main:text.c ¶ :main:titles.c ¶ :main:vclip.c ¶ :main:wall.c ¶ :main:weapon.c ¶ :maths:fixc.c ¶ :maths:rand.c ¶ :maths:tables.c ¶ :maths:vecmat.c ¶ :mem:mem.c ¶ :misc:args.c ¶ :misc:dl_list.c ¶ :misc:error.c ¶ :misc:hash.c ¶ :misc:hmp.c ¶ :misc:ignorecase.c ¶ :misc:physfsrwops.c ¶ :misc:physfsx.c ¶ :misc:strio.c ¶ :misc:strutil.c ¶ :texmap:ntmap.c ¶ :texmap:scanline.c ¶ :texmap:tmapflat.c ¶ :texmap:tmapppc.a ### Object Files ### OpenGLObjects = ¶ "{ObjDir}gr.c.x" ¶ "{ObjDir}ogl.c.x" SDLVideoObjects = ¶ "{ObjDir}SDL:gr.c.x" GeneralObjects = ¶ {ObjDir}2dsline.c.x ¶ {ObjDir}bitblt.c.x ¶ {ObjDir}bitmap.c.x ¶ {ObjDir}box.c.x ¶ {ObjDir}canvas.c.x ¶ {ObjDir}circle.c.x ¶ {ObjDir}disc.c.x ¶ {ObjDir}font.c.x ¶ {ObjDir}gpixel.c.x ¶ {ObjDir}line.c.x ¶ {ObjDir}palette.c.x ¶ {ObjDir}pcx.c.x ¶ {ObjDir}pixel.c.x ¶ {ObjDir}poly.c.x ¶ {ObjDir}rect.c.x ¶ {ObjDir}rle.c.x ¶ {ObjDir}scalec.c.x ¶ {ObjDir}tmerge.c.x ¶ {ObjDir}clipper.c.x ¶ {ObjDir}draw.c.x ¶ {ObjDir}globvars.c.x ¶ {ObjDir}instance.c.x ¶ {ObjDir}interp.c.x ¶ {ObjDir}matrix.c.x ¶ {ObjDir}points.c.x ¶ {ObjDir}rod.c.x ¶ {ObjDir}setup.c.x ¶ {ObjDir}SDL_main.c.x ¶ {ObjDir}digi.c.x ¶ {ObjDir}digi_audio.c.x ¶ {ObjDir}digi_mixer.c.x ¶ {ObjDir}digi_mixer_music.c.x ¶ {ObjDir}event.c.x ¶ {ObjDir}init.c.x ¶ {ObjDir}joy.c.x ¶ {ObjDir}jukebox.c.x ¶ {ObjDir}key.c.x ¶ {ObjDir}mouse.c.x ¶ {ObjDir}rbaudio.c.x ¶ {ObjDir}timer.c.x ¶ {ObjDir}window.c.x ¶ {ObjDir}iff.c.x ¶ {ObjDir}decoder16.c.x ¶ {ObjDir}decoder8.c.x ¶ {ObjDir}mvelib.c.x ¶ {ObjDir}mveplay.c.x ¶ {ObjDir}mve_audio.c.x ¶ {ObjDir}ai.c.x ¶ {ObjDir}ai2.c.x ¶ {ObjDir}aipath.c.x ¶ {ObjDir}automap.c.x ¶ {ObjDir}bm.c.x ¶ {ObjDir}cntrlcen.c.x ¶ {ObjDir}collide.c.x ¶ {ObjDir}config.c.x ¶ {ObjDir}console.c.x ¶ {ObjDir}controls.c.x ¶ {ObjDir}credits.c.x ¶ {ObjDir}crypt.c.x ¶ {ObjDir}digiobj.c.x ¶ {ObjDir}effects.c.x ¶ {ObjDir}endlevel.c.x ¶ {ObjDir}escort.c.x ¶ {ObjDir}fireball.c.x ¶ {ObjDir}fuelcen.c.x ¶ {ObjDir}fvi.c.x ¶ {ObjDir}game.c.x ¶ {ObjDir}gamecntl.c.x ¶ {ObjDir}gamefont.c.x ¶ {ObjDir}gamemine.c.x ¶ {ObjDir}gamepal.c.x ¶ {ObjDir}gamerend.c.x ¶ {ObjDir}gamesave.c.x ¶ {ObjDir}gameseg.c.x ¶ {ObjDir}gameseq.c.x ¶ {ObjDir}gauges.c.x ¶ {ObjDir}hostage.c.x ¶ {ObjDir}hud.c.x ¶ {ObjDir}inferno.c.x ¶ {ObjDir}kconfig.c.x ¶ {ObjDir}kmatrix.c.x ¶ {ObjDir}laser.c.x ¶ {ObjDir}lighting.c.x ¶ {ObjDir}menu.c.x ¶ {ObjDir}mglobal.c.x ¶ {ObjDir}mission.c.x ¶ {ObjDir}morph.c.x ¶ {ObjDir}movie.c.x ¶ # {ObjDir}multi.c.x ¶ # {ObjDir}multibot.c.x ¶ # {ObjDir}net_ipx.c.x ¶ # {ObjDir}net_udp.c.x ¶ {ObjDir}newdemo.c.x ¶ {ObjDir}newmenu.c.x ¶ {ObjDir}object.c.x ¶ {ObjDir}paging.c.x ¶ {ObjDir}physics.c.x ¶ {ObjDir}piggy.c.x ¶ {ObjDir}player.c.x ¶ {ObjDir}playsave.c.x ¶ {ObjDir}polyobj.c.x ¶ {ObjDir}powerup.c.x ¶ {ObjDir}render.c.x ¶ {ObjDir}robot.c.x ¶ {ObjDir}scores.c.x ¶ {ObjDir}segment.c.x ¶ {ObjDir}slew.c.x ¶ {ObjDir}songs.c.x ¶ {ObjDir}state.c.x ¶ {ObjDir}switch.c.x ¶ {ObjDir}terrain.c.x ¶ {ObjDir}texmerge.c.x ¶ {ObjDir}text.c.x ¶ {ObjDir}titles.c.x ¶ {ObjDir}vclip.c.x ¶ {ObjDir}wall.c.x ¶ {ObjDir}weapon.c.x ¶ {ObjDir}fixc.c.x ¶ {ObjDir}rand.c.x ¶ {ObjDir}tables.c.x ¶ {ObjDir}vecmat.c.x ¶ {ObjDir}mem.c.x ¶ {ObjDir}args.c.x ¶ {ObjDir}dl_list.c.x ¶ {ObjDir}error.c.x ¶ {ObjDir}hash.c.x ¶ {ObjDir}hmp.c.x ¶ {ObjDir}ignorecase.c.x ¶ {ObjDir}physfsrwops.c.x ¶ {ObjDir}physfsx.c.x ¶ {ObjDir}strio.c.x ¶ {ObjDir}strutil.c.x ¶ {ObjDir}ntmap.c.x ¶ {ObjDir}scanline.c.x ¶ {ObjDir}tmapflat.c.x ¶ {ObjDir}tmapppc.a.x ### Libraries ### GeneralLibFiles = ¶ "{SharedLibraries}PhysicsFS" ¶ "{SharedLibraries}SDL" ¶ "{SharedLibraries}SDL_mixer" ¶ "{SharedLibraries}StdCLib" ¶ # "{SharedLibraries}CarbonLib" ¶ "{SharedLibraries}DialogsLib" ¶ "{SharedLibraries}InterfaceLib" ¶ "{SharedLibraries}MathLib" ¶ "{PPCLibraries}StdCRuntime.o" ¶ "{PPCLibraries}PPCCRuntime.o" ¶ "{PPCLibraries}PPCToolLibs.o" OpenGLFiles = ¶ "{SharedLibraries}OpenGLLibraryStub" ¶ "{SharedLibraries}OpenGLUtilityStub" ### Default Rules ### .a.x Ä .a {¥MondoBuild¥} {PPCAsm} {depDir}{default}.a -o {targDir}{default}.a.x {PPCAOptions} .c.x Ä .c {¥MondoBuild¥} {PPCC} {depDir}{default}.c -o {targDir}{default}.c.x {PPCCOptions} ### Build Rules ### # Comment out OpenGLObjects and OpenGLFiles for SDL Video build, commment out SDLVideoObjects for OpenGL build # This should be done for the following line as well as the arguments to PPCLink D2X ÄÄ directories {GeneralObjects} {GeneralLibFiles} {¥MondoBuild¥} {OpenGLObjects} {OpenGLFiles} #{SDLVideoObjects} PPCLink ¶ -o {Targ} ¶ {GeneralObjects} ¶ # {SDLVideoObjects} ¶ {OpenGLObjects} ¶ {GeneralLibFiles} ¶ {OpenGLFiles} ¶ {Sym-PPC} ¶ -mf -d ¶ -m main ¶ -t 'APPL' ¶ -c 'DCT2' Rez -a -o {Targ} ":arch:carbon:descent.r" # This is used to create the directories needed for build directories Ä if !`Exists obj` ; NewFolder obj ; end if !`Exists :obj:SDL` ; NewFolder :obj:SDL ; end ### Required Dependencies ### {ObjDir}2dsline.c.x Ä :2d:2dsline.c {ObjDir}bitblt.c.x Ä :2d:bitblt.c {ObjDir}bitmap.c.x Ä :2d:bitmap.c {ObjDir}box.c.x Ä :2d:box.c {ObjDir}canvas.c.x Ä :2d:canvas.c {ObjDir}circle.c.x Ä :2d:circle.c {ObjDir}disc.c.x Ä :2d:disc.c {ObjDir}font.c.x Ä :2d:font.c {ObjDir}gpixel.c.x Ä :2d:gpixel.c {ObjDir}line.c.x Ä :2d:line.c {ObjDir}palette.c.x Ä :2d:palette.c {ObjDir}pcx.c.x Ä :2d:pcx.c {ObjDir}pixel.c.x Ä :2d:pixel.c {ObjDir}poly.c.x Ä :2d:poly.c {ObjDir}rect.c.x Ä :2d:rect.c {ObjDir}rle.c.x Ä :2d:rle.c {ObjDir}scalec.c.x Ä :2d:scalec.c {ObjDir}tmerge.c.x Ä :2d:tmerge.c {ObjDir}clipper.c.x Ä :3d:clipper.c {ObjDir}draw.c.x Ä :3d:draw.c {ObjDir}globvars.c.x Ä :3d:globvars.c {ObjDir}instance.c.x Ä :3d:instance.c {ObjDir}interp.c.x Ä :3d:interp.c {ObjDir}matrix.c.x Ä :3d:matrix.c {ObjDir}points.c.x Ä :3d:points.c {ObjDir}rod.c.x Ä :3d:rod.c {ObjDir}setup.c.x Ä :3d:setup.c {ObjDir}SDL_main.c.x Ä :arch:carbon:SDL_main.c {ObjDir}gr.c.x Ä :arch:ogl:gr.c {ObjDir}ogl.c.x Ä :arch:ogl:ogl.c {ObjDir}digi.c.x Ä :arch:sdl:digi.c {ObjDir}digi_audio.c.x Ä :arch:sdl:digi_audio.c {ObjDir}digi_mixer.c.x Ä :arch:sdl:digi_mixer.c {ObjDir}digi_mixer_music.c.x Ä :arch:sdl:digi_mixer_music.c {ObjDir}event.c.x Ä :arch:sdl:event.c {ObjDir}SDL:gr.c.x Ä :arch:sdl:gr.c {ObjDir}init.c.x Ä :arch:sdl:init.c {ObjDir}joy.c.x Ä :arch:sdl:joy.c {ObjDir}jukebox.c.x Ä :arch:sdl:jukebox.c {ObjDir}key.c.x Ä :arch:sdl:key.c {ObjDir}mouse.c.x Ä :arch:sdl:mouse.c {ObjDir}rbaudio.c.x Ä :arch:sdl:rbaudio.c {ObjDir}timer.c.x Ä :arch:sdl:timer.c {ObjDir}window.c.x Ä :arch:sdl:window.c {ObjDir}iff.c.x Ä :iff:iff.c {ObjDir}decoder16.c.x Ä :libmve:decoder16.c {ObjDir}decoder8.c.x Ä :libmve:decoder8.c {ObjDir}mvelib.c.x Ä :libmve:mvelib.c {ObjDir}mveplay.c.x Ä :libmve:mveplay.c {ObjDir}mve_audio.c.x Ä :libmve:mve_audio.c {ObjDir}ai.c.x Ä :main:ai.c {ObjDir}ai2.c.x Ä :main:ai2.c {ObjDir}aipath.c.x Ä :main:aipath.c {ObjDir}automap.c.x Ä :main:automap.c {ObjDir}bm.c.x Ä :main:bm.c {ObjDir}cntrlcen.c.x Ä :main:cntrlcen.c {ObjDir}collide.c.x Ä :main:collide.c {ObjDir}config.c.x Ä :main:config.c {ObjDir}console.c.x Ä :main:console.c {ObjDir}controls.c.x Ä :main:controls.c {ObjDir}credits.c.x Ä :main:credits.c {ObjDir}crypt.c.x Ä :main:crypt.c {ObjDir}digiobj.c.x Ä :main:digiobj.c {ObjDir}effects.c.x Ä :main:effects.c {ObjDir}endlevel.c.x Ä :main:endlevel.c {ObjDir}escort.c.x Ä :main:escort.c {ObjDir}fireball.c.x Ä :main:fireball.c {ObjDir}fuelcen.c.x Ä :main:fuelcen.c {ObjDir}fvi.c.x Ä :main:fvi.c {ObjDir}game.c.x Ä :main:game.c {ObjDir}gamecntl.c.x Ä :main:gamecntl.c {ObjDir}gamefont.c.x Ä :main:gamefont.c {ObjDir}gamemine.c.x Ä :main:gamemine.c {ObjDir}gamepal.c.x Ä :main:gamepal.c {ObjDir}gamerend.c.x Ä :main:gamerend.c {ObjDir}gamesave.c.x Ä :main:gamesave.c {ObjDir}gameseg.c.x Ä :main:gameseg.c {ObjDir}gameseq.c.x Ä :main:gameseq.c {ObjDir}gauges.c.x Ä :main:gauges.c {ObjDir}hostage.c.x Ä :main:hostage.c {ObjDir}hud.c.x Ä :main:hud.c {ObjDir}inferno.c.x Ä :main:inferno.c {ObjDir}kconfig.c.x Ä :main:kconfig.c {ObjDir}kmatrix.c.x Ä :main:kmatrix.c {ObjDir}laser.c.x Ä :main:laser.c {ObjDir}lighting.c.x Ä :main:lighting.c {ObjDir}menu.c.x Ä :main:menu.c {ObjDir}mglobal.c.x Ä :main:mglobal.c {ObjDir}mission.c.x Ä :main:mission.c {ObjDir}morph.c.x Ä :main:morph.c {ObjDir}movie.c.x Ä :main:movie.c {ObjDir}multi.c.x Ä :main:multi.c {ObjDir}multibot.c.x Ä :main:multibot.c {ObjDir}net_ipx.c.x Ä :main:net_ipx.c {ObjDir}net_udp.c.x Ä :main:net_udp.c {ObjDir}newdemo.c.x Ä :main:newdemo.c {ObjDir}newmenu.c.x Ä :main:newmenu.c {ObjDir}object.c.x Ä :main:object.c {ObjDir}paging.c.x Ä :main:paging.c {ObjDir}physics.c.x Ä :main:physics.c {ObjDir}piggy.c.x Ä :main:piggy.c {ObjDir}player.c.x Ä :main:player.c {ObjDir}playsave.c.x Ä :main:playsave.c {ObjDir}polyobj.c.x Ä :main:polyobj.c {ObjDir}powerup.c.x Ä :main:powerup.c {ObjDir}render.c.x Ä :main:render.c {ObjDir}robot.c.x Ä :main:robot.c {ObjDir}scores.c.x Ä :main:scores.c {ObjDir}segment.c.x Ä :main:segment.c {ObjDir}slew.c.x Ä :main:slew.c {ObjDir}songs.c.x Ä :main:songs.c {ObjDir}state.c.x Ä :main:state.c {ObjDir}switch.c.x Ä :main:switch.c {ObjDir}terrain.c.x Ä :main:terrain.c {ObjDir}texmerge.c.x Ä :main:texmerge.c {ObjDir}text.c.x Ä :main:text.c {ObjDir}titles.c.x Ä :main:titles.c {ObjDir}vclip.c.x Ä :main:vclip.c {ObjDir}wall.c.x Ä :main:wall.c {ObjDir}weapon.c.x Ä :main:weapon.c {ObjDir}fixc.c.x Ä :maths:fixc.c {ObjDir}rand.c.x Ä :maths:rand.c {ObjDir}tables.c.x Ä :maths:tables.c {ObjDir}vecmat.c.x Ä :maths:vecmat.c {ObjDir}mem.c.x Ä :mem:mem.c {ObjDir}args.c.x Ä :misc:args.c {ObjDir}dl_list.c.x Ä :misc:dl_list.c {ObjDir}error.c.x Ä :misc:error.c {ObjDir}hash.c.x Ä :misc:hash.c {ObjDir}hmp.c.x Ä :misc:hmp.c {ObjDir}ignorecase.c.x Ä :misc:ignorecase.c {ObjDir}physfsrwops.c.x Ä :misc:physfsrwops.c {ObjDir}physfsx.c.x Ä :misc:physfsx.c {ObjDir}strio.c.x Ä :misc:strio.c {ObjDir}strutil.c.x Ä :misc:strutil.c {ObjDir}ntmap.c.x Ä :texmap:ntmap.c {ObjDir}scanline.c.x Ä :texmap:scanline.c {ObjDir}tmapflat.c.x Ä :texmap:tmapflat.c {ObjDir}tmapppc.a.x Ä :texmap:tmapppc.a ### Optional Dependencies ### ### Build this target to generate "include file" dependencies. ### Dependencies Ä $OutOfDate MakeDepend ¶ -append {MAKEFILE} ¶ -ignore "{CIncludes}" ¶ -objdir "{ObjDir}" ¶ -objext .x ¶ {Includes} ¶ {SrcFiles} dxx-rebirth-0.58.1-d2x/English.lproj/000077500000000000000000000000001217717237500172725ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/English.lproj/InfoPlist.strings000077500000000000000000000010441217717237500226160ustar00rootroot00000000000000þÿ/* Localized versions of Info.plist keys */ CFBundleName = "D2X"; CFBundleShortVersionString = "D2X-Rebirth v0.57.3"; CFBundleGetInfoString = "D2X-Rebirth v0.57.3, Copyright 2012 Christian Beckhaeuser."; NSHumanReadableCopyright = "Copyright 2012 Christian Beckhaeuser."; dxx-rebirth-0.58.1-d2x/INSTALL.txt000066400000000000000000000160001217717237500164200ustar00rootroot00000000000000Compiling D2X-Rebirth Sourcecode This file describes how to compile D2X-Rebirth from Source. Requirements: ============= 1. C/C++ compiler (gcc/g++) 2. SCons (to compile in *NIX/Win32) / XCode (to compile on MacOS) 3. SDL(-devel) 4. PhysFS(-devel) 5. GLU/GL 6. NASM (optional for Assembler-based Texture-mapper in non-OpenGL Build) 7. SDL_mixer(-devel) (+ dependencies) for external music support Compiling: ========== *NIX: ----- Type 'scons' to compile the source. You can also give additional options like 'scons use_udp=0'. See 'scons -h' for available options. To install, use 'scons install' but remember to use all your options as well or SCons will re-compile and install without any options given to prior compiling. However it's STRONGLY recommended NOT to use the 'install' argument but to create a package for your Linux distribution or operating system. 'install' will compile the resulting binary (d2x-rebirth) to /usr/local/bin/ by default so to uninstall, just delete the binary. MacOS: ------ For Mac OS X, an Xcode project is available (requires Xcode 2.1 or later). Xcode includes the compiler and OpenGL. The standard SDL and SDL_mixer libraries from the SDL website may be used, these go in /Library/Frameworks or ~/Library/Frameworks. However, to fix MP3 support for the 'Release' build I used SDL 1.2.8 with Diedel's modified SMPEG library from his D2X-XL website. To debug these libraries compile the frameworks from source as 'Debug' builds, then use these instead. PhysicsFS must be compiled from source. Put its enclosing folder 'physfs', renaming if necessary, next to D1X's (typically d1x-rebirth). In CMake ensure the build path points to 'build' inside 'physfs'. Specify 'i386;ppc' as the architecture for a universal binary. In Xcode, build 'Debug' and 'Release' from the dynamic library target. SCons also works on MacOS X, but it's recommended to use XCode instead. For Mac OS 9, an MPW Makefile is available. MPW includes the compiler. As for the shared libraries, compile PhysicsFS version 1.0 and the latest SDL and SDL_mixer (as of writing) from source. For SDL_mixer 1.2.11 you will need to disable MikMod support, from SDL_mixer.make, otherwise use SDL_mixer 1.2.8. For any sources to compile, they will need to be made into text files using a typecode changing program, if they were downloaded outside of Mac OS 9 (including Mac OS X). This will also need to be done after any Terminal command (diff, svn update etc) edits the source files. Note that there are ready-to-go packages on http://www.dxx-rebirth.com Win32: ------ Use the SCons way like described in the *NIX-instructions from an MSYS/MinGW environment. However you will not need to use 'install' but just drag the resulting binary to your Descent-folder. Note that there are ready-to-go packages on http://www.dxx-rebirth.com Needed files: ============= Since D2X-Rebirth is a Sourceport of the Descent2-Engine you will need the Game-Content data files to run the game. You don't own the full game, yet? Just visit GOOD OLD GAMES via: http://www.gog.com/en/gamecard/descent_1_descent_2/pp/fc074d501302eb2b93e2554793fcaf50b3bf7291 and download it for a very low price! DRM-FREE! Following files are needed to run the game: descent2.ham descent2.hog descent2.s11 descent2.s22 alien1.pig alien2.pig fire.pig groupa.pig ice.pig water.pig intro-h.mvl and/or intro-l.mvl other-h.mvl and/or other-l.mvl robots-h.mvl and/or robots-l.mvl With the PC version, these files - except the Movies (*.mvl) - are archived in the file 'descent2.sow' on the Descent2 CD-Rom. This is an ARJ-archive and can be extracted with an adapted archiver like ‘unarj’ or by installing the game on a Windows/DOS system. Note that the above files must be lowercase if you use an operating system with case-sensitive file management. For the Mac CD-ROM, download The Unarchiver (http://wakaba.c3.cx/s/apps/unarchiver.html) and drag the installer program onto it. Alternatively, for Mac OS 9 or earlier simply run the installer. Unfortunately the movies do not work; if you want the movies consider purchasing Descent 2 for PC (e.g. from Good Old Games) and extract that installer with The Unarchiver. Hey, then you'll have another license for multiplayer. ;) Of course you can also use the Interactive Demo game content with D2X-Rebirth which you can find here: http://www.dxx-rebirth.com/game-content/ Where to put these files: ========================= *NIX ---- The Sharepath (/usr/local/share/games/d1x-rebirth/ by default - if not reconfigured via SCons) or ~/.d1x-rebirth or another directory specified by -hogdir via d1x.ini MacOS ----- Same directory as where the binary is located or another directory specified by -hogdir via d1x.ini Win32 ----- Same directory as where the binary is located another directory specified by -hogdir via d1x.ini Optional files: =============== D2X-Rebirth is expandable. You can add additional content to the game. Vertigo series AddOn -------------------- Can be added by copying the files d2x-h.mvl and/or d2x-l.mvl, hoard.ham to your game-directory/Sharepath and d2x.hog, d2x.mn2 to 'missions/' subdirectory. All these files should be located on the ‘Vertigo Series’ CD-Rom Missions: --------- Those can be found on several websites. Add them to the game by copying them to subdirectory ‘missions/’. They can also go in subdirectories of 'missions/', unlike with the original version. A good place to find additional mission might be the Descent mission Database: http://www.dxx-rebirth.com/descent-mission-database/ Custom Music (MP3, OGG, AIF, etc.): ----------------------------------- Custom Music can be played via the CUSTOM MUSIC options by specifying it in the Sound Options menu. Please note that all custom music has to be in 44Khz format. Supported formats depend on the capabilities of SDL_mixer. AddOn Packs: ------------ Custom AddOn packs will expand the game in many differnt ways. These are usually provided as ZIP or 7Z and can easily be installed by putting them to where your game content resides (OS-dependent - see above). NO EXTRACTION OR ADDITIONAL CONFIGURATION NEEDED. You can find all official AddOns here: http://www.dxx-rebirth.com/addons/ Launching the program ===================== *NIX ---- After compiling and installing, the program can be launched with the command: d2x-rebirth MacOS ----- Simply double-click "D2X-Rebirth". Win32 ----- Doubleclick d2x-rebirth.exe To see a full list of available command-line options append ‘-h’, ‘-?’ to the command or refer file d2x.ini Appendix ======== http://DXX-Rebirth.com dxx-rebirth-0.58.1-d2x/MVEPlayer-Info.plist000066400000000000000000000011311217717237500203220ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable MVEPlayer CFBundleIconFile CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL NSMainNibFile MainMenu NSPrincipalClass NSApplication dxx-rebirth-0.58.1-d2x/README.RPi000066400000000000000000000060201217717237500161230ustar00rootroot00000000000000DXX-Rebirth for the Raspberry Pi BUILDING: ========= Make sure you have installed (the development packages of) all of the required libraries (libsdl, libphysfs, ...). For building, you will also need scons (and for that, python). Most linux distributions should contain all the required packages, debain/raspbian do so for sure. Using a distribution with hardfp ABI is recommended for optimal performance. I developed/tested this on a raspbian wheezy. To build directly on the device, just run: scons raspberrypi=1 [... other options (see scons -h)...] This assumes that the development files (libs/headers) for the VideoCore APIs are located in /opt/vc. You can use rpi_vc_path to specify another location. Currently, there is no direct support for crosscompiling. RUNNING: ======== The game should run with X11 or directly on the console (libsdl with fbcon/ directfb driver). NOTE: *** PLEASE USE THE 128/128MB MEMORY SPLIT *** The game might completely freeze or diplay messed up graphics in out-of-(GPU)-memory situations. If you want to run it with the 192/64MB memory split, you might be able to do so by setting the texture filter to "NONE" in the graphics options. (This disables mip mapping and reduces the memory requirements of the textures. Note that the "BILINEAR" filter still uses mipmapping). If the game freezes during the "Prepare for Descent" phase when loading a level, you probably do not have enough GPU memory. RUNNING ON X11: =============== Recommendation is to use fullscreen mode. However, you can run in "windowed" mode, too. The game will open an X11 window in that case, and the actual game output will be an overlay of the same size, but not at the same position, and always on top (and completely out of control of the X Server). Game input is still handled via the X11 window, so make sure it has the focus. RUNNING ON THE CONSOLE: ======================= libsdl supports running directly on the Linux console. While the SDL Video mode is technically not required on the RPi, we still have to use it to get all the input events we need. libsdl seems to have problems on the RPi, I always get a crash in libsdl when trying to change the resolution. To avoid such crashes, the code will try to detect if it is running on the console and activate a hack to prevent switching the resolution. Note that the in-game framebuffer resolution can still be changed, the RPi will just scale the output to the initial resolution (in "fullscreen" mode). "Windowed" mode will just result in unscaled output. As libsdl creates a black screen, you will not be able to have the "Window" on top of the linux console output :( NOTE: You might need root privileges to use the libsdl fbcon/directfb drivers. BUGS, SUGGESTIONS AND FEEDBACK: =============================== The RPi patch was written by: Marcel Heinz Send bug reports, suggestions and other feedback regarding the operation on the RPi to me via email, or post to the official dxx-rebirth forum at: http://www.dxx-rebirth.com/frm/index.php -- derhass, 2012-08-09 dxx-rebirth-0.58.1-d2x/README.txt000066400000000000000000000070631217717237500162600ustar00rootroot00000000000000 __________ __________/ D2X-Rebirth / http://www.dxx-rebirth.com 0. Introduction: ================ D2X-Rebirth is based on a late D2X-CVS Source, coded and released by Bradley Bell and his team. I spend much time to improve the Sourcecode, tried to fix bugs in there and added some improvements. It is the goal of DXX-Rebirth to keep these games alive and the result is a very stable version of the Descent ][ port - called D2X-Rebirth. I hope you enjoy the game as you did when you played it the first time. If you have something to say about my release, feel free to contact me at zico [at] dxx-rebirth [dot] com 1. Features: ============ DXX-Rebirth has every little feature you already may know from the DOS Version of Descent and much more. For example: * Plays Descent and Descent 2 and all their AddOns and third-party levels. * DXX-Rebirth runs on your favourite Operating System. We officially support Linux (and other *NIX), Mac OS (9/X) and Windows (2000, XP, Vista, 7). Still the code can be compiled on many other systems as well. * OpenGL provides a fast and smooth rendering - even on low-end systems. * Optionally you can enbale several effects like Transparency, Colored lighting, Texture Filtering, FSAA, etc. * Thanks to SDL, a wide palette of Joysticks are supported. Also you can use more Joysticks, buttons and axes than you can ever operate in your state of evolution. * If you prefer steering your Pyro with a mouse, you will not have the problem that the movement becomes slow in high game speed. * Joystick, Keyboard and Mouse can be used simultaneously. * The games can display all resolutions and aspects supported by your Monitor, including an option for VSync. * Besides MIDI and CD-Audio (Redbook), you can play your own custom Music from your Harddrive or a separate AddOn. * Both games can utilize special AddOn packs to replace or expand the original game content. * Multiplayer via UDP protocol provides a fast and easy-to-use LAN and Online action. This includes reliable communication causing less glitches due to lost packages. * The ingame Demo-recording system has been improved. Demos are less glitchy and smaller while still still being backwards-compatible to earlier versions of the games. * Higher game speed will not cause glitches such as unacceptable fast homing projectiles, incredible high damage caused by several collisions or Fusion cannon, etc. * Player files, Savegames, Demos and Missions from DOS-Versions of the games can freely be used in DXX-Rebirth and vice versa. * Mac Command keys are now working - see F1 Help. Command-Q works much like a normal Mac program * Even more ... 2. Installation: ================ See INSTALL.txt. 3. Multiplayer: =============== D2X-Rebirth supports Multiplayer over UDP/IP. Using UDP/IP works over LAN and Internet. By default, each game communicates over UDP-Port 42424. This can be changed via the menus while creating a game and manually join a game, command-line argument or D2X.INI. To successfully host a game online, make sure UDP-Port 42424 (or otherwise if specified correctly) is opened on your Router/Firewall. Clients do not need to open any ports. The game also supports IPv6 if built in while compiling and should be backwards compatible to IPv4 builds as good as possible. 4. Legal stuff: =============== See COPYING.txt 5. Contact: =========== http://www.dxx-rebirth.com/ zico [at] dxx-rebirth [dot] com dxx-rebirth-0.58.1-d2x/RELEASE-NOTES.txt000066400000000000000000000032611217717237500172650ustar00rootroot00000000000000RELEASE NOTES ============= What's new in 0.58.1 -------------------- * Fixed some bugs regarding reactor, making the game virtually unplayable for a lot of people What's new in 0.58.0 -------------------- * Several fixes and improvements for Multiplayer - especially Coop savestates * Sensitivity/Ramping sliders for keyboard input * More efficient postional data for Multiplayer, making ship positions more accurate and require less traffic (Thanks to v66r) * New file extension for AddOns (.dxa) * Key combination ALT+ENTER will not work ingame anymore to not interrupt player input * Command-line option to disable mouse cursor without disabling the mouse altogether * Support for Raspberry Pi by derhass * HUD style "no HUD" * Fixes for lighting code which wasn't updating correctly all the time * Improvement for transparency effects that won't make certain sprites disappear in front of bright surfaces * Support for hmp tempo setting (Thanks to Yarn) * Improvements and fixes for Shareware/Demo data * Improvements for firing mechanism, keeping fire rate accurate at all FPS * More fixes and improvements (see CHANGELOG.txt) Special notes for this release ------------------------------ * AddOns now use filename extension ".dxa". Your old AddOns will not work anymore. You can either re-download them or simply rename them from *.zip to *.dxa. Known issues ------------ * On Windows the mouse is not correctly released if using ALT+TAB to minimize the game. This is not a bug in the program but rather the SDL library. It can be worked around by pausing the game and using ALT+ENTER to get the game to windowed mode. The mosue should not be stuck then anymore. dxx-rebirth-0.58.1-d2x/SConstruct000066400000000000000000000537251217717237500166220ustar00rootroot00000000000000#SConstruct # needed imports import sys import os import SCons.Util class argumentIndirection: def __init__(self,prefix): self.prefix = prefix self.ARGUMENTS = ARGUMENTS def get(self,name,value=None): return self.ARGUMENTS.get('%s_%s' % (self.prefix, name), self.ARGUMENTS.get(name,value)) # endianess-checker def checkEndian(): import struct array = struct.pack('cccc', '\x01', '\x02', '\x03', '\x04') i = struct.unpack('i', array) if i == struct.unpack('i', array): return "big" return "unknown" class DXXCommon: __endian = checkEndian() class UserSettings: def __init__(self,ARGUMENTS): # Paths for the Videocore libs/includes on the Raspberry Pi self.RPI_DEFAULT_VC_PATH='/opt/vc' self.debug = int(ARGUMENTS.get('debug', 0)) self.DESTDIR = ARGUMENTS.get('DESTDIR') self.profiler = int(ARGUMENTS.get('profiler', 0)) self.opengl = int(ARGUMENTS.get('opengl', 1)) self.asm = int(ARGUMENTS.get('asm', 0)) self.editor = int(ARGUMENTS.get('editor', 0)) self.extra_version = ARGUMENTS.get('extra_version', None) self.sdlmixer = int(ARGUMENTS.get('sdlmixer', 1)) self.register_install_target = int(ARGUMENTS.get('register_install_target', 1)) self.ipv6 = int(ARGUMENTS.get('ipv6', 0)) self.program_name = ARGUMENTS.get('program_name') self.use_udp = int(ARGUMENTS.get('use_udp', 1)) self.use_tracker = int(ARGUMENTS.get('use_tracker', 1)) self.verbosebuild = int(ARGUMENTS.get('verbosebuild', 0)) self.raspberrypi = int(ARGUMENTS.get('raspberrypi', 0)) self.rpi_vc_path = str(ARGUMENTS.get('rpi_vc_path', self.RPI_DEFAULT_VC_PATH)) self.default_opengles = 0 self.default_OGLES_LIB = 'GLES_CM' # automatic setup for raspberrypi if (self.raspberrypi == 1): self.default_opengles=1 self.default_OGLES_LIB='GLESv2' self.opengles = int(ARGUMENTS.get('opengles', self.default_opengles)) self.opengles_lib = str(ARGUMENTS.get('opengles_lib', self.default_OGLES_LIB)) builddir_prefix = ARGUMENTS.get('builddir_prefix', None) builddir_suffix = ARGUMENTS.get('builddir_suffix', None) default_builddir = builddir_prefix or '' if builddir_prefix is not None or builddir_suffix is not None: if os.environ.has_key('CC'): default_builddir += '%s-' % os.path.basename(os.environ['CC']) for a in ( ('debug', 'dbg'), ('profiler', 'prf'), ('editor', 'ed'), ('opengl', 'ogl'), ('opengles', 'es'), ): if getattr(self, a[0]): default_builddir += a[1] if builddir_suffix is not None: default_builddir += builddir_prefix self.builddir = ARGUMENTS.get('builddir', default_builddir) if self.builddir != '' and self.builddir[-1:] != '/': self.builddir += '/' # Base class for platform-specific settings processing class _PlatformSettings: tools = None ogllibs = '' osasmdef = None platform_sources = [] platform_objects = [] # Settings to apply to mingw32 builds class Win32PlatformSettings(_PlatformSettings): tools = ['mingw'] osdef = '_WIN32' osasmdef = 'win32' def __init__(self,user_settings): pass def adjust_environment(self,program,env): env.Append(CPPDEFINES = ['_WIN32', 'HAVE_STRUCT_TIMEVAL']) class DarwinPlatformSettings(_PlatformSettings): osdef = '__APPLE__' def __init__(self,user_settings): user_settings.asm = 0 self.lflags = os.environ.get("LDFLAGS", '') def adjust_environment(self,program,env): VERSION = str(program.VERSION_MAJOR) + '.' + str(program.VERSION_MINOR) if (program.VERSION_MICRO): VERSION += '.' + str(program.VERSION_MICRO) env['VERSION_NUM'] = VERSION env['VERSION_NAME'] = program.PROGRAM_NAME + ' v' + VERSION env.Append(CPPDEFINES = ['HAVE_STRUCT_TIMESPEC', 'HAVE_STRUCT_TIMEVAL', '__unix__']) env.Append(CPPPATH = [os.path.join(program.srcdir, '../physfs'), os.path.join(os.getenv("HOME"), 'Library/Frameworks/SDL.framework/Headers'), '/Library/Frameworks/SDL.framework/Headers']) env.Append(FRAMEWORKS = ['ApplicationServices', 'Carbon', 'Cocoa', 'SDL']) env.Append(FRAMEWORKPATH = [os.path.join(os.getenv("HOME"), 'Library/Frameworks'), '/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks']) self.libs = [''] env['LIBPATH'] = '../physfs/build/Debug' # Settings to apply to Linux builds class LinuxPlatformSettings(_PlatformSettings): osdef = '__LINUX__' osasmdef = 'elf' __opengl_libs = ['GL', 'GLU'] __pkg_config_sdl = {} def __init__(self,user_settings): if (user_settings.opengles == 1): self.ogllibs = [ user_settings.opengles_lib, 'EGL'] else: self.ogllibs = self.__opengl_libs def adjust_environment(self,program,env): env.Append(CPPDEFINES = ['__LINUX__', 'HAVE_STRUCT_TIMESPEC', 'HAVE_STRUCT_TIMEVAL']) try: pkgconfig = os.environ['PKG_CONFIG'] except KeyError as e: try: pkgconfig = '%s-pkg-config' % os.environ['CHOST'] except KeyError as e: pkgconfig = 'pkg-config' cmd = '%s --cflags --libs sdl' % pkgconfig try: flags = self.__pkg_config_sdl[cmd] except KeyError as e: if (program.user_settings.verbosebuild != 0): print "%s: reading SDL settings from `%s`" % (program.PROGRAM_NAME, cmd) self.__pkg_config_sdl[cmd] = env.backtick(cmd) flags = self.__pkg_config_sdl[cmd] env.MergeFlags(flags) def __init__(self): pass def prepare_environment(self): if self.user_settings.builddir != '': self.env.VariantDir(self.user_settings.builddir, '.', duplicate=0) # Prettier build messages...... if (self.user_settings.verbosebuild == 0): self.env["CCCOMSTR"] = "Compiling $SOURCE ..." self.env["CXXCOMSTR"] = "Compiling $SOURCE ..." self.env["LINKCOMSTR"] = "Linking $TARGET ..." self.env["ARCOMSTR"] = "Archiving $TARGET ..." self.env["RANLIBCOMSTR"] = "Indexing $TARGET ..." self.env.Append(CCFLAGS = ['-Wall', '-funsigned-char', '-Werror=implicit-int', '-Werror=implicit-function-declaration', '-pthread']) self.env.Append(CFLAGS = ['-std=gnu99']) self.env.Append(CPPDEFINES = ['NETWORK']) # Get traditional compiler environment variables for cc in ['CC', 'CXX']: if os.environ.has_key(cc): self.env[cc] = os.environ[cc] for flags in ['CFLAGS', 'CXXFLAGS']: if os.environ.has_key(flags): self.env[flags] += SCons.Util.CLVar(os.environ[flags]) def check_endian(self): # set endianess if (self.__endian == "big"): print "%s: BigEndian machine detected" % self.PROGRAM_NAME self.asm = 0 self.env.Append(CPPDEFINES = ['WORDS_BIGENDIAN']) elif (self.__endian == "little"): print "%s: LittleEndian machine detected" % self.PROGRAM_NAME def check_platform(self): # windows or *nix? if sys.platform == 'win32': print "%s: compiling on Windows" % self.PROGRAM_NAME platform = self.Win32PlatformSettings elif sys.platform == 'darwin': print "%s: compiling on Mac OS X" % self.PROGRAM_NAME platform = self.DarwinPlatformSettings else: print "%s: compiling on *NIX" % self.PROGRAM_NAME platform = self.LinuxPlatformSettings self.platform_settings = platform(self.user_settings) # Acquire environment object... self.env = Environment(ENV = os.environ, tools = platform.tools) self.platform_settings.adjust_environment(self, self.env) self.platform_settings.libs += ['physfs', 'm'] self.common_sources += self.platform_settings.platform_sources def process_user_settings(self): env = self.env # opengl or software renderer? if (self.user_settings.opengl == 1) or (self.user_settings.opengles == 1): if (self.user_settings.opengles == 1): print "%s: building with OpenGL ES" % self.PROGRAM_NAME env.Append(CPPDEFINES = ['OGLES']) else: print "%s: building with OpenGL" % self.PROGRAM_NAME env.Append(CPPDEFINES = ['OGL']) # assembler code? if (self.user_settings.asm == 1) and (self.user_settings.opengl == 0): print "%s: including: ASSEMBLER" % self.PROGRAM_NAME env.Replace(AS = 'nasm') env.Append(ASCOM = ' -f ' + str(self.platform_settings.osasmdef) + ' -d' + str(self.platform_settings.osdef) + ' -Itexmap/ ') self.common_sources += asm_sources else: env.Append(CPPDEFINES = ['NO_ASM']) # SDL_mixer support? if (self.user_settings.sdlmixer == 1): print "%s: including SDL_mixer" % self.PROGRAM_NAME env.Append(CPPDEFINES = ['USE_SDLMIXER']) # debug? if (self.user_settings.debug == 1): print "%s: including: DEBUG" % self.PROGRAM_NAME env.Append(CPPFLAGS = ['-g']) else: env.Append(CPPDEFINES = ['NDEBUG', 'RELEASE']) env.Append(CPPFLAGS = ['-O2']) # profiler? if (self.user_settings.profiler == 1): env.Append(CPPFLAGS = ['-pg']) #editor build? if (self.user_settings.editor == 1): env.Append(CPPDEFINES = ['EDITOR']) self.common_sources += self.editor_sources # IPv6 compability? if (self.user_settings.ipv6 == 1): env.Append(CPPDEFINES = ['IPv6']) # UDP support? if (self.user_settings.use_udp == 1): env.Append(CPPDEFINES = ['USE_UDP']) # Tracker support? (Relies on UDP) if( self.user_settings.use_tracker == 1 ): env.Append( CPPDEFINES = [ 'USE_TRACKER' ] ) # Raspberry Pi? if (self.user_settings.raspberrypi == 1): print "using Raspberry Pi vendor libs in %s" % self.user_settings.rpi_vc_path env.Append(CPPDEFINES = ['RPI', 'WORDS_NEED_ALIGNMENT']) env.Append(CPPPATH = [ self.user_settings.rpi_vc_path+'/include', self.user_settings.rpi_vc_path+'/include/interface/vcos/pthreads', self.user_settings.rpi_vc_path+'/include/interface/vmcs_host/linux']) self.platform_settings.lflags += ' -L' + self.user_settings.rpi_vc_path + '/lib' self.platform_settings.libs += ['bcm_host'] class DXXProgram(DXXCommon): # version number VERSION_MAJOR = 0 VERSION_MINOR = 58 VERSION_MICRO = 1 class UserSettings(DXXCommon.UserSettings): def __init__(self,ARGUMENTS,target): DXXCommon.UserSettings.__init__(self, ARGUMENTS.ARGUMENTS) # installation path PREFIX = str(ARGUMENTS.get('prefix', '/usr/local')) self.BIN_DIR = PREFIX + '/bin' self.DATA_DIR = PREFIX + '/share/games/' + target # command-line parms self.sharepath = str(ARGUMENTS.get('sharepath', self.DATA_DIR)) # Settings to apply to mingw32 builds class Win32PlatformSettings(DXXCommon.Win32PlatformSettings): def __init__(self,user_settings): DXXCommon.Win32PlatformSettings.__init__(self,user_settings) user_settings.sharepath = '' self.lflags = '-mwindows' self.libs = ['glu32', 'wsock32', 'ws2_32', 'winmm', 'mingw32', 'SDLmain', 'SDL'] def adjust_environment(self,program,env): DXXCommon.Win32PlatformSettings.adjust_environment(self, program, env) env.Append(CPPPATH = [os.path.join(program.srcdir, 'arch/win32/include')]) self.platform_sources = [os.path.join(program.srcdir, 'arch/win32/messagebox.c')] rcbasename = 'arch/win32/%s' % program.target self.platform_objects = [env.RES(target='%s%s%s' % (program.user_settings.builddir, rcbasename, env["OBJSUFFIX"]), source='%s.rc' % rcbasename)] # Settings to apply to Apple builds # This appears to be unused. The reference to sdl_only fails to # execute. class DarwinPlatformSettings(DXXCommon.DarwinPlatformSettings): def __init__(self,user_settings): DXXCommon.DarwinPlatformSettings.__init__(self) user_settings.sharepath = '' def adjust_environment(self,program,env): DXXCommon.DarwinPlatformSettings.adjust_environment(self, program, env) self.platform_sources = [os.path.join(program.srcdir, f) for f in ['arch/cocoa/SDLMain.m', 'arch/carbon/messagebox.c']] # Settings to apply to Linux builds class LinuxPlatformSettings(DXXCommon.LinuxPlatformSettings): def __init__(self,user_settings): DXXCommon.LinuxPlatformSettings.__init__(self,user_settings) user_settings.sharepath += '/' self.lflags = os.environ.get("LDFLAGS", '') def adjust_environment(self,program,env): DXXCommon.LinuxPlatformSettings.adjust_environment(self, program, env) self.libs = env['LIBS'] env.Append(CPPPATH = [os.path.join(program.srcdir, 'arch/linux/include')]) def __init__(self): DXXCommon.__init__(self) self.user_settings = self.UserSettings(self.ARGUMENTS, self.target) self.check_platform() self.prepare_environment() self.banner() self.check_endian() self.process_user_settings() self.register_program() def prepare_environment(self): DXXCommon.prepare_environment(self) self.VERSION_STRING = ' v' + str(self.VERSION_MAJOR) + '.' + str(self.VERSION_MINOR) + '.' + str(self.VERSION_MICRO) self.env.Append(CPPDEFINES = [('DXX_VERSION_MAJORi', str(self.VERSION_MAJOR)), ('DXX_VERSION_MINORi', str(self.VERSION_MINOR)), ('DXX_VERSION_MICROi', str(self.VERSION_MICRO))]) def banner(self): print '\n===== ' + self.PROGRAM_NAME + self.VERSION_STRING + ' =====\n' def process_user_settings(self): DXXCommon.process_user_settings(self) env = self.env # opengl or software renderer? if (self.user_settings.opengl == 1) or (self.user_settings.opengles == 1): self.common_sources += self.arch_ogl_sources if (sys.platform != 'darwin'): self.platform_settings.libs += self.platform_settings.ogllibs else: env.Append(FRAMEWORKS = ['OpenGL']) else: print "%s: building with Software Renderer" % self.PROGRAM_NAME self.common_sources += self.arch_sdl_sources # SDL_mixer support? if (self.user_settings.sdlmixer == 1): self.common_sources += self.arch_sdlmixer if (sys.platform != 'darwin'): self.platform_settings.libs += ['SDL_mixer'] else: env.Append(FRAMEWORKS = ['SDL_mixer']) # profiler? if (self.user_settings.profiler == 1): self.platform_settings.lflags += ' -pg' #editor build? if (self.user_settings.editor == 1): env.Append(CPPPATH = [os.path.join(self.srcdir, 'include/editor')]) # UDP support? if (self.user_settings.use_udp == 1): self.common_sources += self.sources_use_udp env.Append(CPPDEFINES = [('SHAREPATH', '\\"' + str(self.user_settings.sharepath) + '\\"')]) def _register_program(self,dxxstr,program_specific_objects=[]): env = self.env exe_target = os.path.join(self.srcdir, self.target) objects = [self.env.StaticObject(target='%s%s%s' % (self.user_settings.builddir, os.path.splitext(s)[0], self.env["OBJSUFFIX"]), source=s) for s in self.common_sources] objects.extend(self.platform_settings.platform_objects) objects.extend(program_specific_objects) versid_cppdefines=env['CPPDEFINES'][:] if self.user_settings.program_name: exe_target = self.user_settings.program_name if self.user_settings.extra_version: versid_cppdefines.append(('DESCENT_VERSION_EXTRA', '\\"%s\\"' % self.user_settings.extra_version)) objects.append(self.env.StaticObject(target='%s%s%s' % (self.user_settings.builddir, 'main/vers_id', self.env["OBJSUFFIX"]), source='main/vers_id.c', CPPDEFINES=versid_cppdefines)) # finally building program... env.Program(target='%s%s' % (self.user_settings.builddir, str(exe_target)), source = objects, LIBS = self.platform_settings.libs, LINKFLAGS = str(self.platform_settings.lflags)) if (sys.platform != 'darwin'): if self.user_settings.register_install_target: install_dir = os.path.join(self.user_settings.DESTDIR or '', self.user_settings.BIN_DIR) env.Install(install_dir, str(exe_target)) env.Alias('install', install_dir) else: sys.path += ['./arch/cocoa'] import tool_bundle tool_bundle.TOOL_BUNDLE(env) env.MakeBundle(self.PROGRAM_NAME + '.app', exe_target, 'free.%s-rebirth' % dxxstr, '%sgl-Info.plist' % dxxstr, typecode='APPL', creator='DCNT', icon_file='arch/cocoa/%s-rebirth.icns' % dxxstr, subst_dict={'%sgl' % dxxstr : exe_target}, # This is required; manually update version for Xcode compatibility resources=[['English.lproj/InfoPlist.strings', 'English.lproj/InfoPlist.strings']]) class D2XProgram(DXXProgram): PROGRAM_NAME = 'D2X-Rebirth' target = 'd2x-rebirth' srcdir = '' ARGUMENTS = argumentIndirection('d2x') def prepare_environment(self): DXXProgram.prepare_environment(self) # Flags and stuff for all platforms... self.env.Append(CPPPATH = [os.path.join(self.srcdir, f) for f in ['include', 'main', 'arch/include']]) def __init__(self): # general source files self.common_sources = [os.path.join(self.srcdir, f) for f in [ '2d/2dsline.c', '2d/bitblt.c', '2d/bitmap.c', '2d/box.c', '2d/canvas.c', '2d/circle.c', '2d/disc.c', '2d/font.c', '2d/gpixel.c', '2d/line.c', '2d/palette.c', '2d/pcx.c', '2d/pixel.c', '2d/rect.c', '2d/rle.c', '2d/scalec.c', '3d/clipper.c', '3d/draw.c', '3d/globvars.c', '3d/instance.c', '3d/interp.c', '3d/matrix.c', '3d/points.c', '3d/rod.c', '3d/setup.c', 'arch/sdl/event.c', 'arch/sdl/init.c', 'arch/sdl/joy.c', 'arch/sdl/key.c', 'arch/sdl/mouse.c', 'arch/sdl/rbaudio.c', 'arch/sdl/timer.c', 'arch/sdl/window.c', 'arch/sdl/digi.c', 'arch/sdl/digi_audio.c', 'iff/iff.c', 'libmve/decoder8.c', 'libmve/decoder16.c', 'libmve/mve_audio.c', 'libmve/mvelib.c', 'libmve/mveplay.c', 'main/ai.c', 'main/ai2.c', 'main/aipath.c', 'main/automap.c', 'main/bm.c', 'main/cntrlcen.c', 'main/collide.c', 'main/config.c', 'main/console.c', 'main/controls.c', 'main/credits.c', 'main/digiobj.c', 'main/dumpmine.c', 'main/effects.c', 'main/endlevel.c', 'main/escort.c', 'main/fireball.c', 'main/fuelcen.c', 'main/fvi.c', 'main/game.c', 'main/gamecntl.c', 'main/gamefont.c', 'main/gamemine.c', 'main/gamepal.c', 'main/gamerend.c', 'main/gamesave.c', 'main/gameseg.c', 'main/gameseq.c', 'main/gauges.c', 'main/hostage.c', 'main/hud.c', 'main/inferno.c', 'main/kconfig.c', 'main/kmatrix.c', 'main/laser.c', 'main/lighting.c', 'main/menu.c', 'main/mglobal.c', 'main/mission.c', 'main/morph.c', 'main/movie.c', 'main/multi.c', 'main/multibot.c', 'main/newdemo.c', 'main/newmenu.c', 'main/object.c', 'main/paging.c', 'main/physics.c', 'main/piggy.c', 'main/player.c', 'main/playsave.c', 'main/polyobj.c', 'main/powerup.c', 'main/render.c', 'main/robot.c', 'main/scores.c', 'main/segment.c', 'main/slew.c', 'main/songs.c', 'main/state.c', 'main/switch.c', 'main/terrain.c', 'main/texmerge.c', 'main/text.c', 'main/titles.c', 'main/vclip.c', 'main/wall.c', 'main/weapon.c', 'maths/fixc.c', 'maths/rand.c', 'maths/tables.c', 'maths/vecmat.c', 'mem/mem.c', 'misc/args.c', 'misc/error.c', 'misc/hash.c', 'misc/hmp.c', 'misc/ignorecase.c', 'misc/physfsrwops.c', 'misc/physfsx.c', 'misc/strio.c', 'misc/strutil.c', 'texmap/ntmap.c', 'texmap/scanline.c' ] ] # for editor self.editor_sources = [os.path.join(self.srcdir, f) for f in [ 'editor/centers.c', 'editor/curves.c', 'editor/autosave.c', 'editor/eglobal.c', 'editor/elight.c', 'editor/eobject.c', 'editor/eswitch.c', 'editor/fixseg.c', 'editor/func.c', 'editor/group.c', 'editor/info.c', 'editor/kbuild.c', 'editor/kcurve.c', 'editor/kfuncs.c', 'editor/kgame.c', 'editor/khelp.c', 'editor/kmine.c', 'editor/ksegmove.c', 'editor/ksegsel.c', 'editor/ksegsize.c', 'editor/ktmap.c', 'editor/kview.c', 'editor/med.c', 'editor/meddraw.c', 'editor/medmisc.c', 'editor/medrobot.c', 'editor/medsel.c', 'editor/medwall.c', 'editor/mine.c', 'editor/objpage.c', 'editor/segment.c', 'editor/seguvs.c', 'editor/texpage.c', 'editor/texture.c', 'main/bmread.c', 'ui/button.c', 'ui/checkbox.c', 'ui/dialog.c', 'ui/file.c', 'ui/gadget.c', 'ui/icon.c', 'ui/inputbox.c', 'ui/keypad.c', 'ui/keypress.c', 'ui/keytrap.c', 'ui/listbox.c', 'ui/menu.c', 'ui/menubar.c', 'ui/message.c', 'ui/popup.c', 'ui/radio.c', 'ui/scroll.c', 'ui/ui.c', 'ui/uidraw.c', 'ui/userbox.c' ] ] DXXProgram.__init__(self) sources_use_udp = [os.path.join(srcdir, 'main/net_udp.c')] # SDL_mixer sound implementation arch_sdlmixer = [os.path.join(srcdir, f) for f in [ 'arch/sdl/digi_mixer.c', 'arch/sdl/digi_mixer_music.c', 'arch/sdl/jukebox.c' ] ] # for opengl arch_ogl_sources = [os.path.join(srcdir, f) for f in [ 'arch/ogl/gr.c', 'arch/ogl/ogl.c', ] ] # for non-ogl arch_sdl_sources = [os.path.join(srcdir, f) for f in [ 'arch/sdl/gr.c', 'texmap/tmapflat.c' ] ] # assembler related asm_sources = [os.path.join(srcdir, f) for f in [ 'texmap/tmap_ll.asm', 'texmap/tmap_flt.asm', 'texmap/tmapfade.asm', 'texmap/tmap_lin.asm', 'texmap/tmap_per.asm' ] ] def register_program(self): self._register_program('d2x') program = D2XProgram() # show some help when running scons -h Help(program.PROGRAM_NAME + ', SConstruct file help:' + """ Type 'scons' to build the binary. Type 'scons install' to build (if it hasn't been done) and install. Type 'scons -c' to clean up. Extra options (add them to command line, like 'scons extraoption=value'): 'sharepath=[DIR]' (non-Mac OS *NIX only) use [DIR] for shared game data. [default: /usr/local/share/games/d2x-rebirth] 'opengl=[0/1]' build with OpenGL support [default: 1] 'opengles=[0/1]' build with OpenGL ES support [default: 0] 'opengles_lib=[NAME]' specify the name of the OpenGL ES library to link against 'sdlmixer=[0/1]' build with SDL_Mixer support for sound and music (includes external music support) [default: 1] 'asm=[0/1]' build with ASSEMBLER code (only with opengl=0, requires NASM and x86) [default: 0] 'debug=[0/1]' build DEBUG binary which includes asserts, debugging output, cheats and more output [default: 0] 'profiler=[0/1]' profiler build [default: 0] 'editor=[0/1]' include editor into build (!EXPERIMENTAL!) [default: 0] 'ipv6=[0/1]' enable IPv6 compability [default: 0] 'use_udp=[0/1]' enable UDP support [default: 1] 'use_tracker=[0/1]' enable Tracker support (requires udp) [default :1] 'verbosebuild=[0/1]' print out all compiler/linker messages during building [default: 0] 'raspberrypi=[0/1]' build for Raspberry Pi (automatically sets opengles and opengles_lib) [default: 0] 'rpi_vc_path=[DIR]' use [DIR] to look for VideoCore libraries/header files (RPi only) Default values: """ + ' sharepath = ' + program.user_settings.DATA_DIR + """ """ + ' opengles_lib = ' + program.user_settings.default_OGLES_LIB + """ """ + ' rpi_vc_path = ' + program.user_settings.RPI_DEFAULT_VC_PATH + """ Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags """) #EOF dxx-rebirth-0.58.1-d2x/arch/000077500000000000000000000000001217717237500154715ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/carbon/000077500000000000000000000000001217717237500167355ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/carbon/SDL_main.c000066400000000000000000000362401217717237500205340ustar00rootroot00000000000000/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2004 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org */ #ifdef SAVE_RCSID static char rcsid = "@(#) $Id: SDL_main.c,v 1.1.1.1 2006/03/17 19:54:28 zicodxx Exp $"; #endif /* This file takes care of command line argument parsing, and stdio redirection in the MacOS environment. */ #include #include #include #include #if defined(__APPLE__) && defined(__MACH__) #include #elif TARGET_API_MAC_CARBON #include #else #include #include #include #include #include #endif /* Include the SDL main definition header */ #include #include "SDL_main.h" #ifdef main #undef main #endif /* The standard output files */ #define STDOUT_FILE "stdout.txt" #define STDERR_FILE "stderr.txt" #if !defined(__MWERKS__) && !TARGET_API_MAC_CARBON /* In MPW, the qd global has been removed from the libraries */ QDGlobals qd; #endif /* Structure for keeping prefs in 1 variable */ typedef struct { Str255 command_line; Str255 video_driver_name; Boolean output_to_file; } PrefsRecord; /* See if the command key is held down at startup */ static Boolean CommandKeyIsDown(void) { KeyMap theKeyMap; GetKeys(theKeyMap); if (((unsigned char *) theKeyMap)[6] & 0x80) { return(true); } return(false); } /* Parse a command line buffer into arguments */ static int ParseCommandLine(char *cmdline, char **argv) { char *bufp; int argc; argc = 0; for ( bufp = cmdline; *bufp; ) { /* Skip leading whitespace */ while ( isspace(*bufp) ) { ++bufp; } /* Skip over argument */ if ( *bufp == '"' ) { ++bufp; if ( *bufp ) { if ( argv ) { argv[argc] = bufp; } ++argc; } /* Skip over word */ while ( *bufp && (*bufp != '"') ) { ++bufp; } } else { if ( *bufp ) { if ( argv ) { argv[argc] = bufp; } ++argc; } /* Skip over word */ while ( *bufp && ! isspace(*bufp) ) { ++bufp; } } if ( *bufp ) { if ( argv ) { *bufp = '\0'; } ++bufp; } } if ( argv ) { argv[argc] = NULL; } return(argc); } /* Remove the output files if there was no output written */ static void cleanup_output(void) { FILE *file; int empty; /* Flush the output in case anything is queued */ fclose(stdout); fclose(stderr); /* See if the files have any output in them */ file = fopen(STDOUT_FILE, "rb"); if ( file ) { empty = (fgetc(file) == EOF) ? 1 : 0; fclose(file); if ( empty ) { remove(STDOUT_FILE); } } file = fopen(STDERR_FILE, "rb"); if ( file ) { empty = (fgetc(file) == EOF) ? 1 : 0; fclose(file); if ( empty ) { remove(STDERR_FILE); } } } static int getCurrentAppName (StrFileName name) { ProcessSerialNumber process; ProcessInfoRec process_info; FSSpec process_fsp; process.highLongOfPSN = 0; process.lowLongOfPSN = kCurrentProcess; process_info.processInfoLength = sizeof (process_info); process_info.processName = NULL; process_info.processAppSpec = &process_fsp; if ( noErr != GetProcessInformation (&process, &process_info) ) return 0; memcpy (name, process_fsp.name, process_fsp.name[0] + 1); return 1; } static int getPrefsFile (FSSpec *prefs_fsp, int create) { /* The prefs file name is the application name, possibly truncated, */ /* plus " Preferences */ #define SUFFIX " Preferences" #define MAX_NAME 19 /* 31 - strlen (SUFFIX) */ short volume_ref_number; long directory_id; StrFileName prefs_name; StrFileName app_name; /* Get Preferences folder - works with Multiple Users */ if ( noErr != FindFolder ( kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &volume_ref_number, &directory_id) ) exit (-1); if ( ! getCurrentAppName (app_name) ) exit (-1); /* Truncate if name is too long */ if (app_name[0] > MAX_NAME ) app_name[0] = MAX_NAME; memcpy (prefs_name + 1, app_name + 1, app_name[0]); memcpy (prefs_name + app_name[0] + 1, SUFFIX, strlen (SUFFIX)); prefs_name[0] = app_name[0] + strlen (SUFFIX); /* Make the file spec for prefs file */ if ( noErr != FSMakeFSSpec (volume_ref_number, directory_id, prefs_name, prefs_fsp) ) if ( !create ) return 0; else { /* Create the prefs file */ memcpy (prefs_fsp->name, prefs_name, prefs_name[0] + 1); prefs_fsp->parID = directory_id; prefs_fsp->vRefNum = volume_ref_number; FSpCreateResFile (prefs_fsp, '????', 'pref', 0); if ( noErr != ResError () ) return 0; } return 1; } static int readPrefsResource (PrefsRecord *prefs) { Handle prefs_handle; prefs_handle = Get1Resource( 'CLne', 128 ); if (prefs_handle != NULL) { int offset = 0; HLock(prefs_handle); /* Get command line string */ memcpy (prefs->command_line, *prefs_handle, (*prefs_handle)[0]+1); /* Get video driver name */ offset += (*prefs_handle)[0] + 1; memcpy (prefs->video_driver_name, *prefs_handle + offset, (*prefs_handle)[offset] + 1); /* Get save-to-file option (1 or 0) */ offset += (*prefs_handle)[offset] + 1; prefs->output_to_file = (*prefs_handle)[offset]; ReleaseResource( prefs_handle ); return ResError() == noErr; } return 0; } static int writePrefsResource (PrefsRecord *prefs, short resource_file) { Handle prefs_handle; UseResFile (resource_file); prefs_handle = Get1Resource ( 'CLne', 128 ); if (prefs_handle != NULL) RemoveResource (prefs_handle); prefs_handle = NewHandle ( prefs->command_line[0] + prefs->video_driver_name[0] + 4 ); if (prefs_handle != NULL) { int offset; HLock (prefs_handle); /* Command line text */ offset = 0; memcpy (*prefs_handle, prefs->command_line, prefs->command_line[0] + 1); /* Video driver name */ offset += prefs->command_line[0] + 1; memcpy (*prefs_handle + offset, prefs->video_driver_name, prefs->video_driver_name[0] + 1); /* Output-to-file option */ offset += prefs->video_driver_name[0] + 1; *( *((char**)prefs_handle) + offset) = (char)prefs->output_to_file; *( *((char**)prefs_handle) + offset + 1) = 0; AddResource (prefs_handle, 'CLne', 128, "\pCommand Line"); WriteResource (prefs_handle); UpdateResFile (resource_file); DisposeHandle (prefs_handle); return ResError() == noErr; } return 0; } static int readPreferences (PrefsRecord *prefs) { int no_error = 1; FSSpec prefs_fsp; /* Check for prefs file first */ if ( getPrefsFile (&prefs_fsp, 0) ) { short prefs_resource; prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdPerm); if ( prefs_resource == -1 ) /* this shouldn't happen, but... */ return 0; UseResFile (prefs_resource); no_error = readPrefsResource (prefs); CloseResFile (prefs_resource); } /* Fall back to application's resource fork (reading only, so this is safe) */ else { no_error = readPrefsResource (prefs); } return no_error; } static int writePreferences (PrefsRecord *prefs) { int no_error = 1; FSSpec prefs_fsp; /* Get prefs file, create if it doesn't exist */ if ( getPrefsFile (&prefs_fsp, 1) ) { short prefs_resource; prefs_resource = FSpOpenResFile (&prefs_fsp, fsRdWrPerm); if (prefs_resource == -1) return 0; no_error = writePrefsResource (prefs, prefs_resource); CloseResFile (prefs_resource); } return no_error; } /* This is where execution begins */ int main(int argc, char *argv[]) { #pragma unused(argc, argv) #define DEFAULT_ARGS "\p" /* pascal string for default args */ #define DEFAULT_VIDEO_DRIVER "\ptoolbox" /* pascal string for default video driver name */ #define DEFAULT_OUTPUT_TO_FILE 1 /* 1 == output to file, 0 == no output */ #define VIDEO_ID_DRAWSPROCKET 1 /* these correspond to popup menu choices */ #define VIDEO_ID_TOOLBOX 2 PrefsRecord prefs = { DEFAULT_ARGS, DEFAULT_VIDEO_DRIVER, DEFAULT_OUTPUT_TO_FILE }; int nargs; char **args; char *commandLine; StrFileName appNameText; int videodriver = VIDEO_ID_TOOLBOX; int settingsChanged = 0; long i; /* Kyle's SDL command-line dialog code ... */ #if !TARGET_API_MAC_CARBON InitGraf (&qd.thePort); InitFonts (); InitWindows (); InitMenus (); InitDialogs (nil); #endif InitCursor (); FlushEvents(everyEvent,0); #if !TARGET_API_MAC_CARBON MaxApplZone (); #endif MoreMasters (); MoreMasters (); #if 0 /* Intialize SDL, and put up a dialog if we fail */ if ( SDL_Init (0) < 0 ) { #define kErr_OK 1 #define kErr_Text 2 DialogPtr errorDialog; short dummyType; Rect dummyRect; Handle dummyHandle; short itemHit; errorDialog = GetNewDialog (1001, nil, (WindowPtr)-1); DrawDialog (errorDialog); GetDialogItem (errorDialog, kErr_Text, &dummyType, &dummyHandle, &dummyRect); SetDialogItemText (dummyHandle, "\pError Initializing SDL"); SetPort (errorDialog); do { ModalDialog (nil, &itemHit); } while (itemHit != kErr_OK); DisposeDialog (errorDialog); exit (-1); } atexit(cleanup_output); atexit(SDL_Quit); #endif /* Set up SDL's QuickDraw environment */ #if !TARGET_API_MAC_CARBON SDL_InitQuickDraw(&qd); #endif if ( readPreferences (&prefs) ) { if (memcmp (prefs.video_driver_name+1, "DSp", 3) == 0) videodriver = 1; else if (memcmp (prefs.video_driver_name+1, "toolbox", 7) == 0) videodriver = 2; } if ( CommandKeyIsDown() ) { #define kCL_OK 1 #define kCL_Cancel 2 #define kCL_Text 3 #define kCL_File 4 #define kCL_Video 6 DialogPtr commandDialog; short dummyType; Rect dummyRect; Handle dummyHandle; short itemHit; /* Assume that they will change settings, rather than do exhaustive check */ settingsChanged = 1; /* Create dialog and display it */ commandDialog = GetNewDialog (1000, nil, (WindowPtr)-1); SetPortDialogPort (commandDialog); /* Setup controls */ GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ SetControlValue ((ControlHandle)dummyHandle, prefs.output_to_file ); GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); SetDialogItemText (dummyHandle, prefs.command_line); GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect); SetControlValue ((ControlRef)dummyHandle, videodriver); SetDialogDefaultItem (commandDialog, kCL_OK); SetDialogCancelItem (commandDialog, kCL_Cancel); do { ModalDialog(nil, &itemHit); /* wait for user response */ /* Toggle command-line output checkbox */ if ( itemHit == kCL_File ) { GetDialogItem(commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ SetControlValue((ControlHandle)dummyHandle, !GetControlValue((ControlHandle)dummyHandle) ); } } while (itemHit != kCL_OK && itemHit != kCL_Cancel); /* Get control values, even if they did not change */ GetDialogItem (commandDialog, kCL_Text, &dummyType, &dummyHandle, &dummyRect); /* MJS */ GetDialogItemText (dummyHandle, prefs.command_line); GetDialogItem (commandDialog, kCL_File, &dummyType, &dummyHandle, &dummyRect); /* MJS */ prefs.output_to_file = GetControlValue ((ControlHandle)dummyHandle); GetDialogItem (commandDialog, kCL_Video, &dummyType, &dummyHandle, &dummyRect); videodriver = GetControlValue ((ControlRef)dummyHandle); DisposeDialog (commandDialog); if (itemHit == kCL_Cancel ) { exit (0); } } /* Set pseudo-environment variables for video driver, update prefs */ switch ( videodriver ) { case VIDEO_ID_DRAWSPROCKET: SDL_putenv ("SDL_VIDEODRIVER=DSp"); memcpy (prefs.video_driver_name, "\pDSp", 4); break; case VIDEO_ID_TOOLBOX: SDL_putenv ("SDL_VIDEODRIVER=toolbox"); memcpy (prefs.video_driver_name, "\ptoolbox", 8); break; } /* Redirect standard I/O to files */ if ( prefs.output_to_file ) { freopen (STDOUT_FILE, "w", stdout); freopen (STDERR_FILE, "w", stderr); } else { fclose (stdout); fclose (stderr); } if (settingsChanged) { /* Save the prefs, even if they might not have changed (but probably did) */ if ( ! writePreferences (&prefs) ) fprintf (stderr, "WARNING: Could not save preferences!\n"); } getCurrentAppName (appNameText); /* check for error here ? */ commandLine = (char*) malloc (appNameText[0] + prefs.command_line[0] + 2); if ( commandLine == NULL ) { exit(-1); } /* Rather than rewrite ParseCommandLine method, let's replace */ /* any spaces in application name with underscores, */ /* so that the app name is only 1 argument */ for (i = 1; i < 1+appNameText[0]; i++) if ( appNameText[i] == ' ' ) appNameText[i] = '_'; /* Copy app name & full command text to command-line C-string */ memcpy (commandLine, appNameText + 1, appNameText[0]); commandLine[appNameText[0]] = ' '; memcpy (commandLine + appNameText[0] + 1, prefs.command_line + 1, prefs.command_line[0]); commandLine[ appNameText[0] + 1 + prefs.command_line[0] ] = '\0'; /* Parse C-string into argv and argc */ nargs = ParseCommandLine (commandLine, NULL); args = (char **)malloc((nargs+1)*(sizeof *args)); if ( args == NULL ) { exit(-1); } ParseCommandLine (commandLine, args); /* Run the main application code */ SDL_main(nargs, args); free (args); free (commandLine); /* Remove useless stdout.txt and stderr.txt */ cleanup_output (); /* Exit cleanly, calling atexit() functions */ exit (0); /* Never reached, but keeps the compiler quiet */ return (0); } dxx-rebirth-0.58.1-d2x/arch/carbon/conf.h000066400000000000000000000032311217717237500200320ustar00rootroot00000000000000/* conf.h. Generated by configure. */ /* conf.h.in. Generated from configure.ac by autoheader. */ // Modified by Chris to work for an Apple computer with OS 9 or above /* Define to enable console */ /* #undef CONSOLE */ /* d2x major version */ #define DXX_VERSION_MAJORi 0 /* d2x minor version */ #define DXX_VERSION_MINORi 58 /* d2x micro version */ #define DXX_VERSION_MICROi 1 /* Define if you want to build the editor */ /* #undef EDITOR */ /* Define if you want to build for mac datafiles */ //#define MACDATA /* Define to disable asserts, int3, etc. */ /* #undef NDEBUG */ /* Define if you want an assembler free build */ #define NO_ASM /* Define if you want an OpenGL build */ //#define OGL /* Define for a "release" build */ /* #undef RELEASE */ /* Define this to be the shared game directory root */ #define SHAREPATH "." /* Define if your processor needs data to be word-aligned */ /* #undef WORDS_NEED_ALIGNMENT */ /* General defines */ #if defined(__APPLE__) && defined(__MACH__) # define __unix__ /* Define if you want a network build */ # define NETWORK # define USE_UDP # define USE_TRACKER //#define IPv6 /* Define to 1 if the system has the type `struct timespec'. */ #define HAVE_STRUCT_TIMESPEC 1 /* Define to 1 if the system has the type `struct timeval'. */ #define HAVE_STRUCT_TIMEVAL 1 #else // Mac OS 9 # ifndef __MWERKS__ # define inline # endif #define OGL_RUNTIME_LOAD // avoids corruption of OpenGL /* Define to 1 if the system has the type `struct timespec'. */ #define HAVE_STRUCT_TIMESPEC 0 /* Define to 1 if the system has the type `struct timeval'. */ #define HAVE_STRUCT_TIMEVAL 0 #endif // OS 9/X #define SDL_INPUT 1 dxx-rebirth-0.58.1-d2x/arch/carbon/descent.r000077500000000000000000000106501217717237500205520ustar00rootroot00000000000000#include "Processes.r" resource 'SIZE' (-1) { reserved, acceptSuspendResumeEvents, reserved, canBackground, doesActivateOnFGSwitch, backgroundAndForeground, getFrontClicks, ignoreAppDiedEvents, is32BitCompatible, isHighLevelEventAware, onlyLocalHLEvents, notStationeryAware, useTextEditServices, reserved, reserved, reserved, 50000*1024, // 50 megs maximum 30000*1024 // 30 megs minimum }; data 'DLOG' (1000) { $"0072 0040 00EA 01B3 0001 0100 0000 0000 0000 03E8 0C43 6F6D 6D61 6E64 204C 696E" /* .r.@.ê.³...........è.Command Lin */ $"6500 280A" /* e.( */ }; data 'DLOG' (1001) { $"0072 0040 00DB 01AC 0001 0100 0000 0000 0000 03E9 0C45 7272 6F72 2057 696E 646F" /* .r.@.Û.¬...........é.Error Windo */ $"7700 280A" /* w.( */ }; data 'DLOG' (1002) { $"00B8 00BE 0147 01D8 0005 0100 0000 0000 0000 03EA 1643 6F6E 6669 726D 2044 6973" /* .¸.¾.G.Ø...........ê.Confirm Dis */ $"706C 6179 2043 6861 6E67 6510 280A" /* play Change.( */ }; data 'DITL' (1000) { $"0005 0000 0000 0052 0113 0066 0158 0402 4F4B 0000 0000 0052 00C2 0066 0107 0406" /* .......R...f.X..OK.....R.Â.f.... */ $"4361 6E63 656C 0000 0000 000F 0084 001F 0155 1000 0000 0000 0054 0019 0066 007D" /* Cancel.......„...U.......T...f.} */ $"050E 4F75 7470 7574 2074 6F20 6669 6C65 0000 0000 000F 0018 001F 007F 080D 436F" /* ..Output to file..............Co */ $"6D6D 616E 6420 4C69 6E65 3A00 0000 0000 0030 0018 0040 0158 0702 0080" /* mmand Line:......0...@.X...€ */ }; data 'DITL' (1001) { $"0001 0000 0000 0046 0120 005A 015A 0402 4F4B 0000 0000 0010 000A 0038 0160 0800" /* .......F. .Z.Z..OK.......Â.8.`.. */ }; data 'DITL' (1002) { $"0002 0000 0000 006F 001E 0083 0058 0406 4361 6E63 656C 0000 0000 006E 00C0 0082" /* .......o...Æ’.X..Cancel.....n.À.‚ */ $"00FA 0402 4F4B 0000 0000 000E 000F 005F 010C 88B3 5468 6520 7365 7474 696E 6720" /* .ú..OK........._..ˆ³The setting */ $"666F 7220 796F 7572 206D 6F6E 6974 6F72 2068 6173 2062 6565 6E20 6368 616E 6765" /* for your monitor has been change */ $"642C 2061 6E64 2069 7420 6D61 7920 6E6F 7420 6265 2064 6973 706C 6179 6564 2063" /* d, and it may not be displayed c */ $"6F72 7265 6374 6C79 2E20 546F 2063 6F6E 6669 726D 2074 6865 2064 6973 706C 6179" /* orrectly. To confirm the display */ $"2069 7320 636F 7272 6563 742C 2063 6C69 636B 204F 4B2E 2054 6F20 7265 7475 726E" /* is correct, click OK. To return */ $"2074 6F20 7468 6520 6F72 6967 696E 616C 2073 6574 7469 6E67 2C20 636C 6963 6B20" /* to the original setting, click */ $"4361 6E63 656C 2E00" /* Cancel.. */ }; data 'MENU' (128, preload) { $"0080 0000 0000 0000 0000 FFFF FFFB 0114 0C41 626F 7574 2053 444C 2E2E 2E00 0000" /* .€........ÿÿÿû...About SDL...... */ $"0001 2D00 0000 0000" /* ..-..... */ }; data 'MENU' (129) { $"0081 0000 0000 0000 0000 FFFF FFFF 0C56 6964 656F 2044 7269 7665 7219 4472 6177" /* .Â........ÿÿÿÿ.Video Driver.Draw */ $"5370 726F 636B 6574 2028 4675 6C6C 7363 7265 656E 2900 0000 001E 546F 6F6C 426F" /* Sprocket (Fullscreen).....ToolBo */ $"7820 2028 4675 6C6C 7363 7265 656E 2F57 696E 646F 7765 6429 0000 0000 00" /* x (Fullscreen/Windowed)..... */ }; data 'CNTL' (128) { $"0000 0000 0010 0140 0000 0100 0064 0081 03F0 0000 0000 0D56 6964 656F 2044 7269" /* .......@.....d.Â.ð.....Video Dri */ $"7665 723A" /* ver: */ }; data 'TMPL' (128, "CLne") { $"0C43 6F6D 6D61 6E64 204C 696E 6550 5354 520C 5669 6465 6F20 4472 6976 6572 5053" /* .Command LinePSTR.Video DriverPS */ $"5452 0C53 6176 6520 546F 2046 696C 6542 4F4F 4C" /* TR.Save To FileBOOL */ }; dxx-rebirth-0.58.1-d2x/arch/carbon/messagebox.c000066400000000000000000000043031217717237500212360ustar00rootroot00000000000000/* * messagebox.c * d1x-rebirth * * Display an error or warning messagebox using the OS's window server. * */ #ifdef __APPLE__ #include #else #include #endif #include "window.h" #include "event.h" #include "messagebox.h" void display_mac_alert(char *message, int error) { window *wind; d_event event; int fullscreen; bool osX = FALSE; uint response; int16_t itemHit; // Handle Descent's windows properly if ((wind = window_get_front())) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); if (grd_curscreen && (fullscreen = gr_check_fullscreen())) gr_toggle_fullscreen(); osX = ( Gestalt(gestaltSystemVersion, (long *) &response) == noErr) && (response >= 0x01000 ); ShowCursor(); if (osX) { #ifdef TARGET_API_MAC_CARBON DialogRef alert; CFStringRef error_text = CFSTR("Sorry, a critical error has occurred."); CFStringRef text = NULL; text = CFStringCreateWithCString(CFAllocatorGetDefault(), message, kCFStringEncodingMacRoman); if (!text) { if (wind) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); return; } if (CreateStandardAlert(error ? kAlertStopAlert : kAlertNoteAlert, error ? error_text : text, error ? text : NULL, 0, &alert) != noErr) { CFRelease(text); if (wind) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); return; } RunStandardAlert(alert, 0, &itemHit); CFRelease(text); #endif } else { // This #if guard removes both compiler warnings // and complications if we didn't link the (older) Mac OS X SDK that actually supports the following. #if !defined(MAC_OS_X_VERSION_MAX_ALLOWED) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_4) Str255 error_text = "\pSorry, a critical error has occurred."; Str255 text; CopyCStringToPascal(message, text); StandardAlert(error ? kAlertStopAlert : kAlertNoteAlert, error ? error_text : text, error ? text : NULL, 0, &itemHit); #endif } if ((wind = window_get_front())) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); if (grd_curscreen && !error && fullscreen) gr_toggle_fullscreen(); } void msgbox_warning(char *message) { display_mac_alert(message, 0); } void msgbox_error(const char *message) { display_mac_alert(message, 1); } dxx-rebirth-0.58.1-d2x/arch/cocoa/000077500000000000000000000000001217717237500165555ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/cocoa/SDLMain.h000066400000000000000000000004631217717237500201600ustar00rootroot00000000000000/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject @end dxx-rebirth-0.58.1-d2x/arch/cocoa/SDLMain.m000066400000000000000000000256751217717237500202010ustar00rootroot00000000000000/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #include "SDL.h" #include "SDLMain.h" #include /* for MAXPATHLEN */ #include /* For some reaon, Apple removed setAppleMenu from the headers in 10.4, but the method still is there and works. To avoid warnings, we declare it ourselves here. */ @interface NSApplication(SDL_Missing_Methods) - (void)setAppleMenu:(NSMenu *)menu; @end /* Use this flag to determine whether we use SDLMain.nib or not */ #define SDL_USE_NIB_FILE 0 /* Use this flag to determine whether we use CPS (docking) or not */ #define SDL_USE_CPS 1 #ifdef SDL_USE_CPS /* Portions of CPS.h */ typedef struct CPSProcessSerNum { UInt32 lo; UInt32 hi; } CPSProcessSerNum; extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ static int gArgc; static char **gArgv; static BOOL gFinderLaunch; static BOOL gCalledAppMainline = FALSE; static NSString *getApplicationName(void) { const NSDictionary *dict; NSString *appName = 0; /* Determine the application name */ dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); if (dict) appName = [dict objectForKey: @"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; return appName; } #if SDL_USE_NIB_FILE /* A helper category for NSString */ @interface NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #endif @interface NSApplication (SDLApplication) @end @implementation NSApplication (SDLApplication) /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { if (shouldChdir) { char parentdir[MAXPATHLEN]; CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); if (CFURLGetFileSystemRepresentation(url2, 1, (UInt8 *)parentdir, MAXPATHLEN)) { chdir(parentdir); /* chdir to the binary app's parent */ } CFRelease(url); CFRelease(url2); } } #if SDL_USE_NIB_FILE /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { NSRange aRange; NSEnumerator *enumerator; NSMenuItem *menuItem; aRange = [[aMenu title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; enumerator = [[aMenu itemArray] objectEnumerator]; while ((menuItem = [enumerator nextObject])) { aRange = [[menuItem title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; if ([menuItem hasSubmenu]) [self fixMenu:[menuItem submenu] withAppName:appName]; } } #else static void setApplicationMenu(void) { /* warning: this code is very odd */ NSMenu *appleMenu; NSMenuItem *menuItem; NSString *title; NSString *appName; appName = getApplicationName(); appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [@"About " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; /* Finally give up our references to the objects */ [appleMenu release]; [menuItem release]; } /* Create a window menu */ static void setupWindowMenu(void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [NSApplication sharedApplication]; #ifdef SDL_USE_CPS { CPSProcessSerNum PSN; /* Tell the dock about us */ if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) [NSApplication sharedApplication]; } #endif /* SDL_USE_CPS */ /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setApplicationMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Start the main event loop */ [NSApp run]; [sdlMain release]; [pool release]; } #endif /* * Catch document open requests...this lets us notice files when the app * was launched by double-clicking a document, or when a document was * dragged/dropped on the app's icon. You need to have a * CFBundleDocumentsType section in your Info.plist to get this message, * apparently. * * Files are added to gArgv, so to the app, they'll look like command line * arguments. Previously, apps launched from the finder had nothing but * an argv[0]. * * This message may be received multiple times to open several docs on launch. * * This message is ignored once the app's mainline has been called. */ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { const char *temparg; size_t arglen; char *arg; char **newargv; if (!gFinderLaunch) /* MacOS is passing command line args. */ return FALSE; if (gCalledAppMainline) /* app has started, ignore this document. */ return FALSE; temparg = [filename UTF8String]; arglen = SDL_strlen(temparg) + 1; arg = (char *) SDL_malloc(arglen); if (arg == NULL) return FALSE; newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); if (newargv == NULL) { SDL_free(arg); return FALSE; } gArgv = newargv; SDL_strlcpy(arg, temparg, arglen); gArgv[gArgc++] = arg; gArgv[gArgc] = NULL; return TRUE; } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE /* Set the main menu to contain the real app name instead of "SDL App" */ [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; #endif /* Hand off to main application code */ gCalledAppMainline = TRUE; status = SDL_main (gArgc, gArgv); /* We're done, thank you for playing */ exit(status); } @end @implementation NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = (unichar *)NSAllocateMemoryPages(bufferSize*sizeof(unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages(buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { /* Copy the arguments into a global variable */ /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgv = (char **) SDL_malloc(sizeof (char *) * 2); gArgv[0] = argv[0]; gArgv[1] = NULL; gArgc = 1; gFinderLaunch = YES; } else { int i; gArgc = argc; gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); for (i = 0; i <= argc; i++) gArgv[i] = argv[i]; gFinderLaunch = NO; } #if SDL_USE_NIB_FILE NSApplicationMain (argc, argv); #else CustomApplicationMain (argc, argv); #endif return 0; } dxx-rebirth-0.58.1-d2x/arch/cocoa/d2x-rebirth.icns000066400000000000000000001614621217717237500215770ustar00rootroot00000000000000icnsã2ics#Hÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿis32Í„'ˆƒ“ŒŠ‰%ƒ GÀ´ðÿõÿõ/‚ ?<eæÿÿé,€ 2*3ØÿØ*€l>$5!Tæ¾' H&'(U>4­Ð" (4/eQ&iã3 .+=4EBå; #CWl@>Í="[CZ9oÙ3 $`'63Ëï,€  !C#?@xÛÙ, %0A §üñÕ3‚ }”æÿþöÚ4„9ôîðóóíÄ+„7:50 „$ƒ’Šˆ‰%ƒ TË´ìÿôÿô/ -N•;{éþÿè,€|d™Œ^‚eTÞÿ×*Y®ÆµƒV|Y;Šä¹#!x²Å²¤žƒy-¼Ê"1g•¥®¤‚¬ a&…ß31Ol“†˜†”K+bã;-FUfo—­Â†QC\Ê=!>KVe®cˆ yI‚Ô/ 6AUj©fzo-)Ðí*€ 3b”_……..ˆÖ×, c^}¬9?ºùðÓ3‚ 8³«íÿüöØ4„5îêíóóíÁ+„ 7:50 „%Œ•’‘”‰%ƒnøäú€ÿú7 (Áäã±Ì÷ýÿî3€JãÿíÔßÈ¢¿õÿå3#ÛÿÿúçÒàÆ´Ýô×/ñúÿûõèîáÕ¬ëÞ, ¨Ûïøùúó÷òϦÕê4ªÇÝëöýüñðÅ©Æí;£¾ÏßîüýýäɸÂß;йÅÔãúçìëÖ¼Ðã4H¸¹ÊÞôÙàÒ«§ïð3 y¸ÐäÎßÚ­¬Ïëç4€ fÍÒáð±´ëüøä4‚'ZŽïçþ€ÿè;„>ôîðòóò×0„7750 s8mkÑéææææææææææææì|ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿ›æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–æÿÿÿÿÿÿÿÿÿÿÿÿÿÿ–òÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆ§¢¢¢¢¢¢¢¢¢¢¢¢©hICN#ÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþil32 nŒ€  &&#" #(%hÕÂÀÙÞßÙ×ÖÚÝàäÞ. ‡ÿéÑéÿüìãÿà‹ E›–¯ˆµÅûñ¾ö€ÿæ"‰fjO 9Ûóøúÿÿþùø.‡ +(@N@´ÿúøúÿÿÚ† € } •õêôÿòÈ%… 3a  Œòþùéß)„ %( 1[ ÃûØÔ¹ƒ 'MS0PA (CÛÎʯ!ƒ +X^50N [,ˆôᵂ 47&)R963¯QC1 Füì¬"‚ /7%_hÕY5`" ÕêÊ&‚ EC'%:g0 éæ.‚ $I/*-'$8O zóò,‚ "#*/(d_Dh mïé-‚  %)*/iw‰xv1 eÌØ0‚ !&'.ƒV%$–E oÁá/‚ $ Rt&"l+?k\8*”Òç2‚  nE$j¯I/ 8Åìă K“3W ‚õüÞ!ƒ -/Sz= V) )Âýúå*„ 33[^!Bw7  sÊÞýë)… 3O6 wGË;ÚÑ"†9 69#}"±þìêëÓ½%ˆQ,T?NJ VÔÿ÷ðùÿõê2ˆ -]3^¸ÿÿúþéèê×ó09žÁÎêÿõ÷ÿüøúíÜÉ+]ýÿïÏí‚ÿþíÖ¾)pø÷÷êðƒøêÝÛ*0-131ƒ0)0/žŒ  %&#! #(%eÓÀ½ØÜÝ×ÕÔÙÜàäÞ. ‚ÿ½¢Îèÿûêâÿß‹Z·§·ƒ®Àûñ»õÿÿþå"ˆ,_ÅΧ=F[¨Þïøúÿÿþùø.‡D]\P~x®¥, 0cÄûùùúÿÿØ…0d…s]MWØV*1=¯óçóÿñÅ$„;tŒ ¨¢zgV|²V29)6©îýùèÝ)„+n–¬¸½µ¥saIx¥L=0(XÙ÷ÖѵƒU}ŸºÆÇ½­—}j_H›Š9Rs}|ÛÊÆª ‚4f‡§ºÇʽ®˜Šx^Q˜?°j**¡ðూ@a„£²º¼´¨¨Å¨‡…ð›4’o0%mþê§"‚!C[{“¥®®« ´œ|±Áûˆ¨Z6*FáæÆ&‚+@Sk‘™ž›½µ}pf‰¸zTB>.5¥ää.+:J]n{†Š•µ–„{s[ƒšGG=0,—íñ+,;DR]ht{ƒ„Ѿd½GH=5)‰êè,.6@LU^fow{}ÁÎàÓÌxGF;,.}Æ×0%2DIMW^for€Ö¨oÞw@GFRO=ºá/‚18FKPW_ef£Èfjj¼ˆ²ª‡iC™Íæ2‚ /6>DLS\\aŦaeV¬ó‹iS4 [ÂéÁ‚#38CHNPYTÎVWOzA=80&—ôû݃ 09>ACruT®·‘]L§i:?9(KÀüùã)„47:>{„µ²?^̃@?5(3|ÄÜýê)„538§vC7YÈ“69=%C£ÄʹÙÏ!…*H¢=5|ƒŠÑH-+LÉûêéêѹ%‡Jž-‡ªÄÈ;3{æûõðùÿóé2ˆ"M''†Á`ÐÿÿøýççéÕó0ŒD¯ÐÒèÿóöÿüøúìÚÆ+XøÿìËì‚ÿþìÓº'nø÷öéïƒøéÛÙ*0-131ƒ0)1/žŒ&##!%''&%#%&(&zâØ×áãä€âááãåß. ‹ÿßÑé÷ÿÿùôÿð(Š '5žôáá¼ÑÜýøÙù€ÿð*ˆ)w¤Íòûï¾ºÇæñõüü€ÿþø0†wÌãÚÎÞÙõè§Ÿ¯Ëí€üýÿÿè%…/®ññêåÝÒÈÓÿƧ§Ÿ¸ìùóùÿùà+„.Åøô÷÷óëáÖÌÜðÅ­®£¶ìõþüôì,ƒ©ôôûýýúôêÞÕÈÝëÁµª¥ÌûùêéØ&ƒläí÷ýÿÿýøïæÝ×Ëëä·ÀÔØÞðãäÓ)‚!ºâíøýÿÿýùñîæÛÕîéÁïʧ«äöñÖ'‚hÍØéõûþþüù÷û÷ëíÿíÄåÌ«£ÑÿôÑ*‘ÅÒâïöûûùøü÷ðøûÿýêïȯ¤ºùóá,£¼ÊÚæîóõöûüöõîéñüå̼µ¥³ãñð/ )¨³ÁÑÝæìðôü€û ÷ñâíïÊ¿´§¬âõö/ /©±»ÉÓÜåëñõû€ÿ ýìöøÊÀ¶«©Úõñ/ )ª¯¸ÅÍÖÞæîôù‚ÿ úÞÆÁ´¦¯Ñâê0šª¹¿ÇÑØâéï÷ÿûôúþÞÍȽ¼¸ËÜï/ˆ¬­½ÃËÓÛâéùþïèéüêçðìáÊ·Òçñ0‚`°«¶½ÇÎ×ÙæýùåàÚðÿàÎïŸÆâõÞ%‚¬¯¹ÂÉÍÖØïùÚÖÑáêÁ¶°¦¨Ûøÿì'ƒ_³¯³¸¿×ÜÛùòèÒÎðѵµ¯¥½àþýï.ƒ‹±­±ºÚáöñÅÏå÷໵«¤´Äßïÿó.„!—¶¨¶åëÑ¿¹Íöà¶±°¡¿àÞåÝíå)…)‹¬¿ó¹±Ôáïø»¦¢¡ÃöûôôõéÛ+†`µí±äíãû÷³Ÿ±Ùÿûû÷üÿúò0ˆ!cŒÀ¬°ÛôÎÛùÿÿüþóôôëö0Š&Šîôîôÿùûÿþüýöîà.sÿÿöçøƒÿ÷ìÞ-ƒ€øñôƒøòíè,2/011ƒ0.1/žl8mkØëêêêêêêêêêêêêêêêêêêêêêêêêêêêïÈíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëAêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíIêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGêÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìGñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðGÑïïîîîîîîîîîîîîîîîîîîîîîîîîîîðàJ*_`__________________________`a/ich#Hÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþÿÿÿÿþih32yô'vtzsxttˆ‹‡Žƒƒy‡xŽŽ+–DÖôáÎâÿõýÿçüóìõüƒÿO–Jñæ½£ÝôõÿóñààòúÿþùûøÛ0–@á𼳦†™¼ïÿýôÈÀƒÿ×.” \cp ±€¨Ä“àÿùÄÏÿþÿÿüýô=‘[lb„*$>qÏäëêúƒÿõöÿF tdD…,:™Øò÷ùüƒÿö: 4 +Ìòðùóð€ÿúÆ&Œ  ‡Q )›íðçê€ÿ×É9‹ € \b)  $›ãèöüýðãêCŠ" +˜5 ©ìúÿñääÝ5‰  %)%€ -n! 9ÓýäÜÓ̱-‰# ,?G:( Vu =&bìØ¾Åι5ˆ  :YeN1 €%rS4›ãÚÐã2‡%  :XdM2!j(.‡ >Ðëéн2‡% ,>F9(/@1d¶]" »þøÛ±4†& &)% :ƒ96q3qü‰t+ ~ýòºª<†& ,"!i_râ—GN\p RêìâÜ9†& R4!''"$6ŽA.* *±ÙèàE†&  C{-&*))(&1q5 “ÛñòG†& $K)(,-.++)&?i áúõA…' ! '+/0-8N&"!6ƒ ‚áöïC…' !$')-1+0’²•5,š` sØßçF†& "%(*-*I“n>•˜tr r¿ÃåG†& #&'*'mŠR&)"š |²ÅîB†& "%&&6½O Tèýõóà=ˆ$ C6Y—`7Og $‘äøøñç>‰# #HPz ER9Jm   [ÁÜîýþò@‰# J=cš(ކ E‹³ÌÎïùå>Š" jP3hl ]µ¿Û»ÏéÙ8‹! 1  *Ái lÞìëÝÚ×ËÆ¶.N5 /ji@U1 ‹êÿöãñûøóÆÛFŽ„jL'bLS, E®ýõïøôøÿþÿñ÷I RŠ/ @¢ðÿÿñûúçßñöÙáûG’ 0Lc»æþûöþÿÿþéèòãÈèùK– ‘¿Øä×âþÿòìýÿÿøüÿûðïÄÊ?– "ÁõÿñÛÅáöýÿüüþòÚìÂÂ:–/Ú÷ÿÿòÖØ÷…ÿüö×Á×A–;êøýÿýùö†ÿýëçðìC–HCCIIJJ†IG=EJHßô%ssyqvrr‡Š†Ž‚‚~w†wŽŽ+–BÒóßËàþôüÿåûñêóûÿþÿO–Iî㹘žÜôôÿòðÞßóúÿþùúøÙ.–=áò·®Ÿ”¸ïÿýôƽþ‚ÿÕ-“ *’º¾}¡¾ÞÿøÁÌÿþÿÿüüô<.N©ÝÑÑ0ROHkÊ·»é|-%#0j¶Ýïöùüƒÿö9H_fgeXR\JOãz)/,#+SÜðïùòð€ÿùÃ$‹!-Zk{„‚wl_XTTßž)454**V´íîæéþÿÿÔÆ9Š" ;ew„•›—“‰~pdZR¨¾l;9633"T»äåöûýïâèC‰#:e}žª°±ªŒ~odYLtéx2<<51'EÅèùÿðãâÛ4‰#(`w𧝹¼¹³¨œˆwi_VI{»bAA:42(fáüâÚÐɬ,ˆ$Lj€›¯¼ÁÃÀ¹°¤qf]XD›¾L?91I¦”˜ëÕ»ÁË´4‡%7ZuФµ¿ÈÌż²¤•ˆvkb\RrÍ^BS›‡]HL°à×Í¿ž1‡%Kb|‘§´½ÇËÄ»²¦˜‰~ke_YfËiBuáD/-&hÔéèι1†&.Faw‘¥°·½Á½µ¯¦”¥Ë™l]hÑï^GOÃ[55-@ÏýøÙ¬2†&9G^rœª±µµ´¯©¡ÀÞ¤™Â™ÅÿèmIN¿g570(Ÿýñ·¥;†&GNTZ`ekquyzˆ©äÁ¬íîØ³_MKHB92+B„¹ÀãG…''12HLHOVZ_ekptv~ÊÝ£rwŠç¿PQQH=:7-2I‰¬ÁíB†&/1?CJKPWZ`ejom‰÷•koqoǦIQ[Zs}“™LQ•¶ÜõG†&.05=MGMQW[_dhiºÛvkjieƦy¦ÎâÇ‹rP(n¬¿ÝëK†& )05;AEJPS[^^cuä¿jieaV¥÷ù”feJ4*%2оÛܯ-†&049?DGR•„Vj¾Î²ŠMGF·EB>?76$K•á÷øðå=ˆ$'=2<=?>bžLT³ÍLYœž€Àd@@:73/3q¼Ùíýþñ?‰#(1568DVšÇêxBJBbâç];C@6/*-`†®ÉËïùä>Š"0415?UÀ©tZDFF\»Ç\=;:;<(:…¹ºÙ¾¶ÍèÖ7‹!*,57s—076=GE©ÿ©/8632,*˜æèêÛØÕɲ-Œ !)AÄ€/1ÄÄžs¾~+1/'H±ñüõâðüøòÂÙE?ØS-[Ó—n¿Ê׉')(5sÌÿóíøó÷ÿþÿðöI',-wc.-KÎþ‡ˆ$ ©éìôùüýýûúõðèàÙÔÍÈâóι¸²¬©©Øûýðìèå×:‡ ÜæðöüþüùôìåßÚÕÑÈæøÈ¶°®Ãèêï÷éÛàæÝ?‡%CÇÝçñ÷üþÿÿþýúõïëäÞÚÕÑáüÖ¼ÈäÝɹÇçïëçàÏ=†&‡ÔÛèñøüþÿÿþýûöñîéâÞÙ×åþÚÁÚþºª¦¥ÕíôôèÞ=†AºÊÙåîöûý€þüû÷òõüóäÜçýþØÄÉöí­£Â÷ýûí×>…'tÃÆÕàëòùûýýüûù÷üþ÷ôúöýÿÿëÎÐö˯®¦¨çýùÛÓB…'”½ÃÑÜçíó÷úúùúøùüöñí÷ùûÿÿýñòô²¯ª¢ÛúôñïA…'%¡¶¾ÌÖáèîòõö÷÷öýûõõóïëëôÿøèÚǽ¶±§£ÍééõñF…':­´ºÆÑÛâêìïòóõûÿûøøöòîéæïùâÍÆ¾·²¨¢ÈäèùúH…G©«µ¿ËÔÛâçëîðôúü€ûü÷÷ðåáñûÔÆÂ¸°«žÁêìýûE…'Oª­¶ºÅÎÕÛâçêïòôøûÿþþÿÿúæçøýÕÄÀ¸±­¢¸äìüøF…J¯­°¹ÄÊÏÖÜâæëðô÷ûƒÿøúÿ÷ÐÅļ³®£½×èðôH…A¬°®¶¿ÇÌÓØÞãéïòôú…ÿðÙÉÅÁ¹±©£ÂÐÚáôH…'0 ¨©¼ÀÀÈÐÔÚàæëïòúÿÿýõøþÿñÕÐ͹·µ«ªÄÌÔâøF…'“¨§´¹ÁÄËÒÖÜâçêïøÿûòìîñÿïÒÓØÐÒ×âäºÃÌÛïûH…'€«§¬´ÄÀÇÍÒØÛáåîüÿôéççæúûêðùýùæÔ½¤ÎÕßðöJ†&Z¯¦«²º¾ÄÊÎ×ÙÛáôÿþíæâÞÛðÿÿåÐϳ¦´×ÝîïØ;†&&—ªª±³ºÂÆÊÏÕ×ÛçùÿåßÝÚÔßüïɽµ¯±§£Ëàìùÿí7†&`ª£ª°º½ÃÉÉÏÖÖ×íÿåÓÕÔÐÕôÍ¿º¹³©£©ÉôþúúñC‡%!š«­°´µ»ÂËèáÕíüùôåÎÉËíñÀºµµ­¬£ÂÍðûûøóD‡%K¨²©²³·¹ÌèÌ×ýøÑÓèéÞçøÓº¶±®«§·ÈÜí÷þÿúEˆ$o¬§¬­¯¼ÑåëùÿÞÀÄÃÚÿÿÔ¸¹¶®¥£³Ã¾ÔäæøýóD‰#s³¬¨«¸ÔùêÔË¿¿ÀÒñ÷͹±²°¯ ¼àÞÚíßÛæõì@Š"‰¯£«´ã︰³¹ÃÊôÿ鯯®«¨£°ìõóõíìêäâÛ;‹![¤§¼ýÛ¬¯Üòøøí÷Ú¨§¦œ¡Èóýýûð÷ýüùâîHŒ@„µÿ§ÍýãÖ÷ûûÞ¥ §²Ûüÿø÷üùû€ÿùüIŽF–­®éÙ´¯Åñÿã§Àßùÿÿþ÷üüóïøúéðýH /Swˆ¥Å×ëéçøüýüúþ€ÿóóùñâôüJ“Xßñ÷õèìüÿøõþÿÿûýÿý÷÷àåD– 8ßùýöëáïûþÿýþþùìöàâB–Eñüÿÿúëìý†ÿûìáîF–Núüÿÿþýû†ÿþ÷ôù÷F–JFFŠIHDGJIßh8mk Òéççççççççççççççççççççççççççççççççççççççççççíhìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ•çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯(çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®'óÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ²'v«»¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¹¼‘-4GEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFDit32r¾ÿÿÿÿÿÿ°9),/&)!$# !,"#,(*00//--(! #,1-,##,* +0*&(*,/+&.-Ã9nóÖÑˤÐðľƹ³½Ì¹«·×¶Ãöîïñûñ÷õüäÅÇÞîêêÙ®¾ôíÕ²®Ùúõëîî÷þíäûøÃƒú¶“ÆÜø÷˹ÚìÛßïÐÍåÀ¿ó€ÿÕÛÜðøõðçôÿѶÜß¿ÊñüÿߨÇõƒÿøÿÿþ‡Ã9tÉ¢¯Ïþô翼ÞïÕìùàïÿÙÅïþÿÿ溽çúããçþèÃÓýùãáïúÿÿôÙýýùøÿøúùíûúÃ(uËÇÚÛøòÓÁ¾«ÃÑÆÜýûóçÓ×ÿÿøüäßÜíøà×âÙðãáìùüû€ÿ û÷ÿûñöÿôýÿ×ðø…Ã)€÷ùðð×೘žªÈ¹ÙøÿüôûïéþùùôàÙíêÔËÇÃùêÚáåóúþÿ ýùíõùýúàéü÷{Ã'†öþöìÎÙ£¸ •Ž£Ëð÷÷üÿùäþÿþöàøý×èåÐÍÐõýõôû‚ÿ ÷ëýýøóýçàõìÁFÃ&ŠôëÝç×Ó¼¬¥‹|Š¶ÆØÐÞÿýèüÿÿüþøàõ÷ÿÿáæÜäÿõúƒÿüøÿÿ€ýöþùº™FÃâ Ðúæ½³À¼®˜›ˆ¾Ù²³€ÿþÿýêúÿûâæûÛÂêëù…ÿûüÿóðÓ¦ZÃ%nëáóÿüÒ¸®”ÁÞ¥ˆŠggƒŠj•åÿÿþüûýþúùÜêô¬„£ï†ÿþþÿìëÛºWÃ%kæêäãáʱŒ”Çîϳ³„mpe†xp®äýÿýüÿþÿ÷Öè ZߌÿþðÇÒZÃ3‚’“•˜Œ– ²ÒÔÁ›‘ˆk|׿‰ih©ò‚ÿ þöß@§þÿÿüý‰ÿùÖío¿(%(*-;JPWw„šÄ°ƒo»­²Ö蜆y¥îùúüûþéÛöÖð€ÿþ‡ÿþÿÿþÿôfº. %TQ!!-" *@SfŠ“˜º²½ÕìÂèÓ£×ðíüùÿúóõøûþÿýƒÿüìÚñÿüýõy¶€/ ˆÿp ,¸Óh 6MTx…­îìÒÚøÿæõÖóÿÿýÿúüýýÿýƒÿ÷Óºßþþùöƒ´/ *œ’8Zƒ¦ËÉÜv .8]žÑÍÏñÿðìÒìîþýŽÿþøøþúÿû}²0   ¥òÖÆ˜4Uæt #Sz­ÌêýóüñóÛô“ÿþÿøn°  € "¦r ‹äŒ! ‚ &\ƒ¬ÜèæôèÝæÿúîóÿýþüþý‰ÿþûøh® ‚ 0   "Mmœ 2Sk”·òñêôûðÝéþýþýúý‰ÿûàÆ^¬ €  €   #Ƴ €  €  /oÚûûùö÷õó÷ÿýþ‰ÿω@« ‚  ‚   € UÊl  A’×îÞÔçûúõüýïÌÕý†ÿýùÖ£K©  €   ¯ € ‚ € BÉαÐòÞÔíùä«Ãû†ÿØ¡‚¶Íl¨  € €AЦ    <€°ÃïüäÐß÷é×Éñþ„ÿô࣯øôb§ €  €qèR  4lªÜìçóøñçøôûýùƒÿ÷Û×îñæS¦ €ƒ \Û- € €   *i¯ÚÌçïÞÑðþøýúƒÿøÄÈÄÇô¥  ƒ€‚ & ¬zX ‚  *u¾ÑÃÈßãñõíûú€ÿ þûîÁ®Þêéü…¤  ‚ €‚  tÎâw€&  +y»ÌæëéìîúéèþÿÿëÕÐäýøÿòën£€ ƒ€…€ lÖ–*€  € 0{ÈøÝÍãôúóûÿþòÙØéöôÿÿâÎV¢ €€Sà³  €  7‹ÆÑßþƒÿ îèùóÜ¿ÍÑæÞf¡# "#"" ƒOè”  AŠÎø‚ÿ úÔÔË·ÔëÄ¥™§˜B )  #&)*))%$! E¨w € [³éüÿÿï÷ÉÅÖÛÉ»ãíл¨”N  "',03441-)%"#† %Ëe  €"vÅñüØÇ¸¨ÿýåêÙ½ÞíÒÎËZŸ €  (-5;?@@<61*& ‚€  ³€  M`(7”×ïìØ¸Ûé¯ÀÑÈËØÐ½ÍÊ`ž" %-5?FJMLF?7/(#ƒƒNÝ5€  7yXA-TªßðȽí®y¢¶ÓÛϵªµ®]ž €  !)1€KU'  %u²ÝÝÒíѲ§¨ºÚí¸–”¦]€ #,6BOYab`ZOC8.'"ƒ€€+ ¦–i€%  =‡ÎëÚëúàÙáÓÌÃ±Šž­Zœ' $-7ES]fie]RE:1)$€‚jè\n¼e  € ]›ÇäÚöòÙÚÜÚ¹À£¥ÁZœ€ %-7FR^fie]QG<1)$€€€‚&ÊŸ W×e€  5o­âÓØïÛåæ²Ä׳²¯R›€  $,5ANX`c_XNC8/(#€€13Ù‡ O¦/ U˜ÌàÑßÜéðÇÈÌÄÁªg›. ")1;FNUWUPG<3,'"‚- \ôY ‹x A˜ØüøðêóëàâÎÈζeš/ &-4=DIJJF>6/)$"_M+‚-! ;ž÷r _‰ &‡ÍñÿûöüñÝÏÞ©±Zš€ & !(.39K=€. O€™÷ÿ/¤+   \©âøþøýþâÐ৪fš €  "'+/1441,)%#!€&i¨S/ozuC  0»ÿúÿØQ€‘T  7Éãÿùòöíܱˆ‰¡f™! !%')*)''%# €)%Dtãÿ—&)7j”t0"'xöîÿÖm/$²P €  s¹ßÿýë×êÇ’˜ ×z™€   ""#$#"!‚>:UBym=$ Í(/TÚÿèît=.+$ x¾#  Y±ñûûõÝ⺚¨¿ßj™ €  F!6/"#$ "œÜ’wcŽÂøüø¨`- UæN  ?šëýÿøããÒÆÐáÊU˜ €€!+$ "#€$4#$EbeiG,OßÿÿúܲŠu†£SqäÍ  )ƒÔÿöçáçøûöÖÜc˜,  !"*%"#$$€%"&&"!#$#*_ƒÜØbeŠšŸœË¦™u9 € f»ëßåïéèûâ×ø|˜ € €%6.##$%%€&€'&%$$&%#&Dɸ-#.(".& € SŸÄÌÐÉæõòä·Ô€˜ €  €R±D$%&&†'.((&%%CÛ¤  Cˆ»ÚÝÏÙåÛ×Ü㘠€   € .ÊÌ" %%''()€(/''&%%$$QÒ¡$ 7ÀÏÔåìÔÆàöøƒ—    €€ @ß«$''(())€*€)/''&%%$$(1©§$ #{̼»êüöìàäõx— € € € /N^Yd%''))*+ƒ*()''&%%$&%$¾¯#  s³£¸î€ÿøõúx— €€ 1o…&",'€*+,++€*)('&€%$#P錀 € !z¥«Áçþîõÿþ÷‚—€  €€" %())*,,€- ..,++,.-*(&%$€#%¤Ã  o»ÂÓýûÎÚúïèn— €€!"!%&')*+-..-/0/-€/76-('&$$##'¯Â(€ fÃÌÕôóìîòÖâf—    €€"#$%&'(*+-./0/04:BD>0('&$$%% (¨îN€€  d½²ÀæóýÿèÞñt—  € !##%&'(**+-./€0 /028J\S>4,'&€%&(&&œûW   Uš­ÒéÚêóóéû„—   €€""#$%&()*,--/‚04245Et…H*)*'&&*3*OéÏ1  M¶ÒÜÀäóòâõ{— €% "#$%&'()*+,-/1100132^±ëôÏ{<'€('69GÆÿ‰  B‘ÆÓâÞàí×Ðër— % !##%%''(**+,/12!03ŒìáüÏñÎn:,-1?¹áq9 €  F޼ÂÕêØÏÔëò~—G  "#$%&'()**,.0114328}í‰EA?>‰ïø™52;žãN#€ €  "Cu³½ÆÍ¼·Ùüò~— €  #$$&€',)**,.02320\Äßq)//078]Ðñ‰i™º] €  J†¹´º¸¼ÛÚðów— € !!#$&&'()**+-/36CãËK(€./44*I¤öý»;€€ !h¡°ª¨¦«¹ÕÓïu— €O !#%&''())*,-00_ÆïŸ9(.,+,/0/-*Näîa  5_“´š¶¯ °õåÝy— €-!#$%&&'(()+,-(U×Ób*,-,+**,-.-)PÌÇ(€   >U}­¹¹¡³çþúÛ{˜d !#$$%%&'(**+*#©àG!--++*(()*+*+(uÇ$  $E\‡¼¿¿¹Ê÷öçÛ€˜  €€!"#$%%&''((+%7ÔÔD),*))()()'€(*%§§" &54s ‡gQ%PnϹ³ÄÚãïðø™ €  "€#€%@''(*Xã®@)**(''()('&&OæO!!   .”˜|±ª’·Ã–F Z‰«Î¸²ÌàâÞøûƒ™ € €€  !€#%%&')'-¬ÖL(+)(''‚&-%%^æB"# (IXw¡ÕÊpThL7+ 7zœÅÆ­ÁÐäòÕûüƒ™  €!€#$%%&*%n㈀+'€&€%/#$%$HÇA%(*7›ÄÊš”¾É¸A  T–²¯³ÛÜÍíòö € €" #$%'*4«åX+/*'%$#,"3µ@57F–ÜÉfD0 .2$ c|™ÉÔÌëæ¿°¿žÊ…š€  € !#$&(%EÍü|'('&%%$€#"€!+·ÀœS›ý›( 4p¥Ú÷ÐÁåùÛ­£} bš € €!" "#$'!Qãóm&&%##""!…üúäíª€ €  MªÔÛ´ÃòùÚÜÉ¡ƒA› € !#$%3—÷x#($##$#!! -Î¥Ïèƒ € [ž“°íÅÛüùüüôá¢<› € "$$0¶Ä=!"!!"! €€Š˜'8I"€  ;‰ªÌÛúúñóüÿÿõßËD› €  "#rôo€ l˜€  _®Üü€ÿøøÿÿüáÒÕbœ €ƒ "aôµ0…€)cš  {»åòÿþÿü÷øþúíöÚo  u÷ÿ‘€Y® € 0‹Ñ×øùòòðèçêôÑèØh+ !^ìÿÿ{€ Jà €  *K„ÒØÖèáÙøüãÓÏ´ÊÚpž  €€H8 $#(£æ®©¹a€ .¦±€  Wy‡ÅôäïîïýÿôîèäÙÎež  €Gzon7"&&*‚Îh>c3 € 1±©0€  :ª¢Åñúþÿûùú‚ÿïrŸ=  "8! $tÞY$Kƒf0 GÅ %€ X™Ã¸¶ìóõöþüôúúÿÿïío "   ,ƒ7"WÚt€9¼–PXÌ|$€ Lj£ÀÐÈÜÉÖçÿÿùýýõåá÷}  € € k; Kã­€5'HˆÏ\vä‚  -eh~§Éäôϸíÿýûýÿøæãðq¡ € 4j' 4OÚ×.€‚ ¡šhç €   *Oirw¢©ÒéϸÛÿîóþ÷ïßÓâj¢ €]ŽK1]޶ÉÓ`ƒ€ ;¾ö‹€  -RlšÀ¡¿ÜÄËÁÍÔÎêÿûñíêöo£ _ðÛ›«t?4&€3˜Þ4  'f£œ³¦­ÞïÓ¨²ÎÎÌäùÿÿ÷éáÚf¤ ®`0€*R60¢f€$ 7lÚÈ–œ¾ÍØì¾©ÀáìäâòÿáÁãäb¥  R¬< € ZÞ˃v €&   'h®«Âؼ½áÚêéÔ¨°ª¿µ¶ÙíçÏÞà\¦€    PZ „€ 0_ÊÿÙJ € "   7{¥ÓçæÐÝëÚ㺦ëÜÞž·ÏÈÀ©Ê»«¦O§ -qC €€ "QKqào #  >†ÂÜÿÿðíñôýùОòÿëÒéæÊÑÊÈǦ¤\¨  m¢(   !7+M·-  € HÉáûñÛôòóÂäÿÿïûüõýþõìóТÂÂÔmªB L' 3TZtn-F«@ !]šÎðèûïÖéñߨïú€ÿ öèûöûëѲ¨¾êêv«& !‰v UÎÅaxϲ8  rC ƒ $  4r¯ÛóûóüÿÿùóíåÆÛýüþøððóÿð¼±ÔØýý„­  %­Ÿ   IËžR ?†›¥ZX^ ƒ % QÀãøùùöñóÿÿþÿÿ¿æÿþýüÿúûÿüéêñ÷ëõ„®%É  0Þ € (>x²c@y’H =tª×éìýýÿÿéÍ×öüùÿøÿü‚ÿûþúöáô…±g '>y0  Mz)ˆw € * 6f™ÆäóûûþýÙÊûóéãóýúúþýÿÿýÿÿþþÿíêøðàú…²<   "\i¶;  :e“½ÝñûüþÿÿýÔ×ÿÿþóøýßÖ÷õúÿ õóþì¯Öüíï´/  UŠeW·y $@h–¾Üïúÿÿ÷õþÿÿüý‚ÿØÙúâ²ÆùüíöþפËÌîÿúô‚¸   257;;3 :`€¡¿Úòøüüýÿúþÿû„ÿû¼»ÕÜžÁýñÈ×ò½ªðþùïÿúƒ¼€€ !8JYo–ÀÎãäìúéðÿÿûâ÷ÿüƒÿûÿãµÞÿõùþðà±¢¼ÇíÿýøþúƒÃ''&-?SRe‹˜•±Öçêöüùùýúùù÷õûÿþ†ÿûøýÿþýþÿÿáÐÞÕì÷áçúû‚Ã0dfq ´»ÇÝÛãææÝÖëîý€ÿþñæÆåÿùý‰ÿú÷úüýÿÿùÕ¾»§ÇöõuÃLžªÈåëëúùïïòÔÅ´Â×è€ÿþþý÷æõþóþƒÿøê÷ýþ€ÿ þóôñïÿîÍ­½ÎØÕ^ÃQ›ÂÝêúðüî÷ô¥¢ÂµÄÝôùùÿöñøÿöþƒÿòÖëöýÿ ùÞÈÛ÷ûîÚέš¸fÃ9|¶×ñäìÿûÿóµÃÕļÎúèçþùôûý‰ÿþûúþ€ÿ þî¼¶äóçÖÝ´¨©¾iÃ<—¶ÏçàöñÿýâéÿúãĵÆßèõøÿÿþÿùüÿúíÚØþþÙ½µ²ßÖÑgÃG¬ÆÍóýþóýüõùóßÍξÂíãßæ÷ÿú€ý öæíÿò̳¶Áã׿€Ã^¾Øïýôÿÿþ€ÿ ëÈÃçÊÅõãÝøñìþŽÿýòþùðéþæÂ¶ÉÍËÊã{ÃYÁáûëëƒÿ üäßúë½óûúÿýùþÿúýùñôêÛȯÀǾÌÕmÃeÔÜåëû‚ÿýþôëü÷Ýø—ÿ þüíåßÞÞâéÜáÕsÃaÏéíòþùýýÿÿýúþúÿõù—ÿ þ÷ìïñëòüÿÿ÷ûø~Ã{ãòúùöëù¢ú ñÈËùøð÷ùúúøôÃ@|~ƒyllu¡ƒ €p_{v|†y}ƒst?ÿÿÿÿÿÿøÿÿÿÿÿÿ°9)+/&) $" ,!#,')00//--' ",1-,$",)+0*&(*,/+&.-Ã9jòÔÏÉ ÎïÀºÃµ¯¹É¶§³Õ´¿öííðûð÷õüâÂÄÝíêéש»ôëÓ®«Öúõêîì÷þìâûøÃ€ù±ÃÙö÷ǵ×ëÙÝíÌÊã¼¼ñ€ÿÓÙÙïøõðäòÿͱÙܺÆðûÿÜÖÂõƒÿøÿÿþ‡Ã9qÄžªÌþ󿼏ÜíÒìøÞíÿØÂîþÿÿå¶¹åûââåþç¿ÐüøáàïúÿÿóØþýùøÿøúùìûúÃ(sÇÄÙÙøðÑ¿»§¿ÎÃÚüúóæÐÕÿÿøüâÝÚíøÞÔáÖïáßëùüü€ÿ û÷ÿúðöÿóýÿÕîø†Ã)~öùîðÔÞ¯“¾™¥ÅµÖ÷ÿüôûîéþùøóß×íèÑÈÄÁùéÙàãòúþÿ ýùìóøýúßçûö{Ã'„ôþõìÌØ¾ž´œˆžÈð÷öüÿøãþÿþöàøýÕåãÎËÍôýöóû‚ÿ öêýýöòýåàôë½CÃ&ˆóêÛæÕѸ§¡…v„²Ã×ÍÜÿüæüÿÿüýøßõ÷þÿßäÚãÿöûƒÿ üøÿÿýüýõþù·’CÃ|à™Íúå»®½¹©Š’–ˆ‚Šº×¯°€ÿþÿýêúÿüàåûÚ¾éëø…ÿûüÿòïСYÃ&kèÞóÿüϳ©¾Û¡ƒ„``}„c‘ãÿÿþüûýþúùÛéó¨}žîþ…ÿþþÿëêØ¶UÃ%pñöïìçͲˆŽÃíͯ®}fi^€qj©ãýÿýüÿþÿöÓç|SÝŒÿþïÃÏXÃF§º¸¸·¥«²¿ÝÚ˜‹‚du‡Õäƒba¥ò‚ÿ þöÜ|9¢ýÿÿüý‰ÿùÔëmº-  6dgabr‚ƒƒ¤©¹Þ¿‡mz¸©®Ôæ˜r îøúüûþèÚôÔð€ÿþ‡ÿþÿÿþÿóe¶2 0J^w ¡qi¢’dE@DBKTdy…®¬¥Á´¼ÓêÀæÑžÔðíûøÿùóõ÷ûþÿýƒÿüë×ðÿüýóx³5 $CcŒ¶ÿÿûéóÅÄÿÿÎx:-2.$/<:Fs‚}˜—¶õíÐØøÿåõÔñÿÿýÿúüýýÿýƒÿ÷жÝþýùõƒ±.D@C\a_i´òóäø‚ÿçy3/1*%+'%0:Pb`|¸áÑÏðÿïëÏíîýýŽÿþ÷øþùÿû|®4 &4K[J@DFCHOQ˜îÿÿúèÊÇõÿÝ„FG723+$!"&);^Š¢ÇÚðþñüïóØô“ÿþÿ÷l¬@7JGFSWEMMJHFGKOýÐ…qÁüÿùžD8E@-*)*&#) !:KQR[ck\XspYSRVXNQenWNSPIX‘§»ÿé2//261.,0/$!#4IBH~æþûøõ÷õò÷ÿýþ‰ÿ̃=¨E?NQ^d_kli_^gh_]^YVUYfgUSTPSWlˆžØÿÕ\310-.-,.64*'%(7Jj°éöÞÒåûúôüüîÉÔý†ÿýøÕž—G§F @VWZdihkigopiimu{pj\[\[VVSRTUS]~Âùò~454100/./5/++&&3Mv²ÞÔ¯ÍòÜÑìøã¦Àû†ÿÖœ{²Ék¥I *LXY_egknrvy‡‘•‘†~lc^[YXWdXONTyßþãm;:646;?6.-..++(%(Cu©ÇÉñüâÍÜõèÕÆðþ„ÿóÝ«øó`¤K3UZ]alqqzŠ“¤“€‚‡Š€ywtqsi`][Y]^WU]|çÿÆZHA88678437:.,23/'%?o–ÀåîåñøðåøôúýøƒÿöÚÕìðãR£L8W\auqtƒ…––‹ŒŒ‰ˆ…ƒ{xtpjgda\XVWXeËÿ±ihK=;98864793/034*'%=e”ÇäÊåîÜÎïþøýùƒÿøÀÆÁÄó¢M:\_hsxyz†ŒŒ“–˜™˜–”‘Ї{vrlhe`\XVSRˆñÿå¿xB;=:=@7432/4?:3-''6g¤×ØÁÄÜáñõìúú€ÿ þúÜèçü†¡[=V[`sy|„‹‘–›Ÿ ££¥¦£žž˜“އ~wnjfc`[WTOM€ÎìÿÚyVI?=@:85431.7G5.,%7j§ÒÒæêçëîùææþÿÿéÒÍãüøÿðêm ?<[`afu‰‡‡‘›ž¢©®¬¬­¯®ª¦¤—‘Š…€{tokfd_[YWRJOqÃÿñ¨[F?<<:78?6/.B7€.#7p¦ÞÿÛËáôúòûÿþñ××èõôÿÿßËTŸL5T\dey–•Ž˜ž§§¬°´´³´´±­«§¡œ–Š…xspjgc^[XTRMId¾ÿð‚AB@=C@?FNA;8862/.,<1$?{«Úú‚ÿ ùÒÒɳÑéÀ “¢’?ž^$IS`zŒš™²®£¨°µ¶¹¼¼»¹¹·µ³®«¥Ÿ¡Ÿ†ƒ{sokfa]\WUSPPOb¬ûÝoKEB>@C<@B>821+2*" D‘Ñóýÿÿî÷ÅÂÓÙÆ·áìη£ŽKž^BOTq•€„•ª´¤¦¯¶¹»¾¾¿¾¼»º¸µ²¯ª¤­¯’‡ƒ~xvpidba^WURPRNO—ÿÒ\NEBA?j¼æñé×´Øè«½ÎÄÈÖθÊÇ^œ` 'FNX_gpy…“œ¢¬´¹»¿ÀÃÄÄÅÃÁ¿»¸µ±®¨¢›•‰‚}wtoifa^[Y[\VPLH¨û§WYNCB?=;86:65N½ÿÍÐÅr…ÆçñŹìªr²ÏØÌ±¦±¨Zœ`<;:8;6<@1,5.++WžÇàÿüêÖêÄŒ“šÕy—e %57=EHOkchr|ˆ“šŸ¤¨¬­¯´³²±²²°°¯­«¨¦¤žœÌâ¾ç̰|rl~ãÿ®‹³Ê÷þøþÿô£‰uPMTZOZËýƒC?<6@F11C0(%HÈöúúôÛà·•¢»Üh—254CGHNcafp{‡Š–œ¡¤¦©¬±±¯®C©¥¤¡›£Ôº†¡}€zuzÞÿìÜçøýþùþÿ𱇇nYOgÄÿ³WHB<8?B13?3*$7y¹òýÿøáàÐÃÍàÆS—.28@EIO]]dmx‚†‘—›Ÿ£¦¨ª««¬«­©¦§¢žš º¢Š‰†„€~{wv ¿¶Ñ«ŠÕÿ'ý÷ëêïëÌ®ÝÿÿŒIGD=::;4240-(+eªßÿõæàçøûõÕÙa—4;:<@FR_[bjs|‡Œ’–›ž¡¤¥¦§§€¨F¦§¤©¨Ÿœ™¡°™ŠŠˆ…‚|ywrpmpld•ÒëÿþãÒåùüöÿþâ̬eJEE?;8>:20-0/3S’ÊëÜäîèçûàÔ÷{– $7B79@CO]Y_hqv|‚‡”˜œž ¤¦¦¤£¢¤ ›˜®Ì´“‹Š‡…‚}zxtrpl+rŽÀöö¯ƒ™“€‘€`TMJJED@<:<700/,..C†³ÄÊÍÆåôðã³Ð–f(/14;9782.,*2(]©°¦¼æþíõÿþö‚–f+)-158AEGKPW\^bgkmqux{}€„……‡ˆ‰Š‹‰ƒ‡‰‚ˆŒŠˆ‰‡†…„ƒ…‚~zy|~tsmgfdbfcˆñúNPNMKHHFD?<9762.-*&%QŸË¿ÑýûËØúîål–( #/*./16;?FILRWZ]bgkmosvy{}€‚ƒ…†ˆ‡ˆ…„ˆ‡‡ˆ9‡††……„‚‡ š}qliffef`ƒëý£ZQOMJHNOB><:742.,*(%J•ÕÉÒóóëíñÒßd–' )6),:C?;>CFJOSXZ^bgikoqvyx{~‚„……††…€†‡‡†‡€…4„…“¥Ãѱ†rmjfijkd”ôÿÀ`POLJHKLA><:735:3*'$F“Ï­»äóüÿçÝðs–+E0-9837?.**?Sj—¸½ÒéÖÌÑëò~–$8893€7:>ADHJMPSTVY\^`ceghkmortuwx€z?||}€‡‰‹Ž’°äÿæÃǾÎöÿÿü½¥Íô÷·xYOONKJLJDDB>96443-+/E\dy®ºÂË·³Öûñ}–f!4.25667;CFIKLNNTWYZY\^`bdfhklmoprrtvx•éÿÉŒ{xwsrppsuxz}¡ìårY[XVUZ_YROJE<88>D7JxjOYF(Btg‚¸¼»µÇööåÙ€—+,.2/048:=>ADJKJMNRU€WLY]^`cdffimnopqqsu®÷ÿÀ|wtsqoprrpqsv”íãs\ZWTUZ^WOICNc\\nŽ•ÅõéÀš\*Gtw˜Ì¶®ÁÙáïðø€—N+-.451489<=@OSGHKLPRTTVX[]^`bcdfikmqnpp}Ïÿ÷¯ysroolnspolmlÇÿÇudYUSNNRYZWl§Þãæð€ÿíÖšR.*RvŽ¨Ë´®ÈÞàÝøûƒ—e%(-520299:BDG€IOLOQPQRXa]ZZ[]`afjr©øÿÞ•thdegda`_^\[ZYXŽùÿýýÓVLKIFDD@>:9BC52,*,*-Qz©«ìÁÙüùüüóßœ9™./,2./74:;:=@BDGGILM€OJQRTVXYZ\]_afjv³øþµp`aaba^^]\\[XWU_Ýú¹£›jGIIFEC?<;8:80/,*(&=i¡­ÊÙùùñóüÿÿõÞÇAš++(.-./247:<<>DHIJIJLNNPRRTWXZ[[\]`cd~×ÿÒnZ€^]]^][YXWVUTÍòpNNZOGHFDABEGGJNPNMNPO]\TY \^^zØÿÿévT€Y€W/VTTUUTPÁótSJIEFDA?>TM6:50/-*"(@M˜ÓÕøúññïçåèóÎçÖf›& #,+,,/217>=?CEDEJNPLcl` ¢bV^hir…Âúÿêäÿ¸aHTWUSQQPOVd”òêWBECDCA>;D952181-,),JyƒÁóãíìïýÿóîçã×ÊdX '(56??3758;;>@CEEHHEP­ßËÔXS_q|†±ýû¼€v›ßÙHFKOQQSO[šòø”JHEDC@><976402B50+&9d•­œÂðúÿÿûùú‚ÿîr_#'4AMK,.2>K?:>@CDDF9pùà‹^HMT_k{¥ëÿ­VLKKn½ê»rRGIOK\¬öô”MKIBA@>;99::5.2;0-&1Js Ã´³ëóõõþüóúúÿþîënž^',7:L8.2IR=8FH:<;594//6+&,ACC6;=20/,*,0/9]kq˜½˜œ»ÚÁǽÊÒËéÿúñìèõn \#4>/)-1533579HVWV\ÅÿÿùïÑ©¥[KJGGHJLPPQ^dTvåýŸXNKHA;@C68;6//.,)*-)9Z‰²œ¯ ¨ÝîУ­ÌÌÊâùÿÿöçß×f¡[$).32>7/127ADRUJlÜúô½„RKJIGGEIKHHJVLMì¿­ù½NCJGA=:88=>826:3-08(5t•œàÇ–ºËÖ뻤¼ÞëãàòÿÞ½àá`¢Z$4=101//36>@>4>?CbØÙU4:>@@?@?ACCDF€GaÆ€ÿ0ý¹K;;:89:53442-6A4(%#=w§¹ÛåäÏÜêØá·¡éÚݘ³Íƽ¥Ç·¦¡M¥W!()().367;GZ‘í·YA:<<;:>B<=>AJOOU“ÿúñÿÐb?<8768:31350--.*#&C|²ØãÿÿïëñõüøÍšóÿéÐçäÇÏÉÄÅ¡ŸZ¦ €)P,.,2;PsØü•aF;<:<>AKNJOhneao’ÂÇçÿ¤@>96557650..+*-+$+OƒµÝçýïØòñó¿âÿÿîûüõüýôêòÍœ¾¿Ñl§E &+*++/=TkÖô~F>9;;AHJ€º¿ËßÖ·ykfaÈÿ°J@7521101.-**)%!2_•½ÞõéûîÔèðÞ£îú€ÿ öçûôúêͬ¢ºéèu¨T!()(-;k³ôÜV*/2472/1729Gg ËûôÿÚ_2()4J_x˜»Öéöýÿÿ÷ôþÿÿüý‚ÿÕ×úà®ÃùüìöþÕ ÈÉîÿúô‚²&"?\3/><01/,-4Dn˜Üà¼H?GTr–«ÀÔç÷ú€üÿúþÿû„ÿû¹¸ÓÚ›¾üïÅÖòº¦ðþùîÿúƒµ+ "$'*'-0/7DHfjUYm€‡”µØÝëèìúçïÿÿüàöÿüƒÿúÿá°Ûÿôøþðß­¸Äìÿüøþúƒ·( 7]^W^p‚{Ž´¼­Ãåïîöûøøýúùù÷ôúÿþ†ÿúøüÿþýýÿÿÞÍÜÓêößæøú‚¾?€ŠªºÎÎ×ëãçæäÛÒçíý€ÿþïäÄäÿùý‰ÿúöùûüÿÿùÓ»·¢ÄõôuÃMŸ­ÌëñîüúïîñÐÁ°¾Õæ€ÿþþýöäõÿóþƒÿøéöýþ€ÿ þòôïíÿíË©¹ËÖÒ]ÃL”½Úçøîûìöõ ¿²ÁÛôùùÿöñøÿöþƒÿòÔèõýÿ ùÜÅØ÷üë×̨•µfÃ3t²Ôðâëÿúÿò°ÀÓ¸Êùçæýùóûý‰ÿþúúþ€ÿ þãóçÓÚ°¢¥»gÃ6‘²ÌåÞöðÿýàçÿùáÀ²ÃÞæôùÿÿþÿùüÿúëÙÖýýÖº°¬ÝÔÍeÃB§ÃÊòýþòýüõøòÝÉ̺¾ìáÞæöÿú€ý õåëÿñɯ²¾âÕã~ÃZº×îýôÿÿþ€ÿ êÅÀåÇÂõáÜøðìþŽÿýñþùîçÿåÁ²ÆÊÇÇâzÃU½Þûêêƒÿ üâÝúëºòûúÿüùþÿúýùñóèÙŪ¼ÄºÊÑkÃaÑÚãêû‚ÿýýóéü÷Ûø—ÿ þüìãÝÚÝàçÚßÒqÃ]Ëèìòþùýýÿÿüùÿùÿôù—ÿ þöìíïêòüÿÿ÷úø}Ãwßñúùõêù¢ú ðÅÈù÷ïöùúúøòÃ?|~ƒxjju¡ƒ €o]{u|†y}ƒrs?ÿÿÿÿÿÿøÿÿÿÿÿÿ°9,,/*#&+')($$''%#&-&'-++//..-.+''(,/.-)'-+'%$-/,*+,-.-*.-Ã9ŽûéçäÏçöàÝâÛ×ÜäÚÒÙéØßùõõ÷ü÷úúýòââíöôôëÓÝúõèÕÕëüùóõöúýöñüø‚ÃÿÛÇæñÿýéÞðúòóûëêöááý€ÿîðñúÿýý÷þÿêÛñóáèüÿÿòðæþ†ÿþ‡Ã9‘éÏÔæþùóÞÜíöêõûïöþìáöþÿÿòÛÜòüññòþôàçýüðð÷ýÿÿùëþþüûÿûýüõýú‚Ã(“ëâííûøèßÞÑßéâíþýøóéëÿÿüþòïíöüðêðìùñïöüýý€ÿ ýúÿýøûÿúþÿê÷ú„Ã(šþü÷øëðÖÇàËÑãÛëüÿýúý÷ôþüüúðë÷ôêåãáüôíñòùý‚ÿ þüöúüþýîóýüÞþÿûöçìßÎÛÌÄÀÍä÷üûþÿûñ€ÿúïüþëôòçæçúþúùý‚ÿ ûõþþûùþóðúöâ`Ã& ÿôíóêèÜÓпµ½Ùãíèîÿþóýÿÿýþûðûûÿÿðóíòÿûýƒÿýûÿÿ€þúÿüÜÌaØõÊæýòÜØÞÜÓÂÇÇ¿¼ÁÝëÖÖ‚ÿ ýõýÿþðóýìàõõü…ÿýýÿùøéÔnÉøïùÿýèÚÓÅÞîλ¾¦¥¹¼§Äñ€ÿ ýþÿþüüîôùÒ¹Ê÷Œÿõõíàkº$ ™þÿüú÷éÚÁÅâ÷åÕÖ¹¨«£¹¯¬Òðþÿýþ€ÿûêõ±j–îŒÿþ÷ãìl·%$,28>>=ðöóòïããäéõñâÉ»§´¿êñ¼¨¦Îùƒÿû﯅̀ÿýþ‰ÿüëùy³4 ,8EQ]jt}…‡‰ºâäÜÚâêåáðíðþéİ·ÚÓÕéôʸ²Îöüüýýÿôíüê÷ÿøt±7 "1BUi}“¨¹ÇÕÝãèéëòïèÚËËÏÒÙßççæîåÛæÜßèôàôèËéøöýüÿýùúüýþÿþƒÿþöìøÿýþù}®,AWrŒ¡²Íãôþ‡ÿ!ëÁ«®ª§¶ÇÇÐèéÚáÖâü÷èëüÿòúêùþÿþÿýþþýÿýƒÿûèÛîþþüúƒ¬1Ihˆ¥½ÊÊÉÕÖÛäõ‡ÿï½­ªžœ¦£§¹ÇÕÛÎÒëúìèùÿööçööþþÿûüÿüÿú€« 1Lo•³ÈÔÕÊÃÄÆÃÇÌÖò‡ÿèɱ©ªŸ—–ª´ÇÝîëóôúÿøý÷úìù•ÿøx© ,Gl—½ÑÔÐÐÑÉÌËÇÇÅÄÈÔñÿüñëêõý€ÿñʳ·´¤¡ žš™§ÂÕãóìíûùóùóîòÿý÷ùÿ€þÿþŠÿýüv¨"=aŒ·ÒÚ×ÓÒÒÑÒÕÐË€Ê ÇÅØ÷æÍÑÓÔêÿ!çÀ°¯§ª²®¦£›œ¤¸ÔëàÌÕàú÷ôúþ÷ïôþþÿþýþ‰ÿþðäo¦!.O{«ÌÚÛÚÛÜÞÙØÞÜÔÑÎÐÏÉÈÖäÑÃÇÇÀÕüÿ깦¦¨«¨¥¤¨¨™— ½ÖÀ®ÅùÿþüûûúúûÿþŠÿçÁ]¥ :`•ÈÜÝÞáßááàÜÛÝÝÚÖÕÒÑÎÎÕÖÊ€ÈËÏâöý€ÿ Ø®©¨¥¤£¢¦°®¡œ©ÃÏÑéýýðéóþýúþþ÷äéþ†ÿþýéÍÎc¤%&EsªÓáààâäâäãâããáßààáÜÙÒÑÐÎËÉÉËÍÎÐØð€ÿ ä·­«¨§¦¦¤¦¬¦¢¢šŸ»×àðúîØçøíéöüòÒàý†ÿì˸Øèv£&*O‚»ÜâáãææçèèéèêêééèçäâáÙÖÓÐÍËÌÒÌÆÇÑê€ÿ!Ỳ®«­´¶­¥£¥¥¡ žš«Òæíñéùüñçîûôëäøþ„ÿúñËÑû÷q¢//WŒÅáããåéêêëîïðíêééêéåâàÞÜÞ×ÒÐÎÍÏÑËË×ëÿÿùÜɹ°°€®¬«®±¥¢ª¬§›¡Ìæçí÷÷óùüøòûùþþûƒÿûíêöøõh¡N2Z”ËâäåéêìïïññðñðïíìëéèæäáßÞÛ×ÕÓÓÐÎËÍÐáþÿøëçȵ³°¯¯¬«­°«¥§¬¬¢› Êãèñøçò÷ïç÷ÿûþüƒÿûàãáãú‚ 1]—Ðåäçêìîðññ€ò$óòòðñðîëêççäàßÜØÖÕÓÏÌËÉÍèþÿÿþèŵ´²µ¹®€©¦«´±­¥ž¤Ãåñúñáâîðøúöýýÿý÷ÞÔîõóû„Ÿ.[—Ðäãæëîîðòóõ€ö=÷ööôôóñðîëéçäâÞÛØÕÓÒÏËÉÇÌçøýÿÿçÐø´¸²­¬ª©§¥®¹°¨¤žÃèòöíóôóõ÷ýôó€ÿ õéæñþüÿùówž*U“Ïääæéìñòòõöøø‚ùGø÷õóòðîëèæäáÞÛØÖÕÓÏÎÎÊÉÓçýÿÿùÜÀµ²²±¯°·®¦¤·¯¦¥§žÆëïùÿîåñùýùþÿÿ÷ëìôûùÿÿðçiM #NŒÊááæèìòôôö÷ùúúûûúûûúù÷õóòñîêèæäàÞÜÙØÕÒÐÎÊÈÅÏäùÿÿîÆ¹·³²¸¿¼³­§¯­££ª­¬Îëóôìï„ÿ öóüùíÝååòñrA~ÂÞßâçëðôõ÷ùúûúüûü€û5úùùøöôñðíëèçäßÝÜØÔÓÑÍÊÈÈÉÌâüÿýßÀº·µ»Ãº²±°®«¦££¯¨§Îéêôþ‚ÿ üééãØèõàÏÆÐÉ]œ`6l´ÙÜâéëðóôøùúûûüýýüýüýúûûúøöóòñðêèæáßÝÛÖÕÓÑÏÌËÊÉÏá÷ÿýâÆ¼¸µ·¼µ·º¶¯ª¨¥¬¢™§Òïùþÿÿþ÷ûáàéìâÛñ÷çÛÑÈe› *[£ÒÙÞæííðôöùúúüüýJþýýüüûúúøöôõóìèçãáßÝÚ×Ö×ÕÐÍÌÊÉÌÕïÿþàɽº¸¶³¸µ±¶±¬¸»­±­¸àòùþýêâÙÏÿÿñôëÝïöéæém›GŠÊØÚàçìîïô÷ùúûüýþJÿýýþýüûúúøõôòîêèåãáßÝÙØØÖÒÏÏÐÍÉÂØýÿöÛι·³²°­±µ°»¶ÏñïáÕäôûúõìÙìóÑÞçâåëæÝæéqš6q·Ó×Üáåéîòô÷ùûüýýƒþHÿþþýüúúøöôñïìêèæãàÞÜÙ×ÕÔÒÔÖÑËÆÌôÿûÜÐúº¶³²°­±´¾Ð÷ÿÿýùçêôøùâÜ÷Ñ³ÍØéìçÙÒÚÙoš &WžÌÒ×ÞäçêîòõùúûüýýƒþHÿþýýüûúù÷õòðîëéçåâßÞÜÙÖÕÕÔÓÏÐÓÑðÿüÞÑÉ¿¼º¸µ³²ºØðûñÜÎÏàèæììòíè÷ç×ÏÐÜëöÚÆÅÕo™>€¾ÏÔØÝãêìðóõùûüüý†þ€ýCüúùøöóñîìêèçäáßÞÝÙØÙÖÔÓÓÛØèþÿðØÌÁ¼¼»¾ÉØçýþ迳¬®±ºÒáäñ÷ìôýïëïéåáÕ¾Ë×m™ (_¨ÊÍÓØÝåéëðóõøúûüýþ€ÿþþ€ý:ûûúøöóòðìííèåãàßÞÛÙ×ÕÓÔÕÒÔîÿÿþêÍŽÀÃÓîýÿøÈ»¶½®£¨Ÿ°×âÞæòíûùì€íÚÞÌÍãm˜@†¿ÉÑÔ×àéçëðò÷ùúûü‚þ€ÿþýüûúøöôòð€î8êçäâàÞÝÚØ×ÖÖØ××åúÿþéÌÇÂÄËÞûÿøÓ°­¬±³¦¥ ›ÆÜÕÞñèë÷íòóÖàëÖÖØh˜'`©ÆÊÔÕØàäæêïóõøûûüýý€þ€ÿ€þEýýüûúø÷õôñîíëéçæäâàßÝÜÛÙ×ÜßÝãøÿýßÉËÉÆÅÌôÿíǶ­«ª®ª¦ªœ«ÐÙÜèîèïîõùáãåáßÕu—<‚¼ÃÇÏÓ×Þâçêîòõøúûüýý…þ€ýCüûúøöõóòðîììëêæäãáàÞÜÚÙßäê÷ÿÿüßÉÌÊÄÀÅéþúѺ¯­¬±¬¨­¡™ÄâìôþûøôùôïñæâæÝt—!W¢Ã¿ÅÉÐÖßäåéíñôøúûûüý„þ€ýüûûúùøöóñðïôüýùîçãááßÞÜÜæóý€ÿ&þæÉÈÇÅÂÁÙýýи²®°¹¯¡¨¬š²âô÷úÿüûý÷íæîáÑÙm— 2u¹Á½ÅÊÐØßàåèëðòõøúûü€ý‚þ€ýüúúùø÷öòñòôüþýÿýöíçáÞßßâö‚ÿ&ýâÎÊÈÈÅÄÐóÿçÀ²¯¯º³¢±²Ÿ¢ÒìíõûÿüþþïçðÏÂÕs–FÁÀ¾ÃÉÏ×ÜÝãæëïòôöùûüûý€þýüü€úùúöõõøúýÿýùûÿÿþ÷ìæàßðÿÿþ€ÿ&þéÓÏÉÈÉÇÄÙý÷¿²±¯³²¦¨¥ ŸÀæêîñÿüùûöíÕ¼½Ïs–#\£¾¼½ÃÈÍÖÙÝáåéíñóô÷úúûûüýýþüúøøööý‚ÿ ûñóöÿÿüùñïüÿþýÿ%÷àÕÐÌÏÊÄáþõÀµ²­²´§£­¤¢¯ÝêíðÿþõìöáÄÇÍî~– 2u´¶µ¼ÄÆÌÙ×Ûàäéëîñóöøùúúüüûü€ûúøø÷õ÷þþüÿüúöîìëõ„ÿþþÿ%úèÕÏÑÔÒÞûÿæÁ·³®µ¸¨§¶§ ÔìñüýýúîðÛÊÑÞóv• AŒÀ´²ÀÅÅÊÖÖÙßãéêìïòôöøùùüûûúúûû€úùøøööùþû÷úõññðîìð„ÿþþÿ%ýöîæÞØëüÿøÖ»²¯¶·¨¬¶­¡™Áêïüþÿüòñèáæðéj•Sž¸­µ»ÁÄÊÑÔØÜáæéëîðòóõøø€ùú ùùøøù÷ööùþúôôó€ñððî÷üúùöù‡ÿ"þúùþÿÿòʾ¼³±±²«ª¬©¥œ±äíöÿûóðôüýûëðr•(d§¸µ·¹¼ÁËÔÑÕÚÞâåçéîðñóôõ÷øøùƒøùù÷öøüÿù€ô óóññðïïîìêèìùŠÿûôÞż¾µ±¯¶²©¦£©¨´Ûæîöîó÷õôýðëú• 1u²³º³µ»¿ÈÑÏÓØÝàãçéëîðñòóôöøø€÷øøö÷üÿÿú€õôôóòññïíìêêéëñüÿ%üûøòñæÚÔËÃü¼·²±´¯¨§¥¤§«ÏçæãåçäòúøñÚê•#;ƒµª®¯·¾¿ÃÌÍÑÖÛßáäçéëìðñòóôôõõö÷ööõ€ö@÷ÿÿþùö÷öõõôôòññïíëìîìçíôúÿÿ÷æáÚÓÏÍÊÅÂÁ½½¸²µ»¯¨°¨¡¡Ãçßáëîçíòìëîñ€•G³§®°µº¾ÁÎÍÎÔÙÝßáäèëëìîððòòóôôƒõAöüÿÿþø÷ø÷÷ööõóòññîìêééèåæòþÿÿðß×ÒÏÐÍÇ¿½½¸²º¾®¨©¥¦§›ºéêçæéñöêâðüúƒ” P›¼³¶°²·ÁÀÇÊÌÒÕÛÝßâêíëêììîðññóóôCõøùýÿÿýùøùùøùøöõôòñðîëéèçãåîôöþÿòÞÓÍÎÐÈÂÁ¾½¹´¹¹­¨¦£¬¬¥±ÝåðÛÛôýúöðòú}”&W¤¹µ¶¯²¶¼¾ÁÇÊÐÔØÚÝßèêçèéëìîïðññòóóõùþÿ6üøúúùùúùøöõôòñïìëêçäåëéåòÿÿõáÑÎ×Ìÿ¿·µ·²¬«¨¤£¤±¯ÜæåËØö€ÿüûù}” #^¦°§¬¬°²¼À¿ÄÉÏÓÕ×ÛÝáãäçèéëíîïïð€òôùüýüüÿý…úù÷ôñòòðîìêäåèäãèüÿÿîÕÌÏËÀÀ¹µ±¯¯±ª¥¢¡¨ªàóàÒÞòÿ÷úÿÿú‚”-&d¨ª¡¦ª®°¹¾½ÂÇÌÑÒÕØÛÝßáåæèéëìííïðñòòôõ÷öøûúúü‚û5üûù÷öùûúôïêæãááãçõÿÿóÖÌÉÇĽ¼·²°®¯©¥£ ›£Ùïïßéÿýæìüø÷x”-)h®¬ ¥¨«¯³·½¿ÄÇÌÎÒÕØÛÞßáäæçèéëìîðññòóôõ÷øùúûü‚ýþþüüý€ÿ-úïêæãâããäôÿÿüàÍÉÇÅÁÉǹ¶³±®ª©¦£ œ Óëôåéúúõ÷øëôt”5+k°® £¯¸¶²¶»½ÂÆÈÌÐÓÖØÛÝßâåççèêëíïðññòôõ÷øùúûüþþÿþýÿþþ‚ÿ-þòêæääçééùÿÿüáÍÊÆÄÁÃø¶³±¯©¬²ª¡žÑêòÖÜòúþÿóïø{”-,k°·«¥±Á¼²µ¹¿ÁÆÈÌÒÓÔÖØÛÝàãææçèêìîððñòóôö÷ùúûü€ÿþýþ…ÿ,ùìèææîøúþÿÿõØÌÉÆÄÄÀºº·µ´¯ª¬¸­ œ¢ÑáßÔçôìõúùôúƒ”3+i°³©¬©µ¹±´¸ÆÈÆÇÊÏÒÒÔØÚÜÝàãååçéëîïðñòóõö÷ùúúüþÿÿþýþ…ÿþõíèè÷‚ÿ!òÕÍÊÇÄÄÀ»º¹Â¼¯ª®¸¨¢§£ÏÚØÚçíÞñùùðù~”.(h®¯£¥¥­²¯³·ÁÇÃÄÇËÏÏÒÖØÙÜÞàããæçéíîïññòôõöøùúüþ‹ÿþùôóþ‚ÿ!öÛÏËÇÄÅÊÈ»ºÀ·°«®¹¦£¨«ÏÍÖâçñïïöëçøz”-%c«¸­©¨§«­²¶¹¾ÂÅÇÉËÍÑÔÕ×ÚÝÞàãäæèéìîññòóôö÷øúýŽÿýþƒÿ!ìÓÌÈÆÃÅÍÆ»¼µ°¯ª¯²¥¡¢·×ÎÒÜÞêõìæéöú”%"]¨µ±µ­®¯°²µ¹»¿ÃÇÉÊÌÏÒÓÕÙÛÝßàãåçéëíïñ€óôö÷û“ÿ%ý÷ñéÔËËÈÆÃÆÅ¼»º¶±­ª¬«¥¡§¼Ýǽ×ÝâæÜÙìþù”,W¢³¥¬°¯­±´´¹½½¿ÄÊÉÊÏÔÓÔØÚÛÝàâäæèêíîïññòôõöú‘ÿ'þøìÞÕÒÏÌÉÈÆÂÅÆ¼¹¸¸²®ªª«§¡£ºÖÄÇÙ×ÛÚÜíìùú}”-Oš·¡ ¯¬§®³º½Ä¾¿ÄÉÈÈÒ×ÓÔÕØÙÞßßâäçéëîïðññòôõúþ…ÿüùû…ÿ'÷åÙÔÓÑÎÌÊËÈÂÁÁ¿¹¸·µ±ª¥£¯¨»Ù××ÓÒÑÐÓÚéê÷|”&E޽§£³«§­®»ÃƼ¼ÁÄÅÆÍÒÐÑÔÕØÜÞÞáãæèéìîð€ñó÷üþƒÿþøòò÷üÿþý€ÿ(ýíÜØÕÓÑÎÌÌËÆÂ¿½¼¸·Á³¨££³°œÀäÈÉ×ÈØÔÌÕúóò~•+:‚º£¢±ª¥©«·ÈÁ¸»½ÂÄÇÉÌÍÏÓÔÖÙÞßßáäçèéëíïïñó÷úƒÿ þøòñððõúúü€ÿ(úçÚÙÔÒÐÒÒÍËž¼¼¹»Ä¾®²¯¢©¬›Äà·¸ÓÚÛÍ×óÿüñ~•+ 0s¯¡¤¥¤©«´Â»¶º¼ÂÃÅÇÉÐÑÓÔÕ×ÚÜÞßâæèèêëìíðòôú‚ÿ6üøóðïîíïòô÷üÿÿûäØÖÔÒÑÖÛÕÎÉÿ»·¸ÀǼÆàؾµ¡ÍÚ¶½ÜÞÝÛäûûóî•+&b¤ª¢¦«¦§«°³´¶¹½ÄÅÃÆÇÍÐÒÒÔÕÙÚÜÝàâåæééììïðñúÿ7ûõòïîìíðîííïöÿÿþîÚÖÔÒÑÕÙÔÍÈÅÑÔÎÓÝççøÿþîá«ÑÔ¿ÉæÛ×áìñøøù‚•+Q˜¯¢¥­­¨ª°¯³´¸ÄÊÂÁÅÆÊÎÏÐÒÔ×ÚÜÝÞàâãæèêíìîóüÿöòðìëêëïîìéêóþÿÿöâÖÑÏÐÒÙàÞ×âõûüƒÿùäÀ£±ÔÌÊÒæÛ×åïðïüúƒ• @ˆ®œ£®ª§©€±³¹ÊȽÀÅÇÈËÎÐÑÔÕØÚÛÜÞáããåçëìïöÿþõïìêéèéèæòÿÿþõêÝÝÚàêóúûø€ÿýõûóèã×Å´¤—¾ßÙÐáâÔÞçòùéýûƒ–) 0s¬¡ž¦¤¤§¯¯°²¸Â¾½¿ÃÇÇÉÊÍÐÒÓÖ×ÙÛÛßãáãæçëôýÿþõíêèççæääæçãéûÿÿüùøùøû„ÿüéÓÑĵ±¦«¨ÑåÓÈÖÕ×ííåõøûøƒ–("\¡©œ©ª¤¦ª¬¯±´½¿¼¿ÀÄÆÈÌÌÎÐÒÓÔ×ÚÛÜßßâåçìùƒÿ óëçæååäâáââßßõ…ÿ!øòèÝíôëäÏ»³®©¥ ®«©ØÞÆÈãêåôòÞÔÝËé…–(D´¨©¤£¤­°­°²¼Á»½¾ÀÃÈÓÌÍÎÏÕÚÖ×ÙÚÜÞàäêóùÿ ýöíèçæäâá߀ÞÛÚíþƒÿ"íÔËÇÃÈÇÄǶ°¯³­¤¢¬ª¤ÂßÖÙìûçßñüíÔηÎq—' 0r­¥ž¨¥£ª¯±´°´º»º¿ÂÄÅÉÊÍÌÏÒÝߨ֨ÚÝàáèñüÿýðè€æ âßÞÞÝÛÙØ×æýÿ$ûçÓÈÃÂÀ½¹¹¶±±³±¬£ «¥ ÔÞÝ×èíØàùýìíã̽^—'T­Ÿ®©£¦¶³¸±²¶¹»ÀÃÂÃÆÉÍËÍÎÒÚÙÕרÚÝÞäëö‚ÿõæáâäáÞÝÜÛÙ×ÖÖÙîÿ$øÛËÄ¿¼»¸µ±°¹º®©£ ¤ ´ÔÒÜÅÓõàìþüýþúðÐZ—)8€¶¨£«¤¥®«±²°³·¹¼ÀÀÂÆÇÉÉÊÍÎÐÓÔÕÖØÛÜÞãèõþ€ÿ8ïßÞÞßÝÜÛÚØØ×ÔÔÒÝþÿýôîßž½»¶³±¯²°¨¥£¡¡ÌØàÙåìüüøùýÿÿûñè`˜($]¥¬¤£¤¥©«®°³´¶»ÀÃÅÂÄÆÈÈËÌÎÐÒÕÖרÙÚÝßäö€ÿ,êÜÜÛÚÙÛÛÙ×ÖÕÓÓÒÚúÿòÖÍÔÇÀÁ½¼¸²·´­ªª«£¥¯ ¬ÐÝèðý€ÿüüÿÿþðéïr˜(=ƒ°¢œ ¤¥ª¬«¯±·¸·¼ÂÅÁÄÉÊÆÈËÌÏØØÕÕÖÖ×ÚÜàò€ÿöÞØØ€×%ØÖÕÓÒÒÑÑÙøþéÐÉÆÁ¿½»¹´·º¯­ª«¬¢§­¢½ÁØæò÷€ÿþûûÿýõûñy™' %\¥«ž¡¦¥­²ª¬®ÀÀ¶º»¾ÁÄÉËÈÇÉÌÌÖ×ÑÔÖÕÔÙÜàóÿêÕÔ€Ó.ÑÐÑÐÐÕöÿíÏÃÀ½¼»¸¶¶Ä¾°³¬¨¦£¡–¯ÇµÒíëüüøùøôóôùçôìt™'9}°¨¡£¢¦¨¨®´½¿·¸¸»½¿ÂÈÎËÊÌÍËÌÓ×ÕÕØÙßç÷ÿ7úÞÒÔÔÓÒÒÐÎÍÎÎÓÝøþâÄÀ¼»¼¼¶³¿Áµ®®¦£¢¢žžÇÊ´Äéëêóðìüþñéç×ãëxš&!Q¯ž¢¤¥¨³½µ·µ³¶»¼¼¿ÃÈÊËÝãÖåñÞÒÚäçòûþ‚ÿ÷ÞÐÑÒÐÐÎÍÌËÓäöÿýÒ½¾€» ¸³³º±¬¨§®¨¤¥¢·ÎÒÅÀàúñöö÷þÿú÷ôñëétš#1m¬¤œ®¯²±«¯¬°³²³·º¼¾ÂÂÀÍõÿûüìÔÑÝì÷ÿ3ûîëñÿûáÐËÊÊËÌÍÎß÷ÿÿðÉÀ½»¼¸³²±¯­¬¦¨¶­ª ¨ÇÏ×ÙÎàøýÿÿýüü‚ÿø{›"C‰¯ž®º»·¤¤ªµ½´±³¸¼»½¾»ØÿøçÓÇÇÐÚæø€ÿôÞÓÑÓÞôÿñßÓÍÇÉÍßöÿÿòÒÅÀº¹·´±¯€²¬¥«²©¥ ¿ÈÈÕãÙØõùûûÿýùýüÿÿøøyœ` &Wœ«£±°»°¤«½Á²°²¶¹¸¹º¹ØÿÛÁÅÄÆÌÛñýÿÿöÙÉÉËÊËÒìÿý÷ðäßßõÿþòÔÁý·¹¸²³¯­³¯¦¦°«¦§¶ØÍ¾Òßçãíâëôÿÿüþþúòñú€œ 3j¨§œ¡ª°´¯¹À³­°´»··¹¸ÍûãÇÐÉÇÔãö€ÿ<íËÆÇÉÈÊÈÎçûÿÿþüûÿÿæÖƾ¾¹¶¿À°³´¬±«¦§°¡›±ÉÀÁ®µÏãòúæÙöÿþýþÿûóòøz/?y¬¡œž¡¬¯¬³¯­¯°´´ºÏÖÈáýÜÖàáïøýÿÿûÝÆÅÅÇÇÆÆÇÈÕèþÿ+øÔÉÁ»¶´ÁÅ·°´±¬§¥£¥©£¨Èʹ³¯°ËÑçóæÚìÿøúÿü÷ïéôvž I…¯ž£­¡§«¦©¬®¯¯²¹ÈÕÐÔïüóóûþþ€ÿ ëÉÁÂÂÃÅÅÆÈÆÄÕö€ÿ,úàÊŽ¶µ¸¹·­²´©¨¥£¡¢©°ÉÔøËßÉËÜîâäßæéåôÿýøöõøyž' 'QŒ°®´¨¡£§­«ª¬®°¾ÉÔÕáüÿýÿþù÷öðÙÉÿ¿ÁÃÅ€Ë3ÚÞÚìÿÿôÛÌÆÂ¸²·»®¯´­¦¦¥¢ ¢¦¦Æ×ÙâÍÕÌÓï÷éÎÕçæäñýÿÿûôïïtŸ]*U’°£¦­ª³¯¦§¨®º¼ÆÍÐéþÿÿüëÕÍÉÈÁ¿½ÃÄÀÀÄÐÇËöÿüúÿóÏÀÂÀº³°¯¯µ¸±©¬³«¥©¯¥Ãëä×óàÃÈÝæëõÝÒßðõòðùÿïÞñõr (-W’®­´©§¨¥¤©­¶º¸ÄçüÿöåÕÁ¼¿¾½¼½»Áƽ½¿ÁÆå‚ÿ.á»·´³±°¯¬¬¸±¤°¾»©¢ª¯ÊÛÞîØßêÚÝñìõôéÐÕÒßÙÙëöòæîòn¡&-V‘¹®žž¤¥£³´«¸¹ÆêÿüÖ¹²´·¶··¶·¼º»¿ÀÁÁß‚ÿ/øÐµ²±¯±±««¬­ª¤«³ª˜¡ËìðèïòòçîöìñÚÍõíîÊØçãÞÒåÛÒÓf¢%*QŒ°¨ž ¥«¯°µÃÚñÿúݽ±³³±²µ¹¶¶ºÂËÌÌÖûÿ0ûܼ²¯¯­°²ª¨¬­§¢¦¨ž™¨ÑíóùôÿÿøöøùþýåÊùÿôèóòäçäãâÑÒn£%&J¬°¡ž¤¦¤«·Òéÿÿ÷⿲³±³¶ºÌÕÌÏâéåàí÷ú€ÿ0öи°¯¬¬¯°­§¥¤¢¡¦¡žµÙîòú÷ÿ÷ìúùùÞñÿÿöýþùþÿûöùæÌßàïx¤H !?o¢²§Ÿ¡£§¸ÛñÿÿêÈ´²´´¸ÃÎêûö÷ÿÿýøòçãõûÿ÷Ö»®­©¨§¦¨¤£¡¡ŸšŸÀåñôøþôý÷êóøïÏöü€ÿ ûôýúýõçÖÐÝõõ{¥ 5]ެ¬ œ¥¹ãüÿÿÔ¬§¨¬®¶Ëò…ÿ&ùïÜÖâÿñÄ´©¦¥£¢¢¡£¢ž—›²ÒêóøûýþùþÿÿüùöðÞë€þ üùøùÿøÜÕéìþû„§)JvŸ¯§œ¬çÿÿï¾­°¬­¯»Ü€ÿùÛÝó€ÿ%ýöêíÿòÄ´­¤¡¡¥¦ª¦™–£ÃáðöùüÿýûûøùÿÿþÿÿÛñ€ÿ ýÿüýÿþóôøüõúƒ¨8]†¦®®ÚÿýÑ©´¸©©½àùÿþ󨶶Ô÷üƒÿ$ûÕ·±¨¨®¬¤¦Ÿ¢¼Ùëó÷üú÷þýÿÿóåéúþýÿûÿþÿÿþ‚ÿýÿüúðú„©'BgŒ©½ëÿå°£¥¤ªÙþÿÿüÔ´¬®ËÞ×ãýÿ$þìÉ­¨®®Ÿœ³ÅØéòöùýüýýþþèßýùôñúþýüÿýÿÿþ‚ÿõõûøðú„« ,Fe…¨Ó೜›ŸºèöàçÞ¶§®±¿¼µÙýþ€ÿûÞ¼¨œ °µÅÝëñõøüýþý€ÿ þççÿÿþúüþïéüûýÿ ùùÿõÓéþøø€¬7 ,B[y—©®®¦¯ÐåÀ´»®¨«³®²¿ÎÞíýûÿÿâ·§«¿Öâåìóùýþþÿÿûúþÿÿþþ‚ÿëíýñ×áûýõûÿçÉãäöÿýùƒ®) '8Mf€–¦±Äؼ­¸¶­«©¥¤±¸ÊãùùòîàÓÓÙåîðóöúþ€ýþÿýþÿý„ÿýÛÛêíËÞþøãêúÜÏ÷ÿü÷ÿúƒ°0+:K^q‚“¡¨®°±²­²¶µ¼ÈÖáâÛÜâæââíú÷ú÷öýô÷ÿÿþðûÿýƒÿüÿïØîÿúûþøïÖÍÜãõÿþûÿúƒ³,$1=HVakt{‚¹ÝÛÔ×àçáåõóæîúüøüýüüþüýüûúüÿþ†ÿýüýÿÿþþÿÿðçïêôûïóüúƒ· %*/545“ÓÐÔåìõòõüööõòíéôöþÿ÷òâñÿüþ‰ÿýúüýþÿÿüéÝÜÐâüú}¼ ƒØÙëøûøþý€÷çà×ßëóƒÿûòùÿù„ÿûóúþ‚ÿ ùù÷÷ÿöåÓÜæëïpÃ{ÍÞíòûöýöûùËÌàØáíùüüÿûùûÿûþƒÿøèôüþÿ üîãíûþöìæÓÉßtÃl¹ÙëøñõÿüÿøÕÞêáÜåüóóÿýùþþ‰ÿþýýÿ þöÝÚòùóêîØÐÓâuÃmËÙæóðú÷ÿþïôÿýòáØáïôûûÿüþÿýöíëþþìÜØ×ïìítÃvÙâåùþÿøÿýúüùîåæÜßöòðòúÿýþýþûòöÿùæØÙßñìöÆãí÷þúƒÿ õâàóäáûñîûøöþŽÿþøþý÷ôÿòàÚäæäåöÂæñýôôƒÿ þñðýõÝùýýÿþüþÿýþüùùôíãÕÞâÜæïwÊðîñôþ‚ÿþþúõþûîü˜ÿ ýöòïîîðôíòîyÉíö÷ùÿýÿþÿÿþýÿþÿúý˜ÿüö÷ùöú€ÿüþú€Ãš€úù¢úøéèúù‚úùö…ÃNƒƒ}ww|¡ƒ ‚yq~|„~ƒ{}Aÿÿÿÿÿÿøt8mk@Úìëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëîè®ïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÁ ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÅ" ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÐD/ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýØ\@ ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiJ# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÜiI# òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßiI# òüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþüÞiJ# ±ÆÑÙÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÞÛÃjJ# (Pl{|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||{xgH" "D\iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifX= 0@IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIJIG=+ ###################################################################################################################" dxx-rebirth-0.58.1-d2x/arch/cocoa/tool_bundle.py000066400000000000000000000205221217717237500214360ustar00rootroot00000000000000# Create an application package. # http://www.scons.org/wiki/SubstInFileBuilder import re from SCons.Script import * from SCons.Builder import * def TOOL_SUBST(env): """Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT from the source to the target. The values of SUBST_DICT first have any construction variables expanded (its keys are not expanded). If a value of SUBST_DICT is a python callable function, it is called and the result is expanded as the value. If there's more than one source and more than one target, each target gets substituted from the corresponding source. """ env.Append(TOOLS = 'SUBST') def do_subst_in_file(targetfile, sourcefile, dict): """Replace all instances of the keys of dict with their values. For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'}, then all instances of %VERSION% in the file will be replaced with 1.2345 etc. """ try: f = open(sourcefile, 'rb') contents = f.read() f.close() except: raise SCons.Errors.UserError, "Can't read source file %s"%sourcefile for (k,v) in dict.items(): contents = re.sub(k, v, contents) try: f = open(targetfile, 'wb') f.write(contents) f.close() except: raise SCons.Errors.UserError, "Can't write target file %s"%targetfile return 0 # success def subst_in_file(target, source, env): if not env.has_key('SUBST_DICT'): raise SCons.Errors.UserError, "SubstInFile requires SUBST_DICT to be set." d = dict(env['SUBST_DICT']) # copy it for (k,v) in d.items(): if callable(v): d[k] = env.subst(v()) elif SCons.Util.is_String(v): d[k]=env.subst(v) else: raise SCons.Errors.UserError, "SubstInFile: key %s: %s must be a string or callable"%(k, repr(v)) for (t,s) in zip(target, source): return do_subst_in_file(str(t), str(s), d) def subst_in_file_string(target, source, env): """This is what gets printed on the console.""" # return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t)) # for (t,s) in zip(target, source)]) def subst_emitter(target, source, env): """Add dependency from substituted SUBST_DICT to target. Returns original target, source tuple unchanged. """ d = env['SUBST_DICT'].copy() # copy it for (k,v) in d.items(): if callable(v): d[k] = env.subst(v()) elif SCons.Util.is_String(v): d[k]=env.subst(v) env.Depends(target, SCons.Node.Python.Value(d)) return target, source subst_action=SCons.Action.Action(subst_in_file, subst_in_file_string) env['BUILDERS']['SubstInFile'] = env.Builder(action=subst_action, emitter=subst_emitter) # http://www.scons.org/wiki/MacOSX (modified to suit) from SCons.Defaults import SharedCheck, ProgScan from SCons.Script.SConscript import SConsEnvironment import sys import os import SCons.Node import SCons.Util import string def TOOL_BUNDLE(env): """defines env.LinkBundle() for linking bundles on Darwin/OSX, and env.MakeBundle() for installing a bundle into its dir. A bundle has this structure: (filenames are case SENSITIVE) sapphire.bundle/ Contents/ Info.plist (an XML key->value database; defined by BUNDLE_INFO_PLIST) PkgInfo (trivially short; defined by value of BUNDLE_PKGINFO) MacOS/ executable (the executable or shared lib, linked with Bundle()) Resources/ """ if 'BUNDLE' in env['TOOLS']: return if sys.platform == 'darwin': #if tools_verbose: print " running tool: TOOL_BUNDLE" env.Append(TOOLS = 'BUNDLE') # This is like the regular linker, but uses different vars. # XXX: NOTE: this may be out of date now, scons 0.96.91 has some bundle linker stuff built in. # Check the docs before using this. """LinkBundle = env.Builder(action=[SharedCheck, "$BUNDLECOM"], emitter="$SHLIBEMITTER", prefix = '$BUNDLEPREFIX', suffix = '$BUNDLESUFFIX', target_scanner = ProgScan, src_suffix = '$BUNDLESUFFIX', src_builder = 'SharedObject') env['BUILDERS']['LinkBundle'] = LinkBundle""" env['BUNDLEEMITTER'] = None env['BUNDLEPREFIX'] = '' env['BUNDLESUFFIX'] = '' env['BUNDLEDIRSUFFIX'] = '.bundle' #env['FRAMEWORKS'] = ['-framework Carbon', '-framework System'] env['BUNDLE'] = '$SHLINK' env['BUNDLEFLAGS'] = ' -bundle' env['BUNDLECOM'] = '$BUNDLE $BUNDLEFLAGS -o ${TARGET} $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $FRAMEWORKS' # This requires some other tools: TOOL_WRITE_VAL(env) TOOL_SUBST(env) # Common type codes are BNDL for generic bundle and APPL for application. def MakeBundle(env, bundledir, app, key, info_plist, typecode='BNDL', creator='SapP', icon_file='#macosx-install/sapphire-icon.icns', subst_dict=None, resources=[]): """Install a bundle into its dir, in the proper format""" # Substitute construction vars: for a in [bundledir, key, info_plist, icon_file, typecode, creator]: a = env.subst(a) if SCons.Util.is_List(app): app = app[0] if SCons.Util.is_String(app): app = env.subst(app) appbase = os.path.basename(app) else: appbase = os.path.basename(str(app)) if not ('.' in bundledir): bundledir += '.$BUNDLEDIRSUFFIX' bundledir = env.subst(bundledir) # substitute again suffix=bundledir[string.rfind(bundledir,'.'):] if (suffix=='.app' and typecode != 'APPL' or suffix!='.app' and typecode == 'APPL'): raise Error, "MakeBundle: inconsistent dir suffix %s and type code %s: app bundles should end with .app and type code APPL."%(suffix, typecode) if subst_dict is None: subst_dict={'%SHORTVERSION%': '$VERSION_NUM', '%LONGVERSION%': '$VERSION_NAME', '%YEAR%': '$COMPILE_YEAR', '%BUNDLE_EXECUTABLE%': appbase, '%ICONFILE%': os.path.basename(icon_file), '%CREATOR%': creator, '%TYPE%': typecode, '%BUNDLE_KEY%': key} env.Install(bundledir+'/Contents/MacOS', app) f=env.SubstInFile(bundledir+'/Contents/Info.plist', info_plist, SUBST_DICT=subst_dict) env.Depends(f,SCons.Node.Python.Value(key+creator+typecode+env['VERSION_NUM']+env['VERSION_NAME'])) env.WriteVal(target=bundledir+'/Contents/PkgInfo', source=SCons.Node.Python.Value(typecode+creator)) resources.append(icon_file) for r in resources: if SCons.Util.is_List(r): env.InstallAs(bundledir+'/Contents/Resources/'+r[1], r[0]) else: env.Install(bundledir+'/Contents/Resources', r) return [ SCons.Node.FS.default_fs.Dir(bundledir) ] # This is not a regular Builder; it's a wrapper function. # So just make it available as a method of Environment. SConsEnvironment.MakeBundle = MakeBundle def TOOL_WRITE_VAL(env): #if tools_verbose: print " running tool: TOOL_WRITE_VAL" env.Append(TOOLS = 'WRITE_VAL') def write_val(target, source, env): """Write the contents of the first source into the target. source is usually a Value() node, but could be a file.""" f = open(str(target[0]), 'wb') f.write(source[0].get_contents()) f.close() env['BUILDERS']['WriteVal'] = env.Builder(action=write_val) dxx-rebirth-0.58.1-d2x/arch/include/000077500000000000000000000000001217717237500171145ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/include/digi_audio.h000066400000000000000000000010461217717237500213630ustar00rootroot00000000000000#ifndef __DIGI_AUDIO__ #define __DIGI_AUDIO__ #include "fix.h" int digi_audio_init(); void digi_audio_reset(); void digi_audio_close(); void digi_audio_stop_all_channels(); int digi_audio_start_sound(short, fix, int, int, int, int, int ); int digi_audio_is_sound_playing(int ); int digi_audio_is_channel_playing(int ); void digi_audio_set_channel_volume(int, int ); void digi_audio_set_channel_pan(int, int ); void digi_audio_stop_sound(int ); void digi_audio_end_sound(int ); void digi_audio_set_digi_volume(int); void digi_audio_debug(); #endif dxx-rebirth-0.58.1-d2x/arch/include/digi_mixer.h000066400000000000000000000011351217717237500214050ustar00rootroot00000000000000#ifndef __DIGI_MIXER__ #define __DIGI_MIXER__ #include "fix.h" int digi_mixer_init(); void digi_mixer_close(); int digi_mixer_start_sound(short, fix, int, int, int, int, int); void digi_mixer_set_channel_volume(int, int); void digi_mixer_set_channel_pan(int, int); void digi_mixer_stop_sound(int); void digi_mixer_end_sound(int); int digi_mixer_is_sound_playing(int); int digi_mixer_is_channel_playing(int); void digi_mixer_reset(); void digi_set_max_channels(int); int digi_get_max_channels(); void digi_mixer_stop_all_channels(); void digi_mixer_set_digi_volume(int); void digi_mixer_debug(); #endif dxx-rebirth-0.58.1-d2x/arch/include/digi_mixer_music.h000066400000000000000000000006021217717237500226030ustar00rootroot00000000000000/* * Header file for music playback through SDL_mixer * * -- MD2211 (2006-04-24) */ #ifndef _SDLMIXER_MUSIC_H #define _SDLMIXER_MUSIC_H int mix_play_music(char *, int); int mix_play_file(char *, int, void (*)()); void mix_set_music_volume(int); void mix_stop_music(); void mix_pause_music(); void mix_resume_music(); void mix_pause_resume_music(); void mix_free_music(); #endif dxx-rebirth-0.58.1-d2x/arch/include/event.h000066400000000000000000000040031217717237500204030ustar00rootroot00000000000000/* * $Source: /cvsroot/dxx-rebirth/d2x-rebirth/arch/include/event.h,v $ * $Revision: 1.1.1.1 $ * $Author: zicodxx $ * $Date: 2006/03/17 19:54:32 $ * * Event header file * * $Log: event.h,v $ * Revision 1.1.1.1 2006/03/17 19:54:32 zicodxx * initial import * * Revision 1.1 2001/01/28 16:10:57 bradleyb * unified input headers. * * */ #ifndef _EVENT_H #define _EVENT_H #include "maths.h" typedef enum event_type { EVENT_IDLE = 0, EVENT_QUIT, EVENT_JOYSTICK_BUTTON_DOWN, EVENT_JOYSTICK_BUTTON_UP, EVENT_JOYSTICK_MOVED, EVENT_MOUSE_BUTTON_DOWN, EVENT_MOUSE_BUTTON_UP, EVENT_MOUSE_DOUBLE_CLICKED, EVENT_MOUSE_MOVED, EVENT_KEY_COMMAND, EVENT_KEY_RELEASE, EVENT_WINDOW_ACTIVATED, EVENT_WINDOW_DEACTIVATED, EVENT_WINDOW_DRAW, EVENT_WINDOW_CLOSE, EVENT_WINDOW_CLOSED, EVENT_NEWMENU_DRAW, // draw after the newmenu stuff is drawn (e.g. savegame previews) EVENT_NEWMENU_CHANGED, // an item had its value/text changed EVENT_NEWMENU_SELECTED, // user chose something - pressed enter/clicked on it EVENT_UI_DIALOG_DRAW, // draw after the dialog stuff is drawn (e.g. spinning robots) EVENT_UI_GADGET_PRESSED, // user 'pressed' a gadget EVENT_UI_LISTBOX_MOVED, EVENT_UI_LISTBOX_SELECTED, EVENT_UI_USERBOX_DRAGGED } event_type; // A vanilla event. Cast to the correct type of event according to 'type'. typedef struct d_event { event_type type; } d_event; int event_init(); // Sends input events to event handlers void event_poll(); void event_flush(); // Set and call the default event handler void set_default_handler(int (*handler)(d_event *event)); int call_default_handler(d_event *event); // Send an event to the front window as first priority, then to the windows behind if it's not modal (editor), then the default handler void event_send(d_event *event); // Sends input, idle and draw events to event handlers void event_process(); void event_toggle_focus(int activate_focus); // See how long we were idle for void event_reset_idle_seconds(); fix event_get_idle_seconds(); #endif dxx-rebirth-0.58.1-d2x/arch/include/joy.h000066400000000000000000000015631217717237500200730ustar00rootroot00000000000000/* * * Header for joystick functions * */ #ifndef _JOY_H #define _JOY_H #include "pstypes.h" #include "fix.h" #include struct d_event; #define MAX_JOYSTICKS 8 #define MAX_AXES_PER_JOYSTICK 128 #define MAX_BUTTONS_PER_JOYSTICK 128 #define MAX_HATS_PER_JOYSTICK 4 #define JOY_MAX_AXES (MAX_AXES_PER_JOYSTICK * MAX_JOYSTICKS) #define JOY_MAX_BUTTONS (MAX_BUTTONS_PER_JOYSTICK * MAX_JOYSTICKS) extern int joy_num_axes; // set to Joystick.n_axes. solve different? extern void joy_init(); extern void joy_close(); extern void event_joystick_get_axis(struct d_event *event, int *axis, int *value); extern void joy_flush(); extern int event_joystick_get_button(struct d_event *event); extern void joy_button_handler(SDL_JoyButtonEvent *jbe); extern void joy_hat_handler(SDL_JoyHatEvent *jhe); extern int joy_axis_handler(SDL_JoyAxisEvent *jae); #endif // _JOY_H dxx-rebirth-0.58.1-d2x/arch/include/jukebox.h000066400000000000000000000004321217717237500207330ustar00rootroot00000000000000#ifndef __JUKEBOX_H__ #define __JUKEBOX_H__ extern const char *const jukebox_exts[7]; void jukebox_unload(); void jukebox_load(); int jukebox_play(); char *jukebox_current(); int jukebox_is_loaded(); int jukebox_is_playing(); int jukebox_numtracks(); void jukebox_list(); #endif dxx-rebirth-0.58.1-d2x/arch/include/key.h000066400000000000000000000124711217717237500200620ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for keyboard functions * */ #ifndef _KEY_H #define _KEY_H #include #include "pstypes.h" #include "fix.h" #include "event.h" #define KEY_BUFFER_SIZE 16 #define KEY_REPEAT_DELAY 400 #define KEY_REPEAT_INTERVAL 50 //========================================================================== // This installs the int9 vector and initializes the keyboard in buffered // ASCII mode. key_close simply undoes that. extern void key_init(); extern void key_close(); // Time in seconds when last key was pressed... extern fix64 keyd_time_when_last_pressed; // Stores Unicode values registered in one event_loop call extern unsigned char unicode_frame_buffer[KEY_BUFFER_SIZE]; extern void key_flush(); // Clears the 256 char buffer extern int event_key_get(d_event *event); // Get the keycode from the EVENT_KEY_COMMAND event extern int event_key_get_raw(d_event *event); // same as above but without mod states extern unsigned char key_ascii(); // Set to 1 if the key is currently down, else 0 extern volatile unsigned char keyd_pressed[256]; extern volatile unsigned char keyd_last_pressed; extern volatile unsigned char keyd_last_released; extern void key_toggle_repeat(int enable); // for key_ismodlck #define KEY_ISMOD 1 #define KEY_ISLCK 2 #define KEY_SHIFTED 0x100 #define KEY_ALTED 0x200 #define KEY_CTRLED 0x400 #define KEY_DEBUGGED 0x800 #define KEY_METAED 0x1000 #define KEY_COMMAND KEY_METAED // Mac meta key #define KEY_0 0x0B #define KEY_1 0x02 #define KEY_2 0x03 #define KEY_3 0x04 #define KEY_4 0x05 #define KEY_5 0x06 #define KEY_6 0x07 #define KEY_7 0x08 #define KEY_8 0x09 #define KEY_9 0x0A #define KEY_A 0x1E #define KEY_B 0x30 #define KEY_C 0x2E #define KEY_D 0x20 #define KEY_E 0x12 #define KEY_F 0x21 #define KEY_G 0x22 #define KEY_H 0x23 #define KEY_I 0x17 #define KEY_J 0x24 #define KEY_K 0x25 #define KEY_L 0x26 #define KEY_M 0x32 #define KEY_N 0x31 #define KEY_O 0x18 #define KEY_P 0x19 #define KEY_Q 0x10 #define KEY_R 0x13 #define KEY_S 0x1F #define KEY_T 0x14 #define KEY_U 0x16 #define KEY_V 0x2F #define KEY_W 0x11 #define KEY_X 0x2D #define KEY_Y 0x15 #define KEY_Z 0x2C #define KEY_MINUS 0x0C #define KEY_EQUAL 0x0D //Note: this is what we normally think of as slash: #define KEY_DIVIDE 0x35 //Note: this is BACKslash: #define KEY_SLASH 0x2B #define KEY_COMMA 0x33 #define KEY_PERIOD 0x34 #define KEY_SEMICOL 0x27 #define KEY_LBRACKET 0x1A #define KEY_RBRACKET 0x1B #define KEY_RAPOSTRO 0x28 #define KEY_LAPOSTRO 0x29 #define KEY_ESC 0x01 #define KEY_ENTER 0x1C #define KEY_BACKSP 0x0E #define KEY_TAB 0x0F #define KEY_SPACEBAR 0x39 #define KEY_NUMLOCK 0x45 #define KEY_SCROLLOCK 0x46 #define KEY_CAPSLOCK 0x3A #define KEY_LSHIFT 0x2A #define KEY_RSHIFT 0x36 #define KEY_LALT 0x38 #define KEY_RALT 0xB8 #define KEY_LCTRL 0x1D #define KEY_RCTRL 0x9D #define KEY_LMETA 0x9E #define KEY_RMETA 0x9F #define KEY_F1 0x3B #define KEY_F2 0x3C #define KEY_F3 0x3D #define KEY_F4 0x3E #define KEY_F5 0x3F #define KEY_F6 0x40 #define KEY_F7 0x41 #define KEY_F8 0x42 #define KEY_F9 0x43 #define KEY_F10 0x44 #define KEY_F11 0x57 #define KEY_F12 0x58 #define KEY_PAD0 0x52 #define KEY_PAD1 0x4F #define KEY_PAD2 0x50 #define KEY_PAD3 0x51 #define KEY_PAD4 0x4B #define KEY_PAD5 0x4C #define KEY_PAD6 0x4D #define KEY_PAD7 0x47 #define KEY_PAD8 0x48 #define KEY_PAD9 0x49 #define KEY_PADMINUS 0x4A #define KEY_PADPLUS 0x4E #define KEY_PADPERIOD 0x53 #define KEY_PADDIVIDE 0xB5 #define KEY_PADMULTIPLY 0x37 #define KEY_PADENTER 0x9C #define KEY_INSERT 0xD2 #define KEY_HOME 0xC7 #define KEY_PAGEUP 0xC9 #define KEY_DELETE 0xD3 #define KEY_END 0xCF #define KEY_PAGEDOWN 0xD1 #define KEY_UP 0xC8 #define KEY_DOWN 0xD0 #define KEY_LEFT 0xCB #define KEY_RIGHT 0xCD #define KEY_PRINT_SCREEN 0xB7 #define KEY_PAUSE 0x61 typedef struct key_props { const char *key_text; unsigned char ascii_value; SDLKey sym; } key_props; extern const key_props key_properties[256]; #endif dxx-rebirth-0.58.1-d2x/arch/include/messagebox.h000066400000000000000000000005211217717237500214200ustar00rootroot00000000000000/* * messagebox.h * d1x-rebirth * * Display an error or warning messagebox using the OS's window server. * */ #ifndef _MESSAGEBOX_H #define _MESSAGEBOX_H // Display a warning in a messagebox extern void msgbox_warning(char *message); // Display an error in a messagebox extern void msgbox_error(const char *message); #endif dxx-rebirth-0.58.1-d2x/arch/include/mouse.h000066400000000000000000000022341217717237500204160ustar00rootroot00000000000000/* * * SDL mouse driver header * */ #ifndef MOUSE_H #define MOUSE_H #include "pstypes.h" #include "fix.h" struct d_event; struct window; #define MOUSE_MAX_BUTTONS 16 #define Z_SENSITIVITY 100 #define MBTN_LEFT 0 #define MBTN_RIGHT 1 #define MBTN_MIDDLE 2 #define MBTN_Z_UP 3 #define MBTN_Z_DOWN 4 #define MBTN_PITCH_BACKWARD 5 #define MBTN_PITCH_FORWARD 6 #define MBTN_BANK_LEFT 7 #define MBTN_BANK_RIGHT 8 #define MBTN_HEAD_LEFT 9 #define MBTN_HEAD_RIGHT 10 #define MBTN_11 11 #define MBTN_12 12 #define MBTN_13 13 #define MBTN_14 14 #define MBTN_15 15 #define MBTN_16 16 #define MOUSE_LBTN 1 #define MOUSE_RBTN 2 #define MOUSE_MBTN 4 extern void mouse_flush(); // clears all mice events... extern void mouse_init(void); extern void mouse_close(void); extern int event_mouse_get_button(struct d_event *event); extern void mouse_get_pos( int *x, int *y, int *z ); extern int mouse_in_window(struct window *wind); extern void mouse_get_delta( int *dx, int *dy, int *dz ); extern void event_mouse_get_delta(struct d_event *event, int *dx, int *dy, int *dz); extern int mouse_get_btns(); extern void mouse_toggle_cursor(int activate); #endif dxx-rebirth-0.58.1-d2x/arch/include/window.h000066400000000000000000000026251217717237500206010ustar00rootroot00000000000000/* * A 'window' is simply a canvas that can receive events. * It can be anything from a simple message box to the * game screen when playing. * * See event.c for event handling code. * * -kreator 2009-05-06 */ #ifndef DESCENT_WINDOW_H #define DESCENT_WINDOW_H #include "event.h" #include "gr.h" #include "console.h" typedef struct window window; extern window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_callback)(window *wind, d_event *event, void *data), void *data); extern int window_close(window *wind); extern int window_exists(window *wind); extern window *window_get_front(void); extern window *window_get_first(void); extern window *window_get_next(window *wind); extern window *window_get_prev(window *wind); extern void window_select(window *wind); extern void window_set_visible(window *wind, int visible); extern int window_is_visible(window *wind); extern grs_canvas *window_get_canvas(window *wind); extern void window_update_canvases(void); extern int window_send_event(window *wind, d_event *event); extern void window_set_modal(window *wind, int modal); extern int window_is_modal(window *wind); #define WINDOW_SEND_EVENT(w, e) \ do { \ con_printf(CON_DEBUG, "Sending event %s to window of dimensions %dx%d\n", #e, window_get_canvas(w)->cv_bitmap.bm_w, window_get_canvas(w)->cv_bitmap.bm_h); \ event.type = e; \ window_send_event(w, &event); \ } while (0) #endif dxx-rebirth-0.58.1-d2x/arch/ogl/000077500000000000000000000000001217717237500162525ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/ogl/gr.c000066400000000000000000000755471217717237500170500ustar00rootroot00000000000000/* * * OGL video functions. - Added 9/15/99 Matthew Mueller * */ #define DECLARE_VARS #ifdef RPI // extra libraries for the Raspberry Pi #include "bcm_host.h" #endif #include #include #include #ifdef _MSC_VER #include #endif #if !defined(_MSC_VER) && !defined(macintosh) #include #endif #if !defined(macintosh) #include #include #include #endif #include #include #include "hudmsg.h" #include "game.h" #include "text.h" #include "gr.h" #include "gamefont.h" #include "grdef.h" #include "palette.h" #include "u_mem.h" #include "dxxerror.h" #include "inferno.h" #include "screens.h" #include "strutil.h" #include "args.h" #include "key.h" #include "physfsx.h" #include "internal.h" #include "render.h" #include "console.h" #include "config.h" #include "playsave.h" #include "vers_id.h" #include "game.h" #if defined(__APPLE__) && defined(__MACH__) #include #else #ifdef OGLES #include #include #include #include #else #include #endif #endif #ifdef OGLES int sdl_video_flags = 0; #ifdef RPI static EGL_DISPMANX_WINDOW_T nativewindow; static DISPMANX_ELEMENT_HANDLE_T dispman_element=DISPMANX_NO_HANDLE; static DISPMANX_DISPLAY_HANDLE_T dispman_display=DISPMANX_NO_HANDLE; #endif #else int sdl_video_flags = SDL_OPENGL; #endif int gr_installed = 0; int gl_initialized=0; int linedotscale=1; // scalar of glLinewidth and glPointSize - only calculated once when resolution changes int sdl_no_modeswitch=0; #ifdef OGLES EGLDisplay eglDisplay=EGL_NO_DISPLAY; EGLConfig eglConfig; EGLSurface eglSurface=EGL_NO_SURFACE; EGLContext eglContext=EGL_NO_CONTEXT; bool TestEGLError(char* pszLocation) { /* * eglGetError returns the last error that has happened using egl, * not the status of the last called function. The user has to * check after every single egl call or at least once every frame. */ EGLint iErr = eglGetError(); if (iErr != EGL_SUCCESS) { con_printf(CON_URGENT, "%s failed (%d).\n", pszLocation, iErr); return 0; } return 1; } #endif void ogl_swap_buffers_internal(void) { #ifdef OGLES eglSwapBuffers(eglDisplay, eglSurface); #else SDL_GL_SwapBuffers(); #endif } #ifdef RPI // MH: I got the following constants for vc_dispmanx_element_change_attributes() from: // http://qt.gitorious.org/qt/qtbase/commit/5933205cfcd73481cb0645fa6183103063fe3e0d // I do not know where they got them from, but OTOH, they are quite obvious. // these constants are not in any headers (yet) #define ELEMENT_CHANGE_LAYER (1<<0) #define ELEMENT_CHANGE_OPACITY (1<<1) #define ELEMENT_CHANGE_DEST_RECT (1<<2) #define ELEMENT_CHANGE_SRC_RECT (1<<3) #define ELEMENT_CHANGE_MASK_RESOURCE (1<<4) #define ELEMENT_CHANGE_TRANSFORM (1<<5) void rpi_destroy_element(void) { if (dispman_element != DISPMANX_NO_HANDLE) { DISPMANX_UPDATE_HANDLE_T dispman_update; con_printf(CON_DEBUG, "RPi: destroying display manager element\n"); dispman_update = vc_dispmanx_update_start( 0 ); if (vc_dispmanx_element_remove( dispman_update, dispman_element)) { con_printf(CON_URGENT, "RPi: failed to remove dispmanx element!\n"); } vc_dispmanx_update_submit_sync( dispman_update ); dispman_element = DISPMANX_NO_HANDLE; } } int rpi_setup_element(int x, int y, Uint32 video_flags, int update) { // this code is based on the work of Ben O'Steen // http://benosteen.wordpress.com/2012/04/27/using-opengl-es-2-0-on-the-raspberry-pi-without-x-windows/ // https://github.com/benosteen/opengles-book-samples/tree/master/Raspi DISPMANX_UPDATE_HANDLE_T dispman_update; VC_RECT_T dst_rect; VC_RECT_T src_rect; VC_DISPMANX_ALPHA_T alpha_descriptor; uint32_t rpi_display_device=DISPMANX_ID_MAIN_LCD; uint32_t display_width; uint32_t display_height; int success; success = graphics_get_display_size(rpi_display_device, &display_width, &display_height); if ( success < 0 ) { con_printf(CON_URGENT, "Could not get RPi display size, assuming 640x480\n"); display_width=640; display_height=480; } if ((uint32_t)x > display_width) { con_printf(CON_URGENT, "RPi: Requested width %d exceeds display width %u, scaling down!\n", x,display_width); x=(int)display_width; } if ((uint32_t)y > display_height) { con_printf(CON_URGENT, "RPi: Requested height %d exceeds display height %u, scaling down!\n", y,display_height); y=(int)display_height; } con_printf(CON_DEBUG, "RPi: display resolution %ux%u, game resolution: %dx%d (%s)\n", display_width, display_height, x, y, (video_flags & SDL_FULLSCREEN)?"fullscreen":"windowed"); if (video_flags & SDL_FULLSCREEN) { /* scale to the full display size... */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = display_width; dst_rect.height= display_height; } else { /* TODO: we could query the position of the X11 window here and try to place the ovelray exactly above that..., we would have to track window movements, though ... */ dst_rect.x = 0; dst_rect.y = 0; dst_rect.width = (uint32_t)x; dst_rect.height= (uint32_t)y; } src_rect.x = 0; src_rect.y = 0; src_rect.width = ((uint32_t)x)<< 16; src_rect.height =((uint32_t)y)<< 16; /* we do not want our overlay to be blended against the background */ alpha_descriptor.flags=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; alpha_descriptor.opacity=0xffffffff; alpha_descriptor.mask=0; // open display, if we do not already have one ... if (dispman_display == DISPMANX_NO_HANDLE) { con_printf(CON_DEBUG, "RPi: opening display: %u\n",rpi_display_device); dispman_display = vc_dispmanx_display_open(rpi_display_device); if (dispman_display == DISPMANX_NO_HANDLE) { con_printf(CON_URGENT,"RPi: failed to open display: %u\n",rpi_display_device); } } if (dispman_element != DISPMANX_NO_HANDLE) { if (!update) { // if the element already exists, and we cannot update it, so recreate it rpi_destroy_element(); } } else { // if the element does not exist, we cannot do an update update=0; } dispman_update = vc_dispmanx_update_start( 0 ); if (update) { con_printf(CON_DEBUG, "RPi: updating display manager element\n"); vc_dispmanx_element_change_attributes ( dispman_update, nativewindow.element, ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT, 0 /*layer*/, 0 /*opacity*/, &dst_rect, &src_rect, 0 /*mask*/, VC_IMAGE_ROT0 /*transform*/); } else { // create a new element con_printf(CON_DEBUG, "RPi: creating display manager element\n"); dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, 0 /*layer*/, &dst_rect, 0 /*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &alpha_descriptor, NULL /*clamp*/, VC_IMAGE_ROT0 /*transform*/); if (dispman_element == DISPMANX_NO_HANDLE) { con_printf(CON_URGENT,"RPi: failed to creat display manager elemenr\n"); } nativewindow.element = dispman_element; } nativewindow.width = display_width; nativewindow.height = display_height; vc_dispmanx_update_submit_sync( dispman_update ); return 0; } #endif // RPI #ifdef OGLES void ogles_destroy(void) { if( eglDisplay != EGL_NO_DISPLAY ) { eglMakeCurrent(eglDisplay, NULL, NULL, EGL_NO_CONTEXT); } if (eglContext != EGL_NO_CONTEXT) { con_printf(CON_DEBUG, "EGL: destroyig context\n"); eglDestroyContext(eglDisplay, eglContext); eglContext = EGL_NO_CONTEXT; } if (eglSurface != EGL_NO_SURFACE) { con_printf(CON_DEBUG, "EGL: destroyig surface\n"); eglDestroySurface(eglDisplay, eglSurface); eglSurface = EGL_NO_SURFACE; } if (eglDisplay != EGL_NO_DISPLAY) { con_printf(CON_DEBUG, "EGL: terminating\n"); eglTerminate(eglDisplay); eglDisplay = EGL_NO_DISPLAY; } } #endif int ogl_init_window(int x, int y) { int use_x,use_y,use_bpp; Uint32 use_flags; #ifdef OGLES SDL_SysWMinfo info; Window x11Window = 0; Display* x11Display = 0; EGLint ver_maj, ver_min; EGLint configAttribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_NONE, EGL_NONE }; // explicitely request an OpenGL ES 1.x context EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE, EGL_NONE }; // explicitely request a doublebuffering window EGLint winAttribs[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE, EGL_NONE }; int iConfigs; #endif // OGLES if (gl_initialized) ogl_smash_texture_list_internal();//if we are or were fullscreen, changing vid mode will invalidate current textures SDL_WM_SetCaption(DESCENT_VERSION, "Descent II"); SDL_WM_SetIcon( SDL_LoadBMP( "d2x-rebirth.bmp" ), NULL ); use_x=x; use_y=y; use_bpp=GameArg.DbgBpp; use_flags=sdl_video_flags; if (sdl_no_modeswitch) { const SDL_VideoInfo *vinfo=SDL_GetVideoInfo(); if (vinfo) { use_x=vinfo->current_w; use_y=vinfo->current_h; use_bpp=vinfo->vfmt->BitsPerPixel; use_flags=SDL_SWSURFACE | SDL_ANYFORMAT; } else { con_printf(CON_URGENT, "Could not query video info\n"); } } if (!SDL_SetVideoMode(use_x, use_y, use_bpp, use_flags)) { #ifdef RPI con_printf(CON_URGENT, "Could not set %dx%dx%d opengl video mode: %s\n (Ignored for RPI)", x, y, GameArg.DbgBpp, SDL_GetError()); #else Error("Could not set %dx%dx%d opengl video mode: %s\n", x, y, GameArg.DbgBpp, SDL_GetError()); #endif } #ifdef OGLES #ifndef RPI // NOTE: on the RPi, the EGL stuff is not connected to the X11 window, // so there is no need to destroy and recreate this ogles_destroy(); #endif SDL_VERSION(&info.version); if (SDL_GetWMInfo(&info) > 0) { if (info.subsystem == SDL_SYSWM_X11) { x11Display = info.info.x11.display; x11Window = info.info.x11.window; con_printf (CON_DEBUG, "Display: %p, Window: %i ===\n", (void*)x11Display, (int)x11Window); } } if (eglDisplay == EGL_NO_DISPLAY) { #ifdef RPI eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); #else eglDisplay = eglGetDisplay((EGLNativeDisplayType)x11Display); #endif if (eglDisplay == EGL_NO_DISPLAY) { con_printf(CON_URGENT, "EGL: Error querying EGL Display\n"); } if (!eglInitialize(eglDisplay, &ver_maj, &ver_min)) { con_printf(CON_URGENT, "EGL: Error initializing EGL\n"); } else { con_printf(CON_DEBUG, "EGL: Initialized, version: major %i minor %i\n", ver_maj, ver_min); } } #ifdef RPI if (rpi_setup_element(x,y,sdl_video_flags,1)) { Error("RPi: Could not set up a %dx%d element\n", x, y); } #endif if (eglSurface == EGL_NO_SURFACE) { if (!eglChooseConfig(eglDisplay, configAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) { con_printf(CON_URGENT, "EGL: Error choosing config\n"); } else { con_printf(CON_DEBUG, "EGL: config chosen\n"); } #ifdef RPI eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)&nativewindow, winAttribs); #else eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)x11Window, winAttribs); #endif if ((!TestEGLError("eglCreateWindowSurface")) || eglSurface == EGL_NO_SURFACE) { con_printf(CON_URGENT, "EGL: Error creating window surface\n"); } else { con_printf(CON_DEBUG, "EGL: Created window surface\n"); } } if (eglContext == EGL_NO_CONTEXT) { eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs); if ((!TestEGLError("eglCreateContext")) || eglContext == EGL_NO_CONTEXT) { con_printf(CON_URGENT, "EGL: Error creating context\n"); } else { con_printf(CON_DEBUG, "EGL: Created context\n"); } } eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); if (!TestEGLError("eglMakeCurrent")) { con_printf(CON_URGENT, "EGL: Error making current\n"); } else { con_printf(CON_DEBUG, "EGL: made context current\n"); } #endif linedotscale = ((x/640sc_w, grd_curscreen->sc_h); } // Set the buffer to draw to. 0 is front, 1 is back void gr_set_draw_buffer(int buf) { #ifndef OGLES glDrawBuffer((buf == 0) ? GL_FRONT : GL_BACK); #endif } const char *gl_vendor, *gl_renderer, *gl_version, *gl_extensions; void ogl_get_verinfo(void) { #ifndef OGLES gl_vendor = (const char *) glGetString (GL_VENDOR); gl_renderer = (const char *) glGetString (GL_RENDERER); gl_version = (const char *) glGetString (GL_VERSION); gl_extensions = (const char *) glGetString (GL_EXTENSIONS); con_printf(CON_VERBOSE, "OpenGL: vendor: %s\nOpenGL: renderer: %s\nOpenGL: version: %s\n",gl_vendor,gl_renderer,gl_version); #ifdef _WIN32 dglMultiTexCoord2fARB = (glMultiTexCoord2fARB_fp)wglGetProcAddress("glMultiTexCoord2fARB"); dglActiveTextureARB = (glActiveTextureARB_fp)wglGetProcAddress("glActiveTextureARB"); dglMultiTexCoord2fSGIS = (glMultiTexCoord2fSGIS_fp)wglGetProcAddress("glMultiTexCoord2fSGIS"); dglSelectTextureSGIS = (glSelectTextureSGIS_fp)wglGetProcAddress("glSelectTextureSGIS"); #endif //add driver specific hacks here. whee. if ((d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.0\n")==0 || d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.2\n")==0) && d_stricmp(gl_version,"1.2 Mesa 3.0")==0) { GameArg.DbgGlIntensity4Ok=0;//ignores alpha, always black background instead of transparent. GameArg.DbgGlReadPixelsOk=0;//either just returns all black, or kills the X server entirely GameArg.DbgGlGetTexLevelParamOk=0;//returns random data.. } if (d_stricmp(gl_vendor,"Matrox Graphics Inc.")==0) { //displays garbage. reported by // redomen@crcwnet.com (render="Matrox G400" version="1.1.3 5.52.015") // orulz (Matrox G200) GameArg.DbgGlIntensity4Ok=0; } #ifdef macintosh if (d_stricmp(gl_renderer,"3dfx Voodoo 3")==0) // strangely, includes Voodoo 2 GameArg.DbgGlGetTexLevelParamOk=0; // Always returns 0 #endif #ifndef NDEBUG con_printf(CON_VERBOSE,"gl_intensity4:%i gl_luminance4_alpha4:%i gl_rgba2:%i gl_readpixels:%i gl_gettexlevelparam:%i\n",GameArg.DbgGlIntensity4Ok,GameArg.DbgGlLuminance4Alpha4Ok,GameArg.DbgGlRGBA2Ok,GameArg.DbgGlReadPixelsOk,GameArg.DbgGlGetTexLevelParamOk); #endif if (!d_stricmp(gl_extensions,"GL_EXT_texture_filter_anisotropic")==0) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ogl_maxanisotropy); con_printf(CON_VERBOSE,"ogl_maxanisotropy:%f\n",ogl_maxanisotropy); } else if (GameCfg.TexFilt >= 3) GameCfg.TexFilt = 2; #endif } // returns possible (fullscreen) resolutions if any. int gr_list_modes( u_int32_t gsmodes[] ) { SDL_Rect** modes; int i = 0, modesnum = 0; #ifdef OGLES int sdl_check_flags = SDL_FULLSCREEN; // always use Fullscreen as lead. #else int sdl_check_flags = SDL_OPENGL | SDL_FULLSCREEN; // always use Fullscreen as lead. #endif if (sdl_no_modeswitch) { /* TODO: we could use the tvservice to list resolutions on the RPi */ return 0; } modes = SDL_ListModes(NULL, sdl_check_flags); if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 return 0; if (modes == (SDL_Rect**)-1) { return 0; // can obviously use any resolution... strange! } else { for (i = 0; modes[i]; ++i) { if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (changed to 0xFFF0 to fix warning) || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 continue; gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); modesnum++; if (modesnum >= 50) // that really seems to be enough big boy. break; } return modesnum; } } int gr_check_mode(u_int32_t mode) { unsigned int w, h; w=SM_W(mode); h=SM_H(mode); if (sdl_no_modeswitch == 0) { return SDL_VideoModeOK(w, h, GameArg.DbgBpp, sdl_video_flags); } else { // just tell the caller that any mode is valid... return 32; } } int gr_set_mode(u_int32_t mode) { unsigned int w, h; char *gr_bm_data; if (mode<=0) return 0; w=SM_W(mode); h=SM_H(mode); if (!gr_check_mode(mode)) { con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480\n",w,h); w=640; h=480; Game_screen_mode=mode=SM(w,h); } gr_bm_data=(char *)grd_curscreen->sc_canvas.cv_bitmap.bm_data;//since we use realloc, we want to keep this pointer around. memset( grd_curscreen, 0, sizeof(grs_screen)); grd_curscreen->sc_mode = mode; grd_curscreen->sc_w = w; grd_curscreen->sc_h = h; grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*GameCfg.AspectX,grd_curscreen->sc_h*GameCfg.AspectY); gr_init_canvas(&grd_curscreen->sc_canvas, d_realloc(gr_bm_data,w*h), BM_OGL, w, h); gr_set_current_canvas(NULL); ogl_init_window(w,h);//platform specific code ogl_get_verinfo(); OGL_VIEWPORT(0,0,w,h); ogl_init_state(); gamefont_choose_game_font(w,h); gr_remap_color_fonts(); gr_remap_mono_fonts(); return 0; } #define GLstrcmptestr(a,b) if (d_stricmp(a,#b)==0 || d_stricmp(a,"GL_" #b)==0)return GL_ ## b; int ogl_atotexfilti(char *a,int min) { GLstrcmptestr(a,NEAREST); GLstrcmptestr(a,LINEAR); if (min) {//mipmaps are valid only for the min filter GLstrcmptestr(a,NEAREST_MIPMAP_NEAREST); GLstrcmptestr(a,NEAREST_MIPMAP_LINEAR); GLstrcmptestr(a,LINEAR_MIPMAP_NEAREST); GLstrcmptestr(a,LINEAR_MIPMAP_LINEAR); } Error("unknown/invalid texture filter %s\n",a); } #ifdef _WIN32 char *OglLibPath="opengl32.dll"; int ogl_rt_loaded=0; int ogl_init_load_library(void) { int retcode=0; if (!ogl_rt_loaded) { retcode = OpenGL_LoadLibrary(true); if(retcode) { if(!glEnd) { Error("Opengl: Functions not imported\n"); } } else { Error("Opengl: error loading %s\n", OglLibPath); } ogl_rt_loaded=1; } return retcode; } #endif void gr_set_attributes(void) { #ifndef OGLES SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,0); SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,0); SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,0); SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,0); SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1); SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL,GameCfg.VSync); if (GameCfg.Multisample) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); } else { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } #endif ogl_smash_texture_list_internal(); gr_remap_color_fonts(); gr_remap_mono_fonts(); } int gr_init(int mode) { #ifdef RPI char sdl_driver[32]; char *sdl_driver_ret; #endif int retcode; // Only do this function once! if (gr_installed==1) return -1; #ifdef RPI // Initialize the broadcom host library // we have to call this before we can create an OpenGL ES context bcm_host_init(); // Check if we are running with SDL directfb driver ... sdl_driver_ret=SDL_VideoDriverName(sdl_driver,32); if (sdl_driver_ret) { if (strcmp(sdl_driver_ret,"x11")) { con_printf(CON_URGENT,"RPi: activating hack for console driver\n"); sdl_no_modeswitch=1; } } #endif #ifdef _WIN32 ogl_init_load_library(); #endif if (!GameCfg.WindowMode && !GameArg.SysWindow) sdl_video_flags|=SDL_FULLSCREEN; if (GameArg.SysNoBorders) sdl_video_flags|=SDL_NOFRAME; gr_set_attributes(); ogl_init_texture_list_internal(); CALLOC( grd_curscreen,grs_screen,1 ); grd_curscreen->sc_canvas.cv_bitmap.bm_data = NULL; // Set the mode. if ((retcode=gr_set_mode(mode))) return retcode; grd_curscreen->sc_canvas.cv_color = 0; grd_curscreen->sc_canvas.cv_fade_level = GR_FADE_OFF; grd_curscreen->sc_canvas.cv_blend_func = GR_BLEND_NORMAL; grd_curscreen->sc_canvas.cv_drawmode = 0; grd_curscreen->sc_canvas.cv_font = NULL; grd_curscreen->sc_canvas.cv_font_fg_color = 0; grd_curscreen->sc_canvas.cv_font_bg_color = 0; gr_set_current_canvas( &grd_curscreen->sc_canvas ); ogl_init_pixel_buffers(256, 128); // for gamefont_init gr_installed = 1; return 0; } void gr_close() { ogl_brightness_r = ogl_brightness_g = ogl_brightness_b = 0; if (gl_initialized) { ogl_smash_texture_list_internal(); } if (grd_curscreen) { if (grd_curscreen->sc_canvas.cv_bitmap.bm_data) d_free(grd_curscreen->sc_canvas.cv_bitmap.bm_data); d_free(grd_curscreen); } ogl_close_pixel_buffers(); #ifdef _WIN32 if (ogl_rt_loaded) OpenGL_LoadLibrary(false); #endif #ifdef OGLES ogles_destroy(); #ifdef RPI con_printf(CON_DEBUG, "RPi: cleanuing up\n"); if (dispman_display != DISPMANX_NO_HANDLE) { rpi_destroy_element(); con_printf(CON_DEBUG, "RPi: closing display\n"); vc_dispmanx_display_close(dispman_display); dispman_display = DISPMANX_NO_HANDLE; } #endif #endif } extern int r_upixelc; void ogl_upixelc(int x, int y, int c) { GLfloat vertex_array[] = { (x+grd_curcanv->cv_bitmap.bm_x)/(float)last_width, 1.0-(y+grd_curcanv->cv_bitmap.bm_y)/(float)last_height }; GLfloat color_array[] = { CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), 1.0, CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), 1.0, CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), 1.0, CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), 1.0 }; r_upixelc++; OGL_DISABLE(TEXTURE_2D); glPointSize(linedotscale); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_POINTS, 0, 1); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } unsigned char ogl_ugpixel( grs_bitmap * bitmap, int x, int y ) { GLint gl_draw_buffer; ubyte buf[4]; #ifndef OGLES glGetIntegerv(GL_DRAW_BUFFER, &gl_draw_buffer); glReadBuffer(gl_draw_buffer); #endif glReadPixels(bitmap->bm_x + x, SHEIGHT - bitmap->bm_y - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf); return gr_find_closest_color(buf[0]/4, buf[1]/4, buf[2]/4); } void ogl_urect(int left,int top,int right,int bot) { GLfloat xo, yo, xf, yf, color_r, color_g, color_b, color_a; GLfloat color_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GLfloat vertex_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; int c=COLOR; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); xo=(left+grd_curcanv->cv_bitmap.bm_x)/(float)last_width; xf = (right + 1 + grd_curcanv->cv_bitmap.bm_x) / (float)last_width; yo=1.0-(top+grd_curcanv->cv_bitmap.bm_y)/(float)last_height; yf = 1.0 - (bot + 1 + grd_curcanv->cv_bitmap.bm_y) / (float)last_height; OGL_DISABLE(TEXTURE_2D); color_r = CPAL2Tr(c); color_g = CPAL2Tg(c); color_b = CPAL2Tb(c); if (grd_curcanv->cv_fade_level >= GR_FADE_OFF) color_a = 1.0; else color_a = 1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0); color_array[0] = color_array[4] = color_array[8] = color_array[12] = color_r; color_array[1] = color_array[5] = color_array[9] = color_array[13] = color_g; color_array[2] = color_array[6] = color_array[10] = color_array[14] = color_b; color_array[3] = color_array[7] = color_array[11] = color_array[15] = color_a; vertex_array[0] = xo; vertex_array[1] = yo; vertex_array[2] = xo; vertex_array[3] = yf; vertex_array[4] = xf; vertex_array[5] = yf; vertex_array[6] = xf; vertex_array[7] = yo; glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS glDisableClientState(GL_VERTEX_ARRAY); } void ogl_ulinec(int left,int top,int right,int bot,int c) { GLfloat xo,yo,xf,yf; GLfloat color_array[] = { CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0), CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0), CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), 1.0, CPAL2Tr(c), CPAL2Tg(c), CPAL2Tb(c), (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0) }; GLfloat vertex_array[] = { 0.0, 0.0, 0.0, 0.0 }; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); xo = (left + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width; xf = (right + grd_curcanv->cv_bitmap.bm_x + 1.0) / (float)last_width; yo = 1.0 - (top + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height; yf = 1.0 - (bot + grd_curcanv->cv_bitmap.bm_y + 1.0) / (float)last_height; OGL_DISABLE(TEXTURE_2D); vertex_array[0] = xo; vertex_array[1] = yo; vertex_array[2] = xf; vertex_array[3] = yf; glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_LINES, 0, 2); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } GLfloat last_r=0, last_g=0, last_b=0; int do_pal_step=0; void ogl_do_palfx(void) { GLfloat color_array[] = { last_r, last_g, last_b, 1.0, last_r, last_g, last_b, 1.0, last_r, last_g, last_b, 1.0, last_r, last_g, last_b, 1.0 }; GLfloat vertex_array[] = { 0,0,0,1,1,1,1,0 }; OGL_DISABLE(TEXTURE_2D); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); if (do_pal_step) { glEnable(GL_BLEND); glBlendFunc(GL_ONE,GL_ONE); } else return; glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } int ogl_brightness_ok = 0; int ogl_brightness_r = 0, ogl_brightness_g = 0, ogl_brightness_b = 0; static int old_b_r = 0, old_b_g = 0, old_b_b = 0; void gr_palette_step_up(int r, int g, int b) { old_b_r = ogl_brightness_r; old_b_g = ogl_brightness_g; old_b_b = ogl_brightness_b; ogl_brightness_r = max(r + gr_palette_gamma, 0); ogl_brightness_g = max(g + gr_palette_gamma, 0); ogl_brightness_b = max(b + gr_palette_gamma, 0); if (!ogl_brightness_ok) { last_r = ogl_brightness_r / 63.0; last_g = ogl_brightness_g / 63.0; last_b = ogl_brightness_b / 63.0; do_pal_step = (r || g || b || gr_palette_gamma); } else { do_pal_step = 0; } } #undef min static inline int min(int x, int y) { return x < y ? x : y; } void gr_palette_load( ubyte *pal ) { int i; for (i=0; i<768; i++ ) { gr_current_pal[i] = pal[i]; if (gr_current_pal[i] > 63) gr_current_pal[i] = 63; } gr_palette_step_up(0, 0, 0); // make ogl_setbrightness_internal get run so that menus get brightened too. init_computed_colors(); } void gr_palette_read(ubyte * pal) { int i; for (i=0; i<768; i++ ) { pal[i]=gr_current_pal[i]; if (pal[i] > 63) pal[i] = 63; } } #define GL_BGR_EXT 0x80E0 typedef struct { unsigned char TGAheader[12]; unsigned char header[6]; } TGA_header; //writes out an uncompressed RGB .tga file //if we got really spiffy, we could optionally link in libpng or something, and use that. void write_bmp(char *savename,int w,int h,unsigned char *buf) { PHYSFS_file* TGAFile; TGA_header TGA; GLbyte HeightH,HeightL,WidthH,WidthL; unsigned int pixel; unsigned char *rgbaBuf; buf = (unsigned char*)d_calloc(w*h*4,sizeof(unsigned char)); rgbaBuf = (unsigned char*) d_calloc(w * h * 4, sizeof(unsigned char)); glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf); for(pixel = 0; pixel < w * h; pixel++) { *(buf + pixel * 3) = *(rgbaBuf + pixel * 4 + 2); *(buf + pixel * 3 + 1) = *(rgbaBuf + pixel * 4 + 1); *(buf + pixel * 3 + 2) = *(rgbaBuf + pixel * 4); } d_free(rgbaBuf); if (!(TGAFile = PHYSFSX_openWriteBuffered(savename))) { con_printf(CON_URGENT,"Could not create TGA file to dump screenshot!"); d_free(buf); return; } HeightH = (GLbyte)(h / 256); HeightL = (GLbyte)(h % 256); WidthH = (GLbyte)(w / 256); WidthL = (GLbyte)(w % 256); // Write TGA Header TGA.TGAheader[0] = 0; TGA.TGAheader[1] = 0; TGA.TGAheader[2] = 2; TGA.TGAheader[3] = 0; TGA.TGAheader[4] = 0; TGA.TGAheader[5] = 0; TGA.TGAheader[6] = 0; TGA.TGAheader[7] = 0; TGA.TGAheader[8] = 0; TGA.TGAheader[9] = 0; TGA.TGAheader[10] = 0; TGA.TGAheader[11] = 0; TGA.header[0] = (GLbyte) WidthL; TGA.header[1] = (GLbyte) WidthH; TGA.header[2] = (GLbyte) HeightL; TGA.header[3] = (GLbyte) HeightH; TGA.header[4] = (GLbyte) 24; TGA.header[5] = 0; PHYSFS_write(TGAFile,&TGA,sizeof(TGA_header),1); PHYSFS_write(TGAFile,buf,w*h*3*sizeof(unsigned char),1); PHYSFS_close(TGAFile); d_free(buf); } void save_screen_shot(int automap_flag) { static int savenum=0; char savename[13+sizeof(SCRNS_DIR)]; unsigned char *buf; if (!GameArg.DbgGlReadPixelsOk){ if (!automap_flag) HUD_init_message_literal(HM_DEFAULT, "glReadPixels not supported on your configuration"); return; } stop_time(); if (!PHYSFSX_exists(SCRNS_DIR,0)) PHYSFS_mkdir(SCRNS_DIR); //try making directory do { sprintf(savename, "%sscrn%04d.tga",SCRNS_DIR, savenum++); } while (PHYSFSX_exists(savename,0)); if (!automap_flag) HUD_init_message(HM_DEFAULT, "%s 'scrn%04d.tga'", TXT_DUMPING_SCREEN, savenum-1 ); #ifndef OGLES glReadBuffer(GL_FRONT); #endif buf = d_malloc(grd_curscreen->sc_w*grd_curscreen->sc_h*3); write_bmp(savename,grd_curscreen->sc_w,grd_curscreen->sc_h,buf); d_free(buf); start_time(); } dxx-rebirth-0.58.1-d2x/arch/ogl/ogl.c000066400000000000000000001470121217717237500172040ustar00rootroot00000000000000/* * * Graphics support functions for OpenGL. * */ //#include #ifdef _WIN32 #include #include #endif #if defined(__APPLE__) && defined(__MACH__) #include #include #else #ifdef OGLES #include #else #include #include #endif #endif #include #include #include #include "3d.h" #include "piggy.h" #include "../../3d/globvars.h" #include "dxxerror.h" #include "texmap.h" #include "palette.h" #include "rle.h" #include "console.h" #include "u_mem.h" #ifdef HAVE_LIBPNG #include "pngfile.h" #endif #include "segment.h" #include "textures.h" #include "texmerge.h" #include "effects.h" #include "weapon.h" #include "powerup.h" #include "laser.h" #include "player.h" #include "polyobj.h" #include "gamefont.h" #include "byteswap.h" #include "internal.h" #include "gauges.h" #include "playsave.h" #include "args.h" //change to 1 for lots of spew. #if 0 #define glmprintf(0,a) con_printf(CON_DEBUG, a) #else #define glmprintf(a) #endif #ifndef M_PI #define M_PI 3.14159 #endif #if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__)) || defined(__sun__) || defined(macintosh) #define cosf(a) cos(a) #define sinf(a) sin(a) #endif unsigned char *ogl_pal=gr_palette; int last_width=-1,last_height=-1; int GL_TEXTURE_2D_enabled=-1; int GL_texclamp_enabled=-1; GLfloat ogl_maxanisotropy = 0; int r_texcount = 0, r_cachedtexcount = 0; #ifdef OGLES int ogl_rgba_internalformat = GL_RGBA; int ogl_rgb_internalformat = GL_RGB; #else int ogl_rgba_internalformat = GL_RGBA8; int ogl_rgb_internalformat = GL_RGB8; #endif GLfloat *sphere_va = NULL, *circle_va = NULL, *disk_va = NULL; GLfloat *secondary_lva[3]={NULL, NULL, NULL}; int r_polyc,r_tpolyc,r_bitmapc,r_ubitbltc,r_upixelc; extern int linedotscale; #define f2glf(x) (f2fl(x)) #define OGL_BINDTEXTURE(a) glBindTexture(GL_TEXTURE_2D, a); ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE]; int ogl_texture_list_cur; /* some function prototypes */ #define GL_TEXTURE0_ARB 0x84C0 extern GLubyte *pixels; extern GLubyte *texbuf; void ogl_filltexbuf(unsigned char *data, GLubyte *texp, int truewidth, int width, int height, int dxo, int dyo, int twidth, int theight, int type, int bm_flags, int data_format); void ogl_loadbmtexture(grs_bitmap *bm); int ogl_loadtexture(unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format, int texfilt); void ogl_freetexture(ogl_texture *gltexture); #ifdef OGLES // Replacement for gluPerspective void perspective(double fovy, double aspect, double zNear, double zFar) { double xmin, xmax, ymin, ymax; glMatrixMode(GL_PROJECTION); glLoadIdentity(); ymax = zNear * tan(fovy * M_PI / 360.0); ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar); glMatrixMode(GL_MODELVIEW); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glDepthMask(GL_TRUE); } #endif void ogl_init_texture_stats(ogl_texture* t){ t->prio=0.3;//default prio t->numrend=0; } void ogl_init_texture(ogl_texture* t, int w, int h, int flags) { t->handle = 0; #ifndef OGLES if (flags & OGL_FLAG_NOCOLOR) { // use GL_INTENSITY instead of GL_RGB if (flags & OGL_FLAG_ALPHA) { if (GameArg.DbgGlIntensity4Ok) { t->internalformat = GL_INTENSITY4; t->format = GL_LUMINANCE; } else if (GameArg.DbgGlLuminance4Alpha4Ok) { t->internalformat = GL_LUMINANCE4_ALPHA4; t->format = GL_LUMINANCE_ALPHA; } else if (GameArg.DbgGlRGBA2Ok) { t->internalformat = GL_RGBA2; t->format = GL_RGBA; } else { t->internalformat = ogl_rgba_internalformat; t->format = GL_RGBA; } } else { // there are certainly smaller formats we could use here, but nothing needs it ATM. t->internalformat = ogl_rgb_internalformat; t->format = GL_RGB; } } else { #endif if (flags & OGL_FLAG_ALPHA) { t->internalformat = ogl_rgba_internalformat; t->format = GL_RGBA; } else { t->internalformat = ogl_rgb_internalformat; t->format = GL_RGB; } #ifndef OGLES } #endif t->wrapstate = -1; t->lw = t->w = w; t->h = h; ogl_init_texture_stats(t); } void ogl_reset_texture(ogl_texture* t) { ogl_init_texture(t, 0, 0, 0); } void ogl_reset_texture_stats_internal(void){ int i; for (i=0;i0){ ogl_init_texture_stats(&ogl_texture_list[i]); } } void ogl_init_texture_list_internal(void){ int i; ogl_texture_list_cur=0; for (i=0;i0){ glDeleteTextures( 1, &ogl_texture_list[i].handle ); ogl_texture_list[i].handle=0; } ogl_texture_list[i].wrapstate = -1; } } ogl_texture* ogl_get_free_texture(void){ int i; for (i=0;i=OGL_TEXTURE_LIST_SIZE) ogl_texture_list_cur=0; } Error("OGL: texture list full!\n"); } void ogl_texture_stats(void) { int used = 0, usedother = 0, usedidx = 0, usedrgb = 0, usedrgba = 0; int databytes = 0, truebytes = 0, datatexel = 0, truetexel = 0, i; int prio0=0,prio1=0,prio2=0,prio3=0,prioh=0; GLint idx, r, g, b, a, dbl, depth; int res, colorsize, depthsize; ogl_texture* t; for (i=0;ihandle>0){ used++; datatexel+=t->w*t->h; truetexel+=t->tw*t->th; databytes+=t->bytesu; truebytes+=t->bytes; if (t->prio<0.299)prio0++; else if (t->prio<0.399)prio1++; else if (t->prio<0.499)prio2++; else if (t->prio<0.599)prio3++; else prioh++; if (t->format == GL_RGBA) usedrgba++; else if (t->format == GL_RGB) usedrgb++; #ifndef OGLES else if (t->format == GL_COLOR_INDEX) usedidx++; #endif else usedother++; } } res = SWIDTH * SHEIGHT; #ifndef OGLES glGetIntegerv(GL_INDEX_BITS, &idx); #endif glGetIntegerv(GL_RED_BITS, &r); glGetIntegerv(GL_GREEN_BITS, &g); glGetIntegerv(GL_BLUE_BITS, &b); glGetIntegerv(GL_ALPHA_BITS, &a); #ifndef OGLES glGetIntegerv(GL_DOUBLEBUFFER, &dbl); #endif dbl += 1; glGetIntegerv(GL_DEPTH_BITS, &depth); gr_set_current_canvas(NULL); gr_set_curfont( GAME_FONT ); gr_set_fontcolor( BM_XRGB(255,255,255),-1 ); colorsize = (idx * res * dbl) / 8; depthsize = res * depth / 8; gr_printf(FSPACX(2),FSPACY(1),"%i flat %i tex %i sprites %i bitmaps",r_polyc,r_tpolyc,r_bitmapc); gr_printf(FSPACX(2), FSPACY(1)+LINE_SPACING, "%i(%i,%i,%i,%i) %iK(%iK wasted) (%i postcachedtex)", used, usedrgba, usedrgb, usedidx, usedother, truebytes / 1024, (truebytes - databytes) / 1024, r_texcount - r_cachedtexcount); gr_printf(FSPACX(2), FSPACY(1)+(LINE_SPACING*2), "%ibpp(r%i,g%i,b%i,a%i)x%i=%iK depth%i=%iK", idx, r, g, b, a, dbl, colorsize / 1024, depth, depthsize / 1024); gr_printf(FSPACX(2), FSPACY(1)+(LINE_SPACING*3), "total=%iK", (colorsize + depthsize + truebytes) / 1024); } void ogl_bindbmtex(grs_bitmap *bm){ if (bm->gltexture==NULL || bm->gltexture->handle<=0) ogl_loadbmtexture(bm); OGL_BINDTEXTURE(bm->gltexture->handle); bm->gltexture->numrend++; } //gltexture MUST be bound first void ogl_texwrap(ogl_texture *gltexture,int state) { if (gltexture->wrapstate != state || gltexture->numrend < 1) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, state); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, state); gltexture->wrapstate = state; } } //crude texture precaching //handles: powerups, walls, weapons, polymodels, etc. //it is done with the horrid do_special_effects kludge so that sides that have to be texmerged and have animated textures will be correctly cached. //similarly, with the objects(esp weapons), we could just go through and cache em all instead, but that would get ones that might not even be on the level //TODO: doors void ogl_cache_polymodel_textures(int model_num) { polymodel *po; int i; if (model_num < 0) return; po = &Polygon_models[model_num]; for (i=0;in_textures;i++) { ogl_loadbmtexture(&GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]); } } void ogl_cache_vclip_textures(vclip *vc){ int i; for (i=0;inum_frames;i++){ PIGGY_PAGE_IN(vc->frames[i]); ogl_loadbmtexture(&GameBitmaps[vc->frames[i].index]); } } void ogl_cache_vclipn_textures(int i) { if (i >= 0 && i < VCLIP_MAXNUM) ogl_cache_vclip_textures(&Vclip[i]); } void ogl_cache_weapon_textures(int weapon_type) { weapon_info *w; if (weapon_type < 0) return; w = &Weapon_info[weapon_type]; ogl_cache_vclipn_textures(w->flash_vclip); ogl_cache_vclipn_textures(w->robot_hit_vclip); ogl_cache_vclipn_textures(w->wall_hit_vclip); if (w->render_type==WEAPON_RENDER_VCLIP) ogl_cache_vclipn_textures(w->weapon_vclip); else if (w->render_type == WEAPON_RENDER_POLYMODEL) { ogl_cache_polymodel_textures(w->model_num); ogl_cache_polymodel_textures(w->model_num_inner); } } void ogl_cache_level_textures(void) { int seg,side,i; eclip *ec; short tmap1,tmap2; grs_bitmap *bm,*bm2; struct side *sidep; int max_efx=0,ef; ogl_reset_texture_stats_internal();//loading a new lev should reset textures for (i=0,ec=Effects;ivc.num_frames>max_efx) max_efx=ec->vc.num_frames; } glmprintf((0,"max_efx:%i\n",max_efx)); for (ef=0;eftime_left=-1; } do_special_effects(); for (seg=0;segtmap_num; tmap2=sidep->tmap_num2; if (tmap1<0 || tmap1>=NumTextures){ glmprintf((0,"ogl_cache_level_textures %i %i %i %i\n",seg,side,tmap1,NumTextures)); // tmap1=0; continue; } PIGGY_PAGE_IN(Textures[tmap1]); bm = &GameBitmaps[Textures[tmap1].index]; if (tmap2 != 0){ PIGGY_PAGE_IN(Textures[tmap2&0x3FFF]); bm2 = &GameBitmaps[Textures[tmap2&0x3FFF].index]; if (GameArg.DbgAltTexMerge == 0 || (bm2->bm_flags & BM_FLAG_SUPER_TRANSPARENT)) bm = texmerge_get_cached_bitmap( tmap1, tmap2 ); else { ogl_loadbmtexture(bm2); } } ogl_loadbmtexture(bm); } } glmprintf((0,"finished ef:%i\n",ef)); } reset_special_effects(); init_special_effects(); { // always have lasers, concs, flares. Always shows player appearance, and at least concs are always available to disappear. ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[LASER_INDEX]); ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[CONCUSSION_INDEX]); ogl_cache_weapon_textures(FLARE_ID); ogl_cache_vclipn_textures(VCLIP_PLAYER_APPEARANCE); ogl_cache_vclipn_textures(VCLIP_POWERUP_DISAPPEARANCE); ogl_cache_polymodel_textures(Player_ship->model_num); ogl_cache_vclipn_textures(Player_ship->expl_vclip_num); for (i=0;i<=Highest_object_index;i++){ if(Objects[i].render_type==RT_POWERUP){ ogl_cache_vclipn_textures(Objects[i].rtype.vclip_info.vclip_num); switch (Objects[i].id){ case POW_VULCAN_WEAPON: ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[VULCAN_INDEX]); break; case POW_SPREADFIRE_WEAPON: ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[SPREADFIRE_INDEX]); break; case POW_PLASMA_WEAPON: ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[PLASMA_INDEX]); break; case POW_FUSION_WEAPON: ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[FUSION_INDEX]); break; case POW_PROXIMITY_WEAPON: ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[PROXIMITY_INDEX]); break; case POW_HOMING_AMMO_1: case POW_HOMING_AMMO_4: ogl_cache_weapon_textures(Primary_weapon_to_weapon_info[HOMING_INDEX]); break; case POW_SMARTBOMB_WEAPON: ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[SMART_INDEX]); break; case POW_MEGA_WEAPON: ogl_cache_weapon_textures(Secondary_weapon_to_weapon_info[MEGA_INDEX]); break; } } else if(Objects[i].render_type==RT_POLYOBJ){ if (Objects[i].type == OBJ_ROBOT) { ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp1_vclip_num); ogl_cache_vclipn_textures(Robot_info[Objects[i].id].exp2_vclip_num); ogl_cache_weapon_textures(Robot_info[Objects[i].id].weapon_type); } if (Objects[i].rtype.pobj_info.tmap_override != -1) ogl_loadbmtexture(&GameBitmaps[Textures[Objects[i].rtype.pobj_info.tmap_override].index]); else ogl_cache_polymodel_textures(Objects[i].rtype.pobj_info.model_num); } } } glmprintf((0,"finished caching\n")); r_cachedtexcount = r_texcount; } bool g3_draw_line(const g3s_point *p0,const g3s_point *p1) { int c; GLfloat color_r, color_g, color_b; GLfloat color_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GLfloat vertex_array[] = { f2glf(p0->p3_vec.x),f2glf(p0->p3_vec.y),-f2glf(p0->p3_vec.z), f2glf(p1->p3_vec.x),f2glf(p1->p3_vec.y),-f2glf(p1->p3_vec.z) }; c=grd_curcanv->cv_color; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); OGL_DISABLE(TEXTURE_2D); color_r = PAL2Tr(c); color_g = PAL2Tg(c); color_b = PAL2Tb(c); color_array[0] = color_array[4] = color_r; color_array[1] = color_array[5] = color_g; color_array[2] = color_array[6] = color_b; color_array[3] = color_array[7] = 1.0; glVertexPointer(3, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_LINES, 0, 2); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); return 1; } void ogl_drawcircle(int nsides, int type, GLfloat *vertex_array) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex_array); glDrawArrays(type, 0, nsides); glDisableClientState(GL_VERTEX_ARRAY); } GLfloat *circle_array_init(int nsides) { int i; float ang; GLfloat *vertex_array = (GLfloat *) d_malloc(sizeof(GLfloat) * nsides * 2); for(i = 0; i < nsides; i++) { ang = 2.0 * M_PI * i / nsides; vertex_array[i * 2] = cosf(ang); vertex_array[i * 2 + 1] = sinf(ang); } return vertex_array; } GLfloat *circle_array_init_2(int nsides, float xsc, float xo, float ysc, float yo) { int i; float ang; GLfloat *vertex_array = (GLfloat *) d_malloc(sizeof(GLfloat) * nsides * 2); for(i = 0; i < nsides; i++) { ang = 2.0 * M_PI * i / nsides; vertex_array[i * 2] = cosf(ang) * xsc + xo; vertex_array[i * 2 + 1] = sinf(ang) * ysc + yo; } return vertex_array; } void ogl_draw_vertex_reticle(int cross,int primary,int secondary,int color,int alpha,int size_offs) { int size=270+(size_offs*20), i; float scale = ((float)SWIDTH/SHEIGHT), ret_rgba[4], ret_dark_rgba[4]; GLfloat cross_lva[8 * 2] = { -4.0, 2.0, -2.0, 0, -3.0, -4.0, -2.0, -3.0, 4.0, 2.0, 2.0, 0, 3.0, -4.0, 2.0, -3.0, }; GLfloat primary_lva[4][4 * 2] = { { -5.5, -5.0, -6.5, -7.5, -10.0, -7.0, -10.0, -8.7 }, { -10.0, -7.0, -10.0, -8.7, -15.0, -8.5, -15.0, -9.5 }, { 5.5, -5.0, 6.5, -7.5, 10.0, -7.0, 10.0, -8.7 }, { 10.0, -7.0, 10.0, -8.7, 15.0, -8.5, 15.0, -9.5 } }; GLfloat dark_lca[16 * 4] = { 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6 }; GLfloat bright_lca[16 * 4] = { 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0 }; GLfloat cross_lca[8 * 4] = { 0.125, 0.54, 0.125, 0.6, 0.125, 1.0, 0.125, 1.0, 0.125, 0.54, 0.125, 0.6, 0.125, 1.0, 0.125, 1.0, 0.125, 0.54, 0.125, 0.6, 0.125, 1.0, 0.125, 1.0, 0.125, 0.54, 0.125, 0.6, 0.125, 1.0, 0.125, 1.0 }; GLfloat primary_lca[2][4 * 4] = { {0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6}, {0.125, 0.54, 0.125, 0.6, 0.125, 0.54, 0.125, 0.6, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0, 0.125, 1.0} }; ret_rgba[0] = PAL2Tr(color); ret_dark_rgba[0] = ret_rgba[0]/2; ret_rgba[1] = PAL2Tg(color); ret_dark_rgba[1] = ret_rgba[1]/2; ret_rgba[2] = PAL2Tb(color); ret_dark_rgba[2] = ret_rgba[2]/2; ret_rgba[3] = 1.0 - ((float)alpha / ((float)GR_FADE_LEVELS)); ret_dark_rgba[3] = ret_rgba[3]/2; for (i = 0; i < 16*4; i += 4) { bright_lca[i] = ret_rgba[0]; dark_lca[i] = ret_dark_rgba[0]; bright_lca[i+1] = ret_rgba[1]; dark_lca[i+1] = ret_dark_rgba[1]; bright_lca[i+2] = ret_rgba[2]; dark_lca[i+2] = ret_dark_rgba[2]; bright_lca[i+3] = ret_rgba[3]; dark_lca[i+3] = ret_dark_rgba[3]; } for (i = 0; i < 8*4; i += 8) { cross_lca[i] = ret_dark_rgba[0]; cross_lca[i+1] = ret_dark_rgba[1]; cross_lca[i+2] = ret_dark_rgba[2]; cross_lca[i+3] = ret_dark_rgba[3]; cross_lca[i+4] = ret_rgba[0]; cross_lca[i+5] = ret_rgba[1]; cross_lca[i+6] = ret_rgba[2]; cross_lca[i+7] = ret_rgba[3]; } primary_lca[0][0] = primary_lca[0][4] = primary_lca[1][8] = primary_lca[1][12] = ret_rgba[0]; primary_lca[0][1] = primary_lca[0][5] = primary_lca[1][9] = primary_lca[1][13] = ret_rgba[1]; primary_lca[0][2] = primary_lca[0][6] = primary_lca[1][10] = primary_lca[1][14] = ret_rgba[2]; primary_lca[0][3] = primary_lca[0][7] = primary_lca[1][11] = primary_lca[1][15] = ret_rgba[3]; primary_lca[1][0] = primary_lca[1][4] = primary_lca[0][8] = primary_lca[0][12] = ret_dark_rgba[0]; primary_lca[1][1] = primary_lca[1][5] = primary_lca[0][9] = primary_lca[0][13] = ret_dark_rgba[1]; primary_lca[1][2] = primary_lca[1][6] = primary_lca[0][10] = primary_lca[0][14] = ret_dark_rgba[2]; primary_lca[1][3] = primary_lca[1][7] = primary_lca[0][11] = primary_lca[0][15] = ret_dark_rgba[3]; glPushMatrix(); glTranslatef((grd_curcanv->cv_bitmap.bm_w/2+grd_curcanv->cv_bitmap.bm_x)/(float)last_width,1.0-(grd_curcanv->cv_bitmap.bm_h/2+grd_curcanv->cv_bitmap.bm_y)/(float)last_height,0); if (scale >= 1) { size/=scale; glScalef(f2glf(size),f2glf(size*scale),f2glf(size)); } else { size*=scale; glScalef(f2glf(size/scale),f2glf(size),f2glf(size)); } glLineWidth(linedotscale*2); OGL_DISABLE(TEXTURE_2D); glDisable(GL_CULL_FACE); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); //cross if(cross) glColorPointer(4, GL_FLOAT, 0, cross_lca); else glColorPointer(4, GL_FLOAT, 0, dark_lca); glVertexPointer(2, GL_FLOAT, 0, cross_lva); glDrawArrays(GL_LINES, 0, 8); //left primary bar if(primary == 0) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, primary_lca[0]); glVertexPointer(2, GL_FLOAT, 0, primary_lva[0]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if(primary != 2) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, primary_lca[1]); glVertexPointer(2, GL_FLOAT, 0, primary_lva[1]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //right primary bar if(primary == 0) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, primary_lca[0]); glVertexPointer(2, GL_FLOAT, 0, primary_lva[2]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if(primary != 2) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, primary_lca[1]); glVertexPointer(2, GL_FLOAT, 0, primary_lva[3]); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (secondary<=2){ //left secondary if (secondary != 1) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, bright_lca); if(!secondary_lva[0]) secondary_lva[0] = circle_array_init_2(16, 2.0, -10.0, 2.0, -2.0); ogl_drawcircle(16, GL_LINE_LOOP, secondary_lva[0]); //right secondary if (secondary != 2) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, bright_lca); if(!secondary_lva[1]) secondary_lva[1] = circle_array_init_2(16, 2.0, 10.0, 2.0, -2.0); ogl_drawcircle(16, GL_LINE_LOOP, secondary_lva[1]); } else { //bottom/middle secondary if (secondary != 4) glColorPointer(4, GL_FLOAT, 0, dark_lca); else glColorPointer(4, GL_FLOAT, 0, bright_lca); if(!secondary_lva[2]) secondary_lva[2] = circle_array_init_2(16, 2.0, 0.0, 2.0, -8.0); ogl_drawcircle(16, GL_LINE_LOOP, secondary_lva[2]); } //glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glPopMatrix(); glLineWidth(linedotscale); } /* * Stars on heaven in exit sequence, automap objects */ int g3_draw_sphere(g3s_point *pnt,fix rad){ int c=grd_curcanv->cv_color, i; float scale = ((float)grd_curcanv->cv_bitmap.bm_w/grd_curcanv->cv_bitmap.bm_h); GLfloat color_array[20*4]; for (i = 0; i < 20*4; i += 4) { color_array[i] = CPAL2Tr(c); color_array[i+1] = CPAL2Tg(c); color_array[i+2] = CPAL2Tb(c); color_array[i+3] = 1.0; } OGL_DISABLE(TEXTURE_2D); glDisable(GL_CULL_FACE); glPushMatrix(); glTranslatef(f2glf(pnt->p3_vec.x),f2glf(pnt->p3_vec.y),-f2glf(pnt->p3_vec.z)); if (scale >= 1) { rad/=scale; glScalef(f2glf(rad),f2glf(rad*scale),f2glf(rad)); } else { rad*=scale; glScalef(f2glf(rad/scale),f2glf(rad),f2glf(rad)); } if(!sphere_va) sphere_va = circle_array_init(20); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_FLOAT, 0, color_array); ogl_drawcircle(20, GL_TRIANGLE_FAN, sphere_va); glDisableClientState(GL_COLOR_ARRAY); glPopMatrix(); return 0; } int gr_ucircle(fix xc1, fix yc1, fix r1) { int c, nsides; c=grd_curcanv->cv_color; OGL_DISABLE(TEXTURE_2D); glColor4f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c),(grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0)); glPushMatrix(); glTranslatef( (f2fl(xc1) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width, 1.0 - (f2fl(yc1) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0); glScalef(f2fl(r1) / last_width, f2fl(r1) / last_height, 1.0); nsides = 10 + 2 * (int)(M_PI * f2fl(r1) / 19); if(!circle_va) circle_va = circle_array_init(nsides); ogl_drawcircle(nsides, GL_LINE_LOOP, circle_va); glPopMatrix(); return 0; } int gr_circle(fix xc1,fix yc1,fix r1){ return gr_ucircle(xc1,yc1,r1); } int gr_disk(fix x,fix y,fix r) { int c, nsides; c=grd_curcanv->cv_color; OGL_DISABLE(TEXTURE_2D); glColor4f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c),(grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0)); glPushMatrix(); glTranslatef( (f2fl(x) + grd_curcanv->cv_bitmap.bm_x + 0.5) / (float)last_width, 1.0 - (f2fl(y) + grd_curcanv->cv_bitmap.bm_y + 0.5) / (float)last_height,0); glScalef(f2fl(r) / last_width, f2fl(r) / last_height, 1.0); nsides = 10 + 2 * (int)(M_PI * f2fl(r) / 19); if(!disk_va) disk_va = circle_array_init(nsides); ogl_drawcircle(nsides, GL_TRIANGLE_FAN, disk_va); glPopMatrix(); return 0; } /* * Draw flat-shaded Polygon (Lasers, Drone-arms, Driller-ears) */ bool g3_draw_poly(int nv,const g3s_point **pointlist) { int c, index3, index4; float color_r, color_g, color_b, color_a; GLfloat *vertex_array, *color_array; MALLOC(vertex_array, GLfloat, nv*3); MALLOC(color_array, GLfloat, nv*4); r_polyc++; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); c = grd_curcanv->cv_color; OGL_DISABLE(TEXTURE_2D); color_r = PAL2Tr(c); color_g = PAL2Tg(c); color_b = PAL2Tb(c); if (grd_curcanv->cv_fade_level >= GR_FADE_OFF) color_a = 1.0; else color_a = 1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0); for (c=0; cp3_vec.x); vertex_array[index3+1] = f2glf(pointlist[c]->p3_vec.y); vertex_array[index3+2] = -f2glf(pointlist[c]->p3_vec.z); } glVertexPointer(3, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glDrawArrays(GL_TRIANGLE_FAN, 0, nv); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); d_free(vertex_array); d_free(color_array); return 0; } void gr_upoly_tmap(int nverts, int *vert ){ glmprintf((0,"gr_upoly_tmap: unhandled\n"));//should never get called } void draw_tmap_flat(grs_bitmap *bm,int nv,g3s_point **vertlist){ glmprintf((0,"draw_tmap_flat: unhandled\n"));//should never get called } extern void (*tmap_drawer_ptr)(grs_bitmap *bm,int nv,g3s_point **vertlist); /* * Everything texturemapped (walls, robots, ship) */ bool g3_draw_tmap(int nv,const g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm) { int c, index2, index3, index4; GLfloat *vertex_array, *color_array, *texcoord_array, color_alpha = 1.0; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); if (tmap_drawer_ptr == draw_tmap) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); OGL_ENABLE(TEXTURE_2D); ogl_bindbmtex(bm); ogl_texwrap(bm->gltexture, GL_REPEAT); r_tpolyc++; color_alpha = (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:(1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0)); } else if (tmap_drawer_ptr == draw_tmap_flat) { OGL_DISABLE(TEXTURE_2D); /* for cloaked state faces */ color_alpha = 1.0 - (grd_curcanv->cv_fade_level/(GLfloat)NUM_LIGHTING_LEVELS); } else { glmprintf((0,"g3_draw_tmap: unhandled tmap_drawer %p\n",tmap_drawer_ptr)); return 0; } MALLOC(vertex_array, GLfloat, nv*3); MALLOC(color_array, GLfloat, nv*4); MALLOC(texcoord_array, GLfloat, nv*2); for (c=0; cp3_vec.x); vertex_array[index3+1] = f2glf(pointlist[c]->p3_vec.y); vertex_array[index3+2] = -f2glf(pointlist[c]->p3_vec.z); if (tmap_drawer_ptr == draw_tmap_flat) { color_array[index4] = 0; color_array[index4+1] = color_array[index4]; color_array[index4+2] = color_array[index4]; color_array[index4+3] = color_alpha; } else { color_array[index4] = bm->bm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].r); color_array[index4+1] = bm->bm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].g); color_array[index4+2] = bm->bm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].b); color_array[index4+3] = color_alpha; } texcoord_array[index2] = f2glf(uvl_list[c].u); texcoord_array[index2+1] = f2glf(uvl_list[c].v); } glVertexPointer(3, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); if (tmap_drawer_ptr == draw_tmap) { glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array); } glDrawArrays(GL_TRIANGLE_FAN, 0, nv); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); d_free(vertex_array); d_free(color_array); d_free(texcoord_array); return 0; } /* * Everything texturemapped with secondary texture (walls with secondary texture) */ bool g3_draw_tmap_2(int nv, const g3s_point **pointlist, g3s_uvl *uvl_list, g3s_lrgb *light_rgb, grs_bitmap *bmbot, grs_bitmap *bm, int orient) { int c, index2, index3, index4; GLfloat *vertex_array, *color_array, *texcoord_array; MALLOC(vertex_array, GLfloat, nv*3); MALLOC(color_array, GLfloat, nv*4); MALLOC(texcoord_array, GLfloat, nv*2); g3_draw_tmap(nv,pointlist,uvl_list,light_rgb,bmbot);//draw the bottom texture first.. could be optimized with multitexturing.. glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); r_tpolyc++; OGL_ENABLE(TEXTURE_2D); ogl_bindbmtex(bm); ogl_texwrap(bm->gltexture,GL_REPEAT); for (c=0; cbm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].r); color_array[index4+1] = bm->bm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].g); color_array[index4+2] = bm->bm_flags & BM_FLAG_NO_LIGHTING ? 1.0 : f2glf(light_rgb[c].b); color_array[index4+3] = (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:(1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0)); vertex_array[index3] = f2glf(pointlist[c]->p3_vec.x); vertex_array[index3+1] = f2glf(pointlist[c]->p3_vec.y); vertex_array[index3+2] = -f2glf(pointlist[c]->p3_vec.z); } glVertexPointer(3, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array); glDrawArrays(GL_TRIANGLE_FAN, 0, nv); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); d_free(vertex_array); d_free(color_array); d_free(texcoord_array); return 0; } /* * 2d Sprites (Fireaballs, powerups, explosions). NOT hostages */ bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm) { vms_vector pv,v1; int i; GLfloat vertex_array[12], color_array[16], texcoord_array[8]; r_bitmapc++; v1.z=0; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); OGL_ENABLE(TEXTURE_2D); ogl_bindbmtex(bm); ogl_texwrap(bm->gltexture,GL_CLAMP_TO_EDGE); width = fixmul(width,Matrix_scale.x); height = fixmul(height,Matrix_scale.y); for (i=0;i<4;i++){ vm_vec_sub(&v1,pos,&View_position); vm_vec_rotate(&pv,&v1,&View_matrix); switch (i){ case 0: texcoord_array[i*2] = 0.0; texcoord_array[i*2+1] = 0.0; pv.x+=-width; pv.y+=height; break; case 1: texcoord_array[i*2] = bm->gltexture->u; texcoord_array[i*2+1] = 0.0; pv.x+=width; pv.y+=height; break; case 2: texcoord_array[i*2] = bm->gltexture->u; texcoord_array[i*2+1] = bm->gltexture->v; pv.x+=width; pv.y+=-height; break; case 3: texcoord_array[i*2] = 0.0; texcoord_array[i*2+1] = bm->gltexture->v; pv.x+=-width; pv.y+=-height; break; } color_array[i*4] = 1.0; color_array[i*4+1] = 1.0; color_array[i*4+2] = 1.0; color_array[i*4+3] = (grd_curcanv->cv_fade_level >= GR_FADE_OFF)?1.0:(1.0 - (float)grd_curcanv->cv_fade_level / ((float)GR_FADE_LEVELS - 1.0)); vertex_array[i*3] = f2glf(pv.x); vertex_array[i*3+1] = f2glf(pv.y); vertex_array[i*3+2] = -f2glf(pv.z); } glVertexPointer(3, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Replaced GL_QUADS glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); return 0; } /* * Movies * Since this function will create a new texture each call, mipmapping can be very GPU intensive - so it has an optional setting for texture filtering. */ bool ogl_ubitblt_i(int dw,int dh,int dx,int dy, int sw, int sh, int sx, int sy, grs_bitmap * src, grs_bitmap * dest, int texfilt) { GLfloat xo,yo,xs,ys,u1,v1; GLfloat color_array[] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 }; GLfloat texcoord_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GLfloat vertex_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; ogl_texture tex; r_ubitbltc++; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); ogl_init_texture(&tex, sw, sh, OGL_FLAG_ALPHA); tex.prio = 0.0; tex.lw=src->bm_rowsize; u1=v1=0; dx+=dest->bm_x; dy+=dest->bm_y; xo=dx/(float)last_width; xs=dw/(float)last_width; yo=1.0-dy/(float)last_height; ys=dh/(float)last_height; OGL_ENABLE(TEXTURE_2D); ogl_pal=gr_current_pal; ogl_loadtexture(src->bm_data, sx, sy, &tex, src->bm_flags, 0, texfilt); ogl_pal=gr_palette; OGL_BINDTEXTURE(tex.handle); ogl_texwrap(&tex,GL_CLAMP_TO_EDGE); vertex_array[0] = xo; vertex_array[1] = yo; vertex_array[2] = xo+xs; vertex_array[3] = yo; vertex_array[4] = xo+xs; vertex_array[5] = yo-ys; vertex_array[6] = xo; vertex_array[7] = yo-ys; texcoord_array[0] = u1; texcoord_array[1] = v1; texcoord_array[2] = tex.u; texcoord_array[3] = v1; texcoord_array[4] = tex.u; texcoord_array[5] = tex.v; texcoord_array[6] = u1; texcoord_array[7] = tex.v; glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); ogl_freetexture(&tex); return 0; } bool ogl_ubitblt(int w,int h,int dx,int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest){ return ogl_ubitblt_i(w,h,dx,dy,w,h,sx,sy,src,dest,0); } /* * set depth testing on or off */ void ogl_toggle_depth_test(int enable) { if (enable) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); } /* * set blending function */ void ogl_set_blending() { switch ( grd_curcanv->cv_blend_func ) { case GR_BLEND_ADDITIVE_A: glBlendFunc( GL_SRC_ALPHA, GL_ONE ); break; case GR_BLEND_ADDITIVE_C: glBlendFunc( GL_ONE, GL_ONE ); break; case GR_BLEND_NORMAL: default: glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); break; } } GLubyte *pixels = NULL; void ogl_start_frame(void){ r_polyc=0;r_tpolyc=0;r_bitmapc=0;r_ubitbltc=0;r_upixelc=0; OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,Canvas_width,Canvas_height); glClearColor(0.0, 0.0, 0.0, 0.0); glLineWidth(linedotscale); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL,0.02); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glClear(GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); glShadeModel(GL_SMOOTH); glMatrixMode(GL_PROJECTION); glLoadIdentity();//clear matrix #ifdef OGLES perspective(90.0,1.0,0.1,5000.0); #else gluPerspective(90.0,1.0,0.1,5000.0); #endif glMatrixMode(GL_MODELVIEW); glLoadIdentity();//clear matrix } void ogl_end_frame(void){ OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h); glMatrixMode(GL_PROJECTION); glLoadIdentity();//clear matrix #ifdef OGLES glOrthof(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); #else glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); #endif glMatrixMode(GL_MODELVIEW); glLoadIdentity();//clear matrix glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); } void gr_flip(void) { if (GameArg.DbgRenderStats) ogl_texture_stats(); ogl_do_palfx(); ogl_swap_buffers_internal(); glClear(GL_COLOR_BUFFER_BIT); } int tex_format_supported(int iformat,int format) { #ifndef OGLES switch (iformat){ case GL_INTENSITY4: if (!GameArg.DbgGlIntensity4Ok) return 0; break; case GL_LUMINANCE4_ALPHA4: if (!GameArg.DbgGlLuminance4Alpha4Ok) return 0; break; case GL_RGBA2: if (!GameArg.DbgGlRGBA2Ok) return 0; break; } if (GameArg.DbgGlGetTexLevelParamOk){ GLint internalFormat; glTexImage2D(GL_PROXY_TEXTURE_2D, 0, iformat, 64, 64, 0, format, GL_UNSIGNED_BYTE, texbuf);//NULL? glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat); return (internalFormat==iformat); }else #endif return 1; } //little hack to find the nearest bigger power of 2 for a given number int pow2ize(int x){ int i; for (i=2; i max(grd_curscreen->sc_w, 1024)) || (height > max(grd_curscreen->sc_h, 256))) Error("Texture is too big: %ix%i", width, height); i=0; for (y=0;yinternalformat,tex->format)){ glmprintf((0,"tex format %x not supported",tex->internalformat)); switch (tex->internalformat){ #ifdef OGLES case GL_RGB: tex->format=GL_RGB; break; case GL_RGBA: tex->format=GL_RGBA; #else case GL_INTENSITY4: if (GameArg.DbgGlLuminance4Alpha4Ok){ tex->internalformat=GL_LUMINANCE4_ALPHA4; tex->format=GL_LUMINANCE_ALPHA; break; }//note how it will fall through here if the statement is false case GL_LUMINANCE4_ALPHA4: if (GameArg.DbgGlRGBA2Ok){ tex->internalformat=GL_RGBA2; tex->format=GL_RGBA; break; }//note how it will fall through here if the statement is false case GL_RGBA2: #if defined(__APPLE__) && defined(__MACH__) case GL_RGB8: // Quartz doesn't support RGB only #endif tex->internalformat = ogl_rgba_internalformat; tex->format=GL_RGBA; break; #endif // OGLES default: glmprintf((0,"...no tex format to fall back on\n")); return 1; } glmprintf((0,"...falling back to %x\n",tex->internalformat)); } return 0; } void tex_set_size1(ogl_texture *tex,int dbits,int bits,int w, int h){ int u; if (tex->tw!=w || tex->th!=h){ u=(tex->w/(float)tex->tw*w) * (tex->h/(float)tex->th*h); glmprintf((0,"shrunken texture?\n")); }else u=tex->w*tex->h; if (bits<=0){//the beta nvidia GLX server. doesn't ever return any bit sizes, so just use some assumptions. tex->bytes=((float)w*h*dbits)/8.0; tex->bytesu=((float)u*dbits)/8.0; }else{ tex->bytes=((float)w*h*bits)/8.0; tex->bytesu=((float)u*bits)/8.0; } glmprintf((0,"tex_set_size1: %ix%i, %ib(%i) %iB\n",w,h,bits,dbits,tex->bytes)); } void tex_set_size(ogl_texture *tex){ GLint w,h; int bi=16,a=0; #ifndef OGLES if (GameArg.DbgGlGetTexLevelParamOk){ GLint t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&w); glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&h); glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_LUMINANCE_SIZE,&t);a+=t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_INTENSITY_SIZE,&t);a+=t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_RED_SIZE,&t);a+=t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_GREEN_SIZE,&t);a+=t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_BLUE_SIZE,&t);a+=t; glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_ALPHA_SIZE,&t);a+=t; } else #endif { w=tex->tw; h=tex->th; } switch (tex->format){ case GL_LUMINANCE: bi=8; break; case GL_LUMINANCE_ALPHA: bi=8; break; case GL_RGB: case GL_RGBA: bi=16; break; #ifndef OGLES case GL_COLOR_INDEX: bi = 8; break; #endif default: Error("tex_set_size unknown texformat\n"); break; } tex_set_size1(tex,bi,a,w,h); } //loads a palettized bitmap into a ogl RGBA texture. //Sizes and pads dimensions to multiples of 2 if necessary. //In theory this could be a problem for repeating textures, but all real //textures (not sprites, etc) in descent are 64x64, so we are ok. //stores OpenGL textured id in *texid and u/v values required to get only the real data in *u/*v int ogl_loadtexture (unsigned char *data, int dxo, int dyo, ogl_texture *tex, int bm_flags, int data_format, int texfilt) { GLubyte *bufP = texbuf; tex->tw = pow2ize (tex->w); tex->th = pow2ize (tex->h);//calculate smallest texture size that can accomodate us (must be multiples of 2) //calculate u/v values that would make the resulting texture correctly sized tex->u = (float) ((double) tex->w / (double) tex->tw); tex->v = (float) ((double) tex->h / (double) tex->th); if (data) { if (bm_flags >= 0) ogl_filltexbuf (data, texbuf, tex->lw, tex->w, tex->h, dxo, dyo, tex->tw, tex->th, tex->format, bm_flags, data_format); else { if (!dxo && !dyo && (tex->w == tex->tw) && (tex->h == tex->th)) bufP = data; else { int h, w, tw; h = tex->lw / tex->w; w = (tex->w - dxo) * h; data += tex->lw * dyo + h * dxo; bufP = texbuf; tw = tex->tw * h; h = tw - w; for (; dyo < tex->h; dyo++, data += tex->lw) { memcpy (bufP, data, w); bufP += w; memset (bufP, 0, h); bufP += h; } memset (bufP, 0, tex->th * tw - (bufP - texbuf)); bufP = texbuf; } } } // Generate OpenGL texture IDs. glGenTextures (1, &tex->handle); #ifndef OGLES //set priority glPrioritizeTextures (1, &tex->handle, &tex->prio); #endif // Give our data to OpenGL. OGL_BINDTEXTURE(tex->handle); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (texfilt) { #ifdef OGLES // in OpenGL ES 1.1 the mipmaps are automatically generated by a parameter glTexParameteri (GL_TEXTURE_2D, GL_GENERATE_MIPMAP, texfilt ? GL_TRUE : GL_FALSE); #endif glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (texfilt>=2?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST)); #ifndef OGLES if (texfilt >= 3 && ogl_maxanisotropy > 1.0) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, ogl_maxanisotropy); #endif } else { glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } #ifndef OGLES // see comment above if (texfilt) { gluBuild2DMipmaps ( GL_TEXTURE_2D, tex->internalformat, tex->tw, tex->th, tex->format, GL_UNSIGNED_BYTE, bufP); } else #endif { glTexImage2D ( GL_TEXTURE_2D, 0, tex->internalformat, tex->tw, tex->th, 0, tex->format, // RGBA textures. GL_UNSIGNED_BYTE, // imageData is a GLubyte pointer. bufP); } tex_set_size (tex); r_texcount++; return 0; } unsigned char decodebuf[1024*1024]; void ogl_loadbmtexture_f(grs_bitmap *bm, int texfilt) { unsigned char *buf; #ifdef HAVE_LIBPNG char *bitmapname; #endif while (bm->bm_parent) bm=bm->bm_parent; if (bm->gltexture && bm->gltexture->handle > 0) return; buf=bm->bm_data; #ifdef HAVE_LIBPNG if ((bitmapname = piggy_game_bitmap_name(bm))) { char filename[64]; png_data pdata; sprintf(filename, "textures/%s.png", bitmapname); if (read_png(filename, &pdata)) { con_printf(CON_DEBUG,"%s: %ux%ux%i p=%i(%i) c=%i a=%i chans=%i\n", filename, pdata.width, pdata.height, pdata.depth, pdata.paletted, pdata.num_palette, pdata.color, pdata.alpha, pdata.channels); if (pdata.depth == 8 && pdata.color) { if (bm->gltexture == NULL) ogl_init_texture(bm->gltexture = ogl_get_free_texture(), pdata.width, pdata.height, flags | ((pdata.alpha || bm->bm_flags & BM_FLAG_TRANSPARENT) ? OGL_FLAG_ALPHA : 0)); ogl_loadtexture(pdata.data, 0, 0, bm->gltexture, bm->bm_flags, pdata.paletted ? 0 : pdata.channels, texfilt); free(pdata.data); if (pdata.palette) free(pdata.palette); return; } else { con_printf(CON_DEBUG,"%s: unsupported texture format: must be rgb, rgba, or paletted, and depth 8\n", filename); free(pdata.data); if (pdata.palette) free(pdata.palette); } } } #endif if (bm->gltexture == NULL){ ogl_init_texture(bm->gltexture = ogl_get_free_texture(), bm->bm_w, bm->bm_h, ((bm->bm_flags & (BM_FLAG_TRANSPARENT | BM_FLAG_SUPER_TRANSPARENT))? OGL_FLAG_ALPHA : 0)); } else { if (bm->gltexture->handle>0) return; if (bm->gltexture->w==0){ bm->gltexture->lw=bm->bm_w; bm->gltexture->w=bm->bm_w; bm->gltexture->h=bm->bm_h; } } if (bm->bm_flags & BM_FLAG_RLE){ unsigned char * dbits; unsigned char * sbits; int i, data_offset; data_offset = 1; if (bm->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)]; dbits = decodebuf; for (i=0; i < bm->bm_h; i++ ) { gr_rle_decode(sbits,dbits); if ( bm->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)]))); else sbits += (int)bm->bm_data[4+i]; dbits += bm->bm_w; } buf=decodebuf; } ogl_loadtexture(buf, 0, 0, bm->gltexture, bm->bm_flags, 0, texfilt); } void ogl_loadbmtexture(grs_bitmap *bm) { ogl_loadbmtexture_f(bm, GameCfg.TexFilt); } void ogl_freetexture(ogl_texture *gltexture) { if (gltexture->handle>0) { r_texcount--; glmprintf((0,"ogl_freetexture(%p):%i (%i left)\n",gltexture,gltexture->handle,r_texcount)); glDeleteTextures( 1, &gltexture->handle ); // gltexture->handle=0; ogl_reset_texture(gltexture); } } void ogl_freebmtexture(grs_bitmap *bm){ if (bm->gltexture){ ogl_freetexture(bm->gltexture); bm->gltexture=NULL; } } /* * Menu / gauges */ bool ogl_ubitmapm_cs(int x, int y,int dw, int dh, grs_bitmap *bm,int c, int scale) // to scale bitmaps { GLfloat xo,yo,xf,yf,u1,u2,v1,v2,color_r,color_g,color_b,h; GLfloat color_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GLfloat texcoord_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; GLfloat vertex_array[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; x+=grd_curcanv->cv_bitmap.bm_x; y+=grd_curcanv->cv_bitmap.bm_y; xo=x/(float)last_width; xf=(bm->bm_w+x)/(float)last_width; yo=1.0-y/(float)last_height; yf=1.0-(bm->bm_h+y)/(float)last_height; glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); if (dw < 0) dw = grd_curcanv->cv_bitmap.bm_w; else if (dw == 0) dw = bm->bm_w; if (dh < 0) dh = grd_curcanv->cv_bitmap.bm_h; else if (dh == 0) dh = bm->bm_h; h = (double) scale / (double) F1_0; xo = x / ((double) last_width * h); xf = (dw + x) / ((double) last_width * h); yo = 1.0 - y / ((double) last_height * h); yf = 1.0 - (dh + y) / ((double) last_height * h); OGL_ENABLE(TEXTURE_2D); ogl_bindbmtex(bm); ogl_texwrap(bm->gltexture,GL_CLAMP_TO_EDGE); if (bm->bm_x==0){ u1=0; if (bm->bm_w==bm->gltexture->w) u2=bm->gltexture->u; else u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw; }else { u1=bm->bm_x/(float)bm->gltexture->tw; u2=(bm->bm_w+bm->bm_x)/(float)bm->gltexture->tw; } if (bm->bm_y==0){ v1=0; if (bm->bm_h==bm->gltexture->h) v2=bm->gltexture->v; else v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th; }else{ v1=bm->bm_y/(float)bm->gltexture->th; v2=(bm->bm_h+bm->bm_y)/(float)bm->gltexture->th; } if (c < 0) { color_r = 1.0; color_g = 1.0; color_b = 1.0; } else { color_r = CPAL2Tr(c); color_g = CPAL2Tg(c); color_b = CPAL2Tb(c); } color_array[0] = color_array[4] = color_array[8] = color_array[12] = color_r; color_array[1] = color_array[5] = color_array[9] = color_array[13] = color_g; color_array[2] = color_array[6] = color_array[10] = color_array[14] = color_b; color_array[3] = color_array[7] = color_array[11] = color_array[15] = 1.0; vertex_array[0] = xo; vertex_array[1] = yo; vertex_array[2] = xf; vertex_array[3] = yo; vertex_array[4] = xf; vertex_array[5] = yf; vertex_array[6] = xo; vertex_array[7] = yf; texcoord_array[0] = u1; texcoord_array[1] = v1; texcoord_array[2] = u2; texcoord_array[3] = v1; texcoord_array[4] = u2; texcoord_array[5] = v2; texcoord_array[6] = u1; texcoord_array[7] = v2; glVertexPointer(2, GL_FLOAT, 0, vertex_array); glColorPointer(4, GL_FLOAT, 0, color_array); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_array); glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); return 0; } dxx-rebirth-0.58.1-d2x/arch/sdl/000077500000000000000000000000001217717237500162535ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/sdl/digi.c000066400000000000000000000122471217717237500173410ustar00rootroot00000000000000/* * Digital audio support * Library-independent stub for dynamic selection of sound system */ #include "pstypes.h" #include "dxxerror.h" #include "fix.h" #include "vecmat.h" #include "gr.h" #include "piggy.h" #include "digi.h" #include "sounds.h" #include "wall.h" #include "newdemo.h" #include "kconfig.h" #include "console.h" #include "rbaudio.h" #include "jukebox.h" #include "args.h" #include #include #include #include #include #ifdef USE_SDLMIXER #include #endif #ifdef _WIN32 #include "hmp.h" #endif /* Sound system function pointers */ int (*fptr_init)() = NULL; void (*fptr_close)() = NULL; void (*fptr_reset)() = NULL; void (*fptr_set_channel_volume)(int, int) = NULL; void (*fptr_set_channel_pan)(int, int) = NULL; int (*fptr_start_sound)(short, fix, int, int, int, int, int) = NULL; void (*fptr_stop_sound)(int) = NULL; void (*fptr_end_sound)(int) = NULL; int (*fptr_is_sound_playing)(int) = NULL; int (*fptr_is_channel_playing)(int) = NULL; void (*fptr_stop_all_channels)() = NULL; void (*fptr_set_digi_volume)(int) = NULL; void digi_select_system(int n) { switch (n) { #ifdef USE_SDLMIXER case SDLMIXER_SYSTEM: con_printf(CON_NORMAL,"Using SDL_mixer library\n"); fptr_init = digi_mixer_init; fptr_close = digi_mixer_close; fptr_reset = digi_mixer_reset; fptr_set_channel_volume = digi_mixer_set_channel_volume; fptr_set_channel_pan = digi_mixer_set_channel_pan; fptr_start_sound = digi_mixer_start_sound; fptr_stop_sound = digi_mixer_stop_sound; fptr_end_sound = digi_mixer_end_sound; fptr_is_sound_playing = digi_mixer_is_sound_playing; fptr_is_channel_playing = digi_mixer_is_channel_playing; fptr_stop_all_channels = digi_mixer_stop_all_channels; fptr_set_digi_volume = digi_mixer_set_digi_volume; break; #endif case SDLAUDIO_SYSTEM: default: con_printf(CON_NORMAL,"Using plain old SDL audio\n"); fptr_init = digi_audio_init; fptr_close = digi_audio_close; fptr_reset = digi_audio_reset; fptr_set_channel_volume = digi_audio_set_channel_volume; fptr_set_channel_pan = digi_audio_set_channel_pan; fptr_start_sound = digi_audio_start_sound; fptr_stop_sound = digi_audio_stop_sound; fptr_end_sound = digi_audio_end_sound; fptr_is_sound_playing = digi_audio_is_sound_playing; fptr_is_channel_playing = digi_audio_is_channel_playing; fptr_stop_all_channels = digi_audio_stop_all_channels; fptr_set_digi_volume = digi_audio_set_digi_volume; break; } } /* Common digi functions */ #ifndef NDEBUG static int digi_initialised = 0; #endif extern int digi_max_channels; int digi_volume = SOUND_MAX_VOLUME; void digi_set_volume(int dvolume) { digi_volume = dvolume; if (fptr_set_digi_volume) digi_set_digi_volume(dvolume); } void digi_set_sample_rate(int r) { GameArg.SndDigiSampleRate = r; } /* Stub functions */ int digi_init() { digi_init_sounds(); return fptr_init(); } void digi_close() { fptr_close(); } void digi_reset() { fptr_reset(); } void digi_set_channel_volume(int channel, int volume) { fptr_set_channel_volume(channel, volume); } void digi_set_channel_pan(int channel, int pan) { fptr_set_channel_pan(channel, pan); } int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj) { return fptr_start_sound(soundnum, volume, pan, looping, loop_start, loop_end, soundobj); } void digi_stop_sound(int channel) { fptr_stop_sound(channel); } void digi_end_sound(int channel) { fptr_end_sound(channel); } int digi_is_sound_playing(int soundno) { return fptr_is_sound_playing(soundno); } int digi_is_channel_playing(int channel) { return fptr_is_channel_playing(channel); } void digi_stop_all_channels() { fptr_stop_all_channels(); } void digi_set_digi_volume(int dvolume) { fptr_set_digi_volume(dvolume); } #ifndef NDEBUG void digi_debug() { int i; int n_voices = 0; if (!digi_initialised) return; for (i = 0; i < digi_max_channels; i++) { if (digi_is_channel_playing(i)) n_voices++; } } #endif #ifdef _WIN32 // Windows native-MIDI stuff. int digi_win32_midi_song_playing=0; static hmp_file *cur_hmp=NULL; static int firstplay = 1; void digi_win32_set_midi_volume( int mvolume ) { hmp_setvolume(cur_hmp, mvolume*MIDI_VOLUME_SCALE/8); } int digi_win32_play_midi_song( char * filename, int loop ) { if (firstplay) { hmp_reset(); firstplay = 0; } digi_win32_stop_midi_song(); if (filename == NULL) return 0; if ((cur_hmp = hmp_open(filename))) { /* * FIXME: to be implemented as soon as we have some kind or checksum function - replacement for ugly hack in hmp.c for descent.hmp * if (***filesize check*** && ***CRC32 or MD5 check***) * (((*cur_hmp).trks)[1]).data[6] = 0x6C; */ if (hmp_play(cur_hmp,loop) != 0) return 0; // error digi_win32_midi_song_playing = 1; digi_win32_set_midi_volume(GameCfg.MusicVolume); return 1; } return 0; } void digi_win32_pause_midi_song() { hmp_pause(cur_hmp); } void digi_win32_resume_midi_song() { hmp_resume(cur_hmp); } void digi_win32_stop_midi_song() { if (!digi_win32_midi_song_playing) return; hmp_close(cur_hmp); cur_hmp = NULL; digi_win32_midi_song_playing = 0; hmp_reset(); } #endif dxx-rebirth-0.58.1-d2x/arch/sdl/digi_audio.c000066400000000000000000000262411217717237500205210ustar00rootroot00000000000000/* * * SDL digital audio support * * */ #include #include #include #include #include #include "pstypes.h" #include "dxxerror.h" #include "fix.h" #include "vecmat.h" #include "gr.h" #include "piggy.h" #include "digi.h" #include "sounds.h" #include "wall.h" #include "newdemo.h" #include "kconfig.h" #include "config.h" #include "args.h" //changed on 980905 by adb to increase number of concurrent sounds #define MAX_SOUND_SLOTS 32 //end changes by adb #define SOUND_BUFFER_SIZE 1024 #define MIN_VOLUME 10 /* This table is used to add two sound values together and pin * the value to avoid overflow. (used with permission from ARDI) * DPH: Taken from SDL/src/SDL_mixer.c. */ static const Uint8 mix8[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; static int digi_initialised = 0; struct sound_slot { int soundno; int playing; // Is there a sample playing on this channel? int looped; // Play this sample looped? fix pan; // 0 = far left, 1 = far right fix volume; // 0 = nothing, 1 = fully on //changed on 980905 by adb from char * to unsigned char * unsigned char *samples; //end changes by adb unsigned int length; // Length of the sample unsigned int position; // Position we are at at the moment. int soundobj; // Which soundobject is on this channel int persistent; // This can't be pre-empted } SoundSlots[MAX_SOUND_SLOTS]; static SDL_AudioSpec WaveSpec; int digi_max_channels = 16; static int next_channel = 0; void digi_stop_sound(int channel); int digi_xlat_sound(int soundno); /* Audio mixing callback */ //changed on 980905 by adb to cleanup, add pan support and optimize mixer static void audio_mixcallback(void *userdata, Uint8 *stream, int len) { Uint8 *streamend = stream + len; struct sound_slot *sl; if (!digi_initialised) return; memset(stream, 0x80, len); // fix "static" sound bug on Mac OS X SDL_LockAudio(); for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) { if (sl->playing) { Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length; Uint8 *sp = stream, s; signed char v; fix vl, vr; int x; if ((x = sl->pan) & 0x8000) { vl = 0x20000 - x * 2; vr = 0x10000; } else { vl = 0x10000; vr = x * 2; } vl = fixmul(vl, (x = sl->volume)); vr = fixmul(vr, x); while (sp < streamend) { if (sldata == slend) { if (!sl->looped) { sl->playing = 0; break; } sldata = sl->samples; } v = *(sldata++) - 0x80; s = *sp; *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ]; s = *sp; *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ]; } sl->position = sldata - sl->samples; } } SDL_UnlockAudio(); } //end changes by adb /* Initialise audio devices. */ int digi_audio_init() { if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) { Error("SDL audio initialisation failed: %s.",SDL_GetError()); } WaveSpec.freq = GameArg.SndDigiSampleRate; //added/changed by Sam Lantinga on 12/01/98 for new SDL version WaveSpec.format = AUDIO_U8; WaveSpec.channels = 2; //end this section addition/change - SL WaveSpec.samples = SOUND_BUFFER_SIZE; WaveSpec.callback = audio_mixcallback; if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) { //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound. Warning("\nError: Couldn't open audio: %s\n", SDL_GetError()); //killed exit(2); return 1; //end edit -MM } SDL_PauseAudio(0); digi_initialised = 1; digi_audio_set_digi_volume( (GameCfg.DigiVolume*32768)/8 ); return 0; } /* Toggle audio */ void digi_audio_reset() { } /* Shut down audio */ void digi_audio_close() { if (!digi_initialised) return; digi_initialised = 0; #ifdef __MINGW32__ SDL_Delay(500); // CloseAudio hangs if it's called too soon after opening? #endif SDL_CloseAudio(); } void digi_audio_stop_all_channels() { int i; for (i = 0; i < MAX_SOUND_SLOTS; i++) digi_audio_stop_sound(i); } extern void digi_end_soundobj(int channel); extern int SoundQ_channel; extern void SoundQ_end(); int verify_sound_channel_free(int channel); // Volume 0-F1_0 int digi_audio_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj) { int i, starting_channel; if (!digi_initialised) return -1; if (soundnum < 0) return -1; SDL_LockAudio(); Assert(GameSounds[soundnum].data != (void *)-1); starting_channel = next_channel; while(1) { if (!SoundSlots[next_channel].playing) break; if (!SoundSlots[next_channel].persistent) break; // use this channel! next_channel++; if (next_channel >= digi_max_channels) next_channel = 0; if (next_channel == starting_channel) { SDL_UnlockAudio(); return -1; } } if (SoundSlots[next_channel].playing) { SoundSlots[next_channel].playing = 0; if (SoundSlots[next_channel].soundobj > -1) { digi_end_soundobj(SoundSlots[next_channel].soundobj); } if (SoundQ_channel == next_channel) SoundQ_end(); } #ifndef NDEBUG verify_sound_channel_free(next_channel); #endif SoundSlots[next_channel].soundno = soundnum; SoundSlots[next_channel].samples = GameSounds[soundnum].data; SoundSlots[next_channel].length = GameSounds[soundnum].length; SoundSlots[next_channel].volume = fixmul(digi_volume, volume); SoundSlots[next_channel].pan = pan; SoundSlots[next_channel].position = 0; SoundSlots[next_channel].looped = looping; SoundSlots[next_channel].playing = 1; SoundSlots[next_channel].soundobj = soundobj; SoundSlots[next_channel].persistent = 0; if ((soundobj > -1) || (looping) || (volume > F1_0)) SoundSlots[next_channel].persistent = 1; i = next_channel; next_channel++; if (next_channel >= digi_max_channels) next_channel = 0; SDL_UnlockAudio(); return i; } // Returns the channel a sound number is playing on, or // -1 if none. int digi_audio_find_channel(int soundno) { if (!digi_initialised) return -1; if (soundno < 0 ) return -1; if (GameSounds[soundno].data == NULL) { Int3(); return -1; } //FIXME: not implemented return -1; } //added on 980905 by adb from original source to make sfx volume work void digi_audio_set_digi_volume( int dvolume ) { dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff); if ( dvolume > SOUND_MAX_VOLUME ) digi_volume = SOUND_MAX_VOLUME; else if ( dvolume < 0 ) digi_volume = 0; else digi_volume = dvolume; if ( !digi_initialised ) return; digi_sync_sounds(); } //end edit by adb int digi_audio_is_sound_playing(int soundno) { int i; soundno = digi_xlat_sound(soundno); for (i = 0; i < MAX_SOUND_SLOTS; i++) //changed on 980905 by adb: added SoundSlots[i].playing && if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno) //end changes by adb return 1; return 0; } //added on 980905 by adb to make sound channel setting work void digi_audio_set_max_channels(int n) { digi_max_channels = n; if ( digi_max_channels < 1 ) digi_max_channels = 1; if (digi_max_channels > MAX_SOUND_SLOTS) digi_max_channels = MAX_SOUND_SLOTS; if ( !digi_initialised ) return; digi_stop_all_channels(); } int digi_audio_get_max_channels() { return digi_max_channels; } // end edit by adb int digi_audio_is_channel_playing(int channel) { if (!digi_initialised) return 0; return SoundSlots[channel].playing; } void digi_audio_set_channel_volume(int channel, int volume) { if (!digi_initialised) return; if (!SoundSlots[channel].playing) return; SoundSlots[channel].volume = fixmuldiv(volume, digi_volume, F1_0); } void digi_audio_set_channel_pan(int channel, int pan) { if (!digi_initialised) return; if (!SoundSlots[channel].playing) return; SoundSlots[channel].pan = pan; } void digi_audio_stop_sound(int channel) { SoundSlots[channel].playing=0; SoundSlots[channel].soundobj = -1; SoundSlots[channel].persistent = 0; } void digi_audio_end_sound(int channel) { if (!digi_initialised) return; if (!SoundSlots[channel].playing) return; SoundSlots[channel].soundobj = -1; SoundSlots[channel].persistent = 0; } #ifndef NDEBUG void digi_audio_debug() { int i; int n_voices = 0; if (!digi_initialised) return; for (i = 0; i < digi_max_channels; i++) { if (digi_is_channel_playing(i)) n_voices++; } } #endif dxx-rebirth-0.58.1-d2x/arch/sdl/digi_mixer.c000066400000000000000000000130441217717237500205410ustar00rootroot00000000000000/* * This is an alternate backend for the sound effect system. * It uses SDL_mixer to provide a more reliable playback, * and allow processing of multiple audio formats. * * This file is based on the original D1X arch/sdl/digi.c * * -- MD2211 (2006-10-12) */ #include #include #include #include #include #if !(defined(__APPLE__) && defined(__MACH__)) #include #else #include #endif #include "pstypes.h" #include "dxxerror.h" #include "sounds.h" #include "digi.h" #include "digi_mixer.h" #include "digi_mixer_music.h" #include "console.h" #include "config.h" #include "args.h" #include "fix.h" #include "gr.h" // needed for piggy.h #include "piggy.h" #define MIX_DIGI_DEBUG 0 #define MIX_OUTPUT_FORMAT AUDIO_S16 #define MIX_OUTPUT_CHANNELS 2 #define MAX_SOUND_SLOTS 64 #if !((defined(__APPLE__) && defined(__MACH__)) || defined(macintosh)) #define SOUND_BUFFER_SIZE 2048 #else #define SOUND_BUFFER_SIZE 1024 #endif #define MIN_VOLUME 10 static int digi_initialised = 0; static int digi_max_channels = MAX_SOUND_SLOTS; static inline int fix2byte(fix f) { return (f / 256) % 256; } Mix_Chunk SoundChunks[MAX_SOUNDS]; ubyte channels[MAX_SOUND_SLOTS]; /* Initialise audio */ int digi_mixer_init() { if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_init %d (SDL_Mixer)\n", MAX_SOUNDS); if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) Error("SDL audio initialisation failed: %s.", SDL_GetError()); if (Mix_OpenAudio(SAMPLE_RATE_44K, MIX_OUTPUT_FORMAT, MIX_OUTPUT_CHANNELS, SOUND_BUFFER_SIZE)) { //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound. con_printf(CON_URGENT,"\nError: Couldn't open audio: %s\n", SDL_GetError()); GameArg.SndNoSound = 1; return 1; } digi_max_channels = Mix_AllocateChannels(digi_max_channels); memset(channels, 0, MAX_SOUND_SLOTS); Mix_Pause(0); digi_initialised = 1; digi_mixer_set_digi_volume( (GameCfg.DigiVolume*32768)/8 ); return 0; } /* Shut down audio */ void digi_mixer_close() { if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_close (SDL_Mixer)\n"); if (!digi_initialised) return; digi_initialised = 0; Mix_CloseAudio(); } /* channel management */ int digi_mixer_find_channel() { int i; for (i = 0; i < digi_max_channels; i++) if (channels[i] == 0) return i; return -1; } void digi_mixer_free_channel(int channel_num) { channels[channel_num] = 0; } /* * Play-time conversion. Performs output conversion only once per sound effect used. * Once the sound sample has been converted, it is cached in SoundChunks[] */ void mixdigi_convert_sound(int i) { SDL_AudioCVT cvt; Uint8 *data = GameSounds[i].data; Uint32 dlen = GameSounds[i].length; int out_freq; Uint16 out_format; int out_channels; Mix_QuerySpec(&out_freq, &out_format, &out_channels); // get current output settings if (SoundChunks[i].abuf) return; //proceed only if not converted yet if (data) { if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"converting %d (%d)\n", i, dlen); SDL_BuildAudioCVT(&cvt, AUDIO_U8, 1, GameArg.SndDigiSampleRate, out_format, out_channels, out_freq); cvt.buf = malloc(dlen * cvt.len_mult); cvt.len = dlen; memcpy(cvt.buf, data, dlen); if (SDL_ConvertAudio(&cvt)) con_printf(CON_DEBUG,"conversion of %d failed\n", i); SoundChunks[i].abuf = cvt.buf; SoundChunks[i].alen = dlen * cvt.len_mult; SoundChunks[i].allocated = 1; SoundChunks[i].volume = 128; // Max volume = 128 } } // Volume 0-F1_0 int digi_mixer_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj) { int mix_vol = fix2byte(fixmul(digi_volume, volume)); int mix_pan = fix2byte(pan); int mix_loop = looping * -1; int channel; if (!digi_initialised) return -1; Assert(GameSounds[soundnum].data != (void *)-1); mixdigi_convert_sound(soundnum); if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_start_sound %d, volume %d, pan %d (start=%d, end=%d)\n", soundnum, mix_vol, mix_pan, loop_start, loop_end); channel = digi_mixer_find_channel(); Mix_PlayChannel(channel, &(SoundChunks[soundnum]), mix_loop); Mix_SetPanning(channel, 255-mix_pan, mix_pan); if (volume > F1_0) Mix_SetDistance(channel, 0); else Mix_SetDistance(channel, 255-mix_vol); channels[channel] = 1; Mix_ChannelFinished(digi_mixer_free_channel); return channel; } void digi_mixer_set_channel_volume(int channel, int volume) { int mix_vol = fix2byte(volume); if (!digi_initialised) return; Mix_SetDistance(channel, 255-mix_vol); } void digi_mixer_set_channel_pan(int channel, int pan) { int mix_pan = fix2byte(pan); Mix_SetPanning(channel, 255-mix_pan, mix_pan); } void digi_mixer_stop_sound(int channel) { if (!digi_initialised) return; if (MIX_DIGI_DEBUG) con_printf(CON_DEBUG,"digi_stop_sound %d\n", channel); Mix_HaltChannel(channel); channels[channel] = 0; } void digi_mixer_end_sound(int channel) { digi_mixer_stop_sound(channel); channels[channel] = 0; } void digi_mixer_set_digi_volume( int dvolume ) { digi_volume = dvolume; if (!digi_initialised) return; Mix_Volume(-1, fix2byte(dvolume)); } int digi_mixer_is_sound_playing(int soundno) { return 0; } int digi_mixer_is_channel_playing(int channel) { return 0; } void digi_mixer_reset() {} void digi_mixer_stop_all_channels() { Mix_HaltChannel(-1); memset(channels, 0, MAX_SOUND_SLOTS); } extern void digi_end_soundobj(int channel); //added on 980905 by adb to make sound channel setting work void digi_mixer_set_max_channels(int n) { } int digi_mixer_get_max_channels() { return digi_max_channels; } // end edit by adb #ifndef NDEBUG void digi_mixer_debug() {} #endif dxx-rebirth-0.58.1-d2x/arch/sdl/digi_mixer_music.c000066400000000000000000000073431217717237500217460ustar00rootroot00000000000000/* * This is an alternate backend for the music system. * It uses SDL_mixer to provide a more reliable playback, * and allow processing of multiple audio formats. * * -- MD2211 (2006-04-24) */ #include #if !(defined(__APPLE__) && defined(__MACH__)) #include #else #include #endif #include #include #include "args.h" #include "hmp.h" #include "digi_mixer_music.h" #include "u_mem.h" #include "console.h" #ifdef _WIN32 extern int digi_win32_play_midi_song( char * filename, int loop ); #endif Mix_Music *current_music = NULL; static unsigned char *current_music_hndlbuf = NULL; /* * Plays a music file from an absolute path or a relative path */ int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) { SDL_RWops *rw = NULL; PHYSFS_file *filehandle = NULL; char full_path[PATH_MAX]; char *fptr; unsigned int bufsize = 0; mix_free_music(); // stop and free what we're already playing, if anything fptr = strrchr(filename, '.'); if (fptr == NULL) return 0; // It's a .hmp! if (!d_stricmp(fptr, ".hmp")) { hmp2mid(filename, ¤t_music_hndlbuf, &bufsize); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); current_music = Mix_LoadMUS_RW(rw); } // try loading music via given filename if (!current_music) current_music = Mix_LoadMUS(filename); // allow the shell convention tilde character to mean the user's home folder // chiefly used for default jukebox level song music referenced in 'descent.m3u' for Mac OS X if (!current_music && *filename == '~') { snprintf(full_path, PATH_MAX, "%s%s", PHYSFS_getUserDir(), &filename[1 + (!strncmp(&filename[1], PHYSFS_getDirSeparator(), strlen(PHYSFS_getDirSeparator())) ? strlen(PHYSFS_getDirSeparator()) : 0)]); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // no luck. so it might be in Searchpath. So try to build absolute path if (!current_music) { PHYSFSX_getRealPath(filename, full_path); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // still nothin'? Let's open via PhysFS in case it's located inside an archive if (!current_music) { filehandle = PHYSFS_openRead(filename); if (filehandle != NULL) { current_music_hndlbuf = d_realloc(current_music_hndlbuf, sizeof(char *)*PHYSFS_fileLength(filehandle)); bufsize = PHYSFS_read(filehandle, current_music_hndlbuf, sizeof(char), PHYSFS_fileLength(filehandle)); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); PHYSFS_close(filehandle); current_music = Mix_LoadMUS_RW(rw); } } if (current_music) { Mix_PlayMusic(current_music, (loop ? -1 : 1)); Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music); return 1; } else { con_printf(CON_CRITICAL,"Music %s could not be loaded: %s\n", filename, Mix_GetError()); mix_stop_music(); } return 0; } // What to do when stopping song playback void mix_free_music() { Mix_HaltMusic(); if (current_music) { Mix_FreeMusic(current_music); current_music = NULL; } if (current_music_hndlbuf) { d_free(current_music_hndlbuf); current_music_hndlbuf = NULL; } } void mix_set_music_volume(int vol) { vol *= MIX_MAX_VOLUME/8; Mix_VolumeMusic(vol); } void mix_stop_music() { Mix_HaltMusic(); if (current_music_hndlbuf) { d_free(current_music_hndlbuf); current_music_hndlbuf = NULL; } } void mix_pause_music() { Mix_PauseMusic(); } void mix_resume_music() { Mix_ResumeMusic(); } void mix_pause_resume_music() { if (Mix_PausedMusic()) Mix_ResumeMusic(); else if (Mix_PlayingMusic()) Mix_PauseMusic(); } dxx-rebirth-0.58.1-d2x/arch/sdl/event.c000066400000000000000000000105061217717237500175420ustar00rootroot00000000000000/* * * SDL Event related stuff * * */ #include #include #include "event.h" #include "key.h" #include "mouse.h" #include "window.h" #include "timer.h" #include "config.h" #include "joy.h" extern void key_handler(SDL_KeyboardEvent *event); extern void mouse_button_handler(SDL_MouseButtonEvent *mbe); extern void mouse_motion_handler(SDL_MouseMotionEvent *mme); extern void mouse_cursor_autohide(); static int initialised=0; void event_poll() { SDL_Event event; int clean_uniframe=1; window *wind = window_get_front(); int idle = 1; // If the front window changes, exit this loop, otherwise unintended behavior can occur // like pressing 'Return' really fast at 'Difficulty Level' causing multiple games to be started while ((wind == window_get_front()) && SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: case SDL_KEYUP: if (clean_uniframe) memset(unicode_frame_buffer,'\0',sizeof(unsigned char)*KEY_BUFFER_SIZE); clean_uniframe=0; key_handler((SDL_KeyboardEvent *)&event); idle = 0; break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: mouse_button_handler((SDL_MouseButtonEvent *)&event); idle = 0; break; case SDL_MOUSEMOTION: mouse_motion_handler((SDL_MouseMotionEvent *)&event); idle = 0; break; case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: joy_button_handler((SDL_JoyButtonEvent *)&event); idle = 0; break; case SDL_JOYAXISMOTION: if (joy_axis_handler((SDL_JoyAxisEvent *)&event)) idle = 0; break; case SDL_JOYHATMOTION: joy_hat_handler((SDL_JoyHatEvent *)&event); idle = 0; break; case SDL_JOYBALLMOTION: break; case SDL_QUIT: { d_event qevent = { EVENT_QUIT }; call_default_handler(&qevent); idle = 0; } break; } } // Send the idle event if there were no other events if (idle) { d_event ievent; ievent.type = EVENT_IDLE; event_send(&ievent); } else event_reset_idle_seconds(); mouse_cursor_autohide(); } void event_flush() { SDL_Event event; while (SDL_PollEvent(&event)); } int event_init() { // We should now be active and responding to events. initialised = 1; return 0; } int (*default_handler)(d_event *event) = NULL; void set_default_handler(int (*handler)(d_event *event)) { default_handler = handler; } int call_default_handler(d_event *event) { if (default_handler) return (*default_handler)(event); return 0; } void event_send(d_event *event) { window *wind; int handled = 0; for (wind = window_get_front(); wind != NULL && !handled; wind = window_get_prev(wind)) if (window_is_visible(wind)) { handled = window_send_event(wind, event); if (!window_exists(wind)) // break away if necessary: window_send_event() could have closed wind by now break; if (window_is_modal(wind)) break; } if (!handled) call_default_handler(event); } // Process the first event in queue, sending to the appropriate handler // This is the new object-oriented system // Uses the old system for now, but this may change void event_process(void) { d_event event; window *wind = window_get_front(); timer_update(); event_poll(); // send input events first // Doing this prevents problems when a draw event can create a newmenu, // such as some network menus when they report a problem if (window_get_front() != wind) return; event.type = EVENT_WINDOW_DRAW; // then draw all visible windows wind = window_get_first(); while (wind != NULL) { window *prev = window_get_prev(wind); if (window_is_visible(wind)) window_send_event(wind, &event); if (!window_exists(wind)) { if (!prev) // well there isn't a previous window ... break; // ... just bail out - we've done everything for this frame we can. wind = window_get_next(prev); // the current window seemed to be closed. so take the next one from the previous which should be able to point to the one after the current closed } else wind = window_get_next(wind); } gr_flip(); } void event_toggle_focus(int activate_focus) { if (activate_focus && GameCfg.Grabinput) SDL_WM_GrabInput(SDL_GRAB_ON); else SDL_WM_GrabInput(SDL_GRAB_OFF); mouse_toggle_cursor(!activate_focus); } static fix64 last_event = 0; void event_reset_idle_seconds() { last_event = timer_query(); } fix event_get_idle_seconds() { return (timer_query() - last_event)/F1_0; } dxx-rebirth-0.58.1-d2x/arch/sdl/gr.c000066400000000000000000000160131217717237500170300ustar00rootroot00000000000000/* * * SDL video functions. * */ #include #include #include #include #include #include "gr.h" #include "grdef.h" #include "palette.h" #include "u_mem.h" #include "dxxerror.h" #include "vers_id.h" #include "gamefont.h" #include "args.h" #include "config.h" int sdl_video_flags = SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF; SDL_Surface *screen,*canvas; int gr_installed = 0; void gr_flip() { SDL_Rect src, dest; dest.x = src.x = dest.y = src.y = 0; dest.w = src.w = canvas->w; dest.h = src.h = canvas->h; SDL_BlitSurface(canvas, &src, screen, &dest); SDL_Flip(screen); } // Set the buffer to draw to. 0 is front, 1 is back // With SDL, can't use it without resetting the video mode void gr_set_draw_buffer(int buf) { buf = buf; } // returns possible (fullscreen) resolutions if any. int gr_list_modes( u_int32_t gsmodes[] ) { SDL_Rect** modes; int i = 0, modesnum = 0; int sdl_check_flags = sdl_video_flags; sdl_check_flags |= SDL_FULLSCREEN; // always use Fullscreen as lead. modes = SDL_ListModes(NULL, sdl_check_flags); if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 return 0; if (modes == (SDL_Rect**)-1) { return 0; // can obviously use any resolution... strange! } else { for (i = 0; modes[i]; ++i) { if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (kreatordxx - made 0xFFF0 to kill warning) || modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200 continue; gsmodes[modesnum] = SM(modes[i]->w,modes[i]->h); modesnum++; if (modesnum >= 50) // that really seems to be enough big boy. break; } return modesnum; } } int gr_check_mode(u_int32_t mode) { unsigned int w, h; w=SM_W(mode); h=SM_H(mode); return SDL_VideoModeOK(w,h,GameArg.DbgBpp,sdl_video_flags); } int gr_set_mode(u_int32_t mode) { unsigned int w, h; if (mode<=0) return 0; w=SM_W(mode); h=SM_H(mode); screen=NULL; SDL_WM_SetCaption(DESCENT_VERSION, "Descent II"); SDL_WM_SetIcon( SDL_LoadBMP( "d2x-rebirth.bmp" ), NULL ); if(SDL_VideoModeOK(w,h,GameArg.DbgBpp,sdl_video_flags)) { screen=SDL_SetVideoMode(w, h, GameArg.DbgBpp, sdl_video_flags); } else { con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480\n",w,h); w=640; h=480; Game_screen_mode=mode=SM(w,h); screen=SDL_SetVideoMode(w, h, GameArg.DbgBpp, sdl_video_flags); } if (screen == NULL) { Error("Could not set %dx%dx%d video mode\n",w,h,GameArg.DbgBpp); exit(1); } canvas = SDL_CreateRGBSurface(sdl_video_flags, w, h, 8, 0, 0, 0, 0); if (canvas == NULL) { Error("Could not create canvas surface\n"); exit(1); } memset(grd_curscreen, 0, sizeof(grs_screen)); grd_curscreen->sc_mode = mode; grd_curscreen->sc_w = w; grd_curscreen->sc_h = h; grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*GameCfg.AspectX,grd_curscreen->sc_h*GameCfg.AspectY); gr_init_canvas(&grd_curscreen->sc_canvas, canvas->pixels, BM_LINEAR, w, h); window_update_canvases(); gr_set_current_canvas(NULL); SDL_ShowCursor(0); gamefont_choose_game_font(w,h); gr_palette_load(gr_palette); gr_remap_color_fonts(); gr_remap_mono_fonts(); return 0; } int gr_check_fullscreen(void) { return (sdl_video_flags & SDL_FULLSCREEN)?1:0; } int gr_toggle_fullscreen(void) { gr_remap_color_fonts(); gr_remap_mono_fonts(); sdl_video_flags^=SDL_FULLSCREEN; SDL_WM_ToggleFullScreen(screen); GameCfg.WindowMode = (sdl_video_flags & SDL_FULLSCREEN)?0:1; return (sdl_video_flags & SDL_FULLSCREEN)?1:0; } void gr_set_attributes(void) { } int gr_init(int mode) { int retcode; // Only do this function once! if (gr_installed==1) return -1; if (SDL_Init(SDL_INIT_VIDEO) < 0) { Error("SDL library video initialisation failed: %s.",SDL_GetError()); } CALLOC( grd_curscreen,grs_screen,1 ); if (!GameCfg.WindowMode && !GameArg.SysWindow) sdl_video_flags|=SDL_FULLSCREEN; if (GameArg.SysNoBorders) sdl_video_flags|=SDL_NOFRAME; if (GameArg.DbgSdlHWSurface) sdl_video_flags|=SDL_HWSURFACE; if (GameArg.DbgSdlASyncBlit) sdl_video_flags|=SDL_ASYNCBLIT; // Set the mode. if ((retcode=gr_set_mode(mode))) return retcode; grd_curscreen->sc_canvas.cv_color = 0; grd_curscreen->sc_canvas.cv_fade_level = GR_FADE_OFF; grd_curscreen->sc_canvas.cv_blend_func = GR_BLEND_NORMAL; grd_curscreen->sc_canvas.cv_drawmode = 0; grd_curscreen->sc_canvas.cv_font = NULL; grd_curscreen->sc_canvas.cv_font_fg_color = 0; grd_curscreen->sc_canvas.cv_font_bg_color = 0; gr_set_current_canvas( &grd_curscreen->sc_canvas ); gr_installed = 1; return 0; } void gr_close() { if (gr_installed==1) { gr_installed = 0; d_free(grd_curscreen); SDL_ShowCursor(1); SDL_FreeSurface(canvas); } } // Palette functions follow. static int last_r=0, last_g=0, last_b=0; void gr_palette_step_up( int r, int g, int b ) { int i; ubyte *p = gr_palette; int temp; SDL_Palette *palette; SDL_Color colors[256]; if ( (r==last_r) && (g==last_g) && (b==last_b) ) return; last_r = r; last_g = g; last_b = b; palette = canvas->format->palette; if (palette == NULL) return; // Display is not palettised for (i=0; i<256; i++) { temp = (int)(*p++) + r + gr_palette_gamma; if (temp<0) temp=0; else if (temp>63) temp=63; colors[i].r = temp * 4; temp = (int)(*p++) + g + gr_palette_gamma; if (temp<0) temp=0; else if (temp>63) temp=63; colors[i].g = temp * 4; temp = (int)(*p++) + b + gr_palette_gamma; if (temp<0) temp=0; else if (temp>63) temp=63; colors[i].b = temp * 4; } SDL_SetColors(canvas, colors, 0, 256); } #undef min static inline int min(int x, int y) { return x < y ? x : y; } void gr_palette_load( ubyte *pal ) { int i, j; SDL_Palette *palette; SDL_Color colors[256]; ubyte gamma[64]; if (memcmp(pal,gr_current_pal,768)) SDL_FillRect(canvas, NULL, SDL_MapRGB(canvas->format, 0, 0, 0)); for (i=0; i<768; i++ ) { gr_current_pal[i] = pal[i]; if (gr_current_pal[i] > 63) gr_current_pal[i] = 63; } if (canvas == NULL) return; palette = canvas->format->palette; if (palette == NULL) return; // Display is not palettised for (i=0;i<64;i++) gamma[i] = (int)((pow(((double)(14)/(double)(32)), 1.0)*i) + 0.5); for (i = 0, j = 0; j < 256; j++) { int c; c = gr_find_closest_color(gamma[gr_palette[j*3]],gamma[gr_palette[j*3+1]],gamma[gr_palette[j*3+2]]); gr_fade_table[14*256+j] = c; colors[j].r = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4; colors[j].g = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4; colors[j].b = (min(gr_current_pal[i++] + gr_palette_gamma, 63)) * 4; } SDL_SetColors(canvas, colors, 0, 256); init_computed_colors(); gr_remap_color_fonts(); gr_remap_mono_fonts(); } void gr_palette_read(ubyte * pal) { SDL_Palette *palette; int i, j; palette = canvas->format->palette; if (palette == NULL) return; // Display is not palettised for (i = 0, j=0; i < 256; i++) { pal[j++] = palette->colors[i].r / 4; pal[j++] = palette->colors[i].g / 4; pal[j++] = palette->colors[i].b / 4; } } dxx-rebirth-0.58.1-d2x/arch/sdl/init.c000066400000000000000000000016021217717237500173610ustar00rootroot00000000000000// Holds the main init and de-init functions for arch-related program parts #include #include "songs.h" #include "key.h" #include "digi.h" #include "mouse.h" #include "joy.h" #include "gr.h" #include "dxxerror.h" #include "text.h" #include "args.h" #include "config.h" void arch_close(void) { songs_uninit(); gr_close(); if (!GameArg.CtlNoJoystick) joy_close(); mouse_close(); if (!GameArg.SndNoSound) { digi_close(); } key_close(); SDL_Quit(); } void arch_init(void) { int t; if (SDL_Init(SDL_INIT_VIDEO) < 0) Error("SDL library initialisation failed: %s.",SDL_GetError()); key_init(); digi_select_system( GameArg.SndDisableSdlMixer ? SDLAUDIO_SYSTEM : SDLMIXER_SYSTEM ); if (!GameArg.SndNoSound) digi_init(); mouse_init(); if (!GameArg.CtlNoJoystick) joy_init(); if ((t = gr_init(0)) != 0) Error(TXT_CANT_INIT_GFX,t); atexit(arch_close); } dxx-rebirth-0.58.1-d2x/arch/sdl/joy.c000066400000000000000000000201771217717237500172270ustar00rootroot00000000000000/* * * SDL joystick support * */ #include // for memset #include "joy.h" #include "dxxerror.h" #include "timer.h" #include "console.h" #include "event.h" #include "text.h" #include "u_mem.h" #include "playsave.h" #include "kconfig.h" int num_joysticks = 0; int joy_num_axes = 0; /* This struct is a "virtual" joystick, which includes all the axes * and buttons of every joystick found. */ static struct joyinfo { int n_axes; int n_buttons; int axis_value[JOY_MAX_AXES]; ubyte button_state[JOY_MAX_BUTTONS]; ubyte button_last_state[JOY_MAX_BUTTONS]; // for HAT movement only } Joystick; typedef struct d_event_joystickbutton { event_type type; int button; } d_event_joystickbutton; typedef struct d_event_joystick_moved { event_type type; // EVENT_JOYSTICK_MOVED int axis; int value; } d_event_joystick_moved; /* This struct is an array, with one entry for each physical joystick * found. */ static struct { SDL_Joystick *handle; int n_axes; int n_buttons; int n_hats; int hat_map[MAX_HATS_PER_JOYSTICK]; //Note: Descent expects hats to be buttons, so these are indices into Joystick.buttons int axis_map[MAX_AXES_PER_JOYSTICK]; int button_map[MAX_BUTTONS_PER_JOYSTICK]; } SDL_Joysticks[MAX_JOYSTICKS]; void joy_button_handler(SDL_JoyButtonEvent *jbe) { int button; d_event_joystickbutton event; button = SDL_Joysticks[jbe->which].button_map[jbe->button]; Joystick.button_state[button] = jbe->state; event.type = (jbe->type == SDL_JOYBUTTONDOWN) ? EVENT_JOYSTICK_BUTTON_DOWN : EVENT_JOYSTICK_BUTTON_UP; event.button = button; con_printf(CON_DEBUG, "Sending event %s, button %d\n", (jbe->type == SDL_JOYBUTTONDOWN) ? "EVENT_JOYSTICK_BUTTON_DOWN" : "EVENT_JOYSTICK_JOYSTICK_UP", event.button); event_send((d_event *)&event); } void joy_hat_handler(SDL_JoyHatEvent *jhe) { int hat = SDL_Joysticks[jhe->which].hat_map[jhe->hat]; int hbi; d_event_joystickbutton event; //Save last state of the hat-button Joystick.button_last_state[hat ] = Joystick.button_state[hat ]; Joystick.button_last_state[hat+1] = Joystick.button_state[hat+1]; Joystick.button_last_state[hat+2] = Joystick.button_state[hat+2]; Joystick.button_last_state[hat+3] = Joystick.button_state[hat+3]; //get current state of the hat-button Joystick.button_state[hat ] = ((jhe->value & SDL_HAT_UP)>0); Joystick.button_state[hat+1] = ((jhe->value & SDL_HAT_RIGHT)>0); Joystick.button_state[hat+2] = ((jhe->value & SDL_HAT_DOWN)>0); Joystick.button_state[hat+3] = ((jhe->value & SDL_HAT_LEFT)>0); //determine if a hat-button up or down event based on state and last_state for(hbi=0;hbi<4;hbi++) { if( !Joystick.button_last_state[hat+hbi] && Joystick.button_state[hat+hbi]) //last_state up, current state down { event.type = EVENT_JOYSTICK_BUTTON_DOWN; event.button = hat+hbi; con_printf(CON_DEBUG, "Sending event EVENT_JOYSTICK_BUTTON_DOWN, button %d\n", event.button); event_send((d_event *)&event); } else if(Joystick.button_last_state[hat+hbi] && !Joystick.button_state[hat+hbi]) //last_state down, current state up { event.type = EVENT_JOYSTICK_BUTTON_UP; event.button = hat+hbi; con_printf(CON_DEBUG, "Sending event EVENT_JOYSTICK_BUTTON_UP, button %d\n", event.button); event_send((d_event *)&event); } } } int joy_axis_handler(SDL_JoyAxisEvent *jae) { int axis; d_event_joystick_moved event; axis = SDL_Joysticks[jae->which].axis_map[jae->axis]; // inaccurate stick is inaccurate. SDL might send SDL_JoyAxisEvent even if the value is the same as before. if (Joystick.axis_value[axis] == jae->value/256) return 0; event.type = EVENT_JOYSTICK_MOVED; event.axis = axis; event.value = Joystick.axis_value[axis] = jae->value/256; con_printf(CON_DEBUG, "Sending event EVENT_JOYSTICK_MOVED, axis: %d, value: %d\n",event.axis, event.value); event_send((d_event *)&event); return 1; } /* ----------------------------------------------- */ void joy_init() { int i,j,n; char temp[10]; if (SDL_Init(SDL_INIT_JOYSTICK) < 0) { con_printf(CON_NORMAL, "sdl-joystick: initialisation failed: %s.",SDL_GetError()); return; } memset(&Joystick,0,sizeof(Joystick)); memset(joyaxis_text, 0, JOY_MAX_AXES * sizeof(char *)); memset(joybutton_text, 0, JOY_MAX_BUTTONS * sizeof(char *)); n = SDL_NumJoysticks(); con_printf(CON_NORMAL, "sdl-joystick: found %d joysticks\n", n); for (i = 0; i < n; i++) { con_printf(CON_NORMAL, "sdl-joystick %d: %s\n", i, SDL_JoystickName(i)); SDL_Joysticks[num_joysticks].handle = SDL_JoystickOpen(i); if (SDL_Joysticks[num_joysticks].handle) { SDL_Joysticks[num_joysticks].n_axes = SDL_JoystickNumAxes(SDL_Joysticks[num_joysticks].handle); if(SDL_Joysticks[num_joysticks].n_axes > MAX_AXES_PER_JOYSTICK) { Warning("sdl-joystick: found %d axes, only %d supported.\n", SDL_Joysticks[num_joysticks].n_axes, MAX_AXES_PER_JOYSTICK); Warning("sdl-joystick: found %d axes, only %d supported.\n", SDL_Joysticks[num_joysticks].n_axes, MAX_AXES_PER_JOYSTICK); SDL_Joysticks[num_joysticks].n_axes = MAX_AXES_PER_JOYSTICK; } SDL_Joysticks[num_joysticks].n_buttons = SDL_JoystickNumButtons(SDL_Joysticks[num_joysticks].handle); if(SDL_Joysticks[num_joysticks].n_buttons > MAX_BUTTONS_PER_JOYSTICK) { Warning("sdl-joystick: found %d buttons, only %d supported.\n", SDL_Joysticks[num_joysticks].n_buttons, MAX_BUTTONS_PER_JOYSTICK); SDL_Joysticks[num_joysticks].n_buttons = MAX_BUTTONS_PER_JOYSTICK; } SDL_Joysticks[num_joysticks].n_hats = SDL_JoystickNumHats(SDL_Joysticks[num_joysticks].handle); if(SDL_Joysticks[num_joysticks].n_hats > MAX_HATS_PER_JOYSTICK) { Warning("sdl-joystick: found %d hats, only %d supported.\n", SDL_Joysticks[num_joysticks].n_hats, MAX_HATS_PER_JOYSTICK); SDL_Joysticks[num_joysticks].n_hats = MAX_HATS_PER_JOYSTICK; } con_printf(CON_NORMAL, "sdl-joystick: %d axes\n", SDL_Joysticks[num_joysticks].n_axes); con_printf(CON_NORMAL, "sdl-joystick: %d buttons\n", SDL_Joysticks[num_joysticks].n_buttons); con_printf(CON_NORMAL, "sdl-joystick: %d hats\n", SDL_Joysticks[num_joysticks].n_hats); for (j=0; j < SDL_Joysticks[num_joysticks].n_axes; j++) { sprintf(temp, "J%d A%d", i + 1, j + 1); joyaxis_text[Joystick.n_axes] = d_strdup(temp); SDL_Joysticks[num_joysticks].axis_map[j] = Joystick.n_axes++; } for (j=0; j < SDL_Joysticks[num_joysticks].n_buttons; j++) { sprintf(temp, "J%d B%d", i + 1, j + 1); joybutton_text[Joystick.n_buttons] = d_strdup(temp); SDL_Joysticks[num_joysticks].button_map[j] = Joystick.n_buttons++; } for (j=0; j < SDL_Joysticks[num_joysticks].n_hats; j++) { SDL_Joysticks[num_joysticks].hat_map[j] = Joystick.n_buttons; //a hat counts as four buttons sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0202); joybutton_text[Joystick.n_buttons++] = d_strdup(temp); sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0177); joybutton_text[Joystick.n_buttons++] = d_strdup(temp); sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0200); joybutton_text[Joystick.n_buttons++] = d_strdup(temp); sprintf(temp, "J%d H%d%c", i + 1, j + 1, 0201); joybutton_text[Joystick.n_buttons++] = d_strdup(temp); } num_joysticks++; } else con_printf(CON_NORMAL, "sdl-joystick: initialization failed!\n"); con_printf(CON_NORMAL, "sdl-joystick: %d axes (total)\n", Joystick.n_axes); con_printf(CON_NORMAL, "sdl-joystick: %d buttons (total)\n", Joystick.n_buttons); } joy_num_axes = Joystick.n_axes; } void joy_close() { SDL_JoystickClose(SDL_Joysticks[num_joysticks].handle); while (Joystick.n_axes--) d_free(joyaxis_text[Joystick.n_axes]); while (Joystick.n_buttons--) d_free(joybutton_text[Joystick.n_buttons]); } void event_joystick_get_axis(d_event *event, int *axis, int *value) { Assert(event->type == EVENT_JOYSTICK_MOVED); *axis = ((d_event_joystick_moved *)event)->axis; *value = ((d_event_joystick_moved *)event)->value; } void joy_flush() { int i; if (!num_joysticks) return; for (i = 0; i < Joystick.n_buttons; i++) Joystick.button_state[i] = SDL_RELEASED; } int event_joystick_get_button(d_event *event) { Assert((event->type == EVENT_JOYSTICK_BUTTON_DOWN) || (event->type == EVENT_JOYSTICK_BUTTON_UP)); return ((d_event_joystickbutton *)event)->button; } dxx-rebirth-0.58.1-d2x/arch/sdl/jukebox.c000066400000000000000000000200741217717237500200710ustar00rootroot00000000000000/* * DXX Rebirth "jukebox" code * MD 2211 , 2007 */ #include #include #include #include "physfsx.h" #include "args.h" #include "hudmsg.h" #include "songs.h" #include "jukebox.h" #include "dxxerror.h" #include "console.h" #include "config.h" #define MUSIC_HUDMSG_MAXLEN 40 #define JUKEBOX_HUDMSG_PLAYING "Now playing:" #define JUKEBOX_HUDMSG_STOPPED "Jukebox stopped" typedef struct jukebox_songs { char **list; // the actual list char *list_buf; // buffer containing song file path text int num_songs; // number of jukebox songs int max_songs; // maximum number of pointers that 'list' can hold, i.e. size of list / size of one pointer int max_buf; // size of list_buf } jukebox_songs; static jukebox_songs JukeboxSongs = { NULL, NULL, 0, 0, 0 }; char hud_msg_buf[MUSIC_HUDMSG_MAXLEN+4]; void jukebox_unload() { if (JukeboxSongs.list_buf) { d_free(JukeboxSongs.list_buf); if (JukeboxSongs.list) d_free(JukeboxSongs.list); } else if (JukeboxSongs.list) { PHYSFS_freeList(JukeboxSongs.list); JukeboxSongs.list = NULL; } JukeboxSongs.num_songs = JukeboxSongs.max_songs = JukeboxSongs.max_buf = 0; } const char *const jukebox_exts[7] = { SONG_EXT_HMP, SONG_EXT_MID, SONG_EXT_OGG, SONG_EXT_FLAC, SONG_EXT_MP3, NULL }; int read_m3u(void) { FILE *fp; int length; char *buf; char *abspath; MALLOC(abspath, char, PATH_MAX); if (!abspath) return 0; if (PHYSFSX_exists(GameCfg.CMLevelMusicPath,0)) // it's a child of Sharepath, build full path PHYSFSX_getRealPath(GameCfg.CMLevelMusicPath, abspath); else { strncpy(abspath, GameCfg.CMLevelMusicPath, PATH_MAX - 1); abspath[PATH_MAX - 1] = '\0'; } fp = fopen(abspath, "rb"); d_free(abspath); if (!fp) return 0; fseek( fp, -1, SEEK_END ); length = ftell(fp) + 1; MALLOC(JukeboxSongs.list_buf, char, length + 1); if (!JukeboxSongs.list_buf) { fclose(fp); return 0; } fseek(fp, 0, SEEK_SET); if (!fread(JukeboxSongs.list_buf, length, 1, fp)) { d_free(JukeboxSongs.list_buf); fclose(fp); return 0; } fclose(fp); // Finished with it // The growing string list is allocated last, hopefully reducing memory fragmentation when it grows MALLOC(JukeboxSongs.list, char *, 1024); if (!JukeboxSongs.list) { d_free(JukeboxSongs.list_buf); return 0; } JukeboxSongs.max_songs = 1024; JukeboxSongs.list_buf[length] = '\0'; // make sure the last string is terminated JukeboxSongs.max_buf = length + 1; buf = JukeboxSongs.list_buf; while (buf < JukeboxSongs.list_buf + length - 1) { while (*buf == 0 || *buf == 10 || *buf == 13) // find new line - support DOS, Unix and Mac line endings buf++; if (*buf != '#') // ignore comments / extra info { if (JukeboxSongs.num_songs >= JukeboxSongs.max_songs) { char **new_list = d_realloc(JukeboxSongs.list, JukeboxSongs.max_buf*sizeof(char *)*MEM_K); if (new_list == NULL) break; JukeboxSongs.max_buf *= MEM_K; JukeboxSongs.list = new_list; } JukeboxSongs.list[JukeboxSongs.num_songs++] = buf; } while (*buf != 0 && *buf != 10 && *buf != 13) // find end of line buf++; *buf = 0; } return 1; } /* Loads music file names from a given directory or M3U playlist */ void jukebox_load() { static int jukebox_init = 1; // initialize JukeboxSongs structure once per runtime if (jukebox_init) { JukeboxSongs.list = NULL; JukeboxSongs.num_songs = JukeboxSongs.max_songs = JukeboxSongs.max_buf = 0; jukebox_init = 0; } jukebox_unload(); // Check if it's an M3U file if (!d_stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) read_m3u(); else // a directory { int new_path = 0; char *p; const char *sep = PHYSFS_getDirSeparator(); int i; // stick a separator on the end if necessary. if (strlen(GameCfg.CMLevelMusicPath) >= strlen(sep)) { p = GameCfg.CMLevelMusicPath + strlen(GameCfg.CMLevelMusicPath) - strlen(sep); if (strcmp(p, sep)) strncat(GameCfg.CMLevelMusicPath, sep, PATH_MAX - 1 - strlen(GameCfg.CMLevelMusicPath)); } // Read directory using PhysicsFS if (PHYSFS_isDirectory(GameCfg.CMLevelMusicPath)) // find files in relative directory JukeboxSongs.list = PHYSFSX_findFiles(GameCfg.CMLevelMusicPath, jukebox_exts); else { new_path = PHYSFSX_isNewPath(GameCfg.CMLevelMusicPath); PHYSFS_addToSearchPath(GameCfg.CMLevelMusicPath, 0); // as mountpoints are no option (yet), make sure only files originating from GameCfg.CMLevelMusicPath are aded to the list. JukeboxSongs.list = PHYSFSX_findabsoluteFiles("", GameCfg.CMLevelMusicPath, jukebox_exts); } if (!JukeboxSongs.list) { if (new_path) PHYSFS_removeFromSearchPath(GameCfg.CMLevelMusicPath); return; } for (i = 0; JukeboxSongs.list[i]; i++) {} JukeboxSongs.num_songs = i; if (new_path) PHYSFS_removeFromSearchPath(GameCfg.CMLevelMusicPath); } if (JukeboxSongs.num_songs) { con_printf(CON_DEBUG,"Jukebox: %d music file(s) found in %s\n", JukeboxSongs.num_songs, GameCfg.CMLevelMusicPath); if (GameCfg.CMLevelMusicTrack[1] != JukeboxSongs.num_songs) { GameCfg.CMLevelMusicTrack[1] = JukeboxSongs.num_songs; GameCfg.CMLevelMusicTrack[0] = 0; // number of songs changed so start from beginning. } } else { GameCfg.CMLevelMusicTrack[0] = -1; GameCfg.CMLevelMusicTrack[1] = -1; con_printf(CON_DEBUG,"Jukebox music could not be found!\n"); } } // To proceed tru our playlist. Usually used for continous play, but can loop as well. void jukebox_hook_next() { if (!JukeboxSongs.list || GameCfg.CMLevelMusicTrack[0] == -1) return; if (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_RAND) GameCfg.CMLevelMusicTrack[0] = d_rand() % GameCfg.CMLevelMusicTrack[1]; // simply a random selection - no check if this song has already been played. But that's how I roll! else GameCfg.CMLevelMusicTrack[0]++; if (GameCfg.CMLevelMusicTrack[0] + 1 > GameCfg.CMLevelMusicTrack[1]) GameCfg.CMLevelMusicTrack[0] = 0; jukebox_play(); } // Play tracks from Jukebox directory. Play track specified in GameCfg.CMLevelMusicTrack[0] and loop depending on GameCfg.CMLevelMusicPlayOrder int jukebox_play() { char *music_filename, *full_filename; unsigned long size_full_filename = 0; if (!JukeboxSongs.list) return 0; if (GameCfg.CMLevelMusicTrack[0] < 0 || GameCfg.CMLevelMusicTrack[0] + 1 > GameCfg.CMLevelMusicTrack[1]) return 0; music_filename = JukeboxSongs.list[GameCfg.CMLevelMusicTrack[0]]; if (!music_filename) return 0; size_full_filename = strlen(GameCfg.CMLevelMusicPath)+strlen(music_filename)+1; CALLOC(full_filename, char, size_full_filename); if (!d_stricmp(&GameCfg.CMLevelMusicPath[strlen(GameCfg.CMLevelMusicPath) - 4], ".m3u")) // if it's from an M3U playlist strcpy(full_filename, music_filename); else // if it's from a specified path snprintf(full_filename, size_full_filename, "%s%s", GameCfg.CMLevelMusicPath, music_filename); if (!songs_play_file(full_filename, ((GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL)?1:0), ((GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL)?NULL:jukebox_hook_next))) { d_free(full_filename); return 0; // whoops, got an error } // Formatting a pretty message if (strlen(music_filename) >= MUSIC_HUDMSG_MAXLEN) { strcpy(hud_msg_buf, "..."); strncat(hud_msg_buf, &music_filename[strlen(music_filename) - MUSIC_HUDMSG_MAXLEN], MUSIC_HUDMSG_MAXLEN); hud_msg_buf[MUSIC_HUDMSG_MAXLEN+3] = '\0'; } else { strcpy(hud_msg_buf, music_filename); } HUD_init_message(HM_DEFAULT, "%s %s", JUKEBOX_HUDMSG_PLAYING, hud_msg_buf); d_free(full_filename); return 1; } char *jukebox_current() { return JukeboxSongs.list[GameCfg.CMLevelMusicTrack[0]]; } int jukebox_is_loaded() { return (JukeboxSongs.list != NULL); } int jukebox_is_playing() { return GameCfg.CMLevelMusicTrack[0] + 1; } int jukebox_numtracks() { return GameCfg.CMLevelMusicTrack[1]; } void jukebox_list() { int i; if (!JukeboxSongs.list) return; if (!(*JukeboxSongs.list)) { con_printf(CON_DEBUG,"* No songs have been found\n"); } else { for (i = 0; i < GameCfg.CMLevelMusicTrack[1]; i++) con_printf(CON_DEBUG,"* %s\n", JukeboxSongs.list[i]); } } dxx-rebirth-0.58.1-d2x/arch/sdl/key.c000066400000000000000000000426151217717237500172170ustar00rootroot00000000000000/* * * SDL keyboard input support * * */ #include #include #include #include "event.h" #include "dxxerror.h" #include "key.h" #include "timer.h" #include "window.h" #include "console.h" #include "args.h" static unsigned char Installed = 0; //-------- Variable accessed by outside functions --------- int keyd_repeat = 0; // 1 = use repeats, 0 no repeats volatile unsigned char keyd_last_pressed; volatile unsigned char keyd_last_released; volatile unsigned char keyd_pressed[256]; fix64 keyd_time_when_last_pressed; unsigned char unicode_frame_buffer[KEY_BUFFER_SIZE] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; typedef struct keyboard { ubyte state[256]; } keyboard; static keyboard key_data; const key_props key_properties[256] = { { "", 255, SDLK_UNKNOWN }, // 0 { "ESC", 255, SDLK_ESCAPE }, { "1", '1', SDLK_1 }, { "2", '2', SDLK_2 }, { "3", '3', SDLK_3 }, { "4", '4', SDLK_4 }, { "5", '5', SDLK_5 }, { "6", '6', SDLK_6 }, { "7", '7', SDLK_7 }, { "8", '8', SDLK_8 }, { "9", '9', SDLK_9 }, // 10 { "0", '0', SDLK_0 }, { "-", '-', SDLK_MINUS }, { "=", '=', SDLK_EQUALS }, { "BSPC", 255, SDLK_BACKSPACE }, { "TAB", 255, SDLK_TAB }, { "Q", 'q', SDLK_q }, { "W", 'w', SDLK_w }, { "E", 'e', SDLK_e }, { "R", 'r', SDLK_r }, { "T", 't', SDLK_t }, // 20 { "Y", 'y', SDLK_y }, { "U", 'u', SDLK_u }, { "I", 'i', SDLK_i }, { "O", 'o', SDLK_o }, { "P", 'p', SDLK_p }, { "[", '[', SDLK_LEFTBRACKET }, { "]", ']', SDLK_RIGHTBRACKET }, { "ENTER", 255, SDLK_RETURN }, { "LCTRL", 255, SDLK_LCTRL }, { "A", 'a', SDLK_a }, // 30 { "S", 's', SDLK_s }, { "D", 'd', SDLK_d }, { "F", 'f', SDLK_f }, { "G", 'g', SDLK_g }, { "H", 'h', SDLK_h }, { "J", 'j', SDLK_j }, { "K", 'k', SDLK_k }, { "L", 'l', SDLK_l }, { ";", ';', SDLK_SEMICOLON }, { "'", '\'', SDLK_QUOTE }, // 40 { "`", '`', SDLK_BACKQUOTE }, { "LSHFT", 255, SDLK_LSHIFT }, { "\\", '\\', SDLK_BACKSLASH }, { "Z", 'z', SDLK_z }, { "X", 'x', SDLK_x }, { "C", 'c', SDLK_c }, { "V", 'v', SDLK_v }, { "B", 'b', SDLK_b }, { "N", 'n', SDLK_n }, { "M", 'm', SDLK_m }, // 50 { ",", ',', SDLK_COMMA }, { ".", '.', SDLK_PERIOD }, { "/", '/', SDLK_SLASH }, { "RSHFT", 255, SDLK_RSHIFT }, { "PAD*", '*', SDLK_KP_MULTIPLY }, { "LALT", 255, SDLK_LALT }, { "SPC", ' ', SDLK_SPACE }, { "CPSLK", 255, SDLK_CAPSLOCK }, { "F1", 255, SDLK_F1 }, { "F2", 255, SDLK_F2 }, // 60 { "F3", 255, SDLK_F3 }, { "F4", 255, SDLK_F4 }, { "F5", 255, SDLK_F5 }, { "F6", 255, SDLK_F6 }, { "F7", 255, SDLK_F7 }, { "F8", 255, SDLK_F8 }, { "F9", 255, SDLK_F9 }, { "F10", 255, SDLK_F10 }, { "NMLCK", 255, SDLK_NUMLOCK }, { "SCLK", 255, SDLK_SCROLLOCK }, // 70 { "PAD7", 255, SDLK_KP7 }, { "PAD8", 255, SDLK_KP8 }, { "PAD9", 255, SDLK_KP9 }, { "PAD-", 255, SDLK_KP_MINUS }, { "PAD4", 255, SDLK_KP4 }, { "PAD5", 255, SDLK_KP5 }, { "PAD6", 255, SDLK_KP6 }, { "PAD+", 255, SDLK_KP_PLUS }, { "PAD1", 255, SDLK_KP1 }, { "PAD2", 255, SDLK_KP2 }, // 80 { "PAD3", 255, SDLK_KP3 }, { "PAD0", 255, SDLK_KP0 }, { "PAD.", 255, SDLK_KP_PERIOD }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "F11", 255, SDLK_F11 }, { "F12", 255, SDLK_F12 }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, // 90 { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "PAUSE", 255, SDLK_PAUSE }, { "W0", 255, SDLK_WORLD_0 }, { "W1", 255, SDLK_WORLD_1 }, { "W2", 255, SDLK_WORLD_2 }, // 100 { "W3", 255, SDLK_WORLD_3 }, { "W4", 255, SDLK_WORLD_4 }, { "W5", 255, SDLK_WORLD_5 }, { "W6", 255, SDLK_WORLD_6 }, { "W7", 255, SDLK_WORLD_7 }, { "W8", 255, SDLK_WORLD_8 }, { "W9", 255, SDLK_WORLD_9 }, { "W10", 255, SDLK_WORLD_10 }, { "W11", 255, SDLK_WORLD_11 }, { "W12", 255, SDLK_WORLD_12 }, // 110 { "W13", 255, SDLK_WORLD_13 }, { "W14", 255, SDLK_WORLD_14 }, { "W15", 255, SDLK_WORLD_15 }, { "W16", 255, SDLK_WORLD_16 }, { "W17", 255, SDLK_WORLD_17 }, { "W18", 255, SDLK_WORLD_18 }, { "W19", 255, SDLK_WORLD_19 }, { "W20", 255, SDLK_WORLD_20 }, { "W21", 255, SDLK_WORLD_21 }, { "W22", 255, SDLK_WORLD_22 }, // 120 { "W23", 255, SDLK_WORLD_23 }, { "W24", 255, SDLK_WORLD_24 }, { "W25", 255, SDLK_WORLD_25 }, { "W26", 255, SDLK_WORLD_26 }, { "W27", 255, SDLK_WORLD_27 }, { "W28", 255, SDLK_WORLD_28 }, { "W29", 255, SDLK_WORLD_29 }, { "W30", 255, SDLK_WORLD_30 }, { "W31", 255, SDLK_WORLD_31 }, { "W32", 255, SDLK_WORLD_32 }, // 130 { "W33", 255, SDLK_WORLD_33 }, { "W34", 255, SDLK_WORLD_34 }, { "W35", 255, SDLK_WORLD_35 }, { "W36", 255, SDLK_WORLD_36 }, { "W37", 255, SDLK_WORLD_37 }, { "W38", 255, SDLK_WORLD_38 }, { "W39", 255, SDLK_WORLD_39 }, { "W40", 255, SDLK_WORLD_40 }, { "W41", 255, SDLK_WORLD_41 }, { "W42", 255, SDLK_WORLD_42 }, // 140 { "W43", 255, SDLK_WORLD_43 }, { "W44", 255, SDLK_WORLD_44 }, { "W45", 255, SDLK_WORLD_45 }, { "W46", 255, SDLK_WORLD_46 }, { "W47", 255, SDLK_WORLD_47 }, { "W48", 255, SDLK_WORLD_48 }, { "W49", 255, SDLK_WORLD_49 }, { "W50", 255, SDLK_WORLD_50 }, { "W51", 255, SDLK_WORLD_51 }, { "", 255, SDLK_UNKNOWN }, // 150 { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "PAD", 255, SDLK_KP_ENTER }, { "RCTRL", 255, SDLK_RCTRL }, { "LCMD", 255, SDLK_LMETA }, { "RCMD", 255, SDLK_RMETA }, { "", 255, SDLK_UNKNOWN }, // 160 { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, // 170 { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, // 180 { "PAD/", 255, SDLK_KP_DIVIDE }, { "", 255, SDLK_UNKNOWN }, { "PRSCR", 255, SDLK_PRINT }, { "RALT", 255, SDLK_RALT }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, // 190 { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "", 255, SDLK_UNKNOWN }, { "HOME", 255, SDLK_HOME }, { "UP", 255, SDLK_UP }, // 200 { "PGUP", 255, SDLK_PAGEUP }, { "", 255, SDLK_UNKNOWN }, { "LEFT", 255, SDLK_LEFT }, { "", 255, SDLK_UNKNOWN }, { "RIGHT", 255, SDLK_RIGHT }, { "", 255, SDLK_UNKNOWN }, { "END", 255, SDLK_END }, { "DOWN", 255, SDLK_DOWN }, { "PGDN", 255, SDLK_PAGEDOWN }, { "INS", 255, SDLK_INSERT }, // 210 { "DEL", 255, SDLK_DELETE }, { "W52", 255, SDLK_WORLD_52 }, { "W53", 255, SDLK_WORLD_53 }, { "W54", 255, SDLK_WORLD_54 }, { "W55", 255, SDLK_WORLD_55 }, { "W56", 255, SDLK_WORLD_56 }, { "W57", 255, SDLK_WORLD_57 }, { "W58", 255, SDLK_WORLD_58 }, { "W59", 255, SDLK_WORLD_59 }, { "W60", 255, SDLK_WORLD_60 }, // 220 { "W61", 255, SDLK_WORLD_61 }, { "W62", 255, SDLK_WORLD_62 }, { "W63", 255, SDLK_WORLD_63 }, { "W64", 255, SDLK_WORLD_64 }, { "W65", 255, SDLK_WORLD_65 }, { "W66", 255, SDLK_WORLD_66 }, { "W67", 255, SDLK_WORLD_67 }, { "W68", 255, SDLK_WORLD_68 }, { "W69", 255, SDLK_WORLD_69 }, { "W70", 255, SDLK_WORLD_70 }, // 230 { "W71", 255, SDLK_WORLD_71 }, { "W72", 255, SDLK_WORLD_72 }, { "W73", 255, SDLK_WORLD_73 }, { "W74", 255, SDLK_WORLD_74 }, { "W75", 255, SDLK_WORLD_75 }, { "W76", 255, SDLK_WORLD_76 }, { "W77", 255, SDLK_WORLD_77 }, { "W78", 255, SDLK_WORLD_78 }, { "W79", 255, SDLK_WORLD_79 }, { "W80", 255, SDLK_WORLD_80 }, // 240 { "W81", 255, SDLK_WORLD_81 }, { "W82", 255, SDLK_WORLD_82 }, { "W83", 255, SDLK_WORLD_83 }, { "W84", 255, SDLK_WORLD_84 }, { "W85", 255, SDLK_WORLD_85 }, { "W86", 255, SDLK_WORLD_86 }, { "W87", 255, SDLK_WORLD_87 }, { "W88", 255, SDLK_WORLD_88 }, { "W89", 255, SDLK_WORLD_89 }, { "W90", 255, SDLK_WORLD_90 }, // 250 { "W91", 255, SDLK_WORLD_91 }, { "W92", 255, SDLK_WORLD_92 }, { "W93", 255, SDLK_WORLD_93 }, { "W94", 255, SDLK_WORLD_94 }, { "W95", 255, SDLK_WORLD_95 }, // 255 }; typedef struct d_event_keycommand { event_type type; // EVENT_KEY_COMMAND/RELEASE int keycode; } d_event_keycommand; int key_ismodlck(int keycode) { switch (keycode) { case KEY_LSHIFT: case KEY_RSHIFT: case KEY_LALT: case KEY_RALT: case KEY_LCTRL: case KEY_RCTRL: case KEY_LMETA: case KEY_RMETA: return KEY_ISMOD; case KEY_NUMLOCK: case KEY_SCROLLOCK: case KEY_CAPSLOCK: return KEY_ISLCK; default: return 0; } } unsigned char key_ascii() { static unsigned char unibuffer[KEY_BUFFER_SIZE] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; int i=0, offset=0, count=0; offset=strlen((const char*)unibuffer); // move temporal chars from unicode_frame_buffer to empty space behind last unibuffer char (if any) for (i=offset; i < KEY_BUFFER_SIZE; i++) if (unicode_frame_buffer[count] != '\0') { unibuffer[i]=unicode_frame_buffer[count]; unicode_frame_buffer[count]='\0'; count++; } // unibuffer is not empty. store first char, remove it, shift all chars one step left and then print our char if (unibuffer[0] != '\0') { unsigned char retval = unibuffer[0]; unsigned char unibuffer_shift[KEY_BUFFER_SIZE]; memset(unibuffer_shift,'\0',sizeof(unsigned char)*KEY_BUFFER_SIZE); memcpy(unibuffer_shift,unibuffer+1,sizeof(unsigned char)*(KEY_BUFFER_SIZE-1)); memcpy(unibuffer,unibuffer_shift,sizeof(unsigned char)*KEY_BUFFER_SIZE); return retval; } else return 255; } void key_handler(SDL_KeyboardEvent *kevent) { int keycode, event_keysym=-1, key_state; // Read SDLK symbol and state event_keysym = kevent->keysym.sym; if (event_keysym == SDLK_UNKNOWN) return; key_state = (kevent->state == SDL_PRESSED)?1:0; // fill the unicode frame-related unicode buffer if (key_state && kevent->keysym.unicode > 31 && kevent->keysym.unicode < 255) { int i = 0; for (i = 0; i < KEY_BUFFER_SIZE; i++) if (unicode_frame_buffer[i] == '\0') { unicode_frame_buffer[i] = kevent->keysym.unicode; break; } } //===================================================== for (keycode = 255; keycode > 0; keycode--) if (key_properties[keycode].sym == event_keysym) break; if (keycode == 0) return; /* * process the key if: * - it's a valid key AND * - if the keystate has changed OR * - key state same as last one and game accepts key repeats but keep out mod/lock keys */ if (key_state != keyd_pressed[keycode] || (keyd_repeat && !key_ismodlck(keycode))) { d_event_keycommand event; // now update the key props if (key_state) { keyd_last_pressed = keycode; keyd_pressed[keycode] = key_data.state[keycode] = 1; } else { keyd_pressed[keycode] = key_data.state[keycode] = 0; } if ( keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) keycode |= KEY_SHIFTED; if ( keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT]) keycode |= KEY_ALTED; if ( keyd_pressed[KEY_LCTRL] || keyd_pressed[KEY_RCTRL]) keycode |= KEY_CTRLED; if ( keyd_pressed[KEY_DELETE] ) keycode |= KEY_DEBUGGED; if ( keyd_pressed[KEY_LMETA] || keyd_pressed[KEY_RMETA]) keycode |= KEY_METAED; // We allowed the key to be added to the queue for now, // because there are still input loops without associated windows event.type = key_state?EVENT_KEY_COMMAND:EVENT_KEY_RELEASE; event.keycode = keycode; con_printf(CON_DEBUG, "Sending event %s: %s %s %s %s %s %s\n", (key_state) ? "EVENT_KEY_COMMAND": "EVENT_KEY_RELEASE", (keycode & KEY_METAED) ? "META" : "", (keycode & KEY_DEBUGGED) ? "DEBUG" : "", (keycode & KEY_CTRLED) ? "CTRL" : "", (keycode & KEY_ALTED) ? "ALT" : "", (keycode & KEY_SHIFTED) ? "SHIFT" : "", key_properties[keycode & 0xff].key_text ); event_send((d_event *)&event); } } void key_close() { Installed = 0; } void key_init() { if (Installed) return; Installed=1; SDL_EnableUNICODE(1); key_toggle_repeat(1); keyd_time_when_last_pressed = timer_query(); // Clear the keyboard array key_flush(); } void key_flush() { int i; Uint8 *keystate = SDL_GetKeyState(NULL); if (!Installed) key_init(); //Clear the unicode buffer for (i=0; itype == EVENT_KEY_COMMAND || event->type == EVENT_KEY_RELEASE); return ((d_event_keycommand *)event)->keycode; } // same as above but without mod states int event_key_get_raw(d_event *event) { int keycode = ((d_event_keycommand *)event)->keycode; Assert(event->type == EVENT_KEY_COMMAND || event->type == EVENT_KEY_RELEASE); if ( keycode & KEY_SHIFTED ) keycode &= ~KEY_SHIFTED; if ( keycode & KEY_ALTED ) keycode &= ~KEY_ALTED; if ( keycode & KEY_CTRLED ) keycode &= ~KEY_CTRLED; if ( keycode & KEY_DEBUGGED ) keycode &= ~KEY_DEBUGGED; if ( keycode & KEY_METAED ) keycode &= ~KEY_METAED; return keycode; } void key_toggle_repeat(int enable) { if (enable) { if (SDL_EnableKeyRepeat(KEY_REPEAT_DELAY, KEY_REPEAT_INTERVAL) == 0) keyd_repeat = 1; } else { SDL_EnableKeyRepeat(0, 0); keyd_repeat = 0; } key_flush(); } dxx-rebirth-0.58.1-d2x/arch/sdl/mouse.c000066400000000000000000000140421217717237500175500ustar00rootroot00000000000000/* * * SDL mouse driver * */ #include #include #include "fix.h" #include "timer.h" #include "event.h" #include "window.h" #include "mouse.h" #include "playsave.h" #include "args.h" static struct mouseinfo { ubyte button_state[MOUSE_MAX_BUTTONS]; fix64 time_lastpressed[MOUSE_MAX_BUTTONS]; int delta_x, delta_y, delta_z, old_delta_x, old_delta_y; int x,y,z; int cursor_enabled; fix64 cursor_time; } Mouse; typedef struct d_event_mousebutton { event_type type; int button; } d_event_mousebutton; typedef struct d_event_mouse_moved { event_type type; // EVENT_MOUSE_MOVED short dx, dy, dz; } d_event_mouse_moved; void mouse_init(void) { memset(&Mouse,0,sizeof(Mouse)); } void mouse_close(void) { SDL_ShowCursor(SDL_ENABLE); } void mouse_button_handler(SDL_MouseButtonEvent *mbe) { // to bad, SDL buttons use a different mapping as descent expects, // this is at least true and tested for the first three buttons int button_remap[17] = { MBTN_LEFT, MBTN_MIDDLE, MBTN_RIGHT, MBTN_Z_UP, MBTN_Z_DOWN, MBTN_PITCH_BACKWARD, MBTN_PITCH_FORWARD, MBTN_BANK_LEFT, MBTN_BANK_RIGHT, MBTN_HEAD_LEFT, MBTN_HEAD_RIGHT, MBTN_11, MBTN_12, MBTN_13, MBTN_14, MBTN_15, MBTN_16 }; int button = button_remap[mbe->button - 1]; // -1 since SDL seems to start counting at 1 d_event_mousebutton event; if (GameArg.CtlNoMouse) return; Mouse.cursor_time = timer_query(); if (mbe->state == SDL_PRESSED) { d_event_mouse_moved event2 = { EVENT_MOUSE_MOVED, 0, 0, 0 }; Mouse.button_state[button] = 1; if (button == MBTN_Z_UP) { Mouse.delta_z += Z_SENSITIVITY; Mouse.z += Z_SENSITIVITY; event2.dz = Z_SENSITIVITY; } else if (button == MBTN_Z_DOWN) { Mouse.delta_z -= Z_SENSITIVITY; Mouse.z -= Z_SENSITIVITY; event2.dz = -1*Z_SENSITIVITY; } if (event2.dz) { //con_printf(CON_DEBUG, "Sending event EVENT_MOUSE_MOVED, relative motion %d,%d,%d\n", // event2.dx, event2.dy, event2.dz); event_send((d_event *)&event2); } } else { Mouse.button_state[button] = 0; } event.type = (mbe->state == SDL_PRESSED) ? EVENT_MOUSE_BUTTON_DOWN : EVENT_MOUSE_BUTTON_UP; event.button = button; con_printf(CON_DEBUG, "Sending event %s, button %d, coords %d,%d,%d\n", (mbe->state == SDL_PRESSED) ? "EVENT_MOUSE_BUTTON_DOWN" : "EVENT_MOUSE_BUTTON_UP", event.button, Mouse.x, Mouse.y, Mouse.z); event_send((d_event *)&event); //Double-click support if (Mouse.button_state[button]) { if (timer_query() <= Mouse.time_lastpressed[button] + F1_0/5) { event.type = EVENT_MOUSE_DOUBLE_CLICKED; //event.button = button; // already set the button con_printf(CON_DEBUG, "Sending event EVENT_MOUSE_DOUBLE_CLICKED, button %d, coords %d,%d\n", event.button, Mouse.x, Mouse.y); event_send((d_event *)&event); } Mouse.time_lastpressed[button] = Mouse.cursor_time; } } void mouse_motion_handler(SDL_MouseMotionEvent *mme) { d_event_mouse_moved event; if (GameArg.CtlNoMouse) return; Mouse.cursor_time = timer_query(); Mouse.x += mme->xrel; Mouse.y += mme->yrel; event.type = EVENT_MOUSE_MOVED; event.dx = mme->xrel; event.dy = mme->yrel; event.dz = 0; // handled in mouse_button_handler Mouse.old_delta_x = event.dx; Mouse.old_delta_y = event.dy; //con_printf(CON_DEBUG, "Sending event EVENT_MOUSE_MOVED, relative motion %d,%d,%d\n", // event.dx, event.dy, event.dz); event_send((d_event *)&event); } void mouse_flush() // clears all mice events... { int i; // event_poll(); for (i=0; i= canv->cv_bitmap.bm_x) && (Mouse.x <= canv->cv_bitmap.bm_x + canv->cv_bitmap.bm_w) && (Mouse.y >= canv->cv_bitmap.bm_y) && (Mouse.y <= canv->cv_bitmap.bm_y + canv->cv_bitmap.bm_h); } void mouse_get_delta( int *dx, int *dy, int *dz ) { SDL_GetRelativeMouseState( &Mouse.delta_x, &Mouse.delta_y ); *dx = Mouse.delta_x; *dy = Mouse.delta_y; *dz = Mouse.delta_z; Mouse.old_delta_x = *dx; Mouse.old_delta_y = *dy; Mouse.delta_x = 0; Mouse.delta_y = 0; Mouse.delta_z = 0; } void event_mouse_get_delta(d_event *event, int *dx, int *dy, int *dz) { Assert(event->type == EVENT_MOUSE_MOVED); *dx = ((d_event_mouse_moved *)event)->dx; *dy = ((d_event_mouse_moved *)event)->dy; *dz = ((d_event_mouse_moved *)event)->dz; } int event_mouse_get_button(d_event *event) { Assert((event->type == EVENT_MOUSE_BUTTON_DOWN) || (event->type == EVENT_MOUSE_BUTTON_UP)); return ((d_event_mousebutton *)event)->button; } int mouse_get_btns() { int i; uint flag=1; int status = 0; // event_poll(); for (i=0; i= timer_query() && hidden_time + (F1_0/2) < timer_query() && !show) SDL_ShowCursor(SDL_ENABLE); else if ( (Mouse.cursor_time + (F1_0*2)) < timer_query() && show) { SDL_ShowCursor(SDL_DISABLE); hidden_time = timer_query(); } } else { if (show) SDL_ShowCursor(SDL_DISABLE); } } dxx-rebirth-0.58.1-d2x/arch/sdl/rbaudio.c000066400000000000000000000141011217717237500200410ustar00rootroot00000000000000/* * * SDL CD Audio functions * * */ #include #include #include #ifdef __linux__ #include #include #endif #include "pstypes.h" #include "dxxerror.h" #include "args.h" #include "rbaudio.h" #include "console.h" #include "timer.h" #define REDBOOK_VOLUME_SCALE 255 static SDL_CD *s_cd = NULL; static int initialised = 0; void RBAExit() { if (s_cd) { SDL_CDStop(s_cd); SDL_CDClose(s_cd); } } void RBAInit() { int num_cds; int i,j; if (initialised) return; if (SDL_Init(SDL_INIT_CDROM) < 0) { Warning("RBAudio: SDL library initialisation failed: %s.",SDL_GetError()); return; } num_cds = SDL_CDNumDrives(); if (num_cds < 1) { con_printf(CON_NORMAL, "RBAudio: No cdrom drives found!\n"); #if defined(__APPLE__) || defined(macintosh) SDL_QuitSubSystem(SDL_INIT_CDROM); // necessary for rescanning CDROMs #endif return; } for (i = 0; i < num_cds; i++) { if (s_cd) SDL_CDClose(s_cd); s_cd = SDL_CDOpen(i); if (s_cd && CD_INDRIVE(SDL_CDStatus(s_cd))) { for (j = 0; j < s_cd->numtracks; j++) { if (s_cd->track[j].type == SDL_AUDIO_TRACK) break; } if (j != s_cd->numtracks) break; // we've found an audio CD } else if (s_cd == NULL) Warning("RBAudio: Could not open cdrom %i for redbook audio:%s\n", i, SDL_GetError()); } if (i == num_cds) { con_printf(CON_NORMAL, "RBAudio: No audio CDs found\n"); if (s_cd) // if there's no audio CD, say that there's no redbook and hence play MIDI instead { SDL_CDClose(s_cd); s_cd = NULL; } #if defined(__APPLE__) || defined(macintosh) SDL_QuitSubSystem(SDL_INIT_CDROM); // necessary for rescanning CDROMs #endif return; } initialised = 1; RBAList(); } int RBAEnabled() { return initialised; } int RBAPlayTrack(int a) { if (!s_cd) return -1; if (CD_INDRIVE(SDL_CDStatus(s_cd)) ) { if (SDL_CDPlayTracks(s_cd, a-1, 0, 0, 0) == 0) { con_printf(CON_VERBOSE, "RBAudio: Playing track %i\n", a); return a; } } return -1; } void (*redbook_finished_hook)() = NULL; void RBAStop() { if (!s_cd) return; SDL_CDStop(s_cd); redbook_finished_hook = NULL; // no calling the finished hook - stopped means stopped here con_printf(CON_VERBOSE, "RBAudio: Playback stopped\n"); } void RBAEjectDisk() { if (!s_cd) return; SDL_CDEject(s_cd); // play nothing until it tries to load a song #if defined(__APPLE__) || defined(macintosh) SDL_QuitSubSystem(SDL_INIT_CDROM); // necessary for rescanning CDROMs #endif initialised = 0; } void RBASetVolume(int volume) { #ifdef __linux__ int cdfile, level; struct cdrom_volctrl volctrl; if (!s_cd) return; cdfile = s_cd->id; level = volume*REDBOOK_VOLUME_SCALE/8; if ((level<0) || (level>REDBOOK_VOLUME_SCALE)) { con_printf(CON_CRITICAL, "RBAudio: illegal volume value (allowed values 0-%i)\n",REDBOOK_VOLUME_SCALE); return; } volctrl.channel0 = volctrl.channel1 = volctrl.channel2 = volctrl.channel3 = level; if ( ioctl(cdfile, CDROMVOLCTRL, &volctrl) == -1 ) { con_printf(CON_CRITICAL, "RBAudio: CDROMVOLCTRL ioctl failed\n"); return; } #endif } void RBAPause() { if (!s_cd) return; SDL_CDPause(s_cd); con_printf(CON_VERBOSE, "RBAudio: Playback paused\n"); } int RBAResume() { if (!s_cd) return -1; SDL_CDResume(s_cd); con_printf(CON_VERBOSE, "RBAudio: Playback resumed\n"); return 1; } int RBAPauseResume() { if (!s_cd) return 0; if (SDL_CDStatus(s_cd) == CD_PLAYING) { SDL_CDPause(s_cd); con_printf(CON_VERBOSE, "RBAudio: Toggle Playback pause\n"); } else if (SDL_CDStatus(s_cd) == CD_PAUSED) { SDL_CDResume(s_cd); con_printf(CON_VERBOSE, "RBAudio: Toggle Playback resume\n"); } else return 0; return 1; } int RBAGetNumberOfTracks() { if (!s_cd) return -1; SDL_CDStatus(s_cd); con_printf(CON_VERBOSE, "RBAudio: Found %i tracks on CD\n", s_cd->numtracks); return s_cd->numtracks; } // check if we need to call the 'finished' hook // needs to go in all event loops // a real hook would be ideal, but is currently unsupported by SDL Audio CD void RBACheckFinishedHook() { static fix64 last_check_time = 0; if (!s_cd) return; if ((timer_query() - last_check_time) >= F2_0) { if ((SDL_CDStatus(s_cd) == CD_STOPPED) && redbook_finished_hook) { con_printf(CON_VERBOSE, "RBAudio: Playback done, calling finished-hook\n"); redbook_finished_hook(); } last_check_time = timer_query(); } } // plays tracks first through last, inclusive int RBAPlayTracks(int first, int last, void (*hook_finished)(void)) { if (!s_cd) return 0; if (CD_INDRIVE(SDL_CDStatus(s_cd))) { redbook_finished_hook = hook_finished; con_printf(CON_VERBOSE, "RBAudio: Playing tracks %i to %i\n", first, last); return SDL_CDPlayTracks(s_cd, first - 1, 0, last - first + 1, 0) == 0; } return 0; } // return the track number currently playing. Useful if RBAPlayTracks() // is called. Returns 0 if no track playing, else track number int RBAGetTrackNum() { if (!s_cd) return 0; if (SDL_CDStatus(s_cd) != CD_PLAYING) return 0; return s_cd->cur_track + 1; } int RBAPeekPlayStatus() { if (!s_cd) return 0; if (SDL_CDStatus(s_cd) == CD_PLAYING) return 1; else if (SDL_CDStatus(s_cd) == CD_PAUSED) // hack so it doesn't keep restarting paused music return -1; return 0; } static int cddb_sum(int n) { int ret; /* For backward compatibility this algorithm must not change */ ret = 0; while (n > 0) { ret = ret + (n % 10); n = n / 10; } return (ret); } unsigned long RBAGetDiscID() { int i, t = 0, n = 0; if (!s_cd) return 0; /* For backward compatibility this algorithm must not change */ i = 0; while (i < s_cd->numtracks) { n += cddb_sum(s_cd->track[i].offset / CD_FPS); i++; } t = (s_cd->track[s_cd->numtracks].offset / CD_FPS) - (s_cd->track[0].offset / CD_FPS); return ((n % 0xff) << 24 | t << 8 | s_cd->numtracks); } void RBAList(void) { int i; if (!s_cd) return; for (i = 0; i < s_cd->numtracks; i++) con_printf(CON_VERBOSE, "RBAudio: CD track %d, type %s, length %d, offset %d", s_cd->track[i].id, (s_cd->track[i].type == SDL_AUDIO_TRACK) ? "audio" : "data", s_cd->track[i].length, s_cd->track[i].offset); } dxx-rebirth-0.58.1-d2x/arch/sdl/timer.c000066400000000000000000000021711217717237500175400ustar00rootroot00000000000000/* * * SDL library timer functions * */ #include #include "maths.h" #include "timer.h" #include "config.h" static fix64 F64_RunTime = 0; void timer_update(void) { static ubyte init = 1; static fix64 last_tv = 0; fix64 cur_tv = SDL_GetTicks()*F1_0/1000; if (init) { last_tv = cur_tv; init = 0; } if (last_tv < cur_tv) // in case SDL_GetTicks wraps, don't update and have a little hickup F64_RunTime += (cur_tv - last_tv); // increment! this value will overflow long after we are all dead... so why bother checking? last_tv = cur_tv; } fix64 timer_query(void) { return (F64_RunTime); } void timer_delay(fix seconds) { SDL_Delay(f2i(fixmul(seconds, i2f(1000)))); } // Replacement for timer_delay which considers calc time the program needs between frames (not reentrant) void timer_delay2(int fps) { static u_int32_t FrameStart=0; u_int32_t FrameLoop=0; while (FrameLoop < 1000u/(GameCfg.VSync?MAXIMUM_FPS:fps)) { u_int32_t tv_now = SDL_GetTicks(); if (FrameStart > tv_now) FrameStart = tv_now; if (!GameCfg.VSync) SDL_Delay(1); FrameLoop=tv_now-FrameStart; } FrameStart=SDL_GetTicks(); } dxx-rebirth-0.58.1-d2x/arch/sdl/window.c000066400000000000000000000116001217717237500177240ustar00rootroot00000000000000/* * A 'window' is simply a canvas that can receive events. * It can be anything from a simple message box to the * game screen when playing. * * See event.c for event handling code. * * -kreator 2009-05-06 */ #include "gr.h" #include "window.h" #include "u_mem.h" #include "dxxerror.h" struct window { grs_canvas w_canv; // the window's canvas to draw to int (*w_callback)(window *wind, d_event *event, void *data); // the event handler int w_visible; // whether it's visible int w_modal; // modal = accept all user input exclusively void *data; // whatever the user wants (eg menu data for 'newmenu' menus) struct window *prev; // the previous window in the doubly linked list struct window *next; // the next window in the doubly linked list }; static window *FrontWindow = NULL; static window *FirstWindow = NULL; window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_callback)(window *wind, d_event *event, void *data), void *data) { window *wind; window *prev = window_get_front(); d_event event; MALLOC(wind, window, 1); if (wind == NULL) return NULL; Assert(src != NULL); Assert(event_callback != NULL); gr_init_sub_canvas(&wind->w_canv, src, x, y, w, h); wind->w_callback = event_callback; wind->w_visible = 1; // default to visible wind->w_modal = 1; // default to modal wind->data = data; if (FirstWindow == NULL) FirstWindow = wind; wind->prev = FrontWindow; if (FrontWindow) FrontWindow->next = wind; wind->next = NULL; FrontWindow = wind; if (prev) WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED); WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); return wind; } int window_close(window *wind) { window *prev; d_event event; int (*w_callback)(window *wind, d_event *event, void *data) = wind->w_callback; if (wind == window_get_front()) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); // Deactivate first event.type = EVENT_WINDOW_CLOSE; con_printf(CON_DEBUG, "Sending event EVENT_WINDOW_CLOSE to window of dimensions %dx%d\n", (wind)->w_canv.cv_bitmap.bm_w, (wind)->w_canv.cv_bitmap.bm_h); if (window_send_event(wind, &event)) { // User 'handled' the event, cancelling close if (wind == window_get_front()) { WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); } return 0; } if (wind == FrontWindow) FrontWindow = wind->prev; if (wind == FirstWindow) FirstWindow = wind->next; if (wind->next) wind->next->prev = wind->prev; if (wind->prev) wind->prev->next = wind->next; if ((prev = window_get_front())) WINDOW_SEND_EVENT(prev, EVENT_WINDOW_ACTIVATED); d_free(wind); event.type = EVENT_WINDOW_CLOSED; w_callback(wind, &event, NULL); // callback needs to recognise this is a NULL pointer! return 1; } int window_exists(window *wind) { window *w; for (w = FirstWindow; w && w != wind; w = w->next) {} return w && w == wind; } // Get the top window that's visible window *window_get_front(void) { window *wind; for (wind = FrontWindow; (wind != NULL) && !wind->w_visible; wind = wind->prev) {} return wind; } window *window_get_first(void) { return FirstWindow; } window *window_get_next(window *wind) { return wind->next; } window *window_get_prev(window *wind) { return wind->prev; } // Make wind the front window void window_select(window *wind) { window *prev = window_get_front(); d_event event; Assert (wind != NULL); if (wind == FrontWindow) return; if ((wind == FirstWindow) && FirstWindow->next) FirstWindow = FirstWindow->next; if (wind->next) wind->next->prev = wind->prev; if (wind->prev) wind->prev->next = wind->next; wind->prev = FrontWindow; FrontWindow->next = wind; wind->next = NULL; FrontWindow = wind; if (window_is_visible(wind)) { if (prev) WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED); WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); } } void window_set_visible(window *wind, int visible) { window *prev = window_get_front(); d_event event; wind->w_visible = visible; wind = window_get_front(); // get the new front window if (wind == prev) return; if (prev) WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED); if (wind) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); } int window_is_visible(window *wind) { return wind->w_visible; } grs_canvas *window_get_canvas(window *wind) { return &wind->w_canv; } extern void window_update_canvases(void) { window *wind; for (wind = FirstWindow; wind != NULL; wind = wind->next) gr_init_sub_bitmap (&wind->w_canv.cv_bitmap, wind->w_canv.cv_bitmap.bm_parent, wind->w_canv.cv_bitmap.bm_x, wind->w_canv.cv_bitmap.bm_y, wind->w_canv.cv_bitmap.bm_w, wind->w_canv.cv_bitmap.bm_h); } int window_send_event(window *wind, d_event *event) { return wind->w_callback(wind, event, wind->data); } void window_set_modal(window *wind, int modal) { wind->w_modal = modal; } int window_is_modal(window *wind) { return wind->w_modal; } dxx-rebirth-0.58.1-d2x/arch/win32/000077500000000000000000000000001217717237500164335ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/win32/d2x-rebirth.ico000066400000000000000000001642761217717237500213010ustar00rootroot00000000000000xx ¨è(xð á  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿN?@ÿƒ||ÿ~~ÿƒƒƒÿ}xyÿwjlÿwjlÿ|uuÿÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿƒƒƒÿ‚€€ÿyopÿq]_ÿ~{{ÿ|uvÿ||ÿ„††ÿ~yyÿ}}ÿƒƒƒÿ{rsÿ}stÿA??ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿšw{ÿúßãÿúñòÿúúúÿùùùÿùõöÿùêëÿùùùÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿúúúÿøðñÿéÅÈÿèÈËÿúùùÿù÷øÿúïðÿúö÷ÿúùùÿúúúÿúúúÿùøøÿöòôÿ…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰]aÿíËÏÿöèéÿ÷ìíÿùòòÿÿþþÿýùùÿÿýýÿþýýÿÿÿÿÿÿÿÿÿþüýÿýùúÿÿÿþÿþùúÿÿÿÿÿúôõÿýùùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿüö÷ÿöììÿ÷íïÿùïñÿöêëÿúòòÿÿüüÿÿÿÿÿÿÿÿÿü÷÷ÿþúûÿúøøÿ€}~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŠaeÿðÑÔÿîÚÜÿñãåÿôêëÿþûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿþýþÿúóôÿõéëÿþüüÿû÷÷ÿîÛÝÿüøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýüüÿöìíÿòãåÿïÝßÿîÚÞÿîÝÞÿðàâÿôçéÿíÚÜÿòßáÿîÒÕÿyqsÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚UYÿæ½ÁÿñÞáÿýûûÿôêëÿôêëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüÿñâäÿðÝßÿýúúÿõëëÿݺ½ÿùòóÿýûûÿýúúÿÿÿÿÿþüýÿüùùÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýúúÿþýýÿüùùÿùññÿùóôÿôèêÿíÙÛÿãÅÈÿÕª¯ÿÞ¼ÀÿâÄÇÿܺ¾ÿæÊÌÿïÑÕÿwkmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ†Z^ÿ㺾ÿíרÿ÷îïÿþýýÿúôôÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿõêëÿâÅÈÿàÀÃÿóåçÿäÇÊÿáÂÅÿûõõÿñáãÿîÜÝÿûøøÿøðñÿöììÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿøñòÿþþþÿýùùÿ÷îðÿôçéÿÿÿþÿòåæÿàÁÂÿÚ²¶ÿäÆÉÿæÊÍÿäÇËÿåÇÊÿöâãÿz{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿvBGÿÙ§¬ÿâÃÆÿåÊÍÿùòóÿþýýÿÿþþÿøòóÿÿýýÿýüüÿúõõÿüøùÿùòóÿîÝßÿåÉÍÿæÌÎÿܺ¾ÿß¾ÂÿöìíÿòáãÿðÞßÿòææÿúö÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýúúÿþýýÿýýýÿþýýÿûõöÿòåæÿöëíÿÿÿÿÿùñòÿæÉÌÿد³ÿÙ²¶ÿß¾ÁÿñâãÿìÕ×ÿöãæÿ~€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿm6<ÿË‘—ÿÙ²¶ÿæÌÏÿóåçÿðÞàÿúööÿ÷ðñÿÿÿÿÿþýýÿïàâÿôçéÿÿÿÿÿýùúÿòáãÿáÀÄÿزµÿáÃÆÿïÞßÿôæèÿûôõÿûùøÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüùùÿþüüÿÿÿÿÿýúúÿöëíÿíÙÚÿëÖØÿþýþÿþýþÿìÖÙÿܺ½ÿذµÿ׬²ÿïÝßÿìÔÖÿíÍÑÿtegÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿl39ÿ¹t|ÿÙ²¶ÿëÔ×ÿøðñÿñâäÿõëìÿÿÿÿÿüúûÿÿÿÿÿøòóÿÕ°µÿÞÀÃÿêÓÕÿáÂÄÿܸ¼ÿåÊÎÿüùúÿóçèÿóæçÿÿýþÿýùùÿùóôÿþûûÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿýúûÿýúúÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿöîîÿݸ¼ÿÚ²¶ÿòãäÿùóóÿóççÿêÓÖÿîÚÝÿذ´ÿТ¨ÿÓ¥©ÿ⻾ÿugiÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{LQÿÍ”›ÿÞ½ÂÿíÚÝÿòçêÿûøúÿöîðÿýûüÿöìîÿûö÷ÿùõôÿË ¥ÿÌ¢ÿà¿ÂÿزµÿáÁÄÿíÛÝÿùôôÿüùùÿüùùÿÿÿÿÿûööÿùññÿûøøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûööÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøòòÿèÔÖÿôèëÿüõöÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüùùÿîÜÞÿãÅÈÿíØÛÿû÷÷ÿþüûÿöëîÿì×ÚÿæÌÎÿÓ¨­ÿÉ•šÿßµ¸ÿtffÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿƒMLÿØŸžÿÙ­ªÿëÌÈÿøëåÿûñëÿøîëÿþüúÿýúùÿ÷ïïÿ÷îïÿ÷ñòÿçÐÔÿàÁÅÿ×°´ÿß¾ÂÿëÕ×ÿóæèÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿýýÿûö÷ÿòäæÿùõõÿÿÿþÿùóóÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûøøÿóéêÿúö÷ÿþýýÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿùòóÿùôôÿ÷ïñÿ÷íïÿÿÿÿÿöíîÿåËÍÿÓ©­ÿܹ½ÿæËÎÿëÖØÿïÒÕÿp]^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿ%ÿ*ÿ/ÿ5ÿ4ÿ5ÿ“?0ÿÓdÿЀfÿÔŠqÿåªÿ캠ÿõδÿòλÿõ×ÇÿüëÝÿöãÛÿöçãÿõææÿòäæÿíÛÝÿéÒÖÿôçëÿöíîÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿ÷ïñÿòäæÿâÄÆÿñäåÿÿÿÿÿüùùÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýúúÿúö÷ÿüùúÿýûüÿþüýÿÿÿÿÿÿÿÿÿüùùÿéÓÕÿÝ»¾ÿÜ·»ÿТ§ÿâÄÇÿüõöÿúôõÿ}uuÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$ÿ1ÿ=ÿHÿVÿaÿk ÿt ÿ{ ÿ ÿ‚ ÿ¹7ÿÝ]'ÿÛ^'ÿÔW&ÿ×^-ÿàp?ÿç‚Sÿá{RÿåŽeÿõ´‹ÿó¼˜ÿæ­•ÿîñÿúåÖÿüïçÿøîêÿüööÿýûüÿüøùÿüøùÿþýýÿüúúÿýùùÿüùùÿû÷÷ÿúôõÿüúûÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýúûÿüøøÿýüýÿÿÿÿÿÿþþÿþýýÿþýþÿÿÿÿÿÿÿÿÿðÞáÿçÍÐÿïÜÞÿêÓÕÿôêìÿûö÷ÿïßáÿóæçÿüøúÿúúûÿƒ‚‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+ÿ:ÿKÿ^ÿq ÿ‚ ÿ“ÿ¡ÿ¨ÿ®"ÿ°$ÿ±'ÿ²*ÿ­'ÿ²-ÿ¶0ÿµ/ÿ¼7ÿÈD ÿÖHÿáfÿâjÿÛUÿÜY!ÿâm8ÿæ€Jÿâ‡Yÿâ”oÿíµ–ÿúØÀÿ÷ÝÎÿúëãÿ÷èäÿöììÿýúúÿôçéÿ÷ïðÿÿÿÿÿÿÿÿÿþüûÿðàâÿûö÷ÿÿÿÿÿýüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüúûÿÿÿÿÿïáãÿذµÿîÛÞÿÿÿÿÿúôõÿûøùÿþþþÿøððÿïßàÿÖ­±ÿÍ¢ÿܸ¼ÿãÄÇÿõìíÿÿÿÿÿþüýÿûøøÿÿþþÿúúúÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ'ÿ8ÿMÿfÿ€ÿ–ÿ¦ÿ±"ÿÄ? ÿØ\ÿ¼3 ÿ­/ ÿ¸> ÿ¶< ÿ­0 ÿ«1 ÿ©/ ÿ¥, ÿ¤- ÿ±4 ÿ¸D ÿÊn2ÿã˜5ÿùÜ7ÿùà;ÿò¼;ÿî3ÿàHÿÓ? ÿÓGÿÙTÿår:ÿî–`ÿð«€ÿóÀ¡ÿöÔ¿ÿúçÚÿþ÷òÿýúøÿýüüÿýüüÿþüýÿÿÿÿÿýúúÿþþþÿÿÿÿÿýûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûûÿÛ¹¼ÿÛ¸»ÿêÓÕÿíÚÜÿË›žÿÞ¾ÁÿþüýÿøïñÿãÅÈÿêÖ×ÿúòòÿܺ½ÿϦªÿ÷ððÿÿþþÿüùùÿ÷îïÿÿÿÿÿúúúÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ,ÿBÿ[ÿyÿ—ÿ©ÿ®$ÿ®*ÿ¦*ÿ¯1 ÿÐ_ÿå‚ÿÀ@ ÿ´8 ÿ»> ÿ®2 ÿ¨/ ÿ«1 ÿ³7 ÿ®2 ÿ²9 ÿ¿G ÿÎgÿÞ UÿíËŠÿýûeÿûôWÿÿÿ·ÿÿÚyÿâ_ÿ·2 ÿ§(ÿ«)ÿ¿4ÿÖJÿâ_$ÿåx@ÿì˜hÿó»–ÿùÖ¾ÿýéÜÿþöïÿþýúÿÿÿÿÿÿÿÿÿû÷÷ÿúôõÿþþþÿÿÿÿÿÿÿÿÿþüüÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëÕØÿí×Ùÿýúúÿñàâÿ×®²ÿáÃÆÿûùùÿýüüÿõìíÿûööÿÿþþÿçÕ×ÿÉ ¤ÿãÈËÿäÉÌÿöîîÿÿÿÿÿýúúÿùôôÿƒ‚‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ,ÿFÿeÿ…ÿ¨ÿÓXÿàiÿ³1ÿœ&ÿ›' ÿŸ* ÿº: ÿètÿö…ÿàhÿç†ÿÞfÿ¶6 ÿ§/ ÿ®3 ÿ±6 ÿ¿Cÿ¼? ÿµ6 ÿÙYÿýÑ"ÿþü\ÿÿüiÿÿÿÿÿþ¶ÿûÅ;ÿÞZÿ¼=ÿ¨- ÿœ' ÿ )ÿ°2ÿµ.ÿÅ9 ÿÝVÿëx:ÿñšeÿõ»“ÿø×½ÿüëÝÿýöñÿþüûÿýüüÿÿþþÿÿÿÿÿÿÿÿÿþýýÿçÒÔÿçÔ×ÿÿÿÿÿÿÿÿÿþýþÿúóóÿüøøÿþüýÿïÞßÿéÓÖÿüö÷ÿûõõÿýûúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùôõÿùóóÿÿÿþÿõëìÿÓ«¯ÿéÓÖÿþüüÿøìíÿøîïÿ€~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ'ÿBÿgÿŒÿ©ÿ½,ÿëgÿÿïÿå‡ÿ°)ÿ£, ÿ¥/ ÿ¤, ÿª. ÿÙfÿþÕ'ÿÿé>ÿÿöyÿü®0ÿÔDÿ´5 ÿ¬3 ÿ®6 ÿËPÿÞ]ÿ×T ÿãe ÿýËMÿÿÿzÿÿô)ÿÿÿˆÿÿüwÿþ» ÿìrÿÉQÿ­1 ÿ¨. ÿ®3 ÿ®8 ÿŸ, ÿœ#ÿ³/ÿÅ8ÿØMÿér6ÿò›fÿöÀ™ÿùÜÆÿýîäÿüöóÿýüûÿýûûÿþýþÿþýýÿèØÙÿßÈÊÿýúûÿùòóÿôèéÿñáãÿúòóÿþþýÿýúúÿüúúÿÿÿþÿýüýÿÿÿÿÿÿÿÿÿþýýÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿÿõìíÿõêêÿûøøÿøððÿðÝàÿúúúÿ„„…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿ]ÿ†ÿ¦ÿ®%ÿ®'ÿÚq%ÿÿÿÉÿý×ÿÑJÿ©* ÿ´Cÿ¸Dÿ©1 ÿ©2 ÿ½= ÿàvÿù¹0ÿÿüÃÿþèžÿóŠ ÿØT ÿ¶3 ÿ¶5 ÿÔOÿ÷”ÿü·>ÿÿâxÿÿÿ²ÿÿúcÿÿñ@ÿÿòyÿÿû’ÿûÏHÿÕOÿ·7 ÿ±6 ÿ¨0 ÿ¨0 ÿ®: ÿ¬6 ÿ¤, ÿ¦. ÿŸ(ÿ¢#ÿ¼0ÿÙOÿëz=ÿó¦tÿ÷ʪÿüç×ÿúïéÿ÷íìÿþüýÿýýýÿÿÿÿÿÿÿÿÿóçéÿåÊÍÿéÔ×ÿúõöÿþýüÿýúùÿÿÿÿÿûøøÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿÿþüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûûÿÿþþÿüûúÿúööÿðßáÿúóôÿ„……ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)ÿJÿv ÿŸÿ¯$ÿ§)ÿœ' ÿ¬+ÿç‡%ÿÿþ­ÿÿóŸÿï ÿ¾7ÿ­7ÿ°: ÿ¬4 ÿ­4 ÿ¯6 ÿ»1 ÿÜQ ÿÿÖIÿÿÿËÿÿýžÿù³RÿÛ\ ÿÝaÿó?ÿÿí†ÿÿþ›ÿÿì¥ÿýËZÿö¤ÿê~ÿíÿÿßXÿòÀ^ÿÄ=ÿ´8 ÿ­3 ÿ¤. ÿ¡, ÿ¡* ÿ¥- ÿ¦. ÿª0 ÿ¦/ ÿ™' ÿ–"ÿ£"ÿÃ4ÿá[ÿð‹Qÿö·ÿù×ÀÿüîãÿÿûøÿýúùÿûùùÿûõöÿøïñÿùòóÿÿÿÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÛ¼¿ÿñäæÿÿÿÿÿÿþþÿÿýýÿýûüÿÿÿÿÿüùúÿýûûÿÿÿÿÿþüüÿóèéÿôêêÿøññÿü÷÷ÿõêëÿúôõÿƒ„„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ5ÿ]ÿŽÿ¬!ÿ¬(ÿ ) ÿœ( ÿ¥- ÿ¹; ÿãk ÿü³!ÿÿô‰ÿÿÜvÿÔVÿ¬*ÿ§/ ÿ¨2 ÿ¬4 ÿ®7 ÿ¶<ÿËKÿòÿÿçUÿÿÿÎÿÿÿÅÿÿåaÿÿæxÿÿÿÏÿÿÿ²ÿÿ¬8ÿù‚ÿïh ÿÜNÿÖD ÿâeÿÿärÿñ­CÿÄ;ÿ´;ÿ©3 ÿ¦0 ÿ¥/ ÿ£. ÿ¢- ÿ¢, ÿ¡* ÿ£- ÿ¢+ ÿž( ÿ—% ÿ›"ÿ²(ÿÒC ÿêr4ÿó¤rÿøÎ¯ÿûéÛÿýøóÿþüûÿùòóÿþüüÿÿÿÿÿÿÿÿÿüøùÿùóóÿöìíÿðãåÿÞÄÆÿëÙÛÿþýýÿþüüÿþþþÿüùøÿùððÿøïðÿùóóÿÿÿÿÿøïðÿܹ¼ÿÕ¬±ÿéÑÔÿìÖØÿþýýÿûýýÿ„„„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ!ÿ?ÿo ÿ¢ÿ²&ÿ§+ÿŸ* ÿ¡+ ÿ£+ ÿ§/ ÿ¸= ÿÛTÿñkÿÿÖLÿÿôÿê~'ÿÈF ÿ´>ÿ²9ÿ´;ÿ´;ÿ¸AÿÃHÿÎJÿê€ÿûº3ÿö¿Tÿ÷ËZÿÿßtÿÿÖnÿý·-ÿøyÿòkÿçfÿãaÿõÿûÈFÿÿÿ«ÿ÷°@ÿÖJÿ»@ÿ®7ÿ­5 ÿ©2 ÿ¨1 ÿ§1 ÿ¦0 ÿ¨1 ÿ¤. ÿ£- ÿ¡* ÿ¡* ÿŸ) ÿš%ÿŸ!ÿÀ2ÿå_!ÿñ•]ÿô½šÿøÞÎÿþõðÿôéèÿýûûÿ÷îïÿêÔÖÿóèéÿøðñÿïÞßÿÏ£¨ÿöîïÿüúúÿÿÿÿÿÿÿÿÿÿÿÿÿûööÿôçèÿýûûÿúôöÿýúûÿõêëÿçÍÑÿÖ¬²ÿТ¨ÿݺ¾ÿõéêÿõèêÿ{uvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&ÿJÿ ÿ¬ÿ°)ÿ¡) ÿž) ÿ¤, ÿ¦. ÿ¤, ÿ«2 ÿ·; ÿÒPÿésÿÿØmÿÿü¢ÿ÷•(ÿâaÿ¿Fÿ²;ÿ³<ÿ±:ÿ³<ÿ¶>ÿºAÿÌKÿÕN ÿÌJÿÏO ÿâhÿén ÿåeÿàaÿíoÿ÷’!ÿúÂ7ÿÿÇ+ÿÿçMÿÿÿ·ÿö¤-ÿÐ@ÿ¸>ÿ°9ÿ¯6ÿ¬5 ÿ¬5 ÿ¯7 ÿ°6 ÿ­5 ÿ§0 ÿ¥. ÿ¤. ÿ¢+ ÿ¡* ÿ¦- ÿ¡+ ÿž$ÿµ+ÿÙOÿîƒHÿòµÿúÝÉÿ÷çáÿÿýûÿ÷ïñÿìØÛÿúòôÿùñòÿùóóÿÞ¿ÂÿñâäÿÿÿÿÿÿÿÿÿöîïÿýûûÿþüüÿùõõÿþüýÿÿýþÿûôõÿöêìÿùòóÿæÍÐÿÌœ¢ÿß¾Âÿà¿ÂÿïÑÔÿxlmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*ÿQÿŒÿ°!ÿ¨(ÿž) ÿ( ÿ ) ÿ¥. ÿ«3 ÿ¯6 ÿ°7 ÿµ; ÿÃGÿÚZÿñ‘-ÿÿíqÿú·CÿÝY ÿ½Aÿ±:ÿ³<ÿ³<ÿ±;ÿ²:ÿµ>ÿ¹Bÿ¶<ÿ¶=ÿº>ÿÂAÿËJÿÌOÿÌOÿÖUÿû“"ÿÿÿQÿÿúKÿÿñqÿÿÿàÿûÐoÿÜbÿ¼?ÿ²<ÿ¯8ÿ¯7ÿ­6ÿ°8ÿ²:ÿª3 ÿ¨1 ÿ¬3 ÿ­5 ÿ§0 ÿ¢- ÿ¦- ÿ¨.ÿž* ÿ™#ÿ¨&ÿÑCÿí|>ÿó²†ÿùØÂÿôãÜÿÿÿÿÿÿÿÿÿøïðÿöëíÿøññÿùõôÿþüýÿýøùÿåÍÐÿÊšžÿùóòÿÿÿÿÿôéëÿèÐÒÿóçéÿòäæÿäÇÊÿçÏÑÿäÉÊÿãÄÈÿâÅÇÿÑ¡¦ÿÒŸ¤ÿnZ\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ-ÿVÿ‘ÿ¹*ÿ®/ ÿž( ÿž( ÿ¤, ÿ¥. ÿ£. ÿ³>ÿ´>ÿ«4 ÿ¸>ÿ¹?ÿÆCÿêb ÿÿØPÿüÙZÿÖUÿ¹4 ÿ²:ÿ´>ÿ·@ÿ¶@ÿ·?ÿ·@ÿ¶?ÿ·Aÿ¼CÿºCÿ»Dÿ¿FÿÀGÿÁGÿÁGÿßaÿÿÆ0ÿÿÿ_ÿÿÿÊÿÿÿÿÿÿýÙÿø¹JÿÐKÿµ;ÿ²;ÿ±:ÿ¯8ÿ±9ÿ±:ÿ«5 ÿ«3 ÿ¬4 ÿ­4 ÿª2 ÿ¤- ÿ«6 ÿ³Aÿª4 ÿ( ÿ˜%ÿ¡#ÿË= ÿìw7ÿð§{ÿè¹¥ÿïÛÓÿòåçÿòäæÿçÏÐÿîÜÝÿöêëÿìØÚÿñáãÿÚ·ºÿÍ¡¦ÿõéëÿíÚÜÿîÝÞÿʘžÿس·ÿçÍÏÿãÆÈÿÞ½ÀÿÒ¥©ÿåÇÊÿÛ·»ÿÒ¦«ÿÓ¡¦ÿfMOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ-ÿWÿ’ÿ®$ÿ­4 ÿ´= ÿ©1 ÿ§0 ÿ¨1 ÿ¥/ ÿ¤/ ÿ©3 ÿ­6 ÿ¶>ÿº@ÿ¸<ÿÄIÿç^ÿü³Rÿÿý¬ÿö¨<ÿår ÿÕXÿÁBÿ¼Eÿ¿Gÿ¾Fÿ½Fÿ¼Dÿ½Fÿ»CÿÁHÿÆMÿ½Fÿ½Fÿ¿GÿÁIÿÆIÿåpÿÿéZÿÿÿÞÿÿþËÿÿÿƒÿÿèvÿákÿ»9 ÿ·Aÿ´?ÿ³<ÿ±:ÿ°:ÿ¯8ÿ¬5ÿ¬6 ÿ¸@ÿ±:ÿ¤, ÿ°?ÿ¾Sÿ»Iÿ©0 ÿ¢* ÿª3 ÿ¯2ÿÊ:ÿÛ^'ÿÞhÿîÄ®ÿد«ÿßÀÂÿêÖØÿÚ¸¼ÿݺ½ÿñàáÿì×ÚÿõéêÿôèéÿéÑÔÿТ¨ÿÕ¬°ÿÒ¥ªÿß¼¿ÿÙ±µÿÙ³¶ÿë×ÙÿöìíÿòåçÿæÌÏÿîÝÞÿòÜàÿnY\ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*ÿUÿ’ÿ°$ÿ£) ÿ¦. ÿ­3 ÿª2 ÿ³> ÿ¯7 ÿ¦/ ÿ§1 ÿ¨2 ÿ®7ÿºAÿ¼DÿÆRÿÍUÿÐJÿélÿþÜÿÿú®ÿÿô`ÿü½0ÿë„ÿÕRÿÍKÿÉJÿÈIÿÁGÿ¿Gÿ½EÿÃIÿÄKÿÀHÿÀHÿÄJÿÐVÿÇLÿËMÿö*ÿÿìRÿü¿6ÿú­0ÿÿù¢ÿó½fÿÏNÿÀCÿÂJÿÀGÿºAÿ³=ÿ°:ÿ¯8ÿ¯8ÿµ=ÿ¸>ÿ±8ÿ©2 ÿ¬6 ÿ³: ÿ«3 ÿ¥- ÿ©0 ÿ¯8 ÿ¥(ÿÃ5ÿët7ÿä•lÿלÿóàÚÿàÇÈÿÖÿÈ–œÿݺ¾ÿæËÍÿëÖØÿõëìÿÝ»¾ÿÒ¤©ÿß¼ÀÿðÞáÿõëìÿòãäÿðàâÿùòòÿÿÿÿÿïÞáÿÞ½Áÿñàãÿõáäÿr`bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ'ÿQÿŒÿ°#ÿ®4 ÿ´> ÿ¨/ ÿ¡) ÿ£- ÿ§1 ÿ­5 ÿ«3 ÿª3 ÿ¬5 ÿ®7ÿ°9ÿ¾HÿÉVÿÔWÿÕVÿá\ÿüÅ_ÿÿÿðÿýÿÛÿÿù›ÿþï«ÿùÑtÿ÷©?ÿö¥4ÿð&ÿÙ[ÿÉKÿÃJÿ¿Gÿ¿GÿÁHÿÃJÿÅLÿËPÿËPÿËQÿÚ^ÿÞdÿÚTÿìvÿÿå˜ÿÿýÞÿôŸ4ÿÛX ÿÌNÿÆKÿÂHÿ¸Aÿ²;ÿ·@ÿ»Cÿ®6ÿ¯8ÿ´;ÿ­6 ÿ¦/ ÿ¦/ ÿ¥. ÿ¢, ÿ ) ÿ¢* ÿ¦- ÿ¦)ÿÆ9ÿ×Z'ÿÙ‰fÿâ²£ÿÍœœÿÕ¯³ÿÌ ¦ÿÓ¨­ÿïÝÞÿ÷îïÿéÐÓÿΣ¨ÿÕ­²ÿçÌÎÿæÌÎÿäÊÌÿñâäÿýùùÿÿÿÿÿÿÿÿÿûö÷ÿôçéÿïßáÿï×Úÿtffÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿIÿ…ÿ¯#ÿž'ÿ£, ÿ­4 ÿ¡+ ÿ§0 ÿ«3 ÿ¦0 ÿ©3 ÿ¬5 ÿ®7ÿ¯8ÿ¯8ÿ²;ÿ¹AÿÈMÿÕYÿÐQÿÔPÿï´]ÿüæŽÿóÃKÿóÅ1ÿûÓ]ÿþïŽÿþü¶ÿÿýÉÿÿÿÓÿÿÚ`ÿë€ÿÉFÿÁHÿÂIÿÂJÿÃKÿÅKÿÅLÿÆMÿÈNÿÆLÿÄGÿÕP ÿö¥;ÿÿÿ¾ÿÿÿöÿÿ÷‹ÿú«ÿàcÿÊOÿÅMÿ½Eÿ¶?ÿµ>ÿ¸Aÿ¹Cÿ·Cÿ­6ÿ²;ÿ´=ÿ©2 ÿ¨0 ÿ¥/ ÿ£, ÿ¡* ÿ¢, ÿ©0 ÿ°/ÿÉ9ÿÔ]-ÿÃkRÿ¸qlÿ˘šÿß½ÀÿɘÿËœ¡ÿÜ»¿ÿîÚÜÿâÁÄÿäÇËÿß½ÁÿæÊÍÿéÒÔÿåËÎÿôéêÿÿÿÿÿýúûÿøññÿöìíÿõèêÿøõöÿynoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿy ÿ¬!ÿ¡(ÿœ' ÿž( ÿ¡+ ÿ¬4 ÿ¯6 ÿ¬4 ÿ³; ÿ¯8 ÿ­6ÿ¯9ÿ°9ÿ´<ÿ´=ÿºCÿÏTÿÖZÿÈFÿáŒ4ÿýèjÿÜ}'ÿÖE ÿàdÿásÿïŒÿø·4ÿýÁOÿÿûÚÿÿÿ×ÿûº.ÿÝXÿÆKÿÅKÿÅLÿÇLÿÇMÿÆLÿÆMÿÇLÿÈKÿÕP ÿèwÿþà¡ÿÿÿšÿÿ÷hÿÿÿçÿÿõÿø›ÿÔQÿÉNÿÁHÿ»Bÿ¶?ÿ´=ÿÁLÿÅUÿ·@ÿ°9ÿ´<ÿ±9 ÿ¬5 ÿ§1 ÿ¥/ ÿ£- ÿ¥- ÿ©/ ÿ£, ÿ¨'ÿÈ8 ÿÊU*ÿ¹aOÿ³jiÿ¯nrÿ°pwÿË¢ÿÑ¥©ÿçÏÒÿóèéÿæÍÏÿÚ´¸ÿìÙÛÿÿÿÿÿøîîÿúóóÿÿþþÿüö÷ÿ÷ïïÿïÝßÿéÐÓÿôàâÿvijÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ3ÿjÿ¨ÿ§(ÿœ( ÿ¡* ÿª4 ÿ°8 ÿ´: ÿ¯6 ÿ¹BÿÀNÿ³<ÿ­6ÿ°9ÿ´=ÿ»Bÿ·@ÿ·@ÿ¹Cÿ¸: ÿÍ` ÿûÆkÿã„;ÿÇB ÿÐTÿÉLÿÇHÿÔNÿã\ÿöuÿÿÇKÿÿûãÿÿí­ÿí~ÿËDÿÆNÿÇNÿÉNÿÈOÿÊPÿÈKÿÎMÿçy'ÿû±HÿÿãˆÿÿÿÏÿþÖ\ÿü­ÿûÏvÿÿüäÿÿá‚ÿænÿÖOÿÆJÿ¾Gÿ¾Eÿ¹Aÿ¶>ÿ¿FÿÀHÿ°:ÿ³<ÿ´;ÿ¬5 ÿ±9 ÿ«4 ÿ¦/ ÿ§/ ÿ°6 ÿ¡+ ÿ›& ÿ±,ÿÉ< ÿÀQ-ÿÁueÿ®hhÿµx~ÿÏ£§ÿãÅÉÿòâäÿúôôÿæÌÏÿÙ³¸ÿöìíÿÿÿÿÿþýýÿýúûÿþýýÿÿÿÿÿûøøÿóåæÿòáãÿøððÿzoqÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ&ÿWÿœÿ«'ÿ£, ÿ±7 ÿ°:ÿ»Lÿ°8 ÿ¤. ÿ«2 ÿ½IÿÁRÿ²=ÿ°8ÿ²<ÿ¶?ÿ¹Aÿ¸Bÿ¹BÿºDÿ¹7 ÿØz,ÿÿèƒÿÛ{7ÿÁ5ÿÅFÿÄJÿÆMÿÌRÿÛ_ÿñw"ÿýŠÿÿÒWÿÿÿÚÿö¼tÿÙTÿÉHÿÉOÿËQÿÊOÿËHÿÒRÿì9ÿÿñÿýò¼ÿ÷Ü–ÿð­PÿähÿßRÿßZÿõ´XÿÿÿÌÿþÔ|ÿò‡$ÿÔQÿÁGÿÃJÿ½Eÿ·?ÿ¹?ÿ¸@ÿ²<ÿ³<ÿ¯7ÿ­5ÿ³:ÿ¯8 ÿ¦0 ÿ¦. ÿ°7 ÿ«1 ÿ¦/ ÿ§/ÿ¶-ÿØTÿÍmLÿ¾tjÿÒ¢£ÿß¾ÀÿçÌÐÿãÅÈÿíÚÜÿâÅÉÿëÕÖÿôæçÿÿÿÿÿÿÿÿÿüùùÿþýýÿþýýÿúõõÿòãåÿñßáÿúö÷ÿ€|}ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿCÿ‰ÿ¯#ÿž'ÿ®4 ÿºA ÿ»Mÿ·Kÿ¤, ÿ¤. ÿª2 ÿµ>ÿ½Kÿ´?ÿ±:ÿ³>ÿ¸@ÿ¼Cÿ»Dÿ½Dÿ¾Fÿ»9ÿØp"ÿÿùÿøàÿç‹8ÿÓ^!ÿÇHÿÇMÿÐTÿÚ_ÿæk ÿø{$ÿÿ¥ÿÿëtÿÿÿÞÿô­YÿÞVÿÓLÿÑKÿÓKÿÞn$ÿô½Kÿÿêƒÿñ»fÿßr0ÿÓRÿÍG ÿÇIÿÉOÿÍKÿß\ÿö¬GÿÿöÅÿÿô ÿò”%ÿÒMÿÅKÿÀIÿºBÿ¹Aÿ·@ÿ´>ÿ±;ÿ¯9ÿ²9ÿ²:ÿ²:ÿ¬5 ÿ¥. ÿ«2 ÿ²; ÿ©0 ÿ¥- ÿ &ÿ¿1ÿÈJÿÈsXÿÕ ™ÿãÃÃÿÙ´¸ÿس¶ÿõëìÿùóóÿûõõÿûõöÿÿþþÿýüüÿùóôÿýúúÿüúúÿÿÿÿÿÿþÿÿøîïÿøëíÿynoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1ÿm ÿ¬ÿ¤'ÿœ( ÿ®5 ÿ¯6 ÿ²?ÿ±?ÿ«3 ÿ¯7ÿ¬5ÿ°8ÿ³;ÿ²;ÿ³>ÿ·@ÿºCÿ¼Eÿ¾EÿÂHÿÂHÿÀEÿÍPÿõ­GÿÿßzÿûËoÿüÔnÿì7ÿÔXÿÑSÿÝ_ÿìq"ÿ÷|&ÿÿ†&ÿÿ±*ÿÿý‚ÿÿûÎÿû¼hÿî€ÿëvÿñ›>ÿÿßÿûÙcÿá3ÿÐH ÿËFÿÊKÿÊOÿËQÿÌQÿÍSÿÎOÿß[ ÿ÷š1ÿÿò±ÿÿø©ÿð”0ÿÉJÿÀHÿ½Eÿ»Dÿ¼Cÿ¸@ÿ³>ÿ²<ÿ±9ÿ¯7ÿ­6ÿ¬4 ÿ¦0 ÿ¨2 ÿ¶Bÿ­5 ÿª0 ÿ + ÿ¨&ÿÇ9ÿÏd:ÿוÿÙ­ªÿΜ¢ÿàÂÅÿøðñÿýúúÿÿÿþÿÿÿÿÿýûûÿüùùÿüúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøîïÿ{rrÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿQÿÿ¯)ÿ) ÿž) ÿ¢, ÿ¤- ÿ¥- ÿ¨/ ÿ³<ÿ½Fÿµ;ÿ·>ÿµ>ÿ³=ÿ¶?ÿ»Cÿ¼Eÿ¼Dÿ¿EÿÃJÿÈNÿÊPÿËLÿÝcÿãlÿÖ`ÿå Hÿñ¢8ÿÞbÿÒVÿÚ^ÿäh ÿçi ÿòr$ÿû…#ÿþÂ(ÿÿú£ÿÿÿæÿÿê®ÿÿä©ÿÿÿ¹ÿ÷¸aÿÞaÿÐHÿÑTÿÒWÿÐUÿÐSÿÎQÿÍQÿÌPÿËOÿÓVÿädÿö”.ÿÿò¦ÿýê±ÿÒWÿ½Bÿ¾Eÿ»Cÿ»Dÿ»Cÿ¸Aÿ³>ÿ³;ÿºDÿ±9ÿ¬5ÿ¨2 ÿ§1 ÿ®8 ÿ¨1 ÿ¤- ÿ¥, ÿ¢) ÿ·,ÿÎJÿÒyWÿÅyÿÀƒ‡ÿàÁÅÿúóôÿñãäÿöíïÿöìîÿ÷ïïÿþýýÿÿÿÿÿúóôÿ÷îîÿôçèÿñãäÿë×ÙÿéÊÎÿtdeÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ9ÿ} ÿ°#ÿ¨, ÿ¡+ ÿ£, ÿ¢, ÿ¦/ ÿ¨2 ÿ¨1 ÿ®7ÿ´<ÿ½Hÿ¿Kÿ·?ÿ¸@ÿ¸Aÿ»Cÿ½Eÿ¿GÿÂIÿÈNÿÎTÿËPÿÊPÿÌNÿÍLÿËJÿÌGÿÓRÿ×[ÿÕXÿÕZÿØ[ÿÙ\ÿßbÿçe!ÿ÷„ÿÿà^ÿÿÿìÿÿÿÿÿÿÿÿÿúÅ{ÿÞ]ÿÒPÿÔXÿÔXÿÓWÿÒWÿÒUÿÐTÿÎRÿÍRÿÎRÿÎRÿÓVÿÝT ÿø¼JÿþõÃÿâiÿÄHÿÀGÿ¼Dÿ»Cÿ¼Eÿ¼Cÿ¶@ÿ³<ÿ¿HÿÁSÿµ@ÿ®6ÿ®6 ÿ¦/ ÿ£. ÿ¢+ ÿ¢+ ÿž) ÿž$ÿÇ8ÿÊT*ÿ´\KÿĆ„ÿéÐÒÿëÕØÿêÓÖÿóçèÿðßáÿìÖÙÿüøøÿþûüÿñáãÿéÐÓÿçÌÏÿ×±´ÿãÆÊÿëÙÚÿxnpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ%ÿ\ÿ¥ÿ«(ÿž( ÿ¡* ÿ¦/ ÿ¥/ ÿ­5 ÿ²9 ÿª4 ÿ¬5ÿ®7ÿÀQÿÀPÿ¶>ÿºBÿ»Eÿ¾GÿÁGÿÄJÿÉNÿËPÿÈNÿÇMÿÉNÿÌPÿÌOÿÖ]ÿ×\ÿÑTÿÔYÿÖYÿÕYÿÔYÿÙ\ÿÜ^ÿà^ÿózÿÿØuÿÿÿ÷ÿÿÿÿÿÿé‘ÿêvÿÕTÿÕYÿÕYÿÕYÿÔWÿÓWÿÓWÿÓVÿÑTÿÐTÿÑUÿÐUÿÐTÿÕPÿöÁYÿÿó®ÿítÿÏSÿÃJÿÀIÿ½Eÿ¼Fÿ»Dÿ¸Aÿ¶?ÿ¶>ÿÄTÿ¾Mÿ°6ÿ³:ÿ¬5 ÿ¨0 ÿ¦/ ÿ£- ÿ¡* ÿ–"ÿ¯(ÿÇ@ÿµM0ÿÒ˜‹ÿíÓÑÿëÕ×ÿüøøÿüúùÿøñòÿùñòÿøïðÿôçèÿóåçÿôèêÿùóôÿçÎÑÿôçèÿìÖØÿtfhÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ=ÿƒÿ°%ÿ¢( ÿœ' ÿ + ÿ¤- ÿ¥/ ÿª4 ÿ¬5 ÿ«5ÿ¯7ÿ±;ÿ·Bÿ¸Bÿ·@ÿ¼DÿÂIÿÅJÿÁHÿÄJÿÉNÿÊPÿÆLÿÈMÿËPÿÌQÿÏRÿØ]ÿØ]ÿÕYÿÕYÿÖZÿÖZÿ×ZÿÚ^ÿÜ` ÿà`"ÿòtÿÿÍaÿÿÿôÿÿùµÿöŸ0ÿÞ[ÿØZÿØ\ÿ×\ÿ×Zÿ×ZÿØ[ÿÖYÿÕWÿÓWÿÒVÿÒVÿÑUÿÑTÿÙVÿøÐcÿþïšÿéjÿÐSÿÉNÿÆKÿÁIÿ¿Fÿ½Eÿ»Dÿ¹Bÿ´=ÿ·AÿºEÿ¯9ÿ­7ÿª4 ÿ«3 ÿ¬4 ÿ¢+ ÿ§1 ÿ­9 ÿ¢)ÿ½/ÿÁH ÿØ’{ÿæÂ»ÿòäåÿ÷ñòÿÿÿÿÿÿþþÿÿÿÿÿþüüÿûö÷ÿûøøÿÿþþÿýúúÿõëíÿûõöÿñØÚÿynoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$ÿ]ÿ¥ÿ¬+ÿ( ÿ¤. ÿ£- ÿ¤. ÿ¥/ ÿ©2 ÿ«4 ÿ®7ÿ°:ÿ³<ÿ´<ÿ¶>ÿ»DÿÀHÿÃIÿÅJÿÂIÿÄJÿÆLÿÈNÿÈNÿËPÿÌRÿÎRÿÐTÿÒWÿÕXÿÖZÿ×[ÿØ[ÿÙ\ÿÚ]ÿÝ` ÿßc"ÿäd#ÿö~ÿÿ×rÿÿÿôÿÿÒoÿênÿÜZ ÿÜ^ ÿÛ^ ÿÚ^ÿÙ]ÿÛ]ÿÛ^ÿÙ]ÿ×[ÿÖYÿÕXÿÓWÿÓVÿÒUÿÚTÿúÍlÿÿò˜ÿòpÿÖNÿÍNÿÔZÿÇOÿÀGÿÁHÿ½Fÿ¼Dÿ¸Aÿ²<ÿ·?ÿ´=ÿ­6ÿª3 ÿª3 ÿ«3 ÿ£- ÿ¥/ ÿ¯: ÿ + ÿ¬'ÿÐJÿÝ…_ÿè¼®ÿðÞÜÿýüüÿÿÿÿÿÿÿÿÿÿÿÿÿüøøÿü÷øÿÿÿÿÿÿÿÿÿþüüÿðßáÿéÐÒÿïÒÕÿr`bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ8ÿ€ÿ¶.ÿ¨/ ÿ£, ÿ«2 ÿ¤. ÿ¥/ ÿ®7 ÿ«4 ÿ±:ÿ²;ÿ°:ÿ³=ÿ·@ÿ¹Bÿ¼DÿÀGÿÀGÿÂIÿÆLÿÇMÿÉOÿÉOÿÊOÿÍQÿÎRÿÐTÿÓVÿÔXÿÕYÿÖZÿØ\ÿÛ]ÿÜ_ ÿÞa ÿãf"ÿèj$ÿõv$ÿþ³0ÿÿø¶ÿÿþÄÿÿµ=ÿïp!ÿß`"ÿÞa!ÿÞa!ÿßb"ÿÝa!ÿÜ^ ÿÛ^ ÿÚ]ÿØ\ÿØ\ÿ×[ÿÔXÿÔWÿÒUÿÝ_ÿþÝŠÿÿú˜ÿý¹'ÿô£8ÿî›Iÿßj"ÿÅGÿÂIÿÂIÿ¾Fÿ½Eÿ»Cÿ¶?ÿ³<ÿ±;ÿ¯8ÿ²:ÿ°8 ÿ¨0 ÿ¥/ ÿ£, ÿ¡* ÿ( ÿ¡&ÿÌ= ÿØi;ÿࡉÿÙ­ªÿåÊÌÿìÙÛÿüùúÿüùúÿøññÿùóóÿýüüÿÿÿÿÿÿÿÿÿûõõÿñÞßÿèÇËÿ`ADÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿTÿÿ­(ÿŸ+ ÿ®5 ÿ©0 ÿ£- ÿ¦1 ÿ¶?ÿ³;ÿ¸?ÿ±;ÿ²;ÿ¶>ÿ¹Bÿ»DÿÀGÿÃIÿÂIÿÃIÿÆLÿÉOÿÍQÿËPÿÍQÿÎRÿÒXÿÚaÿÙ]ÿÕZÿ×ZÿØ[ÿÚ]ÿÝ` ÿÞa!ÿäf#ÿëj$ÿör%ÿÿ©3ÿÿø—ÿÿÿ÷ÿÿÞxÿÿ•#ÿõt(ÿæh$ÿád#ÿâe#ÿäg$ÿád#ÿÞa!ÿÝ`!ÿÜ_ ÿÛ^ ÿÙ\ÿ×[ÿÖZÿÖYÿÙXÿîŽ-ÿÿùÎÿÿÿ¥ÿÿýÏÿÿýèÿøÓƒÿÛV ÿËLÿÄKÿÂIÿ¿Fÿ¼Dÿ»Dÿ¸@ÿµ>ÿ±:ÿ°9ÿ¹BÿºCÿ®5 ÿ©2 ÿ£, ÿ * ÿ¤, ÿ * ÿ´-ÿÔQÿÒz[ÿÜ©žÿÅ“ÿÓ«°ÿõìíÿàÁÅÿìÙÛÿþüüÿüùùÿýüüÿþüüÿúóôÿðßáÿМ¢ÿZ9<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ0ÿr ÿ­"ÿ¥*ÿž* ÿ¨0 ÿ¥/ ÿ£. ÿª2 ÿ¯8 ÿ±:ÿ´=ÿ°:ÿ´=ÿºAÿ»CÿºCÿ¿FÿÂHÿÄKÿÅKÿÉOÿÊPÿÍRÿÌQÿÏSÿÒVÿÝe!ÿßk"ÿØ]ÿÖYÿØ\ÿÚ]ÿÝ_ ÿàc"ÿáe#ÿèl$ÿñq'ÿüz!ÿÿ¾Qÿÿÿãÿÿÿóÿÿâmÿý&ÿðm&ÿèk%ÿæi%ÿæi%ÿæi%ÿâe#ÿßb#ÿÞb"ÿÞa"ÿÝ_!ÿÛ]ÿÙ]ÿØ\ÿ×ZÿæbÿýÓ…ÿÿÿüÿÿÿúÿÿÿäÿÿÿíÿûæªÿç{ÿÓKÿÈLÿÃHÿÂGÿÀFÿ½Eÿ¹Aÿ¹@ÿ¶?ÿ±:ÿ±;ÿ³;ÿ±8ÿ¬4 ÿ£- ÿ * ÿ«1 ÿ¥- ÿ %ÿÔHÿÞ{MÿÝ¢ÿשªÿèÒÔÿíÚÛÿذ´ÿàÀÃÿùòòÿýøùÿìØÚÿíÛÜÿãÆÉÿÌ›¡ÿ½}ƒÿ^?AÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿDÿÿ´*ÿ¨/ ÿ©0 ÿ¤- ÿ£- ÿ¤/ ÿ­5 ÿ°8ÿ­6ÿ°9ÿ²<ÿ¼CÿÁGÿ»Cÿ½Dÿ¾FÿÀHÿÃJÿÈMÿÓZÿÌRÿÍRÿÎRÿÏSÿÕYÿÚ^ÿÖYÿ×ZÿÙ\ÿÚ^ÿÜ_ ÿÞa!ÿàd#ÿäf$ÿên&ÿót(ÿù%ÿÿÂEÿÿÿÍÿÿÿüÿÿí|ÿýœ'ÿöt(ÿío'ÿèm&ÿçi%ÿæh%ÿäf$ÿâe#ÿác#ÿßc#ÿÞa"ÿÞa!ÿÞ`!ÿÛ_!ÿÚYÿí|ÿþô·ÿÿýÀÿÿÿœÿÿüSÿÿÿ›ÿÿÿýÿÿæ›ÿíˆ(ÿÔRÿËLÿÇHÿÃBÿÈHÿÇHÿÄDÿÇJÿ¶?ÿ°:ÿ¯8ÿ³:ÿ­5 ÿ¤/ ÿ¢, ÿ¬5 ÿª2 ÿ¤+ÿÂ5ÿßj4ÿÖŠpÿÙª¥ÿì×Úÿûö÷ÿçÎÐÿß¾ÁÿñäåÿüùùÿíÙÛÿÔ¨­ÿΞ£ÿ·v}ÿΚ ÿq`bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ÿ\ÿ¡ÿ©(ÿœ) ÿ©/ ÿª1 ÿ¤. ÿ¦0 ÿª3 ÿ¬5ÿ¯8ÿ±:ÿ´=ÿ½Dÿ¿Fÿ¼Eÿ¿EÿÀHÿÄKÿÆKÿÈNÿÌRÿÌQÿÎRÿÐUÿÒVÿÓVÿÔXÿ×ZÿÚ]ÿÛ^ ÿÜ_"ÿßb"ÿßc"ÿâe#ÿåh$ÿçj%ÿìl'ÿù~*ÿÿ¹4ÿÿú«ÿÿÿåÿÿÛXÿÿš+ÿÿ†/ÿów*ÿël'ÿçj%ÿæh%ÿåg%ÿåg%ÿäf$ÿâd#ÿád#ÿâe#ÿâe#ÿßc"ÿßZÿõ‹3ÿÿ÷µÿÿØ@ÿÿÕ5ÿÿÇ7ÿÿçFÿÿ÷–ÿÿþÜÿÿÿÉÿøÁfÿò¥DÿèŠ0ÿÝn ÿí.ÿô2ÿëƒ$ÿähÿÏNÿ»=ÿ³8ÿ®6ÿ©3 ÿ¥. ÿ * ÿ®9 ÿ«5 ÿ( ÿ©'ÿØRÿÞ‹cÿÆ„|ÿÈ“™ÿãÆÉÿêÑÔÿåÉÌÿôéëÿòäæÿÞ¼¿ÿÔ¬°ÿÝ»¿ÿË™žÿéÆÊÿ………ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ0ÿs ÿ¬!ÿ¡(ÿž) ÿ¦/ ÿ¤- ÿ¤/ ÿ§1 ÿ¯7ÿ¯8ÿ°9ÿ²;ÿ¸@ÿÂIÿ¾Gÿ½Eÿ¿GÿÃIÿÇLÿÇMÿÉOÿÊOÿÍQÿÐUÿÒVÿÓWÿÖYÿ×[ÿÙ\ÿÛ^ÿÛ_!ÿßb#ÿãf#ÿáe#ÿãf$ÿæh%ÿçi%ÿëm&ÿôs*ÿý“%ÿÿánÿÿÿãÿÿïˆÿÿ¤+ÿþ€+ÿõw+ÿío'ÿêm&ÿèk&ÿçj&ÿçi%ÿæh%ÿäg%ÿäg#ÿæi$ÿçj%ÿãf$ÿéaÿû­HÿÿûÇÿÿ±Aÿü%ÿùƒ(ÿø–*ÿù£ÿø¬7ÿûØ›ÿÿõÄÿÿÿÊÿÿÿšÿÿÿ”ÿÿÿ¾ÿÿÿÉÿÿú¸ÿü½AÿésÿÓP ÿÑPÿÄ@ÿµ1ÿ±-ÿ¦&ÿ«/ÿ¨/ ÿ( ÿ#ÿÑEÿå„TÿÓ’ÿÈ“–ÿÖ®²ÿÕª¯ÿׯ³ÿíÚÛÿíÚÜÿåÊÍÿõëíÿøñòÿûõöÿøìîÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿˆÿ®%ÿœ( ÿ£- ÿ®5 ÿª2 ÿ§0 ÿ©2 ÿ±9ÿ±9ÿ±:ÿ³<ÿ¹AÿÊVÿÈSÿ½CÿÀHÿÅJÿÇKÿÈNÿËPÿÎRÿÐSÿÑUÿÔWÿÕYÿØ[ÿÚ]ÿÛ^ÿÜ` ÿÞb!ÿád#ÿãf#ÿãf#ÿåh%ÿçi%ÿëm&ÿìn'ÿïo)ÿöv'ÿÿ¯-ÿÿô¬ÿÿÿÖÿÿÅLÿþ†(ÿõv+ÿïq)ÿìo(ÿêm'ÿél'ÿèj&ÿèj&ÿèl&ÿèk&ÿél&ÿèk%ÿæi%ÿòiÿÿÒ^ÿÿÿæÿþºBÿõo"ÿêl#ÿÝZÿÝUÿÚOÿàc ÿê‚(ÿó¤IÿúÄXÿûÍwÿøÑÿÿá¡ÿÿþÕÿÿÿÊÿýÙpÿõÅTÿûÄhÿó¡LÿèŒ7ÿã‰+ÿ×hÿÅL ÿ´6ÿ¤'ÿ—!ÿ¾3ÿßk7ÿÙ”zÿОœÿáÂÅÿâÃÆÿÔ©­ÿÞ½ÁÿçÎÐÿòâäÿùñòÿéÑÕÿýúûÿûýüÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿQÿ˜ÿ¯+ÿ¢- ÿ¥. ÿ­4 ÿ­5 ÿ¨1 ÿª4 ÿ°8ÿ¯9ÿ³<ÿ´=ÿ¸@ÿÄOÿÊSÿÂGÿÁHÿÅKÿÆLÿÊPÿÎRÿÏTÿÐTÿÒVÿÔXÿ×[ÿÚ]ÿÜ^ÿÝ`ÿÞb"ÿàc#ÿâd#ÿãf#ÿæi%ÿèk%ÿêm%ÿíq'ÿìn'ÿîp(ÿóp*ÿü}ÿÿÏXÿÿÿãÿÿ÷®ÿÿ¯@ÿöy)ÿòs*ÿðr*ÿìo(ÿëo'ÿêl'ÿën(ÿïs)ÿîp(ÿìo'ÿél&ÿêm&ÿólÿþÇOÿÿÿæÿÿÇOÿöu!ÿâd!ÿÖYÿÑUÿÏSÿÐNÿÒNÿÙR ÿàYÿÞZ ÿ×Wÿâl ÿõ§.ÿûÞ”ÿüã˜ÿÿæ|ÿÿð±ÿÿÿªÿÿÿ’ÿÿÿ·ÿÿíÃÿùÖ–ÿäšFÿÀRÿ£. ÿ±*ÿÔRÿÌvZÿÊŽ‰ÿÒ¨«ÿæËÎÿÛ´¸ÿ×®²ÿåÈÌÿïÞàÿðàâÿïÝÞÿüøøÿúûûÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&ÿbÿ¤ÿª+ÿ¢, ÿ¦. ÿ«2 ÿ¦/ ÿ§0 ÿ«4 ÿ°8ÿ³:ÿ´=ÿ¶>ÿ¹Aÿ½DÿÄJÿÅKÿÃJÿÆMÿÇNÿÍRÿÐUÿÒWÿÒWÿÔWÿÕYÿÙ]ÿÚ^ÿÜ`ÿÝc!ÿàd"ÿâf#ÿåf$ÿæi%ÿém%ÿén&ÿìo'ÿìp'ÿïq(ÿðq(ÿñs+ÿúu%ÿÿ®7ÿÿ÷ÔÿÿÿÔÿÿÀDÿû|)ÿõw,ÿòt*ÿïs)ÿîq)ÿìo(ÿíp)ÿðr(ÿîr)ÿíp'ÿíq(ÿïs(ÿöv(ÿÿ”%ÿÿí§ÿþã§ÿîs"ÿÚ\ÿÖZÿÔWÿÒTÿÑUÿÕZÿÙ^ÿÔWÿÍOÿÈIÿÅCÿÑN ÿÔcÿÎ\ÿÓ\ÿÝn&ÿçŽ5ÿç•4ÿøÅsÿÿõ ÿþé‡ÿîÀgÿášQÿÂ\%ÿ«*ÿÑGÿÔtPÿ¿wnÿɘÿæÌÏÿÛ¶¹ÿ×®³ÿáÁÄÿìÙÚÿñáãÿøïïÿøððÿùøøÿ‚€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ0ÿs ÿ¯$ÿ¡(ÿ) ÿ¤- ÿ¥/ ÿ¤/ ÿ©2 ÿ«4 ÿ´=ÿÂOÿ»Fÿ¶>ÿºCÿ¼FÿÂIÿÃKÿÅLÿÇNÿÉNÿÐTÿÑWÿÓYÿÔZÿÕYÿ×\ÿÚ^ÿÜ`ÿÞbÿßd!ÿâf#ÿæh$ÿèk$ÿèl%ÿêm%ÿëo&ÿìp'ÿír(ÿðr*ÿòt*ÿôv+ÿúx*ÿÿ•#ÿÿé©ÿÿÿàÿÿÉGÿÿŒ!ÿü{-ÿøx-ÿów+ÿðs+ÿïr*ÿîp(ÿíp(ÿïs)ÿòu*ÿôx+ÿ÷z*ÿü}+ÿÿ¡(ÿÿìuÿûåÇÿär$ÿØYÿÖ[ÿÔXÿÒVÿÑUÿÖZÿÛ_ÿÕYÿÎRÿÉOÿÃJÿ¿Eÿ»<ÿ·8 ÿ¸8 ÿÀ>ÿÇDÿ¼7ÿÆJÿàx ÿØj ÿ¾OÿÂY$ÿµFÿ¡(ÿÍBÿÚtEÿ¶g\ÿ½‚‡ÿܸ¼ÿÞ¼¿ÿÝ»¿ÿÛµ¹ÿäÇÊÿûö÷ÿûööÿóåçÿîÙÛÿ€€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ:ÿ‚ÿº6ÿ£. ÿ¢+ ÿ±: ÿª3 ÿ¥/ ÿ©2 ÿ«5ÿ·?ÿÈ]ÿÁNÿ¸?ÿ»Dÿ½GÿÂIÿÄJÿÇLÿÉOÿÌQÿÍTÿÏVÿÓXÿÔYÿÖ[ÿÙ^ÿÞbÿßbÿßcÿáe!ÿäi#ÿçk$ÿèm%ÿén&ÿëp&ÿíq'ÿïs(ÿït(ÿñt)ÿóx+ÿ÷z,ÿú{-ÿÿŽ(ÿÿÕUÿÿÿ×ÿÿõÓÿÿØbÿÿ¤*ÿþƒ,ÿøz-ÿòu,ÿñt+ÿðr*ÿðs*ÿõx,ÿú~-ÿú†.ÿüƒ-ÿÿ‡)ÿÿÛPÿÿýÌÿúáÇÿç{(ÿÚYÿÙ\ÿÔXÿÒUÿÐUÿÒVÿÒUÿÍRÿËOÿÅLÿÂIÿ¾Gÿ¼Fÿ¼Eÿ¹Bÿ»BÿÄTÿ¾Oÿ®1 ÿ²1 ÿ¯2 ÿ¢%ÿ©0ÿ¬7 ÿ›$ÿÄ8 ÿàs>ÿ·dUÿ¸z}ÿÓ¨­ÿÚµ¹ÿÛµ¹ÿÍœ¡ÿ×®³ÿóåçÿÿÿþÿüùúÿñÙÛÿ~{{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿEÿŽÿ½; ÿ§6 ÿ£+ ÿ³8 ÿ«3 ÿ§0 ÿ­5 ÿ®6ÿ»CÿÃNÿÆUÿ¼Dÿ¼EÿÁHÿÄKÿÅKÿÆMÿÍSÿÒXÿÐVÿÑWÿÔYÿÕZÿØ^ÿÜ`ÿÞeÿÞeÿáeÿãh ÿæj!ÿèm#ÿéo%ÿìq&ÿîr'ÿðt'ÿñu(ÿñu)ÿñv)ÿów*ÿ÷{,ÿü-ÿþ‡0ÿÿ¡0ÿÿÝ_ÿÿÿÆÿÿÿïÿÿóŸÿÿ¸9ÿþ~(ÿøy.ÿòu,ÿòu+ÿ÷y,ÿü‚/ÿÿ‰0ÿþ†/ÿý~-ÿÿ™*ÿÿìNÿÿÿäÿýñîÿíŸaÿÜWÿØZÿÕYÿÓWÿÑUÿÎRÿÌQÿÌPÿËQÿÆMÿÂIÿ¿Gÿ½Eÿ¼Eÿ¸Aÿ·@ÿÁLÿÂMÿ³:ÿ¨1 ÿ£. ÿ£, ÿ³Aÿ°?ÿœ%ÿÀ; ÿän5ÿÈv_ÿÉ’“ÿׯ´ÿÈ•šÿز¶ÿÔ«¯ÿÌ› ÿÕ«°ÿúôõÿóäåÿòÚÝÿ~xyÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿOÿšÿ·2ÿ¡- ÿ ) ÿ¯5 ÿ¬4 ÿ§0 ÿ®6 ÿ³;ÿºBÿ½EÿÄLÿ¾Eÿ¿GÿÄKÿÉOÿÈOÿÈOÿÒXÿ×]ÿÓYÿÔYÿÕ\ÿØ^ÿÙ`ÿÞdÿßfÿßfÿâiÿäj!ÿçl!ÿép#ÿëq$ÿîr&ÿït&ÿðu'ÿñv(ÿñw)ÿòx*ÿôx*ÿõ{+ÿú-ÿþƒ/ÿÿŽ3ÿÿ«6ÿÿÆCÿÿéÿÿÿãÿÿøËÿÿµKÿÿ„(ÿü{.ÿù}.ÿû.ÿÿ…/ÿÿ’4ÿÿ4ÿÿš*ÿÿ×Iÿÿü¤ÿÿÿöÿÿÿýÿ÷Ñ»ÿå~;ÿÙWÿÔUÿÓVÿÑVÿÎSÿÌQÿÊOÿËPÿÈNÿÂIÿÁHÿÁHÿ¿Fÿ¹Aÿ¸@ÿ·?ÿµ=ÿ±9ÿª4 ÿ¥0 ÿ£. ÿ¯7 ÿ¨1 ÿ( ÿ»7ÿÙX!ÿׇhÿצ¡ÿÓ«°ÿÒ¦ªÿÑ£¨ÿТ¦ÿÓ¦«ÿÚ´¹ÿéÒÕÿêÑÓÿ÷íïÿ|tuÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿWÿ¢!ÿ³4ÿ¥. ÿ¬2 ÿ°5 ÿ¯6 ÿ­6 ÿ±7ÿ´;ÿ´<ÿ¹Aÿ½Eÿ½Eÿ¿HÿÄLÿÊPÿÉQÿÊRÿÏWÿÔZÿÓZÿÔ[ÿØ_ÿÚbÿÛbÿÝeÿàfÿâiÿäjÿæl ÿèp#ÿêr$ÿís$ÿît&ÿïv'ÿñw'ÿñx'ÿòx)ÿôz*ÿõ{*ÿö|,ÿú€.ÿÿ†0ÿÿ2ÿÿ3ÿÿ”2ÿÿœ0ÿÿÌ\ÿÿþÄÿÿûßÿÿÖqÿÿ•)ÿÿ…/ÿÿ„/ÿÿŠ0ÿÿ§7ÿÿÅ8ÿÿé]ÿÿþÐÿÿÿñÿÿ÷‰ÿÿìiÿþ÷™ÿøÚºÿì¡]ÿÞgÿÕSÿÒTÿÏRÿÌQÿÉPÿÈNÿÆLÿÂIÿÅKÿÆLÿ¼Dÿ¹Aÿ¸@ÿ¸@ÿ²:ÿ®7 ÿª4 ÿª3 ÿ«3 ÿ§/ ÿ¡+ ÿ£+ ÿº6ÿÖPÿÄfJÿÇ‹†ÿÙµ¹ÿ×°´ÿÛ·ºÿÚ´¸ÿÜ·¼ÿíÙÛÿì×Úÿùïðÿúñóÿ}vwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ÿ]ÿ¨$ÿµ8 ÿ±8 ÿµ9 ÿ­3 ÿ®7 ÿ¯7 ÿ°7ÿ²:ÿµ>ÿ¹Aÿ»Dÿ¿HÿÃJÿÇMÿÉPÿÊSÿÌTÿÏVÿÒYÿÓ\ÿÕ^ÿÙ`ÿÛcÿÝeÿßgÿàhÿãkÿåmÿço ÿér"ÿët#ÿíu$ÿïw%ÿñx&ÿóz'ÿóz(ÿóz)ÿô|*ÿö|*ÿ÷},ÿû€.ÿÿ‡0ÿÿ‰1ÿÿ‹1ÿÿ4ÿÿŽ3ÿÿ’2ÿÿ°8ÿÿä}ÿÿÿíÿÿæ‰ÿÿÃEÿÿÇAÿÿ¾?ÿÿÎ>ÿÿö‰ÿÿÿïÿÿÿøÿÿü™ÿÿ½5ÿÿ¥2ÿÿÍ;ÿÿôžÿý÷ãÿ÷·Nÿñÿéx#ÿÔYÿËOÿËOÿÈNÿÆKÿÃJÿÆLÿÅJÿ¼Dÿ»DÿºBÿ¶>ÿ±9ÿ­6 ÿª4 ÿ¬4 ÿ«3 ÿ¥- ÿ¡+ ÿ§/ ÿ¼EÿÝ\"ÿÇdCÿ½yuÿ×®³ÿݺ½ÿâÂÆÿæËÍÿÜ·¼ÿÙ³·ÿìÖÙÿþûüÿùñòÿ}~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%ÿcÿ«&ÿ¸< ÿ­4 ÿ©/ ÿ¨0 ÿ§0 ÿ«3 ÿ­5 ÿ²;ÿ¶?ÿ¹Bÿ¾FÿÂJÿÅLÿÇNÿÉQÿËTÿÍUÿÑXÿÔ\ÿÕ^ÿ×aÿÚcÿÝeÿÞgÿàiÿãlÿänÿæpÿèqÿés!ÿìv#ÿîw#ÿñy%ÿñz%ÿò|'ÿó|'ÿô}(ÿö~*ÿ÷~*ÿø~+ÿú,ÿý„/ÿÿ…1ÿÿŠ2ÿÿ‹2ÿÿˆ2ÿÿ…2ÿÿˆ0ÿÿ¡3ÿÿêŒÿÿÿìÿÿÿáÿÿÿÃÿÿÿ¼ÿÿÿÏÿÿÿñÿÿûÎÿÿænÿÿ¶:ÿýŠ,ÿþ‡-ÿÿž1ÿÿÍ?ÿÿÿ¹ÿÿþáÿÿúqÿÿÐ9ÿìt ÿÓRÿÌPÿÈMÿÆLÿÃJÿÅKÿÍUÿÆPÿ»Bÿ¼Cÿµ>ÿ°9ÿ¯8ÿª3 ÿ¯7 ÿ²? ÿ¥. ÿ¡* ÿ¢* ÿ·? ÿ×SÿÎjFÿÒ—Žÿܸ¼ÿÞ½ÂÿêÒÕÿõéêÿìÖØÿæÌÏÿéÑÔÿöëëÿúòòÿ~~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(ÿhÿ®(ÿ¯6 ÿ£* ÿ¥. ÿ¥- ÿ­4 ÿ²; ÿ¯9 ÿ³;ÿ·?ÿÁJÿÇNÿÃKÿÄMÿÇPÿËUÿÏXÿÏXÿÒ\ÿÖaÿØaÿÙcÿÜgÿÞiÿàkÿãnÿãoÿærÿçtÿéuÿíy ÿîz"ÿï{#ÿñ{$ÿñ}%ÿò}&ÿô€'ÿõ(ÿö)ÿø€*ÿù+ÿú‚,ÿü„-ÿþ„/ÿÿˆ1ÿÿ‡1ÿÿ…0ÿÿƒ0ÿÿ„1ÿÿ3ÿÿ¨2ÿÿã^ÿÿþ±ÿÿÿëÿÿÿôÿÿýÏÿÿä{ÿÿ¾<ÿþŽ'ÿùt(ÿôr(ÿóu(ÿþŸ6ÿÿÈ9ÿÿæGÿÿþÆÿÿÿÿÿÿä‰ÿöÿÛWÿÏSÿËPÿÇLÿÄJÿÅKÿÊSÿÈUÿ»AÿºBÿÀLÿ·Aÿ°8ÿ«4 ÿ®8 ÿ¹Gÿ¦0 ÿ£, ÿ¨/ ÿ«,ÿÏDÿÍhBÿÖ‘ÿâÂÆÿçÎÓÿñáâÿïÝÞÿïÞàÿöìíÿëÖ×ÿçÍÐÿøêëÿzqrÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+ÿi ÿ°*ÿ³@ÿ©/ ÿ¬2 ÿ©0 ÿµ@ÿ¹Eÿ±: ÿ´< ÿ¸AÿÆOÿÈPÿÆOÿÇQÿÊTÿÏXÿÒ[ÿÒ[ÿÔ`ÿØbÿÚcÿÜfÿÝjÿàmÿãpÿåsÿåsÿçuÿéwÿëxÿî|ÿï}"ÿð}"ÿñ~#ÿò~$ÿó%ÿõ‚&ÿö‚(ÿ÷‚)ÿù‚*ÿúƒ,ÿú„-ÿü†-ÿþ‡/ÿÿ‡0ÿÿ†0ÿþ„0ÿý‚0ÿþ‚0ÿÿˆ2ÿÿ4ÿÿ¬5ÿÿðEÿÿÿtÿÿþ…ÿÿæHÿÿ¦*ÿþ)ÿõt*ÿíp'ÿèk&ÿèk&ÿ÷ƒ*ÿÿ3ÿÿ¨*ÿÿÙOÿÿþéÿÿùÏÿòš1ÿÕMÿÍPÿÊQÿÇMÿÄJÿÄKÿÀGÿ»CÿºAÿ¹BÿÂOÿ¼Eÿ¯7ÿª4 ÿ®8 ÿ¸Dÿ¨1 ÿ¢+ ÿ§/ ÿ£'ÿÏEÿÚvMÿØÿÚ²¶ÿçÏÒÿíÛÜÿÞ»Àÿñãäÿùòóÿùñòÿðáâÿùôõÿ~{{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,ÿkÿ°+ÿ·Eÿ«0 ÿ¥- ÿ±< ÿÁUÿ¼Kÿ²: ÿµ= ÿ¹Bÿ¿HÿÁIÿÆOÿÈQÿÌVÿÒ[ÿÓ]ÿÔ^ÿÖbÿØdÿÛfÿÝjÿànÿãsÿæuÿætÿçuÿèyÿê{ÿì{ÿî~ÿð~ ÿð~!ÿñ#ÿò#ÿó‚%ÿôƒ&ÿö„'ÿ÷…(ÿù„*ÿú„*ÿû…+ÿü‡-ÿÿ‡.ÿÿ‡/ÿÿ‡0ÿþ…0ÿýƒ0ÿþ„/ÿÿ…0ÿÿ‹2ÿÿŸ8ÿÿÕJÿÿü\ÿÿôSÿÿÄ>ÿÿ—4ÿùy,ÿìo'ÿèj&ÿæg%ÿæk%ÿîn%ÿø{(ÿú}&ÿþ£&ÿÿ÷œÿÿÿûÿõºWÿØU ÿÌOÿÉOÿÆLÿÄJÿÄJÿÀHÿºCÿºBÿ·?ÿµ<ÿ´<ÿ¯8ÿª3 ÿ¬5 ÿ¸Dÿ­5 ÿ * ÿœ' ÿ¢(ÿÑEÿá‚Uÿß©šÿÔ¨­ÿçÏÒÿôèéÿìØÚÿõéêÿúóóÿùóóÿôèéÿúüûÿƒ„„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ+ÿk ÿ°)ÿ®6 ÿ )ÿ£, ÿ¯: ÿ¸Cÿ¶?ÿ²; ÿ¶> ÿ»Cÿ½FÿÂJÿÆOÿÈSÿÌXÿÐZÿÓ^ÿÖbÿØgÿÛiÿÝkÿßoÿâqÿåvÿçyÿçxÿè{ÿê~ÿëÿíÿïÿðÿñ‚ÿñ„"ÿò…#ÿô…$ÿõ†%ÿ÷†&ÿø…'ÿù†(ÿú†*ÿû†+ÿü‡-ÿþ‡.ÿþ†/ÿÿ‡/ÿþ…/ÿý…/ÿÿ…0ÿþ„/ÿþ…0ÿÿ“4ÿÿ¥:ÿÿÃBÿÿÑDÿÿ±>ÿþ†0ÿòr(ÿêm'ÿæj&ÿäf$ÿäi$ÿçj%ÿék%ÿéd ÿù”(ÿÿô¨ÿÿÿîÿüÀNÿá`ÿÍPÿÊOÿÆLÿÄJÿÁHÿÃKÿÃLÿ¸Aÿ¶>ÿ³<ÿ±:ÿ¯7ÿ©3 ÿ¬5 ÿ²: ÿª3 ÿ¡* ÿ' ÿž$ÿÑFÿê“dÿòϽÿÖ­²ÿÜ»ÀÿòäæÿúóóÿþüýÿÿÿÿÿóçèÿïÝÞÿøðñÿ{stÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ)ÿh ÿ®#ÿ¬/ÿ * ÿ¥. ÿ¨/ ÿ«1 ÿ¯6 ÿ³; ÿ·? ÿ½Fÿ¿IÿÄLÿÇRÿÌWÿÎZÿÒ]ÿÕbÿØgÿÛkÿÞmÿßoÿásÿävÿæyÿç{ÿè}ÿé€ÿëÿì‚ÿîƒÿð…ÿñ†ÿñˆÿò‡!ÿóˆ"ÿô…!ÿõ„ÿ÷ˆ%ÿø‡&ÿù‡'ÿúˆ)ÿûˆ*ÿüˆ+ÿýˆ-ÿý‡.ÿý†.ÿý†-ÿý…/ÿþ…0ÿþ„/ÿü-ÿü‚/ÿý/ÿÿ‡/ÿÿ 7ÿÿš6ÿú}-ÿïq(ÿêl'ÿæi&ÿãf$ÿâf$ÿãe#ÿãf#ÿä`ÿôƒ'ÿÿë¯ÿÿýÂÿü£(ÿàZÿÍQÿÉOÿÇMÿÅJÿÁHÿÉNÿÇOÿ¹Bÿ¶>ÿ³<ÿ±:ÿ®7ÿª4 ÿ©2 ÿ¦. ÿ£, ÿ * ÿœ( ÿ %ÿÓJÿë•fÿôÕÃÿåÉÌÿéÒÕÿúóôÿúóóÿõëìÿ÷íîÿøñòÿëÒÖÿôßâÿtdfÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&ÿdÿ¨ÿª+ÿ¡) ÿ¦- ÿª1 ÿ®5 ÿ°8 ÿ¹A ÿ¾E ÿ½GÿÂKÿÇPÿÌWÿÑ\ÿÒ^ÿÕbÿØgÿÛkÿÝmÿßqÿáuÿåxÿæ{ÿè}ÿé€ÿë„ÿì…ÿí…ÿí‡ÿïˆÿð‰ÿñŠÿò‹ÿò‰ÿôƒÿõ‡ÿ÷‰"ÿö‚ ÿøˆ%ÿûŒ(ÿúŠ)ÿúˆ)ÿü‰*ÿû‡,ÿû†,ÿû…-ÿû„-ÿûƒ-ÿü….ÿû‚.ÿù~,ÿ÷z+ÿöy+ÿù|,ÿû.ÿú~-ÿôt*ÿïs(ÿêm&ÿæg%ÿãf$ÿád#ÿáb#ÿãf#ÿçcÿõˆÿÿñ¤ÿÿúÃÿó ÿÖNÿÌPÿÉNÿÇMÿÄKÿÂHÿÂHÿ½Fÿ¼Dÿ·?ÿ²<ÿ°9ÿ®7ÿ¯6ÿ©2 ÿ¥. ÿ£- ÿ * ÿ›& ÿ£%ÿÙQÿïŸoÿïË»ÿß¿ÂÿéÑÓÿÿýýÿýûûÿæËÎÿìØÚÿüúúÿøîïÿ÷åèÿxlnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ#ÿ^ÿ¦ ÿ°0ÿ§/ ÿ¬2 ÿ¬1 ÿ°5 ÿ²9 ÿ¼C ÿÀG ÿ¿H ÿÄLÿÉSÿÏZÿÓ_ÿÕcÿ×gÿÛkÿÝnÿátÿãxÿäyÿç|ÿèÿéƒÿë†ÿíŠÿî‹ÿï‹ÿïŒÿðŒÿòŒÿòŽÿòŒÿô”ÿù¯1ÿüÑoÿýÝ…ÿü£&ÿü”ÿÿ¦"ÿý“,ÿú‡'ÿú‰*ÿúˆ*ÿú‡*ÿú…+ÿúƒ,ÿú‚,ÿú,ÿù,ÿ÷|+ÿôz+ÿñx*ÿòv*ÿòs*ÿðr)ÿîq(ÿìp'ÿêm&ÿäh%ÿåg%ÿèl%ÿäg$ÿãc#ÿèdÿü³PÿÿÿéÿÿߌÿîwÿÕRÿÌQÿÏRÿËOÿÃJÿÀHÿÀFÿÀGÿ¹Cÿµ>ÿ±;ÿ¯9ÿ¯7ÿ±8ÿª2 ÿ¥. ÿ¢, ÿ¡* ÿ¨2 ÿª(ÿà]!ÿó©zÿà°¥ÿÒ¦«ÿÞ¼Áÿòæçÿÿþþÿ÷íîÿúõõÿÿÿÿÿÿþþÿúö÷ÿ‚‚‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿWÿ¤"ÿ¹9ÿµFÿ¶? ÿ¯1 ÿ²8 ÿ¶= ÿ¼C ÿ¾E ÿÁH ÿÇPÿÊUÿÐ[ÿÔaÿØhÿÚkÿÝoÿßtÿè†ÿê†ÿç~ÿèÿé…ÿë‰ÿìŠÿîŒÿïÿðÿñ’ÿñ‘ÿò’ÿó’ÿóÿõš ÿù¸/ÿþÒNÿÿß^ÿÿçYÿÿäÿÿÙdÿü™ÿø†%ÿúŠ'ÿúˆ'ÿù‡)ÿù…)ÿú„*ÿù+ÿø*ÿö}*ÿõ{*ÿôy*ÿòv*ÿñt*ÿïs)ÿìp'ÿën'ÿêl&ÿçi%ÿäg%ÿåg$ÿëo&ÿém%ÿå]ÿò†$ÿÿõ¾ÿÿá¯ÿõ„#ÿá_ÿÑUÿÎTÿ×[ÿÌPÿÃIÿÂIÿ¿Fÿ¿Fÿ·@ÿµ?ÿ·@ÿ²;ÿ¬5 ÿ«4 ÿ¨1 ÿ¤. ÿ£. ÿ¤- ÿ±= ÿ¯+ÿÜX ÿæšsÿå½³ÿËœ£ÿز¸ÿöíîÿÿÿÿÿÿÿÿÿÿÿÿÿüøøÿûõõÿùùúÿ}yxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿPÿ›ÿ¼6ÿ³@ ÿ¶? ÿ°4 ÿ²7 ÿ·= ÿÁH ÿÀG ÿÇPÿÊS ÿÌXÿÒ_ÿÕeÿÛkÿÝnÿßsÿâwÿêˆÿíÿë‡ÿê‡ÿì‹ÿìÿîÿð’ÿñ”ÿñ•ÿó—ÿó—ÿô–ÿô–ÿô–ÿô–ÿõ–ÿø˜ÿù˜ÿý¿@ÿÿÿßÿÿï«ÿýŸÿù†$ÿøŠ'ÿùˆ'ÿù‡(ÿø…(ÿùƒ)ÿø‚)ÿö*ÿõ|*ÿôz*ÿòx)ÿñu)ÿðs)ÿîq'ÿën'ÿél&ÿèk%ÿçh%ÿãf$ÿåg$ÿîu(ÿôqÿöŒ1ÿþí©ÿÿñ§ÿò„$ÿÞWÿÓXÿÍQÿÎRÿÐUÿÈNÿÂIÿÁGÿ¾Eÿ½Fÿ¹Bÿ´=ÿ¹Cÿ¹Bÿ­6ÿ¨2 ÿ¦0 ÿ£- ÿ¬5 ÿ¬3 ÿ¥. ÿ±-ÿÝ[#ÿåž{ÿðÕÌÿÛ·¼ÿÛ¶»ÿôêêÿýûüÿúõöÿöëìÿðßàÿòâäÿúõõÿ}xxÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿÿ³*ÿ§.ÿ®2 ÿ°5 ÿµ9 ÿº@ ÿ¾C ÿÁH ÿÎ^ÿÍW ÿÎZ ÿÔbÿÙiÿÝnÿßsÿáwÿä|ÿè„ÿëÿëŒÿìŒÿîÿð“ÿð•ÿò—ÿò™ÿóšÿôœÿôœÿõœÿõšÿõšÿõ˜ÿõ–ÿõ•ÿöÿü±.ÿÿÿÊÿÿõÌÿþ°"ÿøˆ ÿ÷Š%ÿø‰%ÿ÷‡'ÿ÷…'ÿöƒ(ÿö(ÿõ(ÿó|(ÿòy)ÿñw(ÿñu(ÿîs(ÿìp'ÿên'ÿél&ÿél%ÿèk%ÿåh$ÿæe$ÿòwÿþÁQÿÿõÒÿÿè¡ÿðƒ$ÿßZÿ×ZÿÒVÿÏTÿÐTÿÍRÿÇMÿÂIÿ¿Hÿ½Eÿ½Eÿ¸Bÿ²;ÿºEÿ¾Kÿ®7ÿ¨2 ÿ©2 ÿ¥/ ÿ¦. ÿ§/ ÿ›%ÿº2ÿér7ÿê­ÿçÄÀÿæÊÏÿéÒÔÿñäåÿöëìÿêÒÔÿâÃÆÿðßàÿüôöÿúøøÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ;ÿƒÿµ(ÿª/ÿ®1 ÿ¯4 ÿ·< ÿ¾C ÿ¿C ÿÃI ÿÌX ÿÍW ÿÑ^ ÿÖe ÿÛnÿßsÿáxÿä~ÿç‚ÿé‡ÿë‹ÿìŽÿð“ÿñ–ÿò™ÿóšÿôÿôžÿõŸÿõ ÿö¢ÿ÷¢ÿö ÿöŸÿõÿöœÿöšÿö˜ÿ÷™ÿÿÒRÿÿþ±ÿþÍDÿù‹ÿöŠ$ÿ÷Š%ÿöˆ&ÿõ†&ÿõƒ'ÿô'ÿô}'ÿòz'ÿñy'ÿñv'ÿït'ÿíq'ÿën'ÿìq(ÿîr(ÿìn&ÿçj%ÿím%ÿômÿú«CÿÿýÛÿÿì¤ÿ÷…ÿæ]ÿá_ÿÚ[ÿÓTÿÏPÿÍPÿÊOÿÅKÿÂIÿÁHÿ½Eÿ½Dÿ¸@ÿ²;ÿµ?ÿ»Eÿ¯8 ÿ¨2 ÿ°8 ÿ¨1 ÿ¡* ÿ¡* ÿ%ÿÃ8 ÿçzCÿß ˆÿá¼»ÿë×ÚÿîÛÝÿçÌÏÿíØÙÿòãåÿìÙÛÿëÕ×ÿîÚÜÿñáãÿ€~ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ1ÿu ÿ²$ÿ³7 ÿºB ÿ³7 ÿµ9 ÿ»@ ÿ¿C ÿÈO ÿÑ] ÿÏY ÿÓ_ ÿØh ÿÝqÿàvÿã|ÿç‚ÿé‡ÿëÿîÿð”ÿñ˜ÿòœÿóžÿô ÿö¤ÿö¤ÿö¤ÿö¤ÿø¦ÿø¦ÿ÷¤ÿ÷£ÿ÷¢ÿø¤ÿø ÿö›ÿ÷˜ÿü®%ÿÿÌ6ÿÿ´.ÿú“#ÿõ‹#ÿõŠ$ÿõ‡%ÿô…%ÿô‚&ÿó&ÿò}&ÿñz'ÿñx'ÿït'ÿír&ÿìp%ÿêl$ÿêl$ÿél&ÿël%ÿñr#ÿüŽ&ÿÿÀDÿÿöÉÿÿö¸ÿÿ¯-ÿüƒ#ÿû™.ÿø“(ÿò€"ÿñ‘.ÿæ€&ÿÚ`ÿÔTÿËMÿÃJÿÃJÿ¼Eÿ¼Dÿ·@ÿ²<ÿ±:ÿ´<ÿ¯7 ÿ¨0 ÿ§0 ÿ¥/ ÿ¤, ÿ§. ÿ«.ÿÏCÿç†Sÿ泟ÿãÄÄÿåÊÌÿçÍÐÿäÆÉÿòåæÿúôõÿøðòÿñãäÿÚ³·ÿêÐÔÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(ÿdÿ§ÿ¸4ÿµ; ÿ·: ÿ¹< ÿ¼@ ÿÁF ÿËR ÿÔ_ ÿÑ[ ÿÕb ÿÚj ÿÞsÿâ|ÿåÿç‡ÿéŒÿî’ÿð–ÿñ›ÿóžÿô¡ÿõ¤ÿ÷¥ÿø¦ÿø§ÿù§ÿø¨ÿø¨ÿø¨ÿø¦ÿø§ÿø¤ÿù© ÿù¨!ÿ÷Ÿÿöœÿø™ÿü¡"ÿÿ°*ÿù™%ÿôŠ"ÿôŠ#ÿôˆ$ÿó…$ÿó‚%ÿñ%ÿñ|%ÿðy&ÿïw&ÿïr"ÿîp!ÿìm#ÿêp$ÿèl#ÿìdÿù•*ÿÿÒ_ÿÿëƒÿÿÿÜÿÿþØÿÿãbÿÿÒeÿÿåŠÿÿùšÿÿüŸÿÿöœÿÿÿËÿÿþ¦ÿÿâ™ÿûÌuÿô¬9ÿÞeÿÅJÿ¼Eÿ¾Eÿµ?ÿ±;ÿ¯8ÿ¶>ÿ²:ÿ©2 ÿ¦0 ÿ£- ÿ©0 ÿ¨/ ÿ´3ÿÛSÿæ’fÿîÊ»ÿöëëÿîÜßÿóäåÿ÷îïÿõèéÿôçèÿýûûÿðàâÿëÔ×ÿú÷øÿ{|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿSÿžÿ¸.ÿ­2ÿµ8 ÿ»@ ÿÁE ÿÄI ÿÊO ÿÑ] ÿÔ] ÿØd ÿÜm ÿáxÿæ‚ÿé†ÿëÿî‘ÿð—ÿò›ÿóŸÿõ£ÿø¦ÿø¨ÿùªÿù«ÿù«ÿú¬ÿú¬ÿú¬ÿú¬ÿù«ÿù­ÿø©ÿø¦ÿù§ÿ÷¢ÿöžÿöšÿù !ÿþº+ÿú¢$ÿôŠ ÿô‰ ÿó†"ÿñ„#ÿñ€$ÿñ~$ÿð{$ÿðw#ÿîv$ÿ÷ Eÿü¿bÿú¶eÿùÑiÿö«GÿùŠ,ÿÿÕOÿÿÿßÿÿÿÿÿÿÿÿÿÿÿúÿÿýÜÿÿ÷²ÿÿëŠÿÿêuÿÿï†ÿþë£ÿúÌÿù®SÿþÝqÿÿÿäÿÿÿÍÿòŒ ÿÊIÿ¾Gÿ¼Dÿ³=ÿ±:ÿ±:ÿ²;ÿ«4 ÿª2 ÿ¬4 ÿ©0 ÿ¥- ÿœ( ÿ±+ÿäe)ÿíªƒÿößÔÿÿÿÿÿûõöÿóæçÿðàáÿôççÿüøøÿýûûÿûõöÿëÕÖÿðÙÜÿracÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAÿŒÿÀ2ÿ´5ÿ²4ÿÀC ÿÅG ÿÅH ÿÊN ÿÖc ÿÖa ÿÙf ÿßp ÿã{ÿé‡ÿêŠÿìÿï–ÿòœÿô¡ÿö¤ÿø¦ÿù©ÿù¬ÿü±ÿû±ÿû¯ÿú¯ÿú¯ÿû¯ÿû®ÿú®ÿú®ÿú®ÿù©ÿø¥ÿø¤ÿö¡ÿö›ÿù£!ÿþÔ6ÿûº/ÿ÷†ÿú¡ÿõÿñ}ÿñ€"ÿð#ÿîz$ÿìu ÿðz"ÿÿÞœÿÿÿÜÿÿì’ÿÿÜwÿÿçcÿÿøŽÿÿýÂÿþþøÿþùüÿÿþøÿÿÿ¨ÿÿð`ÿÿ±-ÿý‡ÿö‡ÿîÿænÿÞY ÿØOÿëgÿüÄUÿÿÿæÿø³NÿÖWÿÂHÿ»Bÿ²<ÿ¯8ÿ¶?ÿ·Bÿ¨1 ÿ¬3 ÿ¶?ÿ­3 ÿ¡* ÿ™$ÿÁ7ÿêy?ÿ﹚ÿüòëÿþýýÿÿÿÿÿüøøÿòáãÿñàãÿèÐÒÿáÃÆÿæÍÐÿðàáÿéÆÊÿjSUÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ2ÿu ÿ´%ÿ¶5ÿµ7ÿ¼= ÿÄE ÿÆH ÿÌO ÿÙk ÿ×c ÿÛh ÿàr ÿä| ÿéˆÿëÿî“ÿñšÿóŸÿö¤ÿø¨ÿù¬ÿú­ÿú¯ÿü´ ÿü³"ÿû²"ÿü±#ÿû²$ÿû²#ÿû°"ÿú°!ÿú¯ÿú­ÿú«ÿø¨ÿø¦ÿ÷¤ÿõžÿ÷œÿþÌ:ÿþâUÿü¾BÿÿçyÿüÌmÿú°=ÿö$ÿî| ÿìrÿëlÿõ~ÿÿãÿÿÿÍÿÿ®(ÿÿ‹ÿÿ³/ÿÿÊTÿÿ÷Úÿþþÿÿþøèÿÿþîÿÿÿtÿÿô=ÿÿ£.ÿú‰+ÿèu$ÿÕPÿÏMÿÑTÿÔZÿÒOÿÞZ ÿûËxÿÿý¾ÿæƒ#ÿÁCÿ·?ÿ³<ÿ®6ÿµ@ÿ¸Fÿ¨1 ÿ§1 ÿ¶Cÿ§0 ÿ( ÿ %ÿÔHÿìYÿñȱÿüöñÿýúûÿýúûÿúôõÿîÛÝÿðàâÿÛ·ºÿÊ•šÿÑ¢¨ÿÞ»¿ÿóÜßÿvhjÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ#ÿ\ÿ£ÿ¾6ÿ¼?ÿ½<ÿÃC ÿÈH ÿÍP ÿÖ` ÿÙa ÿÝj ÿát ÿå~ ÿéˆÿí’ÿñ˜ÿóŸÿô£ÿ÷©ÿú­ÿú¯ÿû°ÿû²!ÿü³%ÿý´'ÿý´)ÿþµ*ÿüµ)ÿüµ'ÿüµ'ÿü²%ÿú±#ÿú¯ ÿú®ÿú­ÿø©ÿø©ÿö¢ÿöÿý­%ÿÿ×Dÿÿøtÿÿÿãÿÿÿÿÿÿþ—ÿû &ÿñzÿóŠ)ÿö–7ÿÿÑjÿÿñ”ÿüÇtÿù˜0ÿñu"ÿïs'ÿü€ÿÿÚxÿþÿöÿý÷îÿÿþÿÿÿÿÖÿÿûmÿÿ·/ÿ÷r$ÿàcÿÕZÿÐVÿÌPÿÏSÿÊQÿÄCÿáeÿþí²ÿõ®PÿÀ@ ÿµ>ÿ²;ÿ­6ÿ²<ÿ´@ÿ§1 ÿ£, ÿ­5 ÿ¤. ÿ¢+ ÿ¯+ÿÝWÿêžsÿíǹÿðàßÿÿÿÿÿþüýÿõêëÿìÖ×ÿöêêÿáÄÇÿÄŒ’ÿÇ“˜ÿÍš ÿîÕ×ÿ~yzÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿFÿÿÁ4ÿÀAÿ¾=ÿÃBÿÉJ ÿÏO ÿ×a ÿÜh ÿÝi ÿãu ÿæ€ ÿë‹ÿï•ÿò›ÿô¢ÿö§ÿù«ÿû¯ÿü°ÿû³"ÿýµ'ÿýµ+ÿý·/ÿý¸1ÿþº4ÿþ»4ÿþ¸1ÿý·,ÿü¶)ÿü´%ÿú²#ÿú¯!ÿú®ÿù­ÿúªÿö¤ÿõ ÿõ›ÿøšÿú«&ÿýÑiÿÿû¨ÿýÇSÿù„ÿû³/ÿÿéoÿÿèzÿþÙuÿ÷ŸCÿìhÿæeÿàe ÿß_ÿðl ÿÿ±0ÿÿý»ÿþÿÿÿÿÿúÿÿÿÿÿÿþØÿþÑQÿébÿÓVÿÏTÿÉNÿÈNÿÉOÿÇMÿÄHÿÙMÿýß‘ÿ÷ÈTÿ¿A ÿ²<ÿ±:ÿ¯7ÿ³:ÿ²9 ÿ¦0 ÿ¨1 ÿ¥- ÿ + ÿŸ(ÿÀ4ÿær7ÿê­ÿîÑÉÿñâãÿÿÿÿÿüùùÿùñòÿûööÿöííÿíÙÜÿÕ¬±ÿ¼ˆÿ½‚‰ÿÏ›¡ÿsdfÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ2ÿu ÿ¹(ÿÁ;ÿ½<ÿÅBÿÊI ÿÐO ÿØa ÿßp ÿào ÿåu ÿè€ ÿëŒÿð–ÿòÿõ¥ÿø©ÿú­ÿû°ÿü³!ÿýµ(ÿý·.ÿý¹3ÿþ»9ÿþ¼<ÿþ¾?ÿþÀAÿþ¾=ÿýº4ÿý¸/ÿý¶*ÿü´&ÿú²"ÿú¯ÿù­ÿø©ÿ÷¦ÿö¢ÿò›ÿñ“ÿò‹ÿô‰ ÿüÌ+ÿþÑJÿýÆ<ÿÿå>ÿýÃKÿö¤=ÿíwÿçfÿáfÿÞeÿßdÿße ÿâc ÿö}ÿÿÐOÿÿù€ÿÿÿ™ÿÿÿ÷ÿÿÿÿÿýâÿâaÿÎOÿÊOÿÈMÿÈNÿÅLÿÄIÿÐMÿó/ÿÿö¤ÿç—+ÿÀBÿ²;ÿ¯8ÿ¯8 ÿºAÿ³;ÿ¢, ÿ±=ÿ²BÿŸ* ÿ¢(ÿÒFÿì‘\ÿí¾©ÿõæâÿû÷øÿÿþþÿüøøÿþýýÿþþþÿïàâÿçÍÐÿðÞàÿÏ£§ÿŠÿÕ¤ªÿscfÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ!ÿWÿ¢ÿÃ6ÿ¿=ÿÅAÿÉEÿÐO ÿÖX ÿßn ÿäw ÿås ÿé€ ÿíŒÿñ–ÿô ÿø¨ÿú¬ÿû®ÿû²ÿüµ&ÿý·-ÿþ¹4ÿþ½=ÿþ¿DÿþÁIÿþÂJÿþÂJÿþÂFÿý¿>ÿýº6ÿý¸/ÿü¶)ÿû´$ÿû°"ÿú­ÿùªÿø§ÿö¢ÿóÿñ—ÿð‘ÿï„ÿô–ÿüÍ_ÿýêMÿù°+ÿîuÿçkÿãiÿáiÿáiÿßfÿÞcÿÜaÿÜaÿæg!ÿó~ ÿýŸ ÿÿÙ;ÿÿþžÿÿþ÷ÿþÒrÿæbÿÉMÿÈMÿÇLÿÅKÿÂJÿÁGÿÙN ÿýÜ_ÿýñ‰ÿÐUÿ¸>ÿ²:ÿ®8ÿ°<ÿ¹Eÿ¯8 ÿ¡* ÿ¨3 ÿ¬: ÿš& ÿ²-ÿâb&ÿô²‡ÿ÷ÜÍÿúòñÿÿÿÿÿüúûÿû÷öÿýüüÿ÷ññÿíÛÝÿæÌÏÿîÜÞÿá¿ÂÿѤ©ÿÙ¬±ÿmWZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ<ÿ‚ÿ¼+ÿÃ=ÿÇCÿÏPÿÓS ÿ×X ÿÞf ÿâk ÿçu ÿê€ ÿîŒ ÿò›ÿõ¢ÿø¨ÿú®ÿû°ÿü³"ÿý¶)ÿý¹1ÿþ½;ÿþÀFÿþÃNÿþÆUÿþÆWÿþÅUÿþÃPÿþÁGÿý½<ÿýº3ÿý·,ÿü´'ÿû±"ÿú®ÿø«ÿö¦ÿõ¡ÿóŸÿò˜ÿð‘ÿîŒÿì†ÿì‡ÿëˆÿêyÿæqÿäpÿãnÿáiÿàgÿÞeÿÜbÿÚ^ÿÙ^ÿßcÿäbÿêe ÿ÷}ÿÿÛ\ÿÿÿôÿüÆYÿßYÿÉNÿÌRÿÊPÿÄJÿÀHÿÅFÿéz ÿþò‹ÿúÛxÿÑWÿºFÿ¯7ÿ­8ÿ¬7ÿ±8 ÿ¬4 ÿ¨1 ÿ­4 ÿ¡+ ÿ™#ÿÄ6ÿâtAÿì´˜ÿôߨÿþüüÿû÷øÿøïðÿôèêÿùòóÿôéëÿïÝàÿñàâÿæÌÎÿâÅÈÿæËÎÿݲ¶ÿtceÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ'ÿ`ÿ©ÿÆ7ÿÊKÿÔ\ ÿÕU ÿØW ÿàj ÿät ÿær ÿê~ ÿïŒÿóŸÿõ¤ÿø§ÿû®ÿû³ÿü¶$ÿý¹,ÿý»5ÿþ¿AÿþÂNÿþÇXÿÿÊ`ÿÿËcÿÿÉ_ÿþÇXÿþÃNÿþÁCÿý½8ÿý¸/ÿü¶(ÿû²#ÿú¯ÿø¬ÿ÷§ÿõ¢ÿôžÿñ˜ÿîÿí‹ÿë…ÿé}ÿçwÿævÿäsÿânÿàkÿßgÿÝdÿÜbÿÛ`ÿÙ]ÿ×\ÿÜ`ÿßbÿÝ`ÿã^ÿø›3ÿÿÿÙÿýà‡ÿßbÿÉNÿËRÿÉOÿÆLÿÅKÿÌE ÿôÄOÿÿþ¦ÿíŽ/ÿÇNÿ¶Aÿ­5ÿ«4 ÿª2 ÿ®5 ÿª2 ÿ¦/ ÿª1 ÿœ' ÿ«(ÿÐFÿÙ{Uÿܦ˜ÿèËÌÿîÞàÿèÎÑÿïÝßÿîÛÜÿõèéÿùïðÿáÄÇÿãÅÈÿåÉÌÿáÁÄÿß½ÁÿÕ¦ªÿufgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@ÿ†ÿ¿.ÿÉBÿÑPÿÔQÿ×Sÿàm ÿé‰ ÿçw ÿë{ ÿð‰ÿò—ÿ÷¡ÿù¨ÿú®ÿû³ÿü¶%ÿþ¹-ÿþ¼7ÿþÁFÿþÄRÿþÉ^ÿÿÌfÿÿÌiÿÿÌeÿþÉ]ÿþÅQÿþÂGÿþÀ<ÿý»1ÿü·)ÿû´$ÿú°ÿø¬ÿö§ÿô ÿòœÿð—ÿîÿîÿî‰ÿê‚ÿç|ÿäuÿâqÿàmÿÞiÿÝfÿÚbÿØ`ÿ×]ÿÖ[ÿÖ[ÿØ]ÿ×\ÿ×\ÿåeÿú¡&ÿÿÿÊÿþëŸÿéoÿÌMÿÇNÿÂIÿÄIÿËQÿÞT ÿûÌWÿÿÿ×ÿøÉeÿÓXÿ°5ÿ­7ÿ¬5 ÿ±9 ÿ³; ÿ¦/ ÿ¥. ÿ ) ÿ›#ÿÆ8ÿÜh5ÿÕ‡oÿÞ´­ÿñââÿèÐÓÿëÖØÿ÷îïÿíÙÛÿòäåÿóææÿÖ®²ÿàÁÄÿëÔ×ÿÖ®³ÿÖ®²ÿت¯ÿhNRÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ(ÿ_ÿ¨ÿÊ<ÿÍFÿÓOÿØVÿÝ^ ÿåw ÿé~ ÿëw ÿð† ÿó“ÿõœÿø¦ÿú¯ÿû³ÿü¶$ÿý¹-ÿþ¼7ÿþÁEÿþÆSÿþÉ]ÿÿÍfÿÿÎiÿÿÌeÿþÉ]ÿþÅRÿýÁEÿý¿:ÿý»1ÿû¶)ÿû³$ÿú°ÿø¬ÿö¦ÿó¡ÿò›ÿð•ÿìÿíŽÿí‹ÿèÿåyÿãsÿànÿßkÿÞgÿÛcÿÙaÿ×^ÿÕ\ÿÓXÿÔYÿÕYÿÒWÿÔUÿîvÿÿájÿÿÿèÿþÝ\ÿêlÿÍNÿÅKÿ½EÿÀGÿÃKÿÓQÿîÿýÔnÿÿú¼ÿøÏeÿÈL ÿ»9 ÿ¶;ÿ½Aÿ®6 ÿ£- ÿ¨- ÿŸ) ÿ°)ÿ×Qÿâ‰]ÿÞ©›ÿæÉÇÿòãäÿí×Úÿûõöÿùñòÿì×ÙÿíØÚÿíÚÜÿíØÚÿÚµ¹ÿÞ»ÀÿÌž£ÿÍ ¥ÿã¼ÁÿmXZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ>ÿ€ ÿ¾.ÿÏDÿÔOÿØSÿÝZÿãj ÿêƒ ÿìy ÿð† ÿó–ÿõœÿù«ÿûµÿü³ÿü·#ÿýº,ÿþ½6ÿþÁBÿþÅOÿþÈYÿþÊaÿþËbÿþË`ÿþÉZÿþÅOÿýÂCÿý¾8ÿý¹.ÿü·'ÿú´"ÿù¯ÿø«ÿö¦ÿó ÿñšÿî“ÿìÿêˆÿè‚ÿç}ÿäwÿáqÿßmÿÞjÿÝfÿÙaÿØ`ÿÙ`ÿÖ]ÿÔYÿÓWÿÓTÿÛj ÿØaÿèzÿþó¦ÿÿæ–ÿð~ÿØZÿÌPÿÁHÿ¼Eÿ¼Dÿ»Cÿ¾EÿÉLÿØVÿçwÿýåiÿþå€ÿè‰%ÿ¿9 ÿ³5 ÿ¬/ ÿ®0 ÿ±1 ÿº5ÿÒ@ ÿár=ÿ䥇ÿñÖÎÿ÷ëëÿì×ÚÿôéëÿýúúÿïÞàÿë×ÙÿïßáÿéÑÓÿåÉÌÿáÀÃÿÕ¬±ÿ¾„ŠÿË™žÿר­ÿmYZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ&ÿWÿžÿÌ<ÿÒIÿ×PÿÞ_ ÿäl ÿçt ÿêt ÿî ÿòŽÿõ˜ÿù§ÿú¯ÿû±ÿüµ!ÿý¹)ÿý¼1ÿþÀ<ÿþÃGÿþÅQÿþÇVÿþÈYÿþÈWÿÿÇQÿþÃHÿýÀ=ÿý¼3ÿü¹,ÿû¶&ÿú³!ÿù¯ÿ÷ªÿõ¥ÿòŸÿð˜ÿî’ÿëŒÿé†ÿçÿåyÿâuÿßpÿÞlÿÜgÿÙcÿÖ`ÿÕ]ÿÕ[ÿÔZÿÓXÿÏTÿÐSÿÓ]ÿÑSÿð)ÿÿù­ÿü°>ÿÞXÿÑTÿÉLÿ¿Gÿ¼EÿºCÿ¸@ÿµ>ÿ³<ÿ²;ÿº<ÿØeÿð¬KÿûÚUÿñ³'ÿÜwÿÎI ÿÏOÿà~ÿèg ÿæd%ÿì uÿìIJÿòßÝÿíÚÝÿèÏÒÿ÷ííÿçÍÑÿׯ²ÿÏ£§ÿУ¨ÿܶºÿëØÚÿöìíÿÚ´¸ÿÆ‘–ÿÅŽ”ÿÕ¡¦ÿo\]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿq ÿ·'ÿÓFÿ×NÿÜXÿá_ÿåg ÿép ÿîy ÿò… ÿô“ÿ÷œÿù¢ÿû¬ÿü´ÿý¹%ÿý»-ÿþ¿5ÿþÀ?ÿþÃFÿþÄJÿþÄMÿþÅLÿÿÃFÿþÁ?ÿþ¿7ÿý»/ÿü¸(ÿúµ#ÿú±ÿø®ÿö¨ÿô¢ÿñ›ÿï•ÿìÿê‰ÿè‚ÿæ}ÿãwÿàtÿÞoÿÜiÿÙfÿ×aÿÕ^ÿÔ[ÿÒYÿÔ[ÿÖ\ÿÑVÿËPÿÆLÿÌHÿô¨NÿÿûÝÿû§5ÿÜWÿÐYÿÃNÿºCÿºBÿ¶?ÿ³=ÿ²;ÿ°8ÿ­6ÿ±:ÿ´6 ÿ¾5ÿÐN ÿ÷½7ÿÿÿyÿÿÍXÿýÐAÿùÅ-ÿçrÿê…TÿôƪÿøçßÿùñðÿâÅÈÿܹ½ÿ÷ìíÿѪ®ÿ³ryÿÍ¢ÿز¶ÿéÏÓÿìØÛÿçÌÏÿÙ±µÿÒ¦ªÿÚ±µÿÙ¨®ÿoZ]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿGÿŠÿÊ9ÿØNÿÚRÿàZÿçt ÿì ÿîw ÿï| ÿôÿ÷¤ÿù£ÿú¦ÿû¯ÿüµ ÿýº(ÿþ¼-ÿþ¿5ÿþÀ;ÿþÀ?ÿÿÁ@ÿýÁ@ÿýÀ<ÿþ¿6ÿý¼1ÿüº*ÿû·&ÿú´ ÿú°ÿø¬ÿõ¦ÿô¤ÿò ÿî”ÿêÿè†ÿå€ÿã{ÿáwÿßrÿÝlÿÙgÿØdÿØbÿÖ_ÿÒYÿÏVÿÏVÿÐVÿÍTÿÉPÿÂEÿØVÿýå ÿÿû³ÿö…ÿÛ[ÿÎ_ÿÂQÿ¹@ÿ·?ÿ³=ÿ²<ÿ°:ÿ­6ÿ±:ÿµ=ÿ°9 ÿ»Dÿ¶6 ÿÏLÿñ¹MÿïÍ`ÿá‹(ÿÕ>ÿäj7ÿô¼”ÿûæ×ÿúñïÿõéìÿìרÿÙ´¸ÿìØÛÿóèéÿÑ«¯ÿÞ½ÀÿçÎÑÿâÄÈÿåÈËÿëÖØÿæÎÐÿݸ½ÿæÊÍÿéÇÊÿq^`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ*ÿ[ÿ£ÿÒBÿÙOÿÞTÿæq ÿí• ÿí€ ÿð„ ÿô•ÿöªÿù´ÿú¤ÿú¦ÿü¯ÿü¶"ÿý¹'ÿý»,ÿý¾0ÿý¾3ÿþ¿4ÿý¾4ÿý¼1ÿü»-ÿüº)ÿû¸%ÿúµ"ÿú²ÿø¯ÿöªÿô¤ÿõ­ÿó¯#ÿì’ÿè‡ÿçƒÿã~ÿáxÿßvÿÝpÿÚiÿ×dÿÖbÿ×aÿÕ^ÿÐWÿÍUÿÌRÿÊPÿÉRÿÌNÿÕO ÿï—%ÿÿÿËÿþÒeÿà\ÿÉNÿ½EÿºBÿ¸Aÿ¶?ÿ³<ÿ¸Bÿµ?ÿ±:ÿ¶?ÿ±: ÿ¬4 ÿ¸Bÿ»Aÿ­2 ÿ±-ÿ­"ÿ¸ ÿàY"ÿò¨vÿùÛÅÿþ÷ñÿýûüÿêÕØÿâÄÇÿÙ´¸ÿϤ¨ÿÿþÿÿÿüýÿñãåÿôéêÿë×Ùÿݹ½ÿïÝÞÿöìíÿéÏÒÿæÊÎÿéÇËÿmXZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ6ÿlÿ´$ÿÙIÿÜSÿâ`ÿé ÿëz ÿðŒ ÿóš ÿô™ÿø²ÿù®ÿú£ÿû¨ÿû°ÿüµ ÿý¶#ÿý¹&ÿü¼)ÿý¼*ÿü»)ÿý¹)ÿú¹%ÿû·$ÿûµ!ÿú³ÿø®ÿö«ÿó¥ÿòŸÿñ¡ÿðŸÿêÿè†ÿæƒÿá{ÿßsÿÝoÿÛkÿÖfÿÕaÿÓ]ÿÑ\ÿÏWÿÌUÿËSÿÊPÿÉPÿÏOÿáb ÿ÷¬Eÿÿû¨ÿýÝwÿâoÿÆKÿ¼Eÿ¸Bÿµ>ÿ·@ÿ¼Cÿµ<ÿ·@ÿºBÿ¶>ÿ¯8 ÿª2 ÿ¨1 ÿ¥+ ÿ¬2 ÿ¢* ÿ™"ÿ§ ÿÒDÿï‘[ÿùѳÿþóéÿÿýüÿÿÿÿÿþÿÿÿ÷îïÿû÷÷ÿáÅÉÿàÂÅÿéÓÖÿìÙÛÿâÆÉÿÛ·»ÿñáãÿ÷ìíÿçÎÐÿÛ·»ÿÑ£¨ÿÈŽ”ÿeKNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAÿ~ ÿÂ/ÿÞRÿßUÿâXÿçd ÿëq ÿðŽ ÿôšÿõšÿ÷¤ÿù¦ÿú£ÿû©ÿú®ÿü³ÿûµÿü·"ÿû¸#ÿû¹"ÿû¸"ÿú· ÿùµÿù±ÿø°ÿö«ÿô§ÿñ¡ÿðšÿí•ÿëŽÿèˆÿç„ÿä~ÿßxÿÝqÿÜlÿØhÿÔcÿÓ_ÿÑZÿÍWÿÊTÿÈQÿÈPÿÉSÿÌMÿâaÿü¿Oÿÿÿèÿýà”ÿßkÿÀ>ÿºCÿ·@ÿµ?ÿ»FÿÃNÿºAÿ²;ÿ±8ÿ°8 ÿ®6 ÿ«2 ÿ¦/ ÿ£. ÿ£, ÿ¯< ÿ¨1 ÿ§$ÿÎ? ÿé{Aÿ꫊ÿôÚÎÿþúøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüùúÿéÒÔÿéÒÔÿãÉËÿس·ÿèÑÔÿõéëÿàÀÄÿÏ ¥ÿÆ“™ÿТ§ÿÉ’˜ÿ]?Bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ#ÿNÿŒÿÊ5ÿáTÿá\ÿæd ÿèe ÿìy ÿò–ÿô•ÿôŽÿö˜ÿ÷žÿù§ÿú§ÿú¬ÿû°ÿû´ÿú´ÿû³ÿû´ÿú´ÿù±ÿ÷­ÿõ«ÿó§ÿò¡ÿñœÿî–ÿêÿèŠÿæ…ÿäÿàxÿÞsÿÜpÿÙjÿØgÿÕcÿÒ^ÿÐ[ÿÎXÿÊTÿÈRÿÅMÿÏIÿädÿù¾Sÿÿÿàÿÿð³ÿî‚ ÿÆA ÿ¹Bÿ·@ÿ³=ÿ²<ÿ¸Bÿ¿Hÿ¼Cÿ³:ÿ­6 ÿ§2 ÿ¯6 ÿ­4 ÿ£- ÿ£, ÿª1 ÿ­9 ÿ¬0ÿÎ@ÿëu7ÿóµ‹ÿôÖÆÿìÓÑÿïÞßÿÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöíîÿóçèÿüúùÿùóóÿíÚÜÿÝ»¿ÿåËÍÿåÎÑÿòäæÿñÜÞÿrdfÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*ÿUÿ“ÿÏ<ÿä[ÿä`ÿæaÿéf ÿìu ÿñ‰ ÿò‡ ÿò‡ÿõ‘ÿö›ÿøžÿø¢ÿù©ÿù®ÿù¬ÿù¬ÿù­ÿø¯ÿ÷®ÿõªÿó¦ÿò¤ÿðÿî—ÿë‘ÿèŠÿæ…ÿä€ÿá{ÿÞtÿÛoÿØkÿÖfÿÕdÿÓ_ÿÏ[ÿÎYÿÎWÿÊRÿÉJÿÓOÿçqÿýÃlÿÿÿÖÿÿñ–ÿù¨*ÿÜ[ÿÀFÿµ?ÿ²<ÿ²<ÿ±:ÿ¯7ÿ°8ÿ·?ÿ®6 ÿ¦/ ÿ¤. ÿ·Bÿ¯7 ÿ¦. ÿ¥. ÿ§. ÿž#ÿÆ7ÿëp0ÿï¦{ÿùÞÈÿÿÿøÿîÛÝÿåËÍÿñáãÿùôôÿýúúÿùòóÿþûûÿÿÿÿÿÿþþÿ÷ñòÿë×ÙÿìרÿôèéÿûõöÿùôôÿÿÿÿÿÿÿÿÿðßâÿçËÎÿiTVÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.ÿ[ÿ—ÿÐ=ÿäVÿã[ÿæ`ÿës ÿî ÿîy ÿð| ÿò„ÿó‹ÿõ‘ÿö–ÿö›ÿöŸÿ÷ ÿö£ÿö£ÿô¥ÿô¦ÿó£ÿñžÿðžÿî˜ÿë“ÿéŽÿç‡ÿäÿâ~ÿÞwÿÛnÿØjÿÕfÿÓcÿÒ`ÿÏ[ÿËWÿÉTÿÇOÿÌM ÿç€ÿøÎtÿýìÎÿÿÿâÿÿÚwÿçyÿÐVÿÃIÿ¸?ÿ´=ÿ¸@ÿ²:ÿ­8ÿ¬5ÿª4 ÿ©3 ÿ§1 ÿ¥. ÿ®7 ÿ¹Gÿ°5 ÿ¨. ÿ¤, ÿž%ÿÃ7ÿèj+ÿò§yÿöÒ»ÿíÒÌÿóææÿôêëÿóçéÿõëìÿ÷îîÿýùúÿôæéÿóæèÿÿþþÿÿÿÿÿÿÿÿÿõéëÿéÒÕÿæÍÐÿñãäÿþüýÿüøøÿÿÿÿÿùðòÿóêëÿwmnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1ÿ]ÿ—ÿÐ:ÿå\ÿä_ÿçh ÿês ÿìx ÿîy ÿðz ÿñ ÿñ†ÿòŒÿòŒÿòÿó“ÿò–ÿò˜ÿð™ÿñ˜ÿð–ÿî”ÿë‘ÿêÿçŠÿç‡ÿäÿà{ÿßvÿÜrÿØlÿÖhÿÕeÿÓ`ÿÏ\ÿÌXÿËVÿÉSÿÍRÿèˆ&ÿþñ ÿÿÿ¬ÿÿåzÿþ¿XÿèxÿÅB ÿµ;ÿ´=ÿ²:ÿµ=ÿ¹@ÿ®7ÿ©4 ÿ©3 ÿ©2 ÿ¦/ ÿ«4 ÿ´?ÿ±: ÿ­3 ÿ¥- ÿž' ÿ¤'ÿÃ6ÿåg*ÿñ¤uÿú×¾ÿñØÑÿáÁÃÿâÄÈÿîÜßÿðáãÿøññÿúõõÿöìíÿýúûÿýúúÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿýúûÿ÷îîÿÞ¾ÁÿÔ©®ÿîÜÞÿõèêÿóçéÿûüüÿ„†…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ2ÿZÿ”ÿË8ÿâWÿä\ÿåa ÿéu ÿêq ÿìt ÿïƒ ÿï… ÿñ–ÿñÿðÿñ–ÿðÿï‹ÿíŒÿìŒÿë‰ÿéˆÿè…ÿæƒÿäÿá{ÿßxÿÞtÿÛpÿ×jÿÕgÿÓdÿÓaÿÐ\ÿÎXÿËVÿÍWÿÐXÿáeÿþË\ÿÿÿÛÿø±-ÿëi ÿçhÿÈKÿµ=ÿ³;ÿ°9ÿ¯8ÿ¯8ÿ¬6ÿ«4 ÿ­7 ÿ°9 ÿ«3 ÿ¥/ ÿ§0 ÿ¬3 ÿ¬4 ÿ¢* ÿ›' ÿ %ÿÊ= ÿãe*ÿè”iÿñǯÿøäÚÿçÊÌÿòåçÿ÷îïÿïÜÞÿçÎÑÿ÷ïðÿÿþþÿûøøÿþýýÿüùúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûøøÿàÀÄÿãÆÈÿáÁÄÿãÄÇÿúóôÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ/ÿWÿŒÿÅ3ÿáUÿãZÿã]ÿåa ÿél ÿêq ÿêq ÿëz ÿîŠ ÿï“ÿð¤ÿí“ÿê€ÿé‚ÿé‡ÿêÿéŠÿå€ÿâyÿàwÿÞtÿÜqÿÞsÿ×iÿÒ`ÿÐ]ÿÎ[ÿÍYÿÏ]ÿÑ^ÿËWÿËUÿ×]ÿë|ÿÿçqÿÿÿèÿùÆRÿÜZÿÉHÿ¹Aÿ°8ÿ°8ÿ®6ÿ®7ÿ®8ÿ¬4 ÿ«3 ÿ®7 ÿ±: ÿ¥. ÿ¢, ÿª2 ÿ¬3 ÿ§/ ÿ›' ÿ¡%ÿÌ? ÿæo4ÿç–lÿíÀªÿ÷åÜÿ÷îìÿóåçÿùñóÿüøøÿøðñÿòåçÿûøøÿùôôÿþúûÿþýýÿûøùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûö÷ÿíÚÛÿêÕ×ÿöìîÿøðñÿõãæÿhRSÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*ÿOÿ‚ ÿ»*ÿÜLÿâXÿáYÿã_ ÿæe ÿæg ÿçk ÿèn ÿèr ÿév ÿèy ÿê‡ÿêÿé‘ÿé•ÿè‘ÿç†ÿäÿâ~ÿáÿÙlÿÖcÿÓ^ ÿÐ[ÿÍYÿËXÿÌWÿÒdÿÌXÿÆOÿÇNÿÑTÿêyÿÿßAÿÿþÐÿÿã¦ÿámÿ»; ÿ²:ÿ®6ÿ«4 ÿ­6ÿ´;ÿ¶?ÿ­6 ÿ¥. ÿ£- ÿ¥. ÿ¥. ÿ¡+ ÿ + ÿž( ÿš%ÿ«(ÿÒCÿæu<ÿí©€ÿñǰÿéÉÃÿùñïÿüüüÿñâäÿçÍÐÿîÜßÿûõ÷ÿôèéÿëÕ×ÿäÆÉÿøðñÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúóôÿñÝàÿË£ÿÑ«¯ÿûøøÿ÷óôÿq`bÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&ÿEÿs ÿª ÿÓ@ÿáVÿàWÿàZÿâd ÿäi ÿâh ÿäk ÿãi ÿâg ÿão ÿãp ÿái ÿßi ÿàm ÿàuÿá{ÿÜp ÿÙj ÿÒ\ ÿÑ[ ÿÐ\ÿÎ[ÿËV ÿÉVÿÉSÿËRÿÍTÿÎUÿÐSÿØ]ÿð~ÿÿÂÿÿùÿÿò¯ÿä~ÿ·4 ÿ­5ÿ«4 ÿ¨1 ÿ§0 ÿ¦0 ÿ¦/ ÿ¤. ÿ¦/ ÿ¬5 ÿ¦/ ÿ¢+ ÿ¢+ ÿš&ÿŸ&ÿ»3ÿ×MÿàvBÿð²ÿúÞÉÿîÔÎÿد±ÿçÍÐÿøòòÿíÜÞÿéÑÔÿöìíÿüøùÿòãäÿÒ¦«ÿàÀÃÿýûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìÖØÿËœ¡ÿ¸{‚ÿز¶ÿèÉÍÿvklÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ:ÿ`ÿ•ÿÈ?ÿÜNÿÝQÿÞ^ÿád ÿß_ ÿák ÿál ÿài ÿÜ_ ÿÛ^ ÿÝg ÿÝh ÿÚ_ ÿÖ] ÿÕ^ ÿÒY ÿÑV ÿÎU ÿÎY ÿÕfÿÖgÿÊU ÿÈS ÿÈTÿÈPÿËSÿÏWÿâlÿöˆÿýžÿÿØUÿÿÿÊÿÿÕlÿØ\ÿ®3 ÿ©1 ÿ¨0 ÿ¥- ÿ¤. ÿ£- ÿ¢, ÿ¦. ÿ°6 ÿ®4 ÿ¡* ÿœ' ÿ%ÿ©(ÿÃ7ÿÏJÿÑjAÿé°’ÿýé×ÿýöîÿðÞÞÿéÒÔÿóåçÿþûûÿýúúÿúôõÿþüüÿþüýÿ÷îïÿäÉÌÿéÔÕÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿýøùÿéÕÖÿÍž£ÿΗÿcGKÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.ÿOÿ{ ÿ«!ÿÌ:ÿÚKÿÛQÿÚRÿÛ[ÿÜc ÿÞk ÿÙ\ ÿØX ÿÞs ÿÜp ÿÔY ÿÑS ÿÎR ÿÐV ÿÏX ÿÉN ÿÈQ ÿÖeÿän ÿÑW ÿÃN ÿÇSÿÇPÿÀIÿÕXÿü‘ÿÿ§ ÿÿ»#ÿÿÿÆÿÿé³ÿê ÿ¹2ÿ¦/ ÿ¦/ ÿ¨2 ÿ«6 ÿ¨1 ÿ¥. ÿ¤, ÿ¨0 ÿ¨/ ÿ™$ ÿ—!ÿ #ÿ½4ÿÖIÿÀBÿ®H/ÿÅ~oÿùæÚÿÿþûÿþûûÿüøùÿûõöÿû÷÷ÿúõõÿúòóÿû÷÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçÌÏÿÁƒ‰ÿ]=@ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"ÿ=ÿaÿŒÿ·(ÿÒDÿÚQÿ×OÿÓMÿÒMÿÒNÿÑM ÿÒU ÿÕ\ ÿÐR ÿËM ÿÊM ÿÊN ÿÊQ ÿÇN ÿÅI ÿØdÿ÷£ÿæy ÿÍEÿÑW ÿÓ]ÿÔ\ÿêxÿÿµ"ÿÿËMÿÿémÿÿóœÿçÿÀ9ÿ°:ÿ¯8 ÿ§/ ÿª4 ÿ²= ÿ®6 ÿ¦. ÿ£, ÿ›' ÿœ%ÿ¤(ÿ¸1ÿÔGÿëp2ÿà€SÿÌ‚kÿÕŸ”ÿà»·ÿúôòÿ÷îñÿôçêÿúôôÿþûûÿ÷îðÿïÛÝÿôæéÿþþþÿþýýÿÿþþÿþüýÿýúúÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþúûÿðÞàÿäÂÆÿo\^ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ,ÿGÿlÿ—ÿ½7ÿÑJÿÔGÿÐFÿÐS ÿÑW ÿÉEÿÌM ÿËM ÿÇJ ÿÇH ÿÅF ÿÄG ÿÈK ÿÔOÿñ"ÿÿý¦ÿüÐrÿñÿë… ÿêqÿõÿýÁÿÿü‹ÿÿÿäÿÿùŒÿñž!ÿÊDÿ³8 ÿ·Eÿ´@ÿ¤- ÿ¡* ÿ ) ÿž* ÿš& ÿ™#ÿ§)ÿÂ<ÿÕNÿãc&ÿó”\ÿ쫃ÿí¬ÿûèÜÿùëèÿóåæÿùòôÿóæèÿîÛÝÿòäæÿÿÿÿÿýùúÿ÷íîÿùòóÿÿÿÿÿþýýÿþþþÿþüüÿÿþþÿþûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿýûûÿü÷øÿvghÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ1ÿLÿo ÿ•ÿ³&ÿÈ4ÿÔKÿÕ[ ÿÊJ ÿÃ@ÿÄD ÿÆF ÿÃCÿÇHÿÌO ÿÖQÿò˜ÿÿî¥ÿÿÿòÿÿÿÖÿÿúÆÿÿè˜ÿÿÊ4ÿÿÇÿÿõUÿÿÿæÿÿÝtÿè„ÿÉFÿÂGÿ±7 ÿ©2 ÿª3 ÿŸ+ ÿ—$ ÿ–!ÿ"ÿª&ÿ´)ÿÇ;ÿÝ^#ÿîŠSÿë¢zÿóÇ­ÿôÚÌÿúðêÿÿþýÿøñóÿýüüÿ÷ïñÿúóóÿìØÛÿùôôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿø÷øÿxlnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ1ÿIÿhÿˆÿ¥ÿ½.ÿÊDÿÊ@ÿÉCÿÕ\ ÿÖa ÿÛ_ ÿäiÿõ´*ÿÿòœÿÿó’ÿÿä8ÿÿøZÿÿÿƒÿÿÿ¦ÿÿÿËÿÿÿÉÿÿÿÜÿÿçvÿïyÿ½3ÿ­/ ÿª1 ÿž* ÿœ%ÿ¦+ÿ£'ÿ§%ÿ¹0ÿÇ:ÿÕPÿÛb.ÿÎ`8ÿÒ|]ÿ븞ÿúáÑÿìÑÍÿèÏÏÿùðñÿÿÿÿÿöïðÿöëìÿçÏÒÿöíìÿöîîÿþýþÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿû÷øÿüøøÿÿþþÿüùúÿÿÿÿÿúûûÿ€|}ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,ÿAÿWÿr ÿŒÿ¡ÿ²$ÿÍCÿãc ÿôŒÿþ¶ÿÿÿˆÿÿÿÿÿÿûpÿÿéÿÿó ÿÿÅÿÿÄ,ÿÿÿ¸ÿÿÿÓÿÿÎhÿëx ÿÁ:ÿ«-ÿ®2ÿª.ÿ§$ÿ¶/ÿÇ<ÿÇ:ÿÐFÿès6ÿé‚MÿÚ}Tÿá˜xÿÖ—…ÿâ¶­ÿüõîÿ÷íìÿèÐÒÿëØÚÿüøøÿÿÿÿÿòåæÿúõõÿêÔÖÿùñóÿþÿÿÿÿÿÿÿþýýÿÿÿÿÿýúúÿþüüÿþýýÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿû÷÷ÿèÐÓÿÛ¶ºÿîÝßÿþþþÿþýþÿüùùÿúõöÿƒƒƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ"ÿ1ÿBÿUÿiÿ} ÿ“ÿ¨0ÿ¹J ÿÇ^%ÿÕwTÿÝQÿã !ÿè¡!ÿéqÿëiÿò¢-ÿï’"ÿèdÿÚEÿË@ÿËD ÿÏB ÿÒKÿÙTÿßd*ÿçy@ÿç…Sÿæfÿÿ嬓ÿÛ¥˜ÿæÁºÿÜ´²ÿß¼½ÿèÓÕÿôêìÿàÀÂÿôæèÿèÑÓÿËž£ÿéÔ×ÿøððÿöííÿýûüÿüøùÿÿÿÿÿýùúÿùóóÿúõõÿü÷øÿýûûÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüüÿöëìÿì×Úÿøðñÿÿÿÿÿýüüÿþýýÿùóõÿ}xyÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ,ÿ8ÿEÿQÿ]ÿjÿtÿ} ÿ…ÿ‡ÿ‰ ÿº6ÿâd%ÿäg(ÿÜa*ÿÚb-ÿâr;ÿê‚JÿåƒPÿáƒWÿð¤wÿí©„ÿð¹šÿþÞÄÿé¿°ÿćƒÿ°moÿ·zÿÚ¸»ÿÓ©­ÿÕ®²ÿéÔÖÿôæèÿʘœÿ¸†ÿ²ryÿΠ¥ÿöîîÿüøùÿüúúÿýüüÿýûûÿÿþþÿôèéÿíÚÛÿüôöÿêÔÖÿ÷ððÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿøóôÿtefÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$ÿ,ÿ2ÿ8ÿ>ÿ>ÿ=ÿF3ÿð§‚ÿöº’ÿó¸“ÿò¸•ÿï·˜ÿ㥌ÿã«–ÿä² ÿ鿲ÿõÝÒÿñÚÔÿâÂÁÿɘ›ÿ‹‘ÿ»‚ˆÿ§dkÿ´u|ÿ¿‡ÿêÕ×ÿñäæÿ¼ƒ‰ÿ¨biÿ¦ahÿÎ¥©ÿùòòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿûööÿïÜßÿ¯|ÿ…9@ÿÌ¢§ÿÿýþÿÿÿÿÿÿÿÿÿýüüÿþýýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüùùÿëÔÖÿùëíÿymoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿ ÿÿÿÿ™pkÿþñæÿÿöêÿüïäÿúìãÿ÷çáÿéÍÊÿÚ²±ÿÁˆŒÿÅŽ”ÿâÃÇÿ÷íîÿåÍÏÿÕ¯³ÿÖ®³ÿ¹}„ÿ¨fmÿ«ipÿ£^eÿ¹€†ÿ¯qxÿ¬jpÿÒ©®ÿðãäÿþýýÿÿÿÿÿýýýÿþüüÿÿÿÿÿÿþþÿÿÿÿÿûö÷ÿêÓÖÿõçèÿ±|ÿj ÿ–SZÿîÝßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþþÿ÷ïðÿãÃÇÿìÏÒÿlXZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‰knÿøèëÿïÞáÿùóóÿÿÿÿÿýüüÿèÏÒÿÚ³¸ÿÓ©®ÿÅ”ÿÞ¾ÁÿîÛÞÿΡ¥ÿ»ƒˆÿ¾„Šÿ¦`gÿ¥`gÿ¹}ƒÿ¼„Šÿ§cjÿÄ‘•ÿñãåÿÿÿÿÿÿÿÿÿÿþþÿýüüÿþûûÿÿýýÿþþþÿüúúÿüùùÿîÛÜÿôéêÿùóôÿÒ¨¬ÿ¹}„ÿÊž£ÿ÷îïÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõëìÿõêëÿíØÛÿයÿkUWÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜|ÿõàâÿÊ™ ÿæÍÐÿýúúÿòåæÿÜ»½ÿØ®³ÿÞ½Àÿܹ¼ÿÓ©®ÿŠÿÇ’˜ÿÇ–›ÿ¿ˆÿ¼‚ˆÿÁŠÿݺ¾ÿë×ÙÿÖ¯²ÿÖ°³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿÿÿÿýýýÿõêêÿýúúÿÿÿÿÿþüûÿðàâÿóåæÿýûûÿìÚÛÿà¾ÂÿõéêÿõëëÿüøùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýûûÿýüüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿùòóÿøïðÿéÐÓÿÔ¡¦ÿnYZÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ˆŠÿÿóôÿôêëÿíÛÝÿóæçÿêÕ×ÿèÑÓÿܸ¼ÿÓ§¬ÿС¥ÿ¿…‹ÿµv|ÿ½„ŠÿÙ²¶ÿãÃÆÿíרÿèÍÐÿîÜÞÿÿÿÿÿþüýÿóæèÿýüüÿÿÿÿÿÿÿÿÿýüüÿþýþÿûøøÿðßàÿûõõÿû÷÷ÿÿþÿÿÿÿÿÿðßáÿóäæÿíÚÜÿòãäÿÿÿÿÿûöõÿýûúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýüüÿûøøÿÿÿÿÿÿÿÿÿþýýÿþüýÿþýýÿúõöÿÿþþÿüùùÿÜ·ºÿÌ’™ÿaCFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿž„†ÿþôöÿÿþþÿûõöÿöììÿçÌÎÿìØÙÿß¾ÂÿΞ£ÿÛ´¸ÿÌœ ÿÄ•ÿÀˆŽÿÍž£ÿäÈËÿ÷ððÿü÷÷ÿûö÷ÿþüüÿÿÿÿÿûøùÿñãäÿÿþþÿÿÿÿÿÿþþÿúööÿïààÿüøøÿþýýÿëÕ×ÿôåèÿòãåÿçÎÐÿæËÍÿçÍÐÿúôõÿþýýÿúöõÿùóôÿýûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûö÷ÿõêëÿþýýÿþýýÿûöøÿùòóÿþýýÿóåçÿðààÿúôõÿöëìÿâ½Áÿ`CFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿš~€ÿþö÷ÿüùùÿ÷îðÿøððÿëÔ×ÿðÞàÿÖ¯³ÿÇ“˜ÿà¾ÂÿË™žÿÑ¥ªÿãÅÈÿÛµ¹ÿëÖÙÿü÷øÿÿÿÿÿýüüÿúôôÿýûûÿ÷îïÿôééÿþþþÿüùùÿüøùÿúóôÿðßàÿë×Ùÿ÷ííÿôèêÿêÑÔÿåÈËÿãÄÇÿáÁÃÿüùùÿôéêÿíÙÚÿñàáÿòãåÿùòóÿýúúÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþýýÿüùùÿöìíÿúóõÿüøùÿþýýÿýúúÿîßàÿóçéÿýûüÿüö÷ÿ{{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ“suÿëÇËÿâÄÇÿíÙÚÿíÙÛÿûøøÿøðòÿèÑÓÿß¿ÁÿÞ»¾ÿѧ«ÿß¿ÃÿéÎÑÿâÃÆÿíÚÜÿþüýÿýúûÿøóóÿóæçÿéÐÓÿëÕ×ÿÿÿÿÿÿÿÿÿüøøÿþüüÿòâäÿïÝßÿíÚÜÿöííÿüøøÿðÞàÿêÔ×ÿðáâÿìÖÙÿùïðÿñáãÿïßáÿöëìÿüùùÿýüüÿýüûÿÿÿÿÿÿÿÿÿÿÿÿÿýûûÿú÷÷ÿÿÿÿÿýúûÿøðñÿûööÿÿÿÿÿúóôÿþýýÿÿÿÿÿêÕ×ÿ÷îðÿúøøÿ„†…ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘qtÿéÄÉÿÏž¢ÿÔª¯ÿæÌÏÿþþþÿùóôÿóæçÿÞ¼¿ÿܸ¼ÿíÜÞÿöíïÿêÒÕÿõììÿûøùÿïÞàÿöíïÿþÿÿÿìØÙÿáÂÅÿöîïÿþþþÿÿÿÿÿÿÿÿÿòåæÿÛ¶ºÿܹ½ÿòåçÿüûúÿñâãÿñâãÿòåçÿþþþÿôçèÿà¿ÃÿçÐÓÿýüýÿüøùÿðáãÿðàáÿ÷ïïÿýúúÿÿÿÿÿÿÿÿÿùóôÿëØÙÿþþýÿþýýÿüùùÿûøøÿÿÿÿÿûøøÿýúúÿüùùÿõìíÿýûûÿúúúÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ƒÿÿùúÿÛ±¶ÿÇ“ÿæÃÆÿñÙÜÿÿöøÿý÷÷ÿéÇËÿÞµ¹ÿð×ÚÿúëìÿòÙÛÿóÝßÿûíïÿëÌÐÿêÊÍÿöãåÿá¼ÀÿἿÿýñóÿÿÿÿÿÿÿÿÿÿÿÿÿîÓÕÿðÙÛÿñÙÜÿúïðÿÿøøÿýõõÿýððÿ÷äçÿþòôÿÿÿÿÿêÍÑÿÛ±¶ÿñÙÜÿóÜßÿếÿèÆÊÿüðñÿÿûüÿÿÿÿÿòÜßÿðÖØÿæÂÇÿþõõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøøÿÿÿÿÿÿÿÿÿþþþÿ‡‡‡ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŽjnÿûòóÿéÔÖÿçÏÑÿäÉËÿÏ ¤ÿçÎÐÿöïðÿàÀÄÿݺ¾ÿâÃÆÿÛµ¹ÿׯ³ÿܹ½ÿäÉÌÿÚ¶¹ÿÒ§«ÿÙ³·ÿéÕ×ÿØ´¶ÿß¿Ãÿùööÿõíîÿõíïÿ÷ðñÿüûûÿ÷ðñÿú÷÷ÿúõõÿýüüÿòâäÿâÂÅÿâÄÇÿíÝÞÿöíîÿôêêÿôéêÿë×ÙÿÓ©®ÿÝ»¾ÿúôôÿõëíÿèÓÕÿÕ®²ÿÕ«®ÿëÖÙÿüúúÿùõõÿóêëÿõîîÿöìîÿú÷÷ÿýþþÿöìíÿñâäÿüûûÿøøøÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ,))ÿ,+,ÿ///ÿ*&&ÿ#ÿ&ÿ+))ÿ' !ÿ)$$ÿ("#ÿ$ÿ$ÿ' ÿ' !ÿ%ÿ#ÿ&ÿ-,,ÿ&!"ÿ'##ÿ-,,ÿ+'(ÿ+)*ÿ/00ÿ/00ÿ.//ÿ.//ÿ---ÿ.--ÿ+'(ÿ' !ÿ' ÿ("#ÿ,,,ÿ/11ÿ.--ÿ-,,ÿ)$#ÿ'"#ÿ-,,ÿ+)*ÿ' ÿ%ÿ$ÿ-++ÿ/00ÿ,**ÿ*&&ÿ+((ÿ,**ÿ-,,ÿ.//ÿ-++ÿ*&&ÿ...ÿ---ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿdxx-rebirth-0.58.1-d2x/arch/win32/d2x-rebirth.rc000066400000000000000000000030141217717237500211110ustar00rootroot00000000000000// Microsoft Visual C++ generated resource script. // #include "include/resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" IDI_DXX_ICON ICON "d2x-rebirth.ico" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "include/resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "IDI_DXX_ICON ICON ""d2x-rebirth.ico""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Icon // #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED dxx-rebirth-0.58.1-d2x/arch/win32/include/000077500000000000000000000000001217717237500200565ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/arch/win32/include/resource.h000066400000000000000000000007521217717237500220620ustar00rootroot00000000000000//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by d2x-rebirth.rc // #define IDI_DXX_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 147 #define _APS_NEXT_COMMAND_VALUE 40028 #define _APS_NEXT_CONTROL_VALUE 1009 #define _APS_NEXT_SYMED_VALUE 102 #endif #endif dxx-rebirth-0.58.1-d2x/arch/win32/messagebox.c000066400000000000000000000017101217717237500207330ustar00rootroot00000000000000/* * messagebox.c * d1x-rebirth * * Display an error or warning messagebox using the OS's window server. * */ #include #include "window.h" #include "event.h" #include "messagebox.h" void display_win32_alert(char *message, int error) { d_event event; window *wind; int fullscreen; // Handle Descent's windows properly if ((wind = window_get_front())) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); if (grd_curscreen && (fullscreen = gr_check_fullscreen())) gr_toggle_fullscreen(); MessageBox(NULL, message, error?"Sorry, a critical error has occurred.":"Attention!", error?MB_OK|MB_ICONERROR:MB_OK|MB_ICONWARNING); if ((wind = window_get_front())) WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); if (grd_curscreen && !error && fullscreen) gr_toggle_fullscreen(); } void msgbox_warning(char *message) { display_win32_alert(message, 0); } void msgbox_error(const char *message) { display_win32_alert(message, 1); } dxx-rebirth-0.58.1-d2x/d2x-Info.plist000066400000000000000000000014311217717237500172160ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable d2x CFBundleIconFile d2x-rebirth CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature DCT2 CFBundleVersion 0.57.3 CSResourcesFileMapped LSPrefersCarbon NSMainNibFile MainMenu NSPrincipalClass NSApplication dxx-rebirth-0.58.1-d2x/d2x-rebirth.bmp000066400000000000000000000040661217717237500174140ustar00rootroot00000000000000BM66(   %&4   GN    WhG t‰‘š"¨!Ÿ ".&%¤%¦)Ÿ*¸+±,3,+¯'¥.¬.£*ª)2/1413¸4©1·0Á5³7±2«3973¯9 ;79¸=·: 8:9À:Â?½@Ç:²<¼=ÎB¹C·?ÊHÇKËF¾HÙM àM ÒN ÎSÍPÉRÛX âX ×]ÒT ÖYÙT!ÐZî]ÍV%ÕaÛ]ÛgÐa#×`$Ùlôjálàb*ÞhêpØj×p æi îi#Öd<Õm%ípçqàróxçz×jDÊjLÚo<àx%óv&åt5ë…ÿ|ì~ç€áñz.âx:ú†ß~.Ú€/÷#ñƒ$ö~6ê7ÿƒ*ëŒü†.î–û!õ–ù’±z…ñ‘#à‹>ù›Ýƒ\ã3ì“$æˆLÙ„f÷ ëFá“Fø§öžé“Jë—>ïœ3ú˜>êaöœ7ô¢%Ó‚ìSè¡Gþ´î Iä•uñ¥>È‘•ú¦C¾”™í¦Mü±#Å”œþ»î®Dۛל”ü¸-ÿ³Aö¬cø°Zê­i÷·PÍ¢§ÿºHþÁ8ÿÀKÓ¨­÷¼bïºmùÀXè®þÈ?õ²ŽýÅNð²”Ô®·Û¯´üÀr÷Âq㲳䶪ùÂ|ýÈlþÌbùËvþšÿß:㻾þÑpî¾·ã½ÆÞÀÄìĹÞÅÍþàlíÈÉâËËþÛýænëÌÐæÏÏîÑÎñÒÖëÔÔýè™ýä©ÿë’ýÜÌûØÛëÚÝûížôÞ×îÞÚöáÙÿí²ÿÿyóáäÿæÒþø–úââôäàîâéóèèþýª÷êò÷íìÿíñúïïüð÷öòôýüÒÿöõýøûþÿéÿýøúüÿÿüþüÿý  ÿÿÿÿÿÿÿÿÿÿÿÿöùÿÜúúÚÝõüÿÿÿüúóÍÜ ÏóðÓõü÷üÿ÷ÿÿðãÕ!.˜y¢áÿúÿÿüÚóÖãÿžc«.—éw%oëÿð÷úúÿðþ '+·G)³›˜b*4'¾ÿ÷ãÿüÚí0(6^Ÿ@39<غ%626šããÖÑÝÕ %44?P²»Ê;EAä¡9B4#n©ÚÝüô 'B6?BgŠJ¯ž{§Jž—9?44'ãúÿú#4BCEERRHè’FQ>Ä>BG4#9ã÷ðí%46CELQRXkàO_XJäž1.64%¬ïüÜ(4?GELRX_}àeddrÉȺ¹gB"mÑÝÙ(6CELRXdde×zeh}°ANT|¡“;¸Ñÿ)/CGLRPdhqq‡Þ™tÉèSLEB23­´ô34?EK[`irxƒtÉñÃ…ñ`EG?63­Ýö+68MW^lu~}}ƒ¨eN±EG64"Æðù32GWjv‚‰‡·»}}qedeÇNEC6(2Æóÿ!8KbsŽ‘”œ†¿z}qh}ߥ–TC6(@Ûîê8Pl„”¨¨¨””É~±µûì€`¹26#mÿÝÕ >Ruœ¨®¶®¨‘œ½€S™øRE§26!ÀýïÂ$Ru”®¿É¶ œ‰i`XHÊTDÎ2".ÛðÖÍ Ii‹ ¶¿¶ œsj[RDÈOPDK{jÔ8#<÷÷úüÿÿÿê JÎÌ×13MŒå÷óÿÿÿÿÿðÿ˼Ҵˆ©æÿã¦ÿÿÿÿô ÿÓ¤´êúüõã÷ÿÿþþÜâöÙôôÿíúôíþþÿÿÿ 7 & ,:5&-, 577dxx-rebirth-0.58.1-d2x/d2x-rebirth.desktop000066400000000000000000000003331217717237500203000ustar00rootroot00000000000000[Desktop Entry] Name=Descent 2 Comment=DXX-Rebirth source port of Descent 2: Counterstrike from 1996... Exec=d2x-rebirth Icon=d2x-rebirth Terminal=false Type=Application Categories=Game;ActionGame; StartupNotify=false dxx-rebirth-0.58.1-d2x/d2x-rebirth.xcodeproj/000077500000000000000000000000001217717237500207025ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/d2x-rebirth.xcodeproj/project.pbxproj000077500000000000000000006165341217717237500240000ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 42; objects = { /* Begin PBXBuildFile section */ 179E6ECE11F37C0500175C54 /* hmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 179E6ECD11F37C0500175C54 /* hmp.c */; }; 179E6ECF11F37C0500175C54 /* hmp.c in Sources */ = {isa = PBXBuildFile; fileRef = 179E6ECD11F37C0500175C54 /* hmp.c */; }; 179E6ED211F37C1900175C54 /* hmp.h in Headers */ = {isa = PBXBuildFile; fileRef = 179E6ED011F37C1900175C54 /* hmp.h */; }; 17DFA6B910C1A2D100674D11 /* net_udp.c in Sources */ = {isa = PBXBuildFile; fileRef = 17DFA6B510C1A2D100674D11 /* net_udp.c */; }; 17DFA6C410C1A3BA00674D11 /* multi.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032DC066B399A008A67A3 /* multi.c */; }; 17DFA6C510C1A3BC00674D11 /* multibot.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032DD066B399A008A67A3 /* multibot.c */; }; 17DFA6C610C1A3D400674D11 /* kmatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032F9066B39CE008A67A3 /* kmatrix.c */; }; 670E39B0066C598A0085B671 /* mve_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421406687AD900DF26D8 /* mve_audio.c */; }; 670E39B1066C598A0085B671 /* decoder16.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421006687AD900DF26D8 /* decoder16.c */; }; 670E39B3066C598B0085B671 /* decoder8.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421106687AD900DF26D8 /* decoder8.c */; }; 670E39B5066C598B0085B671 /* mveplay.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421906687AD900DF26D8 /* mveplay.c */; }; 670E39BF066C598E0085B671 /* mvelib.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421706687AD900DF26D8 /* mvelib.c */; }; 670E39C5066C59A00085B671 /* mve_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 670E39C4066C59A00085B671 /* mve_main.c */; }; 670E39DA066C59C40085B671 /* libmve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0D106688B1100056A5A /* libmve.h */; }; 670E39EC066C5A0F0085B671 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6710AAFE066B2D6100DB0F68 /* SDL.framework */; }; 670E39ED066C5A100085B671 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 670E3A42066C5C420085B671 /* SDLMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 67F6FED0066B13B400443922 /* SDLMain.h */; }; 670E3A43066C5C430085B671 /* SDLMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 67F6FED1066B13B400443922 /* SDLMain.m */; }; 6710AAFF066B2D6100DB0F68 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6710AAFE066B2D6100DB0F68 /* SDL.framework */; }; 6710AB00066B2D6100DB0F68 /* SDL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6710AAFE066B2D6100DB0F68 /* SDL.framework */; }; 6710AB69066B2E0400DB0F68 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6710AB68066B2E0400DB0F68 /* OpenGL.framework */; }; 675ED149066B198A00E42AA7 /* d2x-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 675ED123066B196700E42AA7 /* d2x-Info.plist */; }; 676032E4066B399A008A67A3 /* multi.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032DC066B399A008A67A3 /* multi.c */; }; 676032E5066B399A008A67A3 /* multibot.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032DD066B399A008A67A3 /* multibot.c */; }; 676032FB066B39CE008A67A3 /* kmatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 676032F9066B39CE008A67A3 /* kmatrix.c */; }; 6766BAC20668B3A000A6052D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 676AC1C20668A938007173EB /* u_mem.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B4490F066880A300DF26D8 /* u_mem.h */; }; 676AC1C40668A938007173EB /* gr.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B44914066880C400DF26D8 /* gr.h */; }; 676AC1C50668A938007173EB /* grdef.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B44915066880C400DF26D8 /* grdef.h */; }; 676AC1C60668A938007173EB /* pstypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 676C5D030668840200D9FA2D /* pstypes.h */; }; 676AC1C70668A938007173EB /* byteswap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CE4F0668852C00056A5A /* byteswap.h */; }; 676AC1C80668A938007173EB /* rle.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CE500668852C00056A5A /* rle.h */; }; 676AC1CC0668A938007173EB /* makesig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF2D066887E500056A5A /* makesig.h */; }; 676AC1CE0668A938007173EB /* fix.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF420668881F00056A5A /* fix.h */; }; 676AC1CF0668A938007173EB /* palette.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF4E0668883900056A5A /* palette.h */; }; 676AC1D00668A938007173EB /* pcx.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF620668885500056A5A /* pcx.h */; }; 676AC1D10668A938007173EB /* 3d.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF8D066888DD00056A5A /* 3d.h */; }; 676AC1D20668A938007173EB /* texmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFB10668891200056A5A /* texmap.h */; }; 676AC1D30668A938007173EB /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFC50668893B00056A5A /* interp.h */; }; 676AC1D50668A938007173EB /* event.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFE20668899A00056A5A /* event.h */; }; 676AC1D60668A938007173EB /* joy.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFE30668899A00056A5A /* joy.h */; }; 676AC1D70668A938007173EB /* args.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D00B066889CD00056A5A /* args.h */; }; 676AC1D80668A938007173EB /* console.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D00C066889CD00056A5A /* console.h */; }; 676AC1D90668A938007173EB /* vecmat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D026066889F100056A5A /* vecmat.h */; }; 676AC1DA0668A938007173EB /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D04B06688A2E00056A5A /* timer.h */; }; 676AC1DB0668A938007173EB /* key.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D05B06688A4500056A5A /* key.h */; }; 676AC1DC0668A938007173EB /* mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D07006688A5F00056A5A /* mouse.h */; }; 676AC1DD0668A938007173EB /* rbaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D07E06688A7B00056A5A /* rbaudio.h */; }; 676AC1DE0668A938007173EB /* maths.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D08F06688A9C00056A5A /* maths.h */; }; 676AC1E00668A938007173EB /* strutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0A306688AB900056A5A /* strutil.h */; }; 676AC1E10668A938007173EB /* iff.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0BD06688AE800056A5A /* iff.h */; }; 676AC1E40668A938007173EB /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D12906688EB500056A5A /* hash.h */; }; 676AC1E50668A938007173EB /* strio.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D1550668903B00056A5A /* strio.h */; }; 676AC1E70668A938007173EB /* libmve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0D106688B1100056A5A /* libmve.h */; }; 676AC1E90668A938007173EB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 676AC1EC0668A938007173EB /* 2dsline.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44139066878B300DF26D8 /* 2dsline.c */; }; 676AC1ED0668A938007173EB /* bitblt.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413A066878B300DF26D8 /* bitblt.c */; }; 676AC1EE0668A938007173EB /* bitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413B066878B300DF26D8 /* bitmap.c */; }; 676AC1EF0668A938007173EB /* box.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413D066878B300DF26D8 /* box.c */; }; 676AC1F00668A938007173EB /* canvas.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413E066878B300DF26D8 /* canvas.c */; }; 676AC1F10668A938007173EB /* circle.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413F066878B300DF26D8 /* circle.c */; }; 676AC1F20668A938007173EB /* disc.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44141066878B300DF26D8 /* disc.c */; }; 676AC1F30668A938007173EB /* font.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44142066878B300DF26D8 /* font.c */; }; 676AC1F40668A938007173EB /* gpixel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44143066878B300DF26D8 /* gpixel.c */; }; 676AC1F60668A938007173EB /* line.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44145066878B300DF26D8 /* line.c */; }; 676AC1F70668A938007173EB /* palette.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44148066878B300DF26D8 /* palette.c */; }; 676AC1F80668A938007173EB /* pcx.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44149066878B300DF26D8 /* pcx.c */; }; 676AC1F90668A938007173EB /* pixel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414A066878B300DF26D8 /* pixel.c */; }; 676AC1FA0668A938007173EB /* poly.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414B066878B300DF26D8 /* poly.c */; }; 676AC1FB0668A938007173EB /* rect.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414C066878B300DF26D8 /* rect.c */; }; 676AC1FC0668A938007173EB /* rle.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414D066878B300DF26D8 /* rle.c */; }; 676AC1FD0668A938007173EB /* scalec.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44151066878B300DF26D8 /* scalec.c */; }; 676AC1FF0668A938007173EB /* clipper.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441760668792300DF26D8 /* clipper.c */; }; 676AC2000668A938007173EB /* draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441780668792300DF26D8 /* draw.c */; }; 676AC2010668A938007173EB /* globvars.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441790668792300DF26D8 /* globvars.c */; }; 676AC2020668A938007173EB /* instance.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417B0668792300DF26D8 /* instance.c */; }; 676AC2030668A938007173EB /* interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417D0668792300DF26D8 /* interp.c */; }; 676AC2040668A938007173EB /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417F0668792300DF26D8 /* matrix.c */; }; 676AC2050668A938007173EB /* points.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441800668792300DF26D8 /* points.c */; }; 676AC2060668A938007173EB /* rod.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441810668792300DF26D8 /* rod.c */; }; 676AC2070668A938007173EB /* setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441820668792300DF26D8 /* setup.c */; }; 676AC20A0668A938007173EB /* digi.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D306687A0200DF26D8 /* digi.c */; }; 676AC20B0668A938007173EB /* event.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D406687A0200DF26D8 /* event.c */; }; 676AC20C0668A938007173EB /* gr.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D506687A0200DF26D8 /* gr.c */; }; 676AC20E0668A938007173EB /* joy.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D706687A0200DF26D8 /* joy.c */; }; 676AC2100668A938007173EB /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D906687A0200DF26D8 /* key.c */; }; 676AC2110668A938007173EB /* mouse.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DB06687A0200DF26D8 /* mouse.c */; }; 676AC2120668A938007173EB /* rbaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DC06687A0200DF26D8 /* rbaudio.c */; }; 676AC2130668A938007173EB /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DD06687A0200DF26D8 /* timer.c */; }; 676AC2150668A938007173EB /* iff.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4420006687A9E00DF26D8 /* iff.c */; }; 676AC2160668A938007173EB /* ai.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446CF06687CF400DF26D8 /* ai.c */; }; 676AC2170668A938007173EB /* ai2.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D106687CF400DF26D8 /* ai2.c */; }; 676AC2180668A938007173EB /* aipath.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D206687CF400DF26D8 /* aipath.c */; }; 676AC2190668A938007173EB /* automap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D406687CF400DF26D8 /* automap.c */; }; 676AC21A0668A938007173EB /* bm.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D606687CF400DF26D8 /* bm.c */; }; 676AC21C0668A938007173EB /* cntrlcen.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446DB06687CF400DF26D8 /* cntrlcen.c */; }; 676AC21D0668A938007173EB /* collide.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446DD06687CF400DF26D8 /* collide.c */; }; 676AC21E0668A938007173EB /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E006687CF400DF26D8 /* config.c */; }; 676AC21F0668A938007173EB /* console.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E206687CF400DF26D8 /* console.c */; }; 676AC2200668A938007173EB /* controls.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E306687CF400DF26D8 /* controls.c */; }; 676AC2210668A938007173EB /* credits.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E506687CF400DF26D8 /* credits.c */; }; 676AC2230668A938007173EB /* effects.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446F706687CF400DF26D8 /* effects.c */; }; 676AC2240668A938007173EB /* endlevel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446F906687CF400DF26D8 /* endlevel.c */; }; 676AC2250668A938007173EB /* escort.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FB06687CF400DF26D8 /* escort.c */; }; 676AC2260668A938007173EB /* fireball.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FD06687CF400DF26D8 /* fireball.c */; }; 676AC2270668A938007173EB /* fuelcen.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FF06687CF400DF26D8 /* fuelcen.c */; }; 676AC2280668A938007173EB /* fvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470106687CF400DF26D8 /* fvi.c */; }; 676AC2290668A938007173EB /* game.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470406687CF400DF26D8 /* game.c */; }; 676AC22A0668A938007173EB /* gamecntl.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470606687CF400DF26D8 /* gamecntl.c */; }; 676AC22B0668A938007173EB /* gamefont.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470706687CF400DF26D8 /* gamefont.c */; }; 676AC22C0668A938007173EB /* gamemine.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470906687CF400DF26D8 /* gamemine.c */; }; 676AC22D0668A938007173EB /* gamepal.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470B06687CF400DF26D8 /* gamepal.c */; }; 676AC22E0668A938007173EB /* gamerend.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470D06687CF400DF26D8 /* gamerend.c */; }; 676AC22F0668A938007173EB /* gamesave.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470E06687CF400DF26D8 /* gamesave.c */; }; 676AC2300668A938007173EB /* gameseg.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471006687CF400DF26D8 /* gameseg.c */; }; 676AC2310668A938007173EB /* gameseq.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471206687CF400DF26D8 /* gameseq.c */; }; 676AC2320668A938007173EB /* gauges.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471506687CF400DF26D8 /* gauges.c */; }; 676AC2330668A938007173EB /* hostage.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471706687CF400DF26D8 /* hostage.c */; }; 676AC2340668A938007173EB /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471906687CF400DF26D8 /* hud.c */; }; 676AC2350668A938007173EB /* inferno.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471B06687CF400DF26D8 /* inferno.c */; }; 676AC2360668A938007173EB /* kconfig.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472006687CF400DF26D8 /* kconfig.c */; }; 676AC2380668A938007173EB /* laser.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472506687CF400DF26D8 /* laser.c */; }; 676AC2390668A938007173EB /* lighting.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472706687CF400DF26D8 /* lighting.c */; }; 676AC23A0668A938007173EB /* menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472B06687CF400DF26D8 /* menu.c */; }; 676AC23B0668A938007173EB /* mglobal.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472D06687CF400DF26D8 /* mglobal.c */; }; 676AC23C0668A938007173EB /* mission.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472E06687CF400DF26D8 /* mission.c */; }; 676AC23D0668A938007173EB /* morph.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473106687CF400DF26D8 /* morph.c */; }; 676AC23E0668A938007173EB /* movie.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473306687CF400DF26D8 /* movie.c */; }; 676AC23F0668A938007173EB /* newdemo.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473D06687CF400DF26D8 /* newdemo.c */; }; 676AC2400668A938007173EB /* newmenu.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473F06687CF400DF26D8 /* newmenu.c */; }; 676AC2410668A938007173EB /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4474106687CF400DF26D8 /* object.c */; }; 676AC2420668A938007173EB /* paging.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475906687CF400DF26D8 /* paging.c */; }; 676AC2430668A938007173EB /* physics.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475B06687CF400DF26D8 /* physics.c */; }; 676AC2440668A938007173EB /* piggy.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475D06687CF400DF26D8 /* piggy.c */; }; 676AC2450668A938007173EB /* player.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475F06687CF400DF26D8 /* player.c */; }; 676AC2460668A938007173EB /* playsave.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476106687CF400DF26D8 /* playsave.c */; }; 676AC2470668A938007173EB /* polyobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476306687CF400DF26D8 /* polyobj.c */; }; 676AC2480668A938007173EB /* powerup.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476506687CF400DF26D8 /* powerup.c */; }; 676AC2490668A938007173EB /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476706687CF400DF26D8 /* render.c */; }; 676AC24A0668A938007173EB /* robot.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476A06687CF400DF26D8 /* robot.c */; }; 676AC24B0668A938007173EB /* scores.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476C06687CF400DF26D8 /* scores.c */; }; 676AC24C0668A938007173EB /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476F06687CF400DF26D8 /* segment.c */; }; 676AC24D0668A938007173EB /* slew.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477206687CF400DF26D8 /* slew.c */; }; 676AC24E0668A938007173EB /* songs.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477406687CF400DF26D8 /* songs.c */; }; 676AC24F0668A938007173EB /* state.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477706687CF400DF26D8 /* state.c */; }; 676AC2500668A938007173EB /* switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477906687CF400DF26D8 /* switch.c */; }; 676AC2510668A938007173EB /* terrain.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477B06687CF400DF26D8 /* terrain.c */; }; 676AC2520668A938007173EB /* texmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477D06687CF400DF26D8 /* texmerge.c */; }; 676AC2530668A938007173EB /* text.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477F06687CF500DF26D8 /* text.c */; }; 676AC2540668A938007173EB /* titles.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478206687CF500DF26D8 /* titles.c */; }; 676AC2550668A938007173EB /* vclip.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478406687CF500DF26D8 /* vclip.c */; }; 676AC2560668A938007173EB /* wall.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478706687CF500DF26D8 /* wall.c */; }; 676AC2570668A938007173EB /* weapon.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478906687CF500DF26D8 /* weapon.c */; }; 676AC2580668A938007173EB /* fixc.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484B06687DCE00DF26D8 /* fixc.c */; }; 676AC2590668A938007173EB /* rand.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484D06687DCE00DF26D8 /* rand.c */; }; 676AC25A0668A938007173EB /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484E06687DCE00DF26D8 /* tables.c */; }; 676AC25B0668A938007173EB /* vecmat.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484F06687DCE00DF26D8 /* vecmat.c */; }; 676AC25C0668A938007173EB /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4485E06687DFB00DF26D8 /* mem.c */; }; 676AC25D0668A938007173EB /* args.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486606687E1000DF26D8 /* args.c */; }; 676AC25F0668A938007173EB /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486A06687E1000DF26D8 /* error.c */; }; 676AC2600668A938007173EB /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486C06687E1000DF26D8 /* hash.c */; }; 676AC2610668A938007173EB /* strio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4487206687E1000DF26D8 /* strio.c */; }; 676AC2620668A938007173EB /* strutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4487306687E1000DF26D8 /* strutil.c */; }; 676AC2630668A938007173EB /* ntmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4488806687E5E00DF26D8 /* ntmap.c */; }; 676AC2640668A938007173EB /* scanline.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4488906687E5E00DF26D8 /* scanline.c */; }; 676AC2650668A938007173EB /* tmapflat.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4489206687E5E00DF26D8 /* tmapflat.c */; }; 676AC2660668A938007173EB /* decoder16.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421006687AD900DF26D8 /* decoder16.c */; }; 676AC2670668A938007173EB /* decoder8.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421106687AD900DF26D8 /* decoder8.c */; }; 676AC2680668A938007173EB /* mvelib.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421706687AD900DF26D8 /* mvelib.c */; }; 676AC2690668A938007173EB /* mveplay.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421906687AD900DF26D8 /* mveplay.c */; }; 676AC26A0668A938007173EB /* mve_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421406687AD900DF26D8 /* mve_audio.c */; }; 676AC26C0668A938007173EB /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 676AC2730668A939007173EB /* event.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFE20668899A00056A5A /* event.h */; }; 676AC2740668A939007173EB /* key.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D05B06688A4500056A5A /* key.h */; }; 676AC2750668A939007173EB /* joy.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFE30668899A00056A5A /* joy.h */; }; 676AC2760668A939007173EB /* mouse.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D07006688A5F00056A5A /* mouse.h */; }; 676AC2770668A939007173EB /* 3d.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF8D066888DD00056A5A /* 3d.h */; }; 676AC2780668A939007173EB /* args.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D00B066889CD00056A5A /* args.h */; }; 676AC2790668A939007173EB /* byteswap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CE4F0668852C00056A5A /* byteswap.h */; }; 676AC27C0668A939007173EB /* console.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D00C066889CD00056A5A /* console.h */; }; 676AC2800668A939007173EB /* fix.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF420668881F00056A5A /* fix.h */; }; 676AC2810668A939007173EB /* gr.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B44914066880C400DF26D8 /* gr.h */; }; 676AC2820668A939007173EB /* grdef.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B44915066880C400DF26D8 /* grdef.h */; }; 676AC2830668A939007173EB /* hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D12906688EB500056A5A /* hash.h */; }; 676AC2850668A939007173EB /* iff.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0BD06688AE800056A5A /* iff.h */; }; 676AC2860668A939007173EB /* interp.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFC50668893B00056A5A /* interp.h */; }; 676AC2870668A939007173EB /* libmve.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0D106688B1100056A5A /* libmve.h */; }; 676AC2880668A939007173EB /* makesig.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF2D066887E500056A5A /* makesig.h */; }; 676AC2890668A939007173EB /* maths.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D08F06688A9C00056A5A /* maths.h */; }; 676AC28C0668A939007173EB /* pcx.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF620668885500056A5A /* pcx.h */; }; 676AC28D0668A939007173EB /* palette.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CF4E0668883900056A5A /* palette.h */; }; 676AC28E0668A939007173EB /* pstypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 676C5D030668840200D9FA2D /* pstypes.h */; }; 676AC28F0668A939007173EB /* rbaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D07E06688A7B00056A5A /* rbaudio.h */; }; 676AC2900668A939007173EB /* rle.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CE500668852C00056A5A /* rle.h */; }; 676AC2910668A939007173EB /* strio.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D1550668903B00056A5A /* strio.h */; }; 676AC2920668A939007173EB /* strutil.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D0A306688AB900056A5A /* strutil.h */; }; 676AC2930668A939007173EB /* texmap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791CFB10668891200056A5A /* texmap.h */; }; 676AC2940668A939007173EB /* timer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D04B06688A2E00056A5A /* timer.h */; }; 676AC2960668A939007173EB /* u_mem.h in Headers */ = {isa = PBXBuildFile; fileRef = 67B4490F066880A300DF26D8 /* u_mem.h */; }; 676AC2970668A939007173EB /* vecmat.h in Headers */ = {isa = PBXBuildFile; fileRef = 6791D026066889F100056A5A /* vecmat.h */; }; 676AC2980668A939007173EB /* ogl_init.h in Headers */ = {isa = PBXBuildFile; fileRef = 676AC0E10668A86F007173EB /* ogl_init.h */; }; 676AC29C0668A939007173EB /* 2dsline.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44139066878B300DF26D8 /* 2dsline.c */; }; 676AC29D0668A939007173EB /* bitblt.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413A066878B300DF26D8 /* bitblt.c */; }; 676AC29E0668A939007173EB /* bitmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413B066878B300DF26D8 /* bitmap.c */; }; 676AC29F0668A939007173EB /* box.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413D066878B300DF26D8 /* box.c */; }; 676AC2A00668A939007173EB /* canvas.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413E066878B300DF26D8 /* canvas.c */; }; 676AC2A10668A939007173EB /* circle.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4413F066878B300DF26D8 /* circle.c */; }; 676AC2A20668A939007173EB /* disc.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44141066878B300DF26D8 /* disc.c */; }; 676AC2A30668A939007173EB /* font.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44142066878B300DF26D8 /* font.c */; }; 676AC2A40668A939007173EB /* gpixel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44143066878B300DF26D8 /* gpixel.c */; }; 676AC2A60668A939007173EB /* line.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44145066878B300DF26D8 /* line.c */; }; 676AC2A70668A939007173EB /* palette.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44148066878B300DF26D8 /* palette.c */; }; 676AC2A80668A939007173EB /* pcx.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44149066878B300DF26D8 /* pcx.c */; }; 676AC2A90668A939007173EB /* pixel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414A066878B300DF26D8 /* pixel.c */; }; 676AC2AA0668A939007173EB /* poly.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414B066878B300DF26D8 /* poly.c */; }; 676AC2AB0668A939007173EB /* rect.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414C066878B300DF26D8 /* rect.c */; }; 676AC2AC0668A939007173EB /* rle.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4414D066878B300DF26D8 /* rle.c */; }; 676AC2AD0668A939007173EB /* scalec.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B44151066878B300DF26D8 /* scalec.c */; }; 676AC2AF0668A939007173EB /* clipper.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441760668792300DF26D8 /* clipper.c */; }; 676AC2B00668A939007173EB /* draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441780668792300DF26D8 /* draw.c */; }; 676AC2B10668A939007173EB /* globvars.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441790668792300DF26D8 /* globvars.c */; }; 676AC2B20668A939007173EB /* instance.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417B0668792300DF26D8 /* instance.c */; }; 676AC2B30668A939007173EB /* interp.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417D0668792300DF26D8 /* interp.c */; }; 676AC2B40668A939007173EB /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4417F0668792300DF26D8 /* matrix.c */; }; 676AC2B50668A939007173EB /* points.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441800668792300DF26D8 /* points.c */; }; 676AC2B60668A939007173EB /* rod.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441810668792300DF26D8 /* rod.c */; }; 676AC2B70668A939007173EB /* setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441820668792300DF26D8 /* setup.c */; }; 676AC2BA0668A939007173EB /* digi.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D306687A0200DF26D8 /* digi.c */; }; 676AC2BB0668A939007173EB /* event.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D406687A0200DF26D8 /* event.c */; }; 676AC2BD0668A939007173EB /* joy.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D706687A0200DF26D8 /* joy.c */; }; 676AC2BF0668A939007173EB /* key.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441D906687A0200DF26D8 /* key.c */; }; 676AC2C00668A939007173EB /* mouse.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DB06687A0200DF26D8 /* mouse.c */; }; 676AC2C10668A939007173EB /* rbaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DC06687A0200DF26D8 /* rbaudio.c */; }; 676AC2C20668A939007173EB /* timer.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B441DD06687A0200DF26D8 /* timer.c */; }; 676AC2C30668A939007173EB /* gr.c in Sources */ = {isa = PBXBuildFile; fileRef = 676AC04E0668A814007173EB /* gr.c */; }; 676AC2C40668A939007173EB /* ogl.c in Sources */ = {isa = PBXBuildFile; fileRef = 676AC0510668A814007173EB /* ogl.c */; }; 676AC2C70668A939007173EB /* iff.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4420006687A9E00DF26D8 /* iff.c */; }; 676AC2C80668A939007173EB /* decoder16.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421006687AD900DF26D8 /* decoder16.c */; }; 676AC2C90668A939007173EB /* decoder8.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421106687AD900DF26D8 /* decoder8.c */; }; 676AC2CA0668A939007173EB /* mve_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421406687AD900DF26D8 /* mve_audio.c */; }; 676AC2CB0668A939007173EB /* mvelib.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421706687AD900DF26D8 /* mvelib.c */; }; 676AC2CC0668A939007173EB /* mveplay.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4421906687AD900DF26D8 /* mveplay.c */; }; 676AC2CD0668A939007173EB /* ai.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446CF06687CF400DF26D8 /* ai.c */; }; 676AC2CE0668A939007173EB /* ai2.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D106687CF400DF26D8 /* ai2.c */; }; 676AC2CF0668A939007173EB /* aipath.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D206687CF400DF26D8 /* aipath.c */; }; 676AC2D00668A939007173EB /* automap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D406687CF400DF26D8 /* automap.c */; }; 676AC2D10668A939007173EB /* bm.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446D606687CF400DF26D8 /* bm.c */; }; 676AC2D30668A939007173EB /* cntrlcen.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446DB06687CF400DF26D8 /* cntrlcen.c */; }; 676AC2D40668A939007173EB /* collide.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446DD06687CF400DF26D8 /* collide.c */; }; 676AC2D50668A939007173EB /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E006687CF400DF26D8 /* config.c */; }; 676AC2D60668A939007173EB /* console.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E206687CF400DF26D8 /* console.c */; }; 676AC2D70668A939007173EB /* controls.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E306687CF400DF26D8 /* controls.c */; }; 676AC2D80668A939007173EB /* credits.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446E506687CF400DF26D8 /* credits.c */; }; 676AC2DA0668A939007173EB /* effects.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446F706687CF400DF26D8 /* effects.c */; }; 676AC2DB0668A939007173EB /* endlevel.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446F906687CF400DF26D8 /* endlevel.c */; }; 676AC2DC0668A939007173EB /* escort.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FB06687CF400DF26D8 /* escort.c */; }; 676AC2DD0668A939007173EB /* fireball.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FD06687CF400DF26D8 /* fireball.c */; }; 676AC2DE0668A939007173EB /* fuelcen.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B446FF06687CF400DF26D8 /* fuelcen.c */; }; 676AC2DF0668A939007173EB /* fvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470106687CF400DF26D8 /* fvi.c */; }; 676AC2E00668A939007173EB /* game.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470406687CF400DF26D8 /* game.c */; }; 676AC2E10668A939007173EB /* gamecntl.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470606687CF400DF26D8 /* gamecntl.c */; }; 676AC2E20668A939007173EB /* gamefont.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470706687CF400DF26D8 /* gamefont.c */; }; 676AC2E30668A939007173EB /* gamemine.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470906687CF400DF26D8 /* gamemine.c */; }; 676AC2E40668A939007173EB /* gamepal.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470B06687CF400DF26D8 /* gamepal.c */; }; 676AC2E50668A939007173EB /* gamerend.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470D06687CF400DF26D8 /* gamerend.c */; }; 676AC2E60668A939007173EB /* gamesave.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4470E06687CF400DF26D8 /* gamesave.c */; }; 676AC2E70668A939007173EB /* gameseg.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471006687CF400DF26D8 /* gameseg.c */; }; 676AC2E80668A939007173EB /* gameseq.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471206687CF400DF26D8 /* gameseq.c */; }; 676AC2E90668A939007173EB /* gauges.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471506687CF400DF26D8 /* gauges.c */; }; 676AC2EA0668A939007173EB /* hostage.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471706687CF400DF26D8 /* hostage.c */; }; 676AC2EB0668A939007173EB /* hud.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471906687CF400DF26D8 /* hud.c */; }; 676AC2EC0668A939007173EB /* inferno.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4471B06687CF400DF26D8 /* inferno.c */; }; 676AC2ED0668A939007173EB /* kconfig.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472006687CF400DF26D8 /* kconfig.c */; }; 676AC2EF0668A939007173EB /* laser.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472506687CF400DF26D8 /* laser.c */; }; 676AC2F00668A939007173EB /* lighting.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472706687CF400DF26D8 /* lighting.c */; }; 676AC2F10668A939007173EB /* menu.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472B06687CF400DF26D8 /* menu.c */; }; 676AC2F20668A939007173EB /* mglobal.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472D06687CF400DF26D8 /* mglobal.c */; }; 676AC2F30668A939007173EB /* mission.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4472E06687CF400DF26D8 /* mission.c */; }; 676AC2F40668A939007173EB /* morph.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473106687CF400DF26D8 /* morph.c */; }; 676AC2F50668A939007173EB /* movie.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473306687CF400DF26D8 /* movie.c */; }; 676AC2F60668A939007173EB /* newdemo.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473D06687CF400DF26D8 /* newdemo.c */; }; 676AC2F70668A939007173EB /* newmenu.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4473F06687CF400DF26D8 /* newmenu.c */; }; 676AC2F80668A939007173EB /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4474106687CF400DF26D8 /* object.c */; }; 676AC2F90668A939007173EB /* paging.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475906687CF400DF26D8 /* paging.c */; }; 676AC2FA0668A939007173EB /* physics.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475B06687CF400DF26D8 /* physics.c */; }; 676AC2FB0668A939007173EB /* piggy.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475D06687CF400DF26D8 /* piggy.c */; }; 676AC2FC0668A939007173EB /* player.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4475F06687CF400DF26D8 /* player.c */; }; 676AC2FD0668A939007173EB /* playsave.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476106687CF400DF26D8 /* playsave.c */; }; 676AC2FE0668A939007173EB /* polyobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476306687CF400DF26D8 /* polyobj.c */; }; 676AC2FF0668A939007173EB /* powerup.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476506687CF400DF26D8 /* powerup.c */; }; 676AC3000668A939007173EB /* render.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476706687CF400DF26D8 /* render.c */; }; 676AC3010668A939007173EB /* robot.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476A06687CF400DF26D8 /* robot.c */; }; 676AC3020668A939007173EB /* scores.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476C06687CF400DF26D8 /* scores.c */; }; 676AC3030668A939007173EB /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4476F06687CF400DF26D8 /* segment.c */; }; 676AC3040668A939007173EB /* slew.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477206687CF400DF26D8 /* slew.c */; }; 676AC3050668A939007173EB /* songs.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477406687CF400DF26D8 /* songs.c */; }; 676AC3060668A939007173EB /* state.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477706687CF400DF26D8 /* state.c */; }; 676AC3070668A939007173EB /* switch.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477906687CF400DF26D8 /* switch.c */; }; 676AC3080668A939007173EB /* terrain.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477B06687CF400DF26D8 /* terrain.c */; }; 676AC3090668A939007173EB /* texmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477D06687CF400DF26D8 /* texmerge.c */; }; 676AC30A0668A939007173EB /* text.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4477F06687CF500DF26D8 /* text.c */; }; 676AC30B0668A939007173EB /* titles.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478206687CF500DF26D8 /* titles.c */; }; 676AC30C0668A939007173EB /* vclip.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478406687CF500DF26D8 /* vclip.c */; }; 676AC30D0668A939007173EB /* wall.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478706687CF500DF26D8 /* wall.c */; }; 676AC30E0668A939007173EB /* weapon.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4478906687CF500DF26D8 /* weapon.c */; }; 676AC30F0668A939007173EB /* fixc.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484B06687DCE00DF26D8 /* fixc.c */; }; 676AC3100668A939007173EB /* rand.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484D06687DCE00DF26D8 /* rand.c */; }; 676AC3110668A939007173EB /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484E06687DCE00DF26D8 /* tables.c */; }; 676AC3120668A939007173EB /* vecmat.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4484F06687DCE00DF26D8 /* vecmat.c */; }; 676AC3130668A939007173EB /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4485E06687DFB00DF26D8 /* mem.c */; }; 676AC3140668A939007173EB /* args.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486606687E1000DF26D8 /* args.c */; }; 676AC3160668A939007173EB /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486A06687E1000DF26D8 /* error.c */; }; 676AC3170668A939007173EB /* hash.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4486C06687E1000DF26D8 /* hash.c */; }; 676AC3180668A939007173EB /* strio.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4487206687E1000DF26D8 /* strio.c */; }; 676AC3190668A939007173EB /* strutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4487306687E1000DF26D8 /* strutil.c */; }; 676AC31A0668A939007173EB /* ntmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4488806687E5E00DF26D8 /* ntmap.c */; }; 676AC31B0668A939007173EB /* scanline.c in Sources */ = {isa = PBXBuildFile; fileRef = 67B4488906687E5E00DF26D8 /* scanline.c */; }; 67F6FED2066B13B400443922 /* SDLMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 67F6FED0066B13B400443922 /* SDLMain.h */; }; 67F6FED3066B13B400443922 /* SDLMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 67F6FED1066B13B400443922 /* SDLMain.m */; }; 67F6FED4066B13B400443922 /* SDLMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 67F6FED0066B13B400443922 /* SDLMain.h */; }; 67F6FED5066B13B400443922 /* SDLMain.m in Sources */ = {isa = PBXBuildFile; fileRef = 67F6FED1066B13B400443922 /* SDLMain.m */; }; EB092A8012A25AFB004D9A79 /* messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = EB092A7F12A25AFB004D9A79 /* messagebox.c */; }; EB092A8112A25AFB004D9A79 /* messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = EB092A7F12A25AFB004D9A79 /* messagebox.c */; }; EB1405E9121044B5002B1CC6 /* physfsx.c in Sources */ = {isa = PBXBuildFile; fileRef = EB1405E8121044B5002B1CC6 /* physfsx.c */; }; EB1405EA121044B5002B1CC6 /* physfsx.c in Sources */ = {isa = PBXBuildFile; fileRef = EB1405E8121044B5002B1CC6 /* physfsx.c */; }; EB28D9A30ECEAF1C00E68E9B /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = EB28D9A20ECEAF1C00E68E9B /* init.c */; }; EB28D9A40ECEAF1C00E68E9B /* init.c in Sources */ = {isa = PBXBuildFile; fileRef = EB28D9A20ECEAF1C00E68E9B /* init.c */; }; EB2EEB5810C50CE2005256F2 /* net_udp.c in Sources */ = {isa = PBXBuildFile; fileRef = 17DFA6B510C1A2D100674D11 /* net_udp.c */; }; EB380D360E16886300EBD9AD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; EB3EB4F312A54805005F992D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB3EB4ED12A547C7005F992D /* Carbon.framework */; }; EB3EB4F412A5480D005F992D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB3EB4ED12A547C7005F992D /* Carbon.framework */; }; EB6142BE1501FE89004E2AE8 /* curve.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A51501FD71004E2AE8 /* curve.pad */; }; EB6142BF1501FE89004E2AE8 /* dummy.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A61501FD71004E2AE8 /* dummy.pad */; }; EB6142C01501FE89004E2AE8 /* group.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A71501FD71004E2AE8 /* group.pad */; }; EB6142C11501FE89004E2AE8 /* lighting.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A81501FD71004E2AE8 /* lighting.pad */; }; EB6142C21501FE89004E2AE8 /* med.mnu in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A91501FD71004E2AE8 /* med.mnu */; }; EB6142C31501FE89004E2AE8 /* newobj.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AA1501FD71004E2AE8 /* newobj.pad */; }; EB6142C41501FE89004E2AE8 /* object.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AB1501FD71004E2AE8 /* object.pad */; }; EB6142C51501FE89004E2AE8 /* objmov.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AC1501FD71004E2AE8 /* objmov.pad */; }; EB6142C61501FE89004E2AE8 /* pc6x8.fnt in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AD1501FD71004E2AE8 /* pc6x8.fnt */; }; EB6142C71501FE89004E2AE8 /* pc8x16.fnt in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AE1501FD71004E2AE8 /* pc8x16.fnt */; }; EB6142C81501FE89004E2AE8 /* segmove.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AF1501FD71004E2AE8 /* segmove.pad */; }; EB6142C91501FE89004E2AE8 /* segsize.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B01501FD71004E2AE8 /* segsize.pad */; }; EB6142CA1501FE89004E2AE8 /* test.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B11501FD71004E2AE8 /* test.pad */; }; EB6142CB1501FE89004E2AE8 /* texture.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B21501FD71004E2AE8 /* texture.pad */; }; EB6AFF60170FD9B400ED37CB /* vers_id.c in Sources */ = {isa = PBXBuildFile; fileRef = EB6AFF5F170FD9B400ED37CB /* vers_id.c */; }; EB6AFF61170FD9B400ED37CB /* vers_id.c in Sources */ = {isa = PBXBuildFile; fileRef = EB6AFF5F170FD9B400ED37CB /* vers_id.c */; }; EB91A438126175ED009E0095 /* libphysfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB91A437126175ED009E0095 /* libphysfs.dylib */; }; EB91A439126175ED009E0095 /* libphysfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB91A437126175ED009E0095 /* libphysfs.dylib */; }; EB91A43D12617668009E0095 /* libphysfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB91A43C12617668009E0095 /* libphysfs.dylib */; }; EB91A43E12617668009E0095 /* libphysfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = EB91A43C12617668009E0095 /* libphysfs.dylib */; }; EB92BE600CDD693C0045A32C /* digi_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5C0CDD693C0045A32C /* digi_audio.c */; }; EB92BE610CDD693C0045A32C /* digi_mixer_music.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5D0CDD693C0045A32C /* digi_mixer_music.c */; }; EB92BE620CDD693C0045A32C /* digi_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5E0CDD693C0045A32C /* digi_mixer.c */; }; EB92BE630CDD693C0045A32C /* jukebox.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5F0CDD693C0045A32C /* jukebox.c */; }; EB92BE640CDD693C0045A32C /* digi_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5C0CDD693C0045A32C /* digi_audio.c */; }; EB92BE650CDD693C0045A32C /* digi_mixer_music.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5D0CDD693C0045A32C /* digi_mixer_music.c */; }; EB92BE660CDD693C0045A32C /* digi_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5E0CDD693C0045A32C /* digi_mixer.c */; }; EB92BE670CDD693C0045A32C /* jukebox.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BE5F0CDD693C0045A32C /* jukebox.c */; }; EB92BEA60CDD6A570045A32C /* dl_list.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BEA40CDD6A570045A32C /* dl_list.c */; }; EB92BEA80CDD6A570045A32C /* dl_list.c in Sources */ = {isa = PBXBuildFile; fileRef = EB92BEA40CDD6A570045A32C /* dl_list.c */; }; EB92BEC50CDD6B4B0045A32C /* SDL_mixer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB92BEC40CDD6B4B0045A32C /* SDL_mixer.framework */; }; EB92BEC60CDD6B4B0045A32C /* SDL_mixer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EB92BEC40CDD6B4B0045A32C /* SDL_mixer.framework */; }; EBAEB74C0BF4A86F00FC6E13 /* d2x-rebirth.icns in Resources */ = {isa = PBXBuildFile; fileRef = EBAEB74B0BF4A86F00FC6E13 /* d2x-rebirth.icns */; }; EBAFC23B088E4B2C006329AD /* physfsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC23A088E4B2C006329AD /* physfsx.h */; }; EBAFC23C088E4B2C006329AD /* physfsx.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC23A088E4B2C006329AD /* physfsx.h */; }; EBAFC249088E4C17006329AD /* ignorecase.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC248088E4C17006329AD /* ignorecase.h */; }; EBAFC24A088E4C17006329AD /* ignorecase.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC248088E4C17006329AD /* ignorecase.h */; }; EBAFC24C088E4C53006329AD /* physfsrwops.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC24B088E4C53006329AD /* physfsrwops.h */; }; EBAFC24D088E4C53006329AD /* physfsrwops.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC24B088E4C53006329AD /* physfsrwops.h */; }; EBAFC26E088E508D006329AD /* conf.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC269088E508D006329AD /* conf.h */; }; EBAFC290088E67CD006329AD /* digiobj.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC28F088E67CD006329AD /* digiobj.c */; }; EBAFC291088E67CD006329AD /* digiobj.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC28F088E67CD006329AD /* digiobj.c */; }; EBAFC2B2088E695F006329AD /* ignorecase.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC2B0088E695F006329AD /* ignorecase.c */; }; EBAFC2B3088E695F006329AD /* physfsrwops.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC2B1088E695F006329AD /* physfsrwops.c */; }; EBAFC2B4088E695F006329AD /* ignorecase.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC2B0088E695F006329AD /* ignorecase.c */; }; EBAFC2B5088E695F006329AD /* physfsrwops.c in Sources */ = {isa = PBXBuildFile; fileRef = EBAFC2B1088E695F006329AD /* physfsrwops.c */; }; EBAFC2C0088E6BC7006329AD /* conf.h in Headers */ = {isa = PBXBuildFile; fileRef = EBAFC269088E508D006329AD /* conf.h */; }; EBB66314122E4DC60057352D /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB66313122E4DC60057352D /* ApplicationServices.framework */; }; EBB66315122E4DC60057352D /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBB66313122E4DC60057352D /* ApplicationServices.framework */; }; EBB9E5340D8E82B3003466E6 /* bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = EBB9E5320D8E82B3003466E6 /* bitmap.h */; }; EBB9E5350D8E82B3003466E6 /* clip.h in Headers */ = {isa = PBXBuildFile; fileRef = EBB9E5330D8E82B3003466E6 /* clip.h */; }; EBB9E5360D8E82B3003466E6 /* bitmap.h in Headers */ = {isa = PBXBuildFile; fileRef = EBB9E5320D8E82B3003466E6 /* bitmap.h */; }; EBB9E5370D8E82B3003466E6 /* clip.h in Headers */ = {isa = PBXBuildFile; fileRef = EBB9E5330D8E82B3003466E6 /* clip.h */; }; EBBE05B112C872C30056CF2D /* autosave.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057A12C872C30056CF2D /* autosave.c */; }; EBBE05B212C872C30056CF2D /* centers.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057B12C872C30056CF2D /* centers.c */; }; EBBE05B412C872C30056CF2D /* curves.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057D12C872C30056CF2D /* curves.c */; }; EBBE05B612C872C30056CF2D /* eglobal.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057F12C872C30056CF2D /* eglobal.c */; }; EBBE05B912C872C30056CF2D /* elight.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058212C872C30056CF2D /* elight.c */; }; EBBE05BA12C872C30056CF2D /* eobject.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058312C872C30056CF2D /* eobject.c */; }; EBBE05BC12C872C30056CF2D /* eswitch.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058512C872C30056CF2D /* eswitch.c */; }; EBBE05BE12C872C30056CF2D /* fixseg.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058712C872C30056CF2D /* fixseg.c */; }; EBBE05BF12C872C30056CF2D /* func.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058812C872C30056CF2D /* func.c */; }; EBBE05C012C872C30056CF2D /* group.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058912C872C30056CF2D /* group.c */; }; EBBE05C112C872C30056CF2D /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058A12C872C30056CF2D /* info.c */; }; EBBE05C312C872C30056CF2D /* kbuild.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058C12C872C30056CF2D /* kbuild.c */; }; EBBE05C412C872C30056CF2D /* kcurve.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058D12C872C30056CF2D /* kcurve.c */; }; EBBE05C612C872C30056CF2D /* kfuncs.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058F12C872C30056CF2D /* kfuncs.c */; }; EBBE05C812C872C30056CF2D /* kgame.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059112C872C30056CF2D /* kgame.c */; }; EBBE05CA12C872C30056CF2D /* khelp.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059312C872C30056CF2D /* khelp.c */; }; EBBE05CB12C872C30056CF2D /* kmine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059412C872C30056CF2D /* kmine.c */; }; EBBE05CC12C872C30056CF2D /* ksegmove.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059512C872C30056CF2D /* ksegmove.c */; }; EBBE05CD12C872C30056CF2D /* ksegsel.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059612C872C30056CF2D /* ksegsel.c */; }; EBBE05CE12C872C30056CF2D /* ksegsize.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059712C872C30056CF2D /* ksegsize.c */; }; EBBE05CF12C872C30056CF2D /* ktmap.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059812C872C30056CF2D /* ktmap.c */; }; EBBE05D012C872C30056CF2D /* kview.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059912C872C30056CF2D /* kview.c */; }; EBBE05D312C872C30056CF2D /* med.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059C12C872C30056CF2D /* med.c */; }; EBBE05D412C872C30056CF2D /* meddraw.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059D12C872C30056CF2D /* meddraw.c */; }; EBBE05D712C872C30056CF2D /* medmisc.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A012C872C30056CF2D /* medmisc.c */; }; EBBE05D912C872C30056CF2D /* medrobot.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A212C872C30056CF2D /* medrobot.c */; }; EBBE05DB12C872C30056CF2D /* medsel.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A412C872C30056CF2D /* medsel.c */; }; EBBE05DD12C872C30056CF2D /* medwall.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A612C872C30056CF2D /* medwall.c */; }; EBBE05DF12C872C30056CF2D /* mine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A812C872C30056CF2D /* mine.c */; }; EBBE05E012C872C30056CF2D /* objpage.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A912C872C30056CF2D /* objpage.c */; }; EBBE05E212C872C30056CF2D /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AB12C872C30056CF2D /* segment.c */; }; EBBE05E312C872C30056CF2D /* seguvs.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AC12C872C30056CF2D /* seguvs.c */; }; EBBE05E512C872C30056CF2D /* texpage.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AE12C872C30056CF2D /* texpage.c */; }; EBBE05E712C872C30056CF2D /* texture.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05B012C872C30056CF2D /* texture.c */; }; EBC652100890D6B7004FCAA3 /* ui.h in Headers */ = {isa = PBXBuildFile; fileRef = EBC6520F0890D6B7004FCAA3 /* ui.h */; }; EBC652110890D6B7004FCAA3 /* ui.h in Headers */ = {isa = PBXBuildFile; fileRef = EBC6520F0890D6B7004FCAA3 /* ui.h */; }; EBC652130890D6DF004FCAA3 /* func.h in Headers */ = {isa = PBXBuildFile; fileRef = EBC652120890D6DF004FCAA3 /* func.h */; }; EBC652140890D6DF004FCAA3 /* func.h in Headers */ = {isa = PBXBuildFile; fileRef = EBC652120890D6DF004FCAA3 /* func.h */; }; EBD441821526B3D4002FF2BA /* curve.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A51501FD71004E2AE8 /* curve.pad */; }; EBD441831526B3D4002FF2BA /* dummy.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A61501FD71004E2AE8 /* dummy.pad */; }; EBD441841526B3D4002FF2BA /* group.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A71501FD71004E2AE8 /* group.pad */; }; EBD441851526B3D4002FF2BA /* lighting.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A81501FD71004E2AE8 /* lighting.pad */; }; EBD441861526B3D4002FF2BA /* med.mnu in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142A91501FD71004E2AE8 /* med.mnu */; }; EBD441871526B3D4002FF2BA /* newobj.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AA1501FD71004E2AE8 /* newobj.pad */; }; EBD441881526B3D4002FF2BA /* object.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AB1501FD71004E2AE8 /* object.pad */; }; EBD441891526B3D4002FF2BA /* objmov.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AC1501FD71004E2AE8 /* objmov.pad */; }; EBD4418A1526B3D4002FF2BA /* pc6x8.fnt in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AD1501FD71004E2AE8 /* pc6x8.fnt */; }; EBD4418B1526B3D4002FF2BA /* pc8x16.fnt in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AE1501FD71004E2AE8 /* pc8x16.fnt */; }; EBD4418C1526B3D4002FF2BA /* segmove.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142AF1501FD71004E2AE8 /* segmove.pad */; }; EBD4418D1526B3D4002FF2BA /* segsize.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B01501FD71004E2AE8 /* segsize.pad */; }; EBD4418E1526B3D4002FF2BA /* test.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B11501FD71004E2AE8 /* test.pad */; }; EBD4418F1526B3D4002FF2BA /* texture.pad in CopyFiles */ = {isa = PBXBuildFile; fileRef = EB6142B21501FD71004E2AE8 /* texture.pad */; }; EBD441901526B3EE002FF2BA /* autosave.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057A12C872C30056CF2D /* autosave.c */; }; EBD441911526B3EE002FF2BA /* centers.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057B12C872C30056CF2D /* centers.c */; }; EBD441921526B3EE002FF2BA /* curve.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142A51501FD71004E2AE8 /* curve.pad */; }; EBD441931526B3EE002FF2BA /* curves.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057D12C872C30056CF2D /* curves.c */; }; EBD441941526B3EE002FF2BA /* dummy.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142A61501FD71004E2AE8 /* dummy.pad */; }; EBD441951526B3EE002FF2BA /* eglobal.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE057F12C872C30056CF2D /* eglobal.c */; }; EBD441971526B3EE002FF2BA /* elight.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058212C872C30056CF2D /* elight.c */; }; EBD441981526B3EE002FF2BA /* eobject.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058312C872C30056CF2D /* eobject.c */; }; EBD441991526B3EE002FF2BA /* eswitch.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058512C872C30056CF2D /* eswitch.c */; }; EBD4419A1526B3EE002FF2BA /* fixseg.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058712C872C30056CF2D /* fixseg.c */; }; EBD4419B1526B3EE002FF2BA /* func.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058812C872C30056CF2D /* func.c */; }; EBD4419C1526B3EE002FF2BA /* group.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058912C872C30056CF2D /* group.c */; }; EBD4419D1526B3EE002FF2BA /* group.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142A71501FD71004E2AE8 /* group.pad */; }; EBD4419E1526B3EE002FF2BA /* info.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058A12C872C30056CF2D /* info.c */; }; EBD4419F1526B3EE002FF2BA /* kbuild.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058C12C872C30056CF2D /* kbuild.c */; }; EBD441A01526B3EE002FF2BA /* kcurve.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058D12C872C30056CF2D /* kcurve.c */; }; EBD441A11526B3EE002FF2BA /* kfuncs.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE058F12C872C30056CF2D /* kfuncs.c */; }; EBD441A21526B3EE002FF2BA /* kgame.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059112C872C30056CF2D /* kgame.c */; }; EBD441A41526B3EE002FF2BA /* khelp.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059312C872C30056CF2D /* khelp.c */; }; EBD441A51526B3EE002FF2BA /* kmine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059412C872C30056CF2D /* kmine.c */; }; EBD441A61526B3EE002FF2BA /* ksegmove.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059512C872C30056CF2D /* ksegmove.c */; }; EBD441A71526B3EE002FF2BA /* ksegsel.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059612C872C30056CF2D /* ksegsel.c */; }; EBD441A81526B3EE002FF2BA /* ksegsize.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059712C872C30056CF2D /* ksegsize.c */; }; EBD441A91526B3EE002FF2BA /* ktmap.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059812C872C30056CF2D /* ktmap.c */; }; EBD441AA1526B3EE002FF2BA /* kview.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059912C872C30056CF2D /* kview.c */; }; EBD441AB1526B3EE002FF2BA /* lighting.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142A81501FD71004E2AE8 /* lighting.pad */; }; EBD441AD1526B3EE002FF2BA /* med.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059C12C872C30056CF2D /* med.c */; }; EBD441AE1526B3EE002FF2BA /* med.mnu in Resources */ = {isa = PBXBuildFile; fileRef = EB6142A91501FD71004E2AE8 /* med.mnu */; }; EBD441AF1526B3EE002FF2BA /* meddraw.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE059D12C872C30056CF2D /* meddraw.c */; }; EBD441B01526B3EE002FF2BA /* medmisc.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A012C872C30056CF2D /* medmisc.c */; }; EBD441B11526B3EE002FF2BA /* medrobot.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A212C872C30056CF2D /* medrobot.c */; }; EBD441B21526B3EE002FF2BA /* medsel.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A412C872C30056CF2D /* medsel.c */; }; EBD441B31526B3EE002FF2BA /* medwall.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A612C872C30056CF2D /* medwall.c */; }; EBD441B41526B3EE002FF2BA /* mine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A812C872C30056CF2D /* mine.c */; }; EBD441B51526B3EE002FF2BA /* newobj.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AA1501FD71004E2AE8 /* newobj.pad */; }; EBD441B61526B3EE002FF2BA /* object.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AB1501FD71004E2AE8 /* object.pad */; }; EBD441B71526B3EE002FF2BA /* objmov.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AC1501FD71004E2AE8 /* objmov.pad */; }; EBD441B81526B3EE002FF2BA /* objpage.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05A912C872C30056CF2D /* objpage.c */; }; EBD441B91526B3EE002FF2BA /* pc6x8.fnt in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AD1501FD71004E2AE8 /* pc6x8.fnt */; }; EBD441BA1526B3EE002FF2BA /* pc8x16.fnt in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AE1501FD71004E2AE8 /* pc8x16.fnt */; }; EBD441BB1526B3EE002FF2BA /* segment.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AB12C872C30056CF2D /* segment.c */; }; EBD441BC1526B3EE002FF2BA /* segmove.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142AF1501FD71004E2AE8 /* segmove.pad */; }; EBD441BD1526B3EE002FF2BA /* segsize.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142B01501FD71004E2AE8 /* segsize.pad */; }; EBD441BE1526B3EE002FF2BA /* seguvs.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AC12C872C30056CF2D /* seguvs.c */; }; EBD441BF1526B3EE002FF2BA /* test.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142B11501FD71004E2AE8 /* test.pad */; }; EBD441C01526B3EE002FF2BA /* texpage.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05AE12C872C30056CF2D /* texpage.c */; }; EBD441C11526B3EE002FF2BA /* texture.c in Sources */ = {isa = PBXBuildFile; fileRef = EBBE05B012C872C30056CF2D /* texture.c */; }; EBD441C21526B3EE002FF2BA /* texture.pad in Resources */ = {isa = PBXBuildFile; fileRef = EB6142B21501FD71004E2AE8 /* texture.pad */; }; EBD441C71526B453002FF2BA /* button.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651900890CEAE004FCAA3 /* button.c */; }; EBD441C81526B453002FF2BA /* checkbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651910890CEAE004FCAA3 /* checkbox.c */; }; EBD441C91526B453002FF2BA /* dialog.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A90890CEAE004FCAA3 /* dialog.c */; }; EBD441CA1526B453002FF2BA /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651920890CEAE004FCAA3 /* file.c */; }; EBD441CB1526B453002FF2BA /* gadget.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651940890CEAE004FCAA3 /* gadget.c */; }; EBD441CC1526B453002FF2BA /* icon.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651960890CEAE004FCAA3 /* icon.c */; }; EBD441CD1526B453002FF2BA /* inputbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651970890CEAE004FCAA3 /* inputbox.c */; }; EBD441CE1526B453002FF2BA /* keypad.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651980890CEAE004FCAA3 /* keypad.c */; }; EBD441CF1526B453002FF2BA /* keypress.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651990890CEAE004FCAA3 /* keypress.c */; }; EBD441D01526B453002FF2BA /* keytrap.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519A0890CEAE004FCAA3 /* keytrap.c */; }; EBD441D11526B453002FF2BA /* listbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519B0890CEAE004FCAA3 /* listbox.c */; }; EBD441D21526B453002FF2BA /* menu.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519E0890CEAE004FCAA3 /* menu.c */; }; EBD441D31526B453002FF2BA /* menubar.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519F0890CEAE004FCAA3 /* menubar.c */; }; EBD441D41526B453002FF2BA /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A00890CEAE004FCAA3 /* message.c */; }; EBD441D61526B453002FF2BA /* popup.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A30890CEAE004FCAA3 /* popup.c */; }; EBD441D71526B453002FF2BA /* radio.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A40890CEAE004FCAA3 /* radio.c */; }; EBD441D81526B453002FF2BA /* scroll.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A50890CEAE004FCAA3 /* scroll.c */; }; EBD441D91526B453002FF2BA /* ui.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A60890CEAE004FCAA3 /* ui.c */; }; EBD441DA1526B453002FF2BA /* uidraw.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A70890CEAE004FCAA3 /* uidraw.c */; }; EBD441DB1526B453002FF2BA /* userbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A80890CEAE004FCAA3 /* userbox.c */; }; EBD441DC1526B4DA002FF2BA /* bmread.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC652010890D632004FCAA3 /* bmread.c */; }; EBD441DD1526B4DA002FF2BA /* dumpmine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC652020890D632004FCAA3 /* dumpmine.c */; }; EBE8D6EB0FC583B4009D181F /* window.c in Sources */ = {isa = PBXBuildFile; fileRef = EBE8D6EA0FC583B4009D181F /* window.c */; }; EBE8D6EC0FC583B4009D181F /* window.c in Sources */ = {isa = PBXBuildFile; fileRef = EBE8D6EA0FC583B4009D181F /* window.c */; }; EBECB5D312C03E6300D660B3 /* bmread.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC652010890D632004FCAA3 /* bmread.c */; }; EBECB5F912C03F0C00D660B3 /* button.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651900890CEAE004FCAA3 /* button.c */; }; EBECB5FA12C03F0E00D660B3 /* checkbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651910890CEAE004FCAA3 /* checkbox.c */; }; EBECB5FB12C03F1000D660B3 /* file.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651920890CEAE004FCAA3 /* file.c */; }; EBECB5FD12C03F1D00D660B3 /* gadget.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651940890CEAE004FCAA3 /* gadget.c */; }; EBECB5FE12C03F2700D660B3 /* icon.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651960890CEAE004FCAA3 /* icon.c */; }; EBECB5FF12C03F2C00D660B3 /* inputbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651970890CEAE004FCAA3 /* inputbox.c */; }; EBECB60012C03F3400D660B3 /* keypad.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651980890CEAE004FCAA3 /* keypad.c */; }; EBECB60112C03F3500D660B3 /* keypress.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651990890CEAE004FCAA3 /* keypress.c */; }; EBECB60212C03F3700D660B3 /* keytrap.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519A0890CEAE004FCAA3 /* keytrap.c */; }; EBECB60312C03F3900D660B3 /* listbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519B0890CEAE004FCAA3 /* listbox.c */; }; EBECB60412C03F4300D660B3 /* menu.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519E0890CEAE004FCAA3 /* menu.c */; }; EBECB60512C03F4500D660B3 /* menubar.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC6519F0890CEAE004FCAA3 /* menubar.c */; }; EBECB60612C03F4600D660B3 /* message.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A00890CEAE004FCAA3 /* message.c */; }; EBECB60912C03F7A00D660B3 /* popup.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A30890CEAE004FCAA3 /* popup.c */; }; EBECB60A12C03F7D00D660B3 /* radio.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A40890CEAE004FCAA3 /* radio.c */; }; EBECB60B12C03F7E00D660B3 /* scroll.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A50890CEAE004FCAA3 /* scroll.c */; }; EBECB60C12C03F8200D660B3 /* ui.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A60890CEAE004FCAA3 /* ui.c */; }; EBECB60D12C03F8400D660B3 /* uidraw.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A70890CEAE004FCAA3 /* uidraw.c */; }; EBECB60E12C03F8600D660B3 /* userbox.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A80890CEAE004FCAA3 /* userbox.c */; }; EBECB60F12C03F8700D660B3 /* dialog.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC651A90890CEAE004FCAA3 /* dialog.c */; }; EBECB69412C0475900D660B3 /* dumpmine.c in Sources */ = {isa = PBXBuildFile; fileRef = EBC652020890D632004FCAA3 /* dumpmine.c */; }; EBECB69712C0481A00D660B3 /* d2x-rebirth.icns in Resources */ = {isa = PBXBuildFile; fileRef = EBAEB74B0BF4A86F00FC6E13 /* d2x-rebirth.icns */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ EB6142BC1501FDEB004E2AE8 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = editor; dstSubfolderSpec = 7; files = ( EB6142BE1501FE89004E2AE8 /* curve.pad in CopyFiles */, EB6142BF1501FE89004E2AE8 /* dummy.pad in CopyFiles */, EB6142C01501FE89004E2AE8 /* group.pad in CopyFiles */, EB6142C11501FE89004E2AE8 /* lighting.pad in CopyFiles */, EB6142C21501FE89004E2AE8 /* med.mnu in CopyFiles */, EB6142C31501FE89004E2AE8 /* newobj.pad in CopyFiles */, EB6142C41501FE89004E2AE8 /* object.pad in CopyFiles */, EB6142C51501FE89004E2AE8 /* objmov.pad in CopyFiles */, EB6142C61501FE89004E2AE8 /* pc6x8.fnt in CopyFiles */, EB6142C71501FE89004E2AE8 /* pc8x16.fnt in CopyFiles */, EB6142C81501FE89004E2AE8 /* segmove.pad in CopyFiles */, EB6142C91501FE89004E2AE8 /* segsize.pad in CopyFiles */, EB6142CA1501FE89004E2AE8 /* test.pad in CopyFiles */, EB6142CB1501FE89004E2AE8 /* texture.pad in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; EBD441C31526B419002FF2BA /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = editor; dstSubfolderSpec = 7; files = ( EBD441821526B3D4002FF2BA /* curve.pad in CopyFiles */, EBD441831526B3D4002FF2BA /* dummy.pad in CopyFiles */, EBD441841526B3D4002FF2BA /* group.pad in CopyFiles */, EBD441851526B3D4002FF2BA /* lighting.pad in CopyFiles */, EBD441861526B3D4002FF2BA /* med.mnu in CopyFiles */, EBD441871526B3D4002FF2BA /* newobj.pad in CopyFiles */, EBD441881526B3D4002FF2BA /* object.pad in CopyFiles */, EBD441891526B3D4002FF2BA /* objmov.pad in CopyFiles */, EBD4418A1526B3D4002FF2BA /* pc6x8.fnt in CopyFiles */, EBD4418B1526B3D4002FF2BA /* pc8x16.fnt in CopyFiles */, EBD4418C1526B3D4002FF2BA /* segmove.pad in CopyFiles */, EBD4418D1526B3D4002FF2BA /* segsize.pad in CopyFiles */, EBD4418E1526B3D4002FF2BA /* test.pad in CopyFiles */, EBD4418F1526B3D4002FF2BA /* texture.pad in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 179E6ECD11F37C0500175C54 /* hmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmp.c; sourceTree = ""; }; 179E6ED011F37C1900175C54 /* hmp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hmp.h; path = include/hmp.h; sourceTree = SOURCE_ROOT; }; 17DFA6B510C1A2D100674D11 /* net_udp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = net_udp.c; sourceTree = ""; }; 17DFA6B610C1A2D100674D11 /* net_udp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = net_udp.h; sourceTree = ""; }; 670E3796066C50C30085B671 /* CHANGELOG.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = CHANGELOG.txt; sourceTree = ""; }; 670E3867066C571F0085B671 /* MVEPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MVEPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 670E3869066C571F0085B671 /* MVEPlayer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MVEPlayer-Info.plist"; sourceTree = SOURCE_ROOT; }; 670E39C4066C59A00085B671 /* mve_main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mve_main.c; sourceTree = ""; }; 6710AAFE066B2D6100DB0F68 /* SDL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL.framework; path = /Library/Frameworks/SDL.framework; sourceTree = ""; }; 6710AB68066B2E0400DB0F68 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; 675ED123066B196700E42AA7 /* d2x-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "d2x-Info.plist"; sourceTree = ""; }; 676032DC066B399A008A67A3 /* multi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = multi.c; sourceTree = ""; }; 676032DD066B399A008A67A3 /* multibot.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = multibot.c; sourceTree = ""; }; 676032F9066B39CE008A67A3 /* kmatrix.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = kmatrix.c; sourceTree = ""; }; 676AC04E0668A814007173EB /* gr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gr.c; sourceTree = ""; }; 676AC0510668A814007173EB /* ogl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ogl.c; sourceTree = ""; }; 676AC0E10668A86F007173EB /* ogl_init.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ogl_init.h; sourceTree = ""; }; 676AC26F0668A939007173EB /* d2x.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = d2x.app; sourceTree = BUILT_PRODUCTS_DIR; }; 676AC31D0668A939007173EB /* d2xgl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = d2xgl.app; sourceTree = BUILT_PRODUCTS_DIR; }; 676C5D030668840200D9FA2D /* pstypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pstypes.h; sourceTree = ""; }; 6791CE4F0668852C00056A5A /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = byteswap.h; sourceTree = ""; }; 6791CE500668852C00056A5A /* rle.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rle.h; sourceTree = ""; }; 6791CF2D066887E500056A5A /* makesig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = makesig.h; sourceTree = ""; }; 6791CF420668881F00056A5A /* fix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fix.h; sourceTree = ""; }; 6791CF4E0668883900056A5A /* palette.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = palette.h; sourceTree = ""; }; 6791CF620668885500056A5A /* pcx.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = pcx.h; sourceTree = ""; }; 6791CF8D066888DD00056A5A /* 3d.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = 3d.h; sourceTree = ""; }; 6791CFB10668891200056A5A /* texmap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = texmap.h; sourceTree = ""; }; 6791CFC50668893B00056A5A /* interp.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = interp.h; sourceTree = ""; }; 6791CFE20668899A00056A5A /* event.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = ""; }; 6791CFE30668899A00056A5A /* joy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = joy.h; sourceTree = ""; }; 6791D00B066889CD00056A5A /* args.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = args.h; sourceTree = ""; }; 6791D00C066889CD00056A5A /* console.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = ""; }; 6791D026066889F100056A5A /* vecmat.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = vecmat.h; sourceTree = ""; }; 6791D04B06688A2E00056A5A /* timer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = timer.h; sourceTree = ""; }; 6791D05B06688A4500056A5A /* key.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = key.h; sourceTree = ""; }; 6791D07006688A5F00056A5A /* mouse.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mouse.h; sourceTree = ""; }; 6791D07E06688A7B00056A5A /* rbaudio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = rbaudio.h; sourceTree = ""; }; 6791D08F06688A9C00056A5A /* maths.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = maths.h; sourceTree = ""; }; 6791D0A306688AB900056A5A /* strutil.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = strutil.h; sourceTree = ""; }; 6791D0BD06688AE800056A5A /* iff.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = iff.h; sourceTree = ""; }; 6791D0D106688B1100056A5A /* libmve.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = libmve.h; sourceTree = ""; }; 6791D12906688EB500056A5A /* hash.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; 6791D1550668903B00056A5A /* strio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = strio.h; sourceTree = ""; }; 67B44139066878B300DF26D8 /* 2dsline.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = 2dsline.c; sourceTree = ""; }; 67B4413A066878B300DF26D8 /* bitblt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bitblt.c; sourceTree = ""; }; 67B4413B066878B300DF26D8 /* bitmap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bitmap.c; sourceTree = ""; }; 67B4413D066878B300DF26D8 /* box.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = box.c; sourceTree = ""; }; 67B4413E066878B300DF26D8 /* canvas.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = canvas.c; sourceTree = ""; }; 67B4413F066878B300DF26D8 /* circle.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = circle.c; sourceTree = ""; }; 67B44141066878B300DF26D8 /* disc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = disc.c; sourceTree = ""; }; 67B44142066878B300DF26D8 /* font.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = font.c; sourceTree = ""; }; 67B44143066878B300DF26D8 /* gpixel.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gpixel.c; sourceTree = ""; }; 67B44145066878B300DF26D8 /* line.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = line.c; sourceTree = ""; }; 67B44148066878B300DF26D8 /* palette.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = palette.c; sourceTree = ""; }; 67B44149066878B300DF26D8 /* pcx.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pcx.c; sourceTree = ""; }; 67B4414A066878B300DF26D8 /* pixel.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = pixel.c; sourceTree = ""; }; 67B4414B066878B300DF26D8 /* poly.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = poly.c; sourceTree = ""; }; 67B4414C066878B300DF26D8 /* rect.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rect.c; sourceTree = ""; }; 67B4414D066878B300DF26D8 /* rle.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rle.c; sourceTree = ""; }; 67B44151066878B300DF26D8 /* scalec.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = scalec.c; sourceTree = ""; }; 67B441760668792300DF26D8 /* clipper.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = clipper.c; sourceTree = ""; }; 67B441780668792300DF26D8 /* draw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = draw.c; sourceTree = ""; }; 67B441790668792300DF26D8 /* globvars.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = globvars.c; sourceTree = ""; }; 67B4417B0668792300DF26D8 /* instance.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = instance.c; sourceTree = ""; }; 67B4417D0668792300DF26D8 /* interp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = interp.c; sourceTree = ""; }; 67B4417F0668792300DF26D8 /* matrix.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = matrix.c; sourceTree = ""; }; 67B441800668792300DF26D8 /* points.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = points.c; sourceTree = ""; }; 67B441810668792300DF26D8 /* rod.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rod.c; sourceTree = ""; }; 67B441820668792300DF26D8 /* setup.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = setup.c; sourceTree = ""; }; 67B441D306687A0200DF26D8 /* digi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = digi.c; sourceTree = ""; }; 67B441D406687A0200DF26D8 /* event.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = event.c; sourceTree = ""; }; 67B441D506687A0200DF26D8 /* gr.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gr.c; sourceTree = ""; }; 67B441D706687A0200DF26D8 /* joy.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = joy.c; sourceTree = ""; }; 67B441D906687A0200DF26D8 /* key.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = key.c; sourceTree = ""; }; 67B441DB06687A0200DF26D8 /* mouse.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mouse.c; sourceTree = ""; }; 67B441DC06687A0200DF26D8 /* rbaudio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rbaudio.c; sourceTree = ""; }; 67B441DD06687A0200DF26D8 /* timer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = timer.c; sourceTree = ""; }; 67B4420006687A9E00DF26D8 /* iff.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = iff.c; sourceTree = ""; }; 67B4421006687AD900DF26D8 /* decoder16.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 30; path = decoder16.c; sourceTree = ""; }; 67B4421106687AD900DF26D8 /* decoder8.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = decoder8.c; sourceTree = ""; }; 67B4421406687AD900DF26D8 /* mve_audio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mve_audio.c; sourceTree = ""; }; 67B4421706687AD900DF26D8 /* mvelib.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mvelib.c; sourceTree = ""; }; 67B4421906687AD900DF26D8 /* mveplay.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mveplay.c; sourceTree = ""; }; 67B446CF06687CF400DF26D8 /* ai.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ai.c; sourceTree = ""; }; 67B446D106687CF400DF26D8 /* ai2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ai2.c; sourceTree = ""; }; 67B446D206687CF400DF26D8 /* aipath.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = aipath.c; sourceTree = ""; }; 67B446D406687CF400DF26D8 /* automap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = automap.c; sourceTree = ""; }; 67B446D606687CF400DF26D8 /* bm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bm.c; sourceTree = ""; }; 67B446DB06687CF400DF26D8 /* cntrlcen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = cntrlcen.c; sourceTree = ""; }; 67B446DD06687CF400DF26D8 /* collide.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = collide.c; sourceTree = ""; }; 67B446E006687CF400DF26D8 /* config.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = config.c; sourceTree = ""; }; 67B446E206687CF400DF26D8 /* console.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = console.c; sourceTree = ""; }; 67B446E306687CF400DF26D8 /* controls.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = controls.c; sourceTree = ""; }; 67B446E506687CF400DF26D8 /* credits.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = credits.c; sourceTree = ""; }; 67B446F706687CF400DF26D8 /* effects.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = effects.c; sourceTree = ""; }; 67B446F906687CF400DF26D8 /* endlevel.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = endlevel.c; sourceTree = ""; }; 67B446FB06687CF400DF26D8 /* escort.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = escort.c; sourceTree = ""; }; 67B446FD06687CF400DF26D8 /* fireball.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fireball.c; sourceTree = ""; }; 67B446FF06687CF400DF26D8 /* fuelcen.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fuelcen.c; sourceTree = ""; }; 67B4470106687CF400DF26D8 /* fvi.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fvi.c; sourceTree = ""; }; 67B4470406687CF400DF26D8 /* game.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = game.c; sourceTree = ""; }; 67B4470606687CF400DF26D8 /* gamecntl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamecntl.c; sourceTree = ""; }; 67B4470706687CF400DF26D8 /* gamefont.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamefont.c; sourceTree = ""; }; 67B4470906687CF400DF26D8 /* gamemine.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamemine.c; sourceTree = ""; }; 67B4470B06687CF400DF26D8 /* gamepal.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamepal.c; sourceTree = ""; }; 67B4470D06687CF400DF26D8 /* gamerend.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamerend.c; sourceTree = ""; }; 67B4470E06687CF400DF26D8 /* gamesave.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gamesave.c; sourceTree = ""; }; 67B4471006687CF400DF26D8 /* gameseg.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gameseg.c; sourceTree = ""; }; 67B4471206687CF400DF26D8 /* gameseq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gameseq.c; sourceTree = ""; }; 67B4471506687CF400DF26D8 /* gauges.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gauges.c; sourceTree = ""; }; 67B4471706687CF400DF26D8 /* hostage.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = hostage.c; sourceTree = ""; }; 67B4471906687CF400DF26D8 /* hud.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = hud.c; sourceTree = ""; }; 67B4471B06687CF400DF26D8 /* inferno.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = inferno.c; sourceTree = ""; }; 67B4472006687CF400DF26D8 /* kconfig.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = kconfig.c; sourceTree = ""; }; 67B4472506687CF400DF26D8 /* laser.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = laser.c; sourceTree = ""; }; 67B4472706687CF400DF26D8 /* lighting.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = lighting.c; sourceTree = ""; }; 67B4472B06687CF400DF26D8 /* menu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = menu.c; sourceTree = ""; }; 67B4472D06687CF400DF26D8 /* mglobal.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mglobal.c; sourceTree = ""; }; 67B4472E06687CF400DF26D8 /* mission.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mission.c; sourceTree = ""; }; 67B4473106687CF400DF26D8 /* morph.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = morph.c; sourceTree = ""; }; 67B4473306687CF400DF26D8 /* movie.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = movie.c; sourceTree = ""; }; 67B4473D06687CF400DF26D8 /* newdemo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = newdemo.c; sourceTree = ""; }; 67B4473F06687CF400DF26D8 /* newmenu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = newmenu.c; sourceTree = ""; }; 67B4474106687CF400DF26D8 /* object.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = object.c; sourceTree = ""; }; 67B4475906687CF400DF26D8 /* paging.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = paging.c; sourceTree = ""; }; 67B4475B06687CF400DF26D8 /* physics.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = physics.c; sourceTree = ""; }; 67B4475D06687CF400DF26D8 /* piggy.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = piggy.c; sourceTree = ""; }; 67B4475F06687CF400DF26D8 /* player.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = player.c; sourceTree = ""; }; 67B4476106687CF400DF26D8 /* playsave.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = playsave.c; sourceTree = ""; }; 67B4476306687CF400DF26D8 /* polyobj.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = polyobj.c; sourceTree = ""; }; 67B4476506687CF400DF26D8 /* powerup.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = powerup.c; sourceTree = ""; }; 67B4476706687CF400DF26D8 /* render.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = render.c; sourceTree = ""; }; 67B4476A06687CF400DF26D8 /* robot.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = robot.c; sourceTree = ""; }; 67B4476C06687CF400DF26D8 /* scores.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = scores.c; sourceTree = ""; }; 67B4476F06687CF400DF26D8 /* segment.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = segment.c; sourceTree = ""; }; 67B4477206687CF400DF26D8 /* slew.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = slew.c; sourceTree = ""; }; 67B4477406687CF400DF26D8 /* songs.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = songs.c; sourceTree = ""; }; 67B4477706687CF400DF26D8 /* state.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = state.c; sourceTree = ""; }; 67B4477906687CF400DF26D8 /* switch.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = switch.c; sourceTree = ""; }; 67B4477B06687CF400DF26D8 /* terrain.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = terrain.c; sourceTree = ""; }; 67B4477D06687CF400DF26D8 /* texmerge.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = texmerge.c; sourceTree = ""; }; 67B4477F06687CF500DF26D8 /* text.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = text.c; sourceTree = ""; }; 67B4478206687CF500DF26D8 /* titles.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = titles.c; sourceTree = ""; }; 67B4478406687CF500DF26D8 /* vclip.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = vclip.c; sourceTree = ""; }; 67B4478706687CF500DF26D8 /* wall.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = wall.c; sourceTree = ""; }; 67B4478906687CF500DF26D8 /* weapon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = weapon.c; sourceTree = ""; }; 67B4484B06687DCE00DF26D8 /* fixc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = fixc.c; sourceTree = ""; }; 67B4484D06687DCE00DF26D8 /* rand.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = rand.c; sourceTree = ""; }; 67B4484E06687DCE00DF26D8 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; 67B4484F06687DCE00DF26D8 /* vecmat.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = vecmat.c; sourceTree = ""; }; 67B4485E06687DFB00DF26D8 /* mem.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = ""; }; 67B4486606687E1000DF26D8 /* args.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = args.c; sourceTree = ""; }; 67B4486A06687E1000DF26D8 /* error.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = ""; }; 67B4486C06687E1000DF26D8 /* hash.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = hash.c; sourceTree = ""; }; 67B4487206687E1000DF26D8 /* strio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = strio.c; sourceTree = ""; }; 67B4487306687E1000DF26D8 /* strutil.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = strutil.c; sourceTree = ""; }; 67B4488806687E5E00DF26D8 /* ntmap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ntmap.c; sourceTree = ""; }; 67B4488906687E5E00DF26D8 /* scanline.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = scanline.c; sourceTree = ""; }; 67B4489206687E5E00DF26D8 /* tmapflat.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = tmapflat.c; sourceTree = ""; }; 67B4490F066880A300DF26D8 /* u_mem.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = u_mem.h; sourceTree = ""; }; 67B44914066880C400DF26D8 /* gr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gr.h; sourceTree = ""; }; 67B44915066880C400DF26D8 /* grdef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = grdef.h; sourceTree = ""; }; 67F6FED0066B13B400443922 /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SDLMain.h; path = arch/cocoa/SDLMain.h; sourceTree = ""; }; 67F6FED1066B13B400443922 /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = SDLMain.m; path = arch/cocoa/SDLMain.m; sourceTree = ""; }; 67F6FEEA066B13D900443922 /* d2xgl-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "d2xgl-Info.plist"; sourceTree = ""; }; EB01AFA90A65323200EA4C7C /* newdemo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = newdemo.h; sourceTree = ""; }; EB0420B90A341041002CC961 /* multi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = multi.h; sourceTree = ""; }; EB0420BA0A341042002CC961 /* movie.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = movie.h; sourceTree = ""; }; EB0420BB0A341042002CC961 /* morph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = morph.h; sourceTree = ""; }; EB0420BD0A341042002CC961 /* mission.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mission.h; sourceTree = ""; }; EB0420BE0A341042002CC961 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = ""; }; EB0420BF0A341042002CC961 /* cntrlcen.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = cntrlcen.h; sourceTree = ""; }; EB0420C00A341042002CC961 /* bmread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bmread.h; sourceTree = ""; }; EB0420C10A341042002CC961 /* weapon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = weapon.h; sourceTree = ""; }; EB0420C20A341042002CC961 /* wall.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = wall.h; sourceTree = ""; }; EB0420C30A341042002CC961 /* vers_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = vers_id.h; sourceTree = ""; }; EB0420C40A341042002CC961 /* vclip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = vclip.h; sourceTree = ""; }; EB0420C50A341042002CC961 /* titles.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = titles.h; sourceTree = ""; }; EB0420C60A341042002CC961 /* textures.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = textures.h; sourceTree = ""; }; EB0420C70A341042002CC961 /* text.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = text.h; sourceTree = ""; }; EB0420C80A341042002CC961 /* texmerge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = texmerge.h; sourceTree = ""; }; EB0420C90A341042002CC961 /* terrain.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = terrain.h; sourceTree = ""; }; EB0420CA0A341042002CC961 /* switch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = switch.h; sourceTree = ""; }; EB0420CB0A341042002CC961 /* state.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = state.h; sourceTree = ""; }; EB0420CC0A341042002CC961 /* sounds.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = sounds.h; sourceTree = ""; }; EB0420CD0A341042002CC961 /* songs.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = songs.h; sourceTree = ""; }; EB0420CE0A341042002CC961 /* slew.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = slew.h; sourceTree = ""; }; EB0420CF0A341042002CC961 /* segpoint.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = segpoint.h; sourceTree = ""; }; EB0420D00A341042002CC961 /* segment.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = segment.h; sourceTree = ""; }; EB0420D10A341042002CC961 /* screens.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = screens.h; sourceTree = ""; }; EB0420D20A341042002CC961 /* scores.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = scores.h; sourceTree = ""; }; EB0420D30A341042002CC961 /* robot.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = robot.h; sourceTree = ""; }; EB0420D50A341042002CC961 /* render.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = render.h; sourceTree = ""; }; EB0420D60A341042002CC961 /* powerup.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = powerup.h; sourceTree = ""; }; EB0420D70A341042002CC961 /* polyobj.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = polyobj.h; sourceTree = ""; }; EB0420D80A341042002CC961 /* playsave.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = playsave.h; sourceTree = ""; }; EB0420D90A341042002CC961 /* player.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = player.h; sourceTree = ""; }; EB0420DA0A341042002CC961 /* piggy.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = piggy.h; sourceTree = ""; }; EB0420DB0A341042002CC961 /* physics.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = physics.h; sourceTree = ""; }; EB0420DC0A341042002CC961 /* paging.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = paging.h; sourceTree = ""; }; EB0420DD0A341042002CC961 /* object.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = object.h; sourceTree = ""; }; EB0420DE0A341042002CC961 /* newmenu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = newmenu.h; sourceTree = ""; }; EB0420E10A341042002CC961 /* digi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = digi.h; sourceTree = ""; }; EB0420E30A341042002CC961 /* gameseq.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gameseq.h; sourceTree = ""; }; EB0420E50A341042002CC961 /* credits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = credits.h; sourceTree = ""; }; EB0420E70A341042002CC961 /* multibot.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = multibot.h; sourceTree = ""; }; EB0420E80A341042002CC961 /* gameseg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gameseg.h; sourceTree = ""; }; EB0420E90A341042002CC961 /* gamesave.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gamesave.h; sourceTree = ""; }; EB0420EA0A341042002CC961 /* gamepal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gamepal.h; sourceTree = ""; }; EB0420EB0A341042002CC961 /* gamemine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gamemine.h; sourceTree = ""; }; EB0420EC0A341042002CC961 /* gamefont.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gamefont.h; sourceTree = ""; }; EB0420ED0A341042002CC961 /* game.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = game.h; sourceTree = ""; }; EB0420EF0A341042002CC961 /* fvi.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fvi.h; sourceTree = ""; }; EB0420F00A341042002CC961 /* fuelcen.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fuelcen.h; sourceTree = ""; }; EB0420F10A341042002CC961 /* collide.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = collide.h; sourceTree = ""; }; EB0420F20A341042002CC961 /* kmatrix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kmatrix.h; sourceTree = ""; }; EB0420F30A341042002CC961 /* kconfig.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = kconfig.h; sourceTree = ""; }; EB0420F50A341042002CC961 /* inferno.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = inferno.h; sourceTree = ""; }; EB0420F60A341042002CC961 /* hudmsg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = hudmsg.h; sourceTree = ""; }; EB0420F70A341042002CC961 /* hostage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = hostage.h; sourceTree = ""; }; EB0420F80A341042002CC961 /* gauges.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = gauges.h; sourceTree = ""; }; EB0420FA0A341042002CC961 /* lighting.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = lighting.h; sourceTree = ""; }; EB0420FC0A341042002CC961 /* laser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = laser.h; sourceTree = ""; }; EB0420FD0A341042002CC961 /* fireball.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = fireball.h; sourceTree = ""; }; EB0420FE0A341042002CC961 /* escort.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = escort.h; sourceTree = ""; }; EB0420FF0A341042002CC961 /* endlevel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = endlevel.h; sourceTree = ""; }; EB0421000A341042002CC961 /* effects.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = effects.h; sourceTree = ""; }; EB0421010A341042002CC961 /* aistruct.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = aistruct.h; sourceTree = ""; }; EB0421020A341042002CC961 /* bm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bm.h; sourceTree = ""; }; EB0421030A341042002CC961 /* automap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = automap.h; sourceTree = ""; }; EB0421040A341042002CC961 /* ai.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ai.h; sourceTree = ""; }; EB0421050A341042002CC961 /* controls.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = controls.h; sourceTree = ""; }; EB0421060A341042002CC961 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; EB092A7F12A25AFB004D9A79 /* messagebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messagebox.c; sourceTree = ""; }; EB092A8512A25EC8004D9A79 /* messagebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = messagebox.c; sourceTree = ""; }; EB092A8A12A25EE4004D9A79 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; EB1405E8121044B5002B1CC6 /* physfsx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = physfsx.c; sourceTree = ""; }; EB28D9A20ECEAF1C00E68E9B /* init.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = init.c; sourceTree = ""; }; EB3EB4DF12A5471B005F992D /* messagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = messagebox.h; sourceTree = ""; }; EB3EB4ED12A547C7005F992D /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; EB6142A51501FD71004E2AE8 /* curve.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = curve.pad; sourceTree = ""; }; EB6142A61501FD71004E2AE8 /* dummy.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dummy.pad; sourceTree = ""; }; EB6142A71501FD71004E2AE8 /* group.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = group.pad; sourceTree = ""; }; EB6142A81501FD71004E2AE8 /* lighting.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lighting.pad; sourceTree = ""; }; EB6142A91501FD71004E2AE8 /* med.mnu */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = med.mnu; sourceTree = ""; }; EB6142AA1501FD71004E2AE8 /* newobj.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = newobj.pad; sourceTree = ""; }; EB6142AB1501FD71004E2AE8 /* object.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = object.pad; sourceTree = ""; }; EB6142AC1501FD71004E2AE8 /* objmov.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objmov.pad; sourceTree = ""; }; EB6142AD1501FD71004E2AE8 /* pc6x8.fnt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pc6x8.fnt; sourceTree = ""; }; EB6142AE1501FD71004E2AE8 /* pc8x16.fnt */ = {isa = PBXFileReference; lastKnownFileType = file; path = pc8x16.fnt; sourceTree = ""; }; EB6142AF1501FD71004E2AE8 /* segmove.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = segmove.pad; sourceTree = ""; }; EB6142B01501FD71004E2AE8 /* segsize.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = segsize.pad; sourceTree = ""; }; EB6142B11501FD71004E2AE8 /* test.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = test.pad; sourceTree = ""; }; EB6142B21501FD71004E2AE8 /* texture.pad */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = texture.pad; sourceTree = ""; }; EB6AFF5A170FD7B000ED37CB /* tool_bundle.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; name = tool_bundle.py; path = arch/cocoa/tool_bundle.py; sourceTree = ""; }; EB6AFF5B170FD91C00ED37CB /* d2x-rebirth.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "d2x-rebirth.rc"; sourceTree = ""; }; EB6AFF5C170FD96200ED37CB /* dxxerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dxxerror.h; sourceTree = ""; }; EB6AFF5D170FD96200ED37CB /* pngfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pngfile.h; sourceTree = ""; }; EB6AFF5E170FD98100ED37CB /* esegment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = esegment.h; sourceTree = ""; }; EB6AFF5F170FD9B400ED37CB /* vers_id.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vers_id.c; sourceTree = ""; }; EB6AFF62170FDA0300ED37CB /* scanline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scanline.h; sourceTree = ""; }; EB6AFF63170FDA0300ED37CB /* texmapl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = texmapl.h; sourceTree = ""; }; EB91A437126175ED009E0095 /* libphysfs.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libphysfs.dylib; path = ../physfs/build/Release/libphysfs.dylib; sourceTree = SOURCE_ROOT; }; EB91A43C12617668009E0095 /* libphysfs.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libphysfs.dylib; path = ../physfs/build/Debug/libphysfs.dylib; sourceTree = SOURCE_ROOT; }; EB92BE110CDD68200045A32C /* digi_audio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = digi_audio.h; sourceTree = ""; }; EB92BE120CDD68200045A32C /* digi_mixer_music.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = digi_mixer_music.h; sourceTree = ""; }; EB92BE130CDD68200045A32C /* digi_mixer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = digi_mixer.h; sourceTree = ""; }; EB92BE140CDD68200045A32C /* jukebox.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = jukebox.h; sourceTree = ""; }; EB92BE5C0CDD693C0045A32C /* digi_audio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = digi_audio.c; sourceTree = ""; }; EB92BE5D0CDD693C0045A32C /* digi_mixer_music.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = digi_mixer_music.c; sourceTree = ""; }; EB92BE5E0CDD693C0045A32C /* digi_mixer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = digi_mixer.c; sourceTree = ""; }; EB92BE5F0CDD693C0045A32C /* jukebox.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = jukebox.c; sourceTree = ""; }; EB92BE680CDD69830045A32C /* dl_list.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dl_list.h; sourceTree = ""; }; EB92BEA40CDD6A570045A32C /* dl_list.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dl_list.c; sourceTree = ""; }; EB92BEC40CDD6B4B0045A32C /* SDL_mixer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL_mixer.framework; path = /Library/Frameworks/SDL_mixer.framework; sourceTree = ""; }; EBAEB74B0BF4A86F00FC6E13 /* d2x-rebirth.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = "d2x-rebirth.icns"; path = "arch/cocoa/d2x-rebirth.icns"; sourceTree = ""; }; EBAFC23A088E4B2C006329AD /* physfsx.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = physfsx.h; sourceTree = ""; }; EBAFC248088E4C17006329AD /* ignorecase.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ignorecase.h; sourceTree = ""; }; EBAFC24B088E4C53006329AD /* physfsrwops.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = physfsrwops.h; sourceTree = ""; }; EBAFC269088E508D006329AD /* conf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = conf.h; sourceTree = ""; }; EBAFC26A088E508D006329AD /* descent.r */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.rez; path = descent.r; sourceTree = ""; }; EBAFC26D088E508D006329AD /* SDL_main.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = SDL_main.c; sourceTree = ""; }; EBAFC28F088E67CD006329AD /* digiobj.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = digiobj.c; sourceTree = ""; }; EBAFC2B0088E695F006329AD /* ignorecase.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ignorecase.c; sourceTree = ""; }; EBAFC2B1088E695F006329AD /* physfsrwops.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = physfsrwops.c; sourceTree = ""; }; EBB66313122E4DC60057352D /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; EBB66317122E4DF40057352D /* HIServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HIServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework; sourceTree = ""; }; EBB9E5320D8E82B3003466E6 /* bitmap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = bitmap.h; sourceTree = ""; }; EBB9E5330D8E82B3003466E6 /* clip.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clip.h; sourceTree = ""; }; EBB9E5380D8E82FF003466E6 /* clipper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = clipper.h; sourceTree = ""; }; EBB9E5390D8E82FF003466E6 /* globvars.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = globvars.h; sourceTree = ""; }; EBB9E5480D8E83F2003466E6 /* internal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; EBB9E5490D8E83F2003466E6 /* loadgl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = loadgl.h; sourceTree = ""; }; EBB9E54B0D8E8429003466E6 /* decoders.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = decoders.h; sourceTree = ""; }; EBB9E54C0D8E8429003466E6 /* mve_audio.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mve_audio.h; sourceTree = ""; }; EBB9E54D0D8E8429003466E6 /* mvelib.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = mvelib.h; sourceTree = ""; }; EBBE057A12C872C30056CF2D /* autosave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = autosave.c; sourceTree = ""; }; EBBE057B12C872C30056CF2D /* centers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = centers.c; sourceTree = ""; }; EBBE057D12C872C30056CF2D /* curves.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = curves.c; sourceTree = ""; }; EBBE057F12C872C30056CF2D /* eglobal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eglobal.c; sourceTree = ""; }; EBBE058212C872C30056CF2D /* elight.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = elight.c; sourceTree = ""; }; EBBE058312C872C30056CF2D /* eobject.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eobject.c; sourceTree = ""; }; EBBE058512C872C30056CF2D /* eswitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eswitch.c; sourceTree = ""; }; EBBE058712C872C30056CF2D /* fixseg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fixseg.c; sourceTree = ""; }; EBBE058812C872C30056CF2D /* func.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = func.c; sourceTree = ""; }; EBBE058912C872C30056CF2D /* group.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = group.c; sourceTree = ""; }; EBBE058A12C872C30056CF2D /* info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = info.c; sourceTree = ""; }; EBBE058C12C872C30056CF2D /* kbuild.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kbuild.c; sourceTree = ""; }; EBBE058D12C872C30056CF2D /* kcurve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kcurve.c; sourceTree = ""; }; EBBE058F12C872C30056CF2D /* kfuncs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kfuncs.c; sourceTree = ""; }; EBBE059112C872C30056CF2D /* kgame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kgame.c; sourceTree = ""; }; EBBE059312C872C30056CF2D /* khelp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = khelp.c; sourceTree = ""; }; EBBE059412C872C30056CF2D /* kmine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kmine.c; sourceTree = ""; }; EBBE059512C872C30056CF2D /* ksegmove.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ksegmove.c; sourceTree = ""; }; EBBE059612C872C30056CF2D /* ksegsel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ksegsel.c; sourceTree = ""; }; EBBE059712C872C30056CF2D /* ksegsize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ksegsize.c; sourceTree = ""; }; EBBE059812C872C30056CF2D /* ktmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ktmap.c; sourceTree = ""; }; EBBE059912C872C30056CF2D /* kview.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kview.c; sourceTree = ""; }; EBBE059C12C872C30056CF2D /* med.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = med.c; sourceTree = ""; }; EBBE059D12C872C30056CF2D /* meddraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = meddraw.c; sourceTree = ""; }; EBBE05A012C872C30056CF2D /* medmisc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = medmisc.c; sourceTree = ""; }; EBBE05A212C872C30056CF2D /* medrobot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = medrobot.c; sourceTree = ""; }; EBBE05A412C872C30056CF2D /* medsel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = medsel.c; sourceTree = ""; }; EBBE05A612C872C30056CF2D /* medwall.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = medwall.c; sourceTree = ""; }; EBBE05A812C872C30056CF2D /* mine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mine.c; sourceTree = ""; }; EBBE05A912C872C30056CF2D /* objpage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = objpage.c; sourceTree = ""; }; EBBE05AB12C872C30056CF2D /* segment.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = segment.c; sourceTree = ""; }; EBBE05AC12C872C30056CF2D /* seguvs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seguvs.c; sourceTree = ""; }; EBBE05AE12C872C30056CF2D /* texpage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = texpage.c; sourceTree = ""; }; EBBE05B012C872C30056CF2D /* texture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = texture.c; sourceTree = ""; }; EBBE05FE12C87D250056CF2D /* centers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = centers.h; sourceTree = ""; }; EBBE05FF12C87D250056CF2D /* editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = editor.h; sourceTree = ""; }; EBBE060012C87D250056CF2D /* ehostage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ehostage.h; sourceTree = ""; }; EBBE060112C87D250056CF2D /* eobject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eobject.h; sourceTree = ""; }; EBBE060212C87D250056CF2D /* eswitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eswitch.h; sourceTree = ""; }; EBBE060312C87D250056CF2D /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; EBBE060412C87D250056CF2D /* kdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kdefs.h; sourceTree = ""; }; EBBE060512C87D250056CF2D /* kfuncs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kfuncs.h; sourceTree = ""; }; EBBE060612C87D250056CF2D /* macro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macro.h; sourceTree = ""; }; EBBE060712C87D250056CF2D /* meddraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = meddraw.h; sourceTree = ""; }; EBBE060812C87D250056CF2D /* medlisp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = medlisp.h; sourceTree = ""; }; EBBE060912C87D250056CF2D /* medmisc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = medmisc.h; sourceTree = ""; }; EBBE060A12C87D250056CF2D /* medrobot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = medrobot.h; sourceTree = ""; }; EBBE060B12C87D250056CF2D /* medsel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = medsel.h; sourceTree = ""; }; EBBE060C12C87D250056CF2D /* medwall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = medwall.h; sourceTree = ""; }; EBBE060D12C87D250056CF2D /* objpage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = objpage.h; sourceTree = ""; }; EBBE060E12C87D250056CF2D /* seguvs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = seguvs.h; sourceTree = ""; }; EBBE060F12C87D250056CF2D /* texpage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = texpage.h; sourceTree = ""; }; EBC651900890CEAE004FCAA3 /* button.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = button.c; sourceTree = ""; }; EBC651910890CEAE004FCAA3 /* checkbox.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = checkbox.c; sourceTree = ""; }; EBC651920890CEAE004FCAA3 /* file.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = file.c; sourceTree = ""; }; EBC651940890CEAE004FCAA3 /* gadget.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = gadget.c; sourceTree = ""; }; EBC651960890CEAE004FCAA3 /* icon.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = icon.c; sourceTree = ""; }; EBC651970890CEAE004FCAA3 /* inputbox.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = inputbox.c; sourceTree = ""; }; EBC651980890CEAE004FCAA3 /* keypad.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keypad.c; sourceTree = ""; }; EBC651990890CEAE004FCAA3 /* keypress.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keypress.c; sourceTree = ""; }; EBC6519A0890CEAE004FCAA3 /* keytrap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = keytrap.c; sourceTree = ""; }; EBC6519B0890CEAE004FCAA3 /* listbox.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = listbox.c; sourceTree = ""; }; EBC6519E0890CEAE004FCAA3 /* menu.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = menu.c; sourceTree = ""; }; EBC6519F0890CEAE004FCAA3 /* menubar.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = menubar.c; sourceTree = ""; }; EBC651A00890CEAE004FCAA3 /* message.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = message.c; sourceTree = ""; }; EBC651A30890CEAE004FCAA3 /* popup.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = popup.c; sourceTree = ""; }; EBC651A40890CEAE004FCAA3 /* radio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = radio.c; sourceTree = ""; }; EBC651A50890CEAE004FCAA3 /* scroll.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = scroll.c; sourceTree = ""; }; EBC651A60890CEAE004FCAA3 /* ui.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = ui.c; sourceTree = ""; }; EBC651A70890CEAE004FCAA3 /* uidraw.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = uidraw.c; sourceTree = ""; }; EBC651A80890CEAE004FCAA3 /* userbox.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = userbox.c; sourceTree = ""; }; EBC651A90890CEAE004FCAA3 /* dialog.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dialog.c; sourceTree = ""; }; EBC652010890D632004FCAA3 /* bmread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bmread.c; sourceTree = ""; }; EBC652020890D632004FCAA3 /* dumpmine.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = dumpmine.c; sourceTree = ""; }; EBC6520F0890D6B7004FCAA3 /* ui.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ui.h; sourceTree = ""; }; EBC652120890D6DF004FCAA3 /* func.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = func.h; sourceTree = ""; }; EBE8D6E90FC58365009D181F /* window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; EBE8D6EA0FC583B4009D181F /* window.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = window.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 670E3865066C571F0085B671 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 670E39EC066C5A0F0085B671 /* SDL.framework in Frameworks */, 670E39ED066C5A100085B671 /* Cocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC26B0668A938007173EB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 676AC26C0668A938007173EB /* Cocoa.framework in Frameworks */, 6710AB00066B2D6100DB0F68 /* SDL.framework in Frameworks */, EB92BEC60CDD6B4B0045A32C /* SDL_mixer.framework in Frameworks */, EBB66315122E4DC60057352D /* ApplicationServices.framework in Frameworks */, EB91A439126175ED009E0095 /* libphysfs.dylib in Frameworks */, EB91A43E12617668009E0095 /* libphysfs.dylib in Frameworks */, EB3EB4F412A5480D005F992D /* Carbon.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC31C0668A939007173EB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 6766BAC20668B3A000A6052D /* Cocoa.framework in Frameworks */, 6710AAFF066B2D6100DB0F68 /* SDL.framework in Frameworks */, 6710AB69066B2E0400DB0F68 /* OpenGL.framework in Frameworks */, EB92BEC50CDD6B4B0045A32C /* SDL_mixer.framework in Frameworks */, EBB66314122E4DC60057352D /* ApplicationServices.framework in Frameworks */, EB91A438126175ED009E0095 /* libphysfs.dylib in Frameworks */, EB91A43D12617668009E0095 /* libphysfs.dylib in Frameworks */, EB3EB4F312A54805005F992D /* Carbon.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( 67F6FED0066B13B400443922 /* SDLMain.h */, 67F6FED1066B13B400443922 /* SDLMain.m */, EB6AFF5A170FD7B000ED37CB /* tool_bundle.py */, ); name = Classes; sourceTree = ""; }; 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { isa = PBXGroup; children = ( EB91A43C12617668009E0095 /* libphysfs.dylib */, EB91A437126175ED009E0095 /* libphysfs.dylib */, EBB66317122E4DF40057352D /* HIServices.framework */, EBB66313122E4DC60057352D /* ApplicationServices.framework */, EB92BEC40CDD6B4B0045A32C /* SDL_mixer.framework */, 6710AB68066B2E0400DB0F68 /* OpenGL.framework */, 6710AAFE066B2D6100DB0F68 /* SDL.framework */, 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, ); name = "Linked Frameworks"; sourceTree = ""; }; 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { isa = PBXGroup; children = ( ); name = "Other Frameworks"; sourceTree = ""; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( 676AC26F0668A939007173EB /* d2x.app */, 676AC31D0668A939007173EB /* d2xgl.app */, 670E3867066C571F0085B671 /* MVEPlayer.app */, ); name = Products; sourceTree = ""; }; 29B97314FDCFA39411CA2CEA /* d2x */ = { isa = PBXGroup; children = ( 670E3796066C50C30085B671 /* CHANGELOG.txt */, 080E96DDFE201D6D7F000001 /* Classes */, 29B97315FDCFA39411CA2CEA /* Other Sources */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, 675ED123066B196700E42AA7 /* d2x-Info.plist */, 67F6FEEA066B13D900443922 /* d2xgl-Info.plist */, 670E3869066C571F0085B671 /* MVEPlayer-Info.plist */, ); name = d2x; sourceTree = ""; }; 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( 67B44137066878B300DF26D8 /* 2d */, 67B441740668792300DF26D8 /* 3d */, 67B441EC06687A3F00DF26D8 /* arch */, EBBE057912C872C30056CF2D /* editor */, 67B441F806687A9E00DF26D8 /* iff */, 67B448AC0668803500DF26D8 /* include */, 67B4420E06687AD900DF26D8 /* libmve */, 67B446CD06687CF400DF26D8 /* main */, 67B4484806687DCE00DF26D8 /* maths */, 67B4485B06687DFB00DF26D8 /* mem */, 67B4486406687E1000DF26D8 /* misc */, 67B4488506687E5E00DF26D8 /* texmap */, EBC6518D0890CEAE004FCAA3 /* ui */, ); name = "Other Sources"; sourceTree = ""; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( EBAEB74B0BF4A86F00FC6E13 /* d2x-rebirth.icns */, 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, ); name = Resources; sourceTree = ""; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( EB3EB4ED12A547C7005F992D /* Carbon.framework */, 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, ); name = Frameworks; sourceTree = ""; }; 676AC04B0668A814007173EB /* ogl */ = { isa = PBXGroup; children = ( 676AC04E0668A814007173EB /* gr.c */, 676AC0510668A814007173EB /* ogl.c */, ); name = ogl; path = arch/ogl; sourceTree = SOURCE_ROOT; }; 6791CFE10668899A00056A5A /* include */ = { isa = PBXGroup; children = ( EB3EB4DF12A5471B005F992D /* messagebox.h */, EB92BE110CDD68200045A32C /* digi_audio.h */, EB92BE120CDD68200045A32C /* digi_mixer_music.h */, EB92BE130CDD68200045A32C /* digi_mixer.h */, 6791CFE20668899A00056A5A /* event.h */, 6791D05B06688A4500056A5A /* key.h */, 6791CFE30668899A00056A5A /* joy.h */, EB92BE140CDD68200045A32C /* jukebox.h */, 6791D07006688A5F00056A5A /* mouse.h */, EBE8D6E90FC58365009D181F /* window.h */, ); name = include; path = arch/include; sourceTree = SOURCE_ROOT; }; 67B44137066878B300DF26D8 /* 2d */ = { isa = PBXGroup; children = ( 67B44139066878B300DF26D8 /* 2dsline.c */, 67B4413A066878B300DF26D8 /* bitblt.c */, 67B4413B066878B300DF26D8 /* bitmap.c */, EBB9E5320D8E82B3003466E6 /* bitmap.h */, 67B4413D066878B300DF26D8 /* box.c */, 67B4413E066878B300DF26D8 /* canvas.c */, 67B4413F066878B300DF26D8 /* circle.c */, EBB9E5330D8E82B3003466E6 /* clip.h */, 67B44141066878B300DF26D8 /* disc.c */, 67B44142066878B300DF26D8 /* font.c */, 67B44143066878B300DF26D8 /* gpixel.c */, 67B44145066878B300DF26D8 /* line.c */, 67B44148066878B300DF26D8 /* palette.c */, 67B44149066878B300DF26D8 /* pcx.c */, 67B4414A066878B300DF26D8 /* pixel.c */, 67B4414B066878B300DF26D8 /* poly.c */, 67B4414C066878B300DF26D8 /* rect.c */, 67B4414D066878B300DF26D8 /* rle.c */, 67B44151066878B300DF26D8 /* scalec.c */, ); path = 2d; sourceTree = SOURCE_ROOT; }; 67B441740668792300DF26D8 /* 3d */ = { isa = PBXGroup; children = ( 67B441760668792300DF26D8 /* clipper.c */, EBB9E5380D8E82FF003466E6 /* clipper.h */, 67B441780668792300DF26D8 /* draw.c */, 67B441790668792300DF26D8 /* globvars.c */, EBB9E5390D8E82FF003466E6 /* globvars.h */, 67B4417B0668792300DF26D8 /* instance.c */, 67B4417D0668792300DF26D8 /* interp.c */, 67B4417F0668792300DF26D8 /* matrix.c */, 67B441800668792300DF26D8 /* points.c */, 67B441810668792300DF26D8 /* rod.c */, 67B441820668792300DF26D8 /* setup.c */, ); path = 3d; sourceTree = SOURCE_ROOT; }; 67B441D106687A0200DF26D8 /* sdl */ = { isa = PBXGroup; children = ( EB92BE5C0CDD693C0045A32C /* digi_audio.c */, EB92BE5D0CDD693C0045A32C /* digi_mixer_music.c */, EB92BE5E0CDD693C0045A32C /* digi_mixer.c */, 67B441D306687A0200DF26D8 /* digi.c */, 67B441D406687A0200DF26D8 /* event.c */, 67B441D506687A0200DF26D8 /* gr.c */, EB28D9A20ECEAF1C00E68E9B /* init.c */, 67B441D706687A0200DF26D8 /* joy.c */, EB92BE5F0CDD693C0045A32C /* jukebox.c */, 67B441D906687A0200DF26D8 /* key.c */, 67B441DB06687A0200DF26D8 /* mouse.c */, 67B441DC06687A0200DF26D8 /* rbaudio.c */, 67B441DD06687A0200DF26D8 /* timer.c */, EBE8D6EA0FC583B4009D181F /* window.c */, ); name = sdl; path = arch/sdl; sourceTree = SOURCE_ROOT; }; 67B441EC06687A3F00DF26D8 /* arch */ = { isa = PBXGroup; children = ( EBAFC268088E508D006329AD /* carbon */, 6791CFE10668899A00056A5A /* include */, 676AC04B0668A814007173EB /* ogl */, 67B441D106687A0200DF26D8 /* sdl */, EBB9E53A0D8E8378003466E6 /* win32 */, ); name = arch; sourceTree = ""; }; 67B441F806687A9E00DF26D8 /* iff */ = { isa = PBXGroup; children = ( 67B4420006687A9E00DF26D8 /* iff.c */, ); path = iff; sourceTree = SOURCE_ROOT; }; 67B4420E06687AD900DF26D8 /* libmve */ = { isa = PBXGroup; children = ( 67B4421006687AD900DF26D8 /* decoder16.c */, 67B4421106687AD900DF26D8 /* decoder8.c */, EBB9E54B0D8E8429003466E6 /* decoders.h */, 67B4421406687AD900DF26D8 /* mve_audio.c */, EBB9E54C0D8E8429003466E6 /* mve_audio.h */, 670E39C4066C59A00085B671 /* mve_main.c */, 67B4421706687AD900DF26D8 /* mvelib.c */, EBB9E54D0D8E8429003466E6 /* mvelib.h */, 67B4421906687AD900DF26D8 /* mveplay.c */, ); path = libmve; sourceTree = SOURCE_ROOT; }; 67B446CD06687CF400DF26D8 /* main */ = { isa = PBXGroup; children = ( 67B446CF06687CF400DF26D8 /* ai.c */, 67B446D106687CF400DF26D8 /* ai2.c */, 67B446D206687CF400DF26D8 /* aipath.c */, 67B446D406687CF400DF26D8 /* automap.c */, 67B446D606687CF400DF26D8 /* bm.c */, EBC652010890D632004FCAA3 /* bmread.c */, 67B446DB06687CF400DF26D8 /* cntrlcen.c */, 67B446DD06687CF400DF26D8 /* collide.c */, 67B446E006687CF400DF26D8 /* config.c */, 67B446E206687CF400DF26D8 /* console.c */, 67B446E306687CF400DF26D8 /* controls.c */, 67B446E506687CF400DF26D8 /* credits.c */, EBAFC28F088E67CD006329AD /* digiobj.c */, EBC652020890D632004FCAA3 /* dumpmine.c */, 67B446F706687CF400DF26D8 /* effects.c */, 67B446F906687CF400DF26D8 /* endlevel.c */, 67B446FB06687CF400DF26D8 /* escort.c */, 67B446FD06687CF400DF26D8 /* fireball.c */, 67B446FF06687CF400DF26D8 /* fuelcen.c */, 67B4470106687CF400DF26D8 /* fvi.c */, 67B4470406687CF400DF26D8 /* game.c */, 67B4470606687CF400DF26D8 /* gamecntl.c */, 67B4470706687CF400DF26D8 /* gamefont.c */, 67B4470906687CF400DF26D8 /* gamemine.c */, 67B4470B06687CF400DF26D8 /* gamepal.c */, 67B4470D06687CF400DF26D8 /* gamerend.c */, 67B4470E06687CF400DF26D8 /* gamesave.c */, 67B4471006687CF400DF26D8 /* gameseg.c */, 67B4471206687CF400DF26D8 /* gameseq.c */, 67B4471506687CF400DF26D8 /* gauges.c */, 67B4471706687CF400DF26D8 /* hostage.c */, 67B4471906687CF400DF26D8 /* hud.c */, 67B4471B06687CF400DF26D8 /* inferno.c */, 67B4472006687CF400DF26D8 /* kconfig.c */, 676032F9066B39CE008A67A3 /* kmatrix.c */, 67B4472506687CF400DF26D8 /* laser.c */, 67B4472706687CF400DF26D8 /* lighting.c */, 67B4472B06687CF400DF26D8 /* menu.c */, 67B4472D06687CF400DF26D8 /* mglobal.c */, 67B4472E06687CF400DF26D8 /* mission.c */, 67B4473106687CF400DF26D8 /* morph.c */, 67B4473306687CF400DF26D8 /* movie.c */, 676032DC066B399A008A67A3 /* multi.c */, 676032DD066B399A008A67A3 /* multibot.c */, 17DFA6B510C1A2D100674D11 /* net_udp.c */, 67B4473D06687CF400DF26D8 /* newdemo.c */, 67B4473F06687CF400DF26D8 /* newmenu.c */, 67B4474106687CF400DF26D8 /* object.c */, 67B4475906687CF400DF26D8 /* paging.c */, 67B4475B06687CF400DF26D8 /* physics.c */, 67B4475D06687CF400DF26D8 /* piggy.c */, 67B4475F06687CF400DF26D8 /* player.c */, 67B4476106687CF400DF26D8 /* playsave.c */, 67B4476306687CF400DF26D8 /* polyobj.c */, 67B4476506687CF400DF26D8 /* powerup.c */, 67B4476706687CF400DF26D8 /* render.c */, 67B4476A06687CF400DF26D8 /* robot.c */, 67B4476C06687CF400DF26D8 /* scores.c */, 67B4476F06687CF400DF26D8 /* segment.c */, 67B4477206687CF400DF26D8 /* slew.c */, 67B4477406687CF400DF26D8 /* songs.c */, 67B4477706687CF400DF26D8 /* state.c */, 67B4477906687CF400DF26D8 /* switch.c */, 67B4477B06687CF400DF26D8 /* terrain.c */, 67B4477D06687CF400DF26D8 /* texmerge.c */, 67B4477F06687CF500DF26D8 /* text.c */, 67B4478206687CF500DF26D8 /* titles.c */, 67B4478406687CF500DF26D8 /* vclip.c */, EB6AFF5F170FD9B400ED37CB /* vers_id.c */, 67B4478706687CF500DF26D8 /* wall.c */, 67B4478906687CF500DF26D8 /* weapon.c */, EB0421040A341042002CC961 /* ai.h */, EB0421010A341042002CC961 /* aistruct.h */, EB0421030A341042002CC961 /* automap.h */, EB0421020A341042002CC961 /* bm.h */, EB0420C00A341042002CC961 /* bmread.h */, EB0420F10A341042002CC961 /* collide.h */, EB0421060A341042002CC961 /* config.h */, EB0421050A341042002CC961 /* controls.h */, EB0420BF0A341042002CC961 /* cntrlcen.h */, EB0420E50A341042002CC961 /* credits.h */, EB0420E10A341042002CC961 /* digi.h */, EB0421000A341042002CC961 /* effects.h */, EB0420FF0A341042002CC961 /* endlevel.h */, EB0420FE0A341042002CC961 /* escort.h */, EB0420FD0A341042002CC961 /* fireball.h */, EB0420F00A341042002CC961 /* fuelcen.h */, EB0420EF0A341042002CC961 /* fvi.h */, EB0420ED0A341042002CC961 /* game.h */, EB0420EC0A341042002CC961 /* gamefont.h */, EB0420EB0A341042002CC961 /* gamemine.h */, EB0420EA0A341042002CC961 /* gamepal.h */, EB0420E90A341042002CC961 /* gamesave.h */, EB0420E80A341042002CC961 /* gameseg.h */, EB0420E30A341042002CC961 /* gameseq.h */, EB0420F80A341042002CC961 /* gauges.h */, EB0420F70A341042002CC961 /* hostage.h */, EB0420F60A341042002CC961 /* hudmsg.h */, EB0420F50A341042002CC961 /* inferno.h */, EB0420F30A341042002CC961 /* kconfig.h */, EB0420F20A341042002CC961 /* kmatrix.h */, EB0420FC0A341042002CC961 /* laser.h */, EB0420FA0A341042002CC961 /* lighting.h */, EB0420BE0A341042002CC961 /* menu.h */, EB0420BD0A341042002CC961 /* mission.h */, EB0420BB0A341042002CC961 /* morph.h */, EB0420BA0A341042002CC961 /* movie.h */, EB0420B90A341041002CC961 /* multi.h */, EB0420E70A341042002CC961 /* multibot.h */, 17DFA6B610C1A2D100674D11 /* net_udp.h */, EB01AFA90A65323200EA4C7C /* newdemo.h */, EB0420DE0A341042002CC961 /* newmenu.h */, EB0420DD0A341042002CC961 /* object.h */, EB0420DC0A341042002CC961 /* paging.h */, EB0420DB0A341042002CC961 /* physics.h */, EB0420DA0A341042002CC961 /* piggy.h */, EB0420D90A341042002CC961 /* player.h */, EB0420D80A341042002CC961 /* playsave.h */, EB0420D70A341042002CC961 /* polyobj.h */, EB0420D60A341042002CC961 /* powerup.h */, EB0420D50A341042002CC961 /* render.h */, EB0420D30A341042002CC961 /* robot.h */, EB0420D20A341042002CC961 /* scores.h */, EB0420D10A341042002CC961 /* screens.h */, EB0420D00A341042002CC961 /* segment.h */, EB0420CF0A341042002CC961 /* segpoint.h */, EB0420CE0A341042002CC961 /* slew.h */, EB0420CD0A341042002CC961 /* songs.h */, EB0420CC0A341042002CC961 /* sounds.h */, EB0420CB0A341042002CC961 /* state.h */, EB0420CA0A341042002CC961 /* switch.h */, EB0420C90A341042002CC961 /* terrain.h */, EB0420C80A341042002CC961 /* texmerge.h */, EB0420C70A341042002CC961 /* text.h */, EB0420C60A341042002CC961 /* textures.h */, EB0420C50A341042002CC961 /* titles.h */, EB0420C40A341042002CC961 /* vclip.h */, EB0420C30A341042002CC961 /* vers_id.h */, EB0420C20A341042002CC961 /* wall.h */, EB0420C10A341042002CC961 /* weapon.h */, ); path = main; sourceTree = SOURCE_ROOT; }; 67B4484806687DCE00DF26D8 /* maths */ = { isa = PBXGroup; children = ( 67B4484B06687DCE00DF26D8 /* fixc.c */, 67B4484D06687DCE00DF26D8 /* rand.c */, 67B4484E06687DCE00DF26D8 /* tables.c */, 67B4484F06687DCE00DF26D8 /* vecmat.c */, ); path = maths; sourceTree = SOURCE_ROOT; }; 67B4485B06687DFB00DF26D8 /* mem */ = { isa = PBXGroup; children = ( 67B4485E06687DFB00DF26D8 /* mem.c */, ); path = mem; sourceTree = SOURCE_ROOT; }; 67B4486406687E1000DF26D8 /* misc */ = { isa = PBXGroup; children = ( 67B4486606687E1000DF26D8 /* args.c */, EB92BEA40CDD6A570045A32C /* dl_list.c */, 67B4486A06687E1000DF26D8 /* error.c */, 67B4486C06687E1000DF26D8 /* hash.c */, 179E6ECD11F37C0500175C54 /* hmp.c */, 179E6ED011F37C1900175C54 /* hmp.h */, EBAFC2B0088E695F006329AD /* ignorecase.c */, EBAFC2B1088E695F006329AD /* physfsrwops.c */, EB1405E8121044B5002B1CC6 /* physfsx.c */, 67B4487206687E1000DF26D8 /* strio.c */, 67B4487306687E1000DF26D8 /* strutil.c */, ); path = misc; sourceTree = SOURCE_ROOT; }; 67B4488506687E5E00DF26D8 /* texmap */ = { isa = PBXGroup; children = ( 67B4488806687E5E00DF26D8 /* ntmap.c */, 67B4488906687E5E00DF26D8 /* scanline.c */, 67B4489206687E5E00DF26D8 /* tmapflat.c */, EB6AFF62170FDA0300ED37CB /* scanline.h */, EB6AFF63170FDA0300ED37CB /* texmapl.h */, ); path = texmap; sourceTree = SOURCE_ROOT; }; 67B448AC0668803500DF26D8 /* include */ = { isa = PBXGroup; children = ( EBBE05FD12C87D250056CF2D /* editor */, 6791CF8D066888DD00056A5A /* 3d.h */, 6791D00B066889CD00056A5A /* args.h */, 6791CE4F0668852C00056A5A /* byteswap.h */, 6791D00C066889CD00056A5A /* console.h */, EB92BE680CDD69830045A32C /* dl_list.h */, EB6AFF5C170FD96200ED37CB /* dxxerror.h */, 6791CF420668881F00056A5A /* fix.h */, EBC652120890D6DF004FCAA3 /* func.h */, 67B44914066880C400DF26D8 /* gr.h */, 67B44915066880C400DF26D8 /* grdef.h */, 6791D12906688EB500056A5A /* hash.h */, EBAFC248088E4C17006329AD /* ignorecase.h */, 6791D0BD06688AE800056A5A /* iff.h */, EBB9E5480D8E83F2003466E6 /* internal.h */, 6791CFC50668893B00056A5A /* interp.h */, 6791D0D106688B1100056A5A /* libmve.h */, EBB9E5490D8E83F2003466E6 /* loadgl.h */, 6791CF2D066887E500056A5A /* makesig.h */, 6791D08F06688A9C00056A5A /* maths.h */, 676AC0E10668A86F007173EB /* ogl_init.h */, 6791CF4E0668883900056A5A /* palette.h */, 6791CF620668885500056A5A /* pcx.h */, EBAFC24B088E4C53006329AD /* physfsrwops.h */, EBAFC23A088E4B2C006329AD /* physfsx.h */, EB6AFF5D170FD96200ED37CB /* pngfile.h */, 676C5D030668840200D9FA2D /* pstypes.h */, 6791D07E06688A7B00056A5A /* rbaudio.h */, 6791CE500668852C00056A5A /* rle.h */, 6791D1550668903B00056A5A /* strio.h */, 6791D0A306688AB900056A5A /* strutil.h */, 6791CFB10668891200056A5A /* texmap.h */, 6791D04B06688A2E00056A5A /* timer.h */, EBC6520F0890D6B7004FCAA3 /* ui.h */, 67B4490F066880A300DF26D8 /* u_mem.h */, 6791D026066889F100056A5A /* vecmat.h */, ); path = include; sourceTree = SOURCE_ROOT; }; EB092A8612A25EE4004D9A79 /* include */ = { isa = PBXGroup; children = ( EB092A8A12A25EE4004D9A79 /* resource.h */, ); path = include; sourceTree = ""; }; EB6142A41501FD71004E2AE8 /* data */ = { isa = PBXGroup; children = ( EB6142A51501FD71004E2AE8 /* curve.pad */, EB6142A61501FD71004E2AE8 /* dummy.pad */, EB6142A71501FD71004E2AE8 /* group.pad */, EB6142A81501FD71004E2AE8 /* lighting.pad */, EB6142A91501FD71004E2AE8 /* med.mnu */, EB6142AA1501FD71004E2AE8 /* newobj.pad */, EB6142AB1501FD71004E2AE8 /* object.pad */, EB6142AC1501FD71004E2AE8 /* objmov.pad */, EB6142AD1501FD71004E2AE8 /* pc6x8.fnt */, EB6142AE1501FD71004E2AE8 /* pc8x16.fnt */, EB6142AF1501FD71004E2AE8 /* segmove.pad */, EB6142B01501FD71004E2AE8 /* segsize.pad */, EB6142B11501FD71004E2AE8 /* test.pad */, EB6142B21501FD71004E2AE8 /* texture.pad */, ); path = data; sourceTree = ""; }; EBAFC268088E508D006329AD /* carbon */ = { isa = PBXGroup; children = ( EB092A7F12A25AFB004D9A79 /* messagebox.c */, EBAFC269088E508D006329AD /* conf.h */, EBAFC26A088E508D006329AD /* descent.r */, EBAFC26D088E508D006329AD /* SDL_main.c */, ); name = carbon; path = arch/carbon; sourceTree = ""; }; EBB9E53A0D8E8378003466E6 /* win32 */ = { isa = PBXGroup; children = ( EB6AFF5B170FD91C00ED37CB /* d2x-rebirth.rc */, EB092A8612A25EE4004D9A79 /* include */, EB092A8512A25EC8004D9A79 /* messagebox.c */, ); name = win32; path = arch/win32; sourceTree = ""; }; EBBE057912C872C30056CF2D /* editor */ = { isa = PBXGroup; children = ( EBBE057A12C872C30056CF2D /* autosave.c */, EB6142A41501FD71004E2AE8 /* data */, EBBE057B12C872C30056CF2D /* centers.c */, EBBE057D12C872C30056CF2D /* curves.c */, EBBE057F12C872C30056CF2D /* eglobal.c */, EBBE058212C872C30056CF2D /* elight.c */, EBBE058312C872C30056CF2D /* eobject.c */, EBBE058512C872C30056CF2D /* eswitch.c */, EBBE058712C872C30056CF2D /* fixseg.c */, EBBE058812C872C30056CF2D /* func.c */, EBBE058912C872C30056CF2D /* group.c */, EBBE058A12C872C30056CF2D /* info.c */, EBBE058C12C872C30056CF2D /* kbuild.c */, EBBE058D12C872C30056CF2D /* kcurve.c */, EBBE058F12C872C30056CF2D /* kfuncs.c */, EBBE059112C872C30056CF2D /* kgame.c */, EBBE059312C872C30056CF2D /* khelp.c */, EBBE059412C872C30056CF2D /* kmine.c */, EBBE059512C872C30056CF2D /* ksegmove.c */, EBBE059612C872C30056CF2D /* ksegsel.c */, EBBE059712C872C30056CF2D /* ksegsize.c */, EBBE059812C872C30056CF2D /* ktmap.c */, EBBE059912C872C30056CF2D /* kview.c */, EBBE059C12C872C30056CF2D /* med.c */, EBBE059D12C872C30056CF2D /* meddraw.c */, EBBE05A012C872C30056CF2D /* medmisc.c */, EBBE05A212C872C30056CF2D /* medrobot.c */, EBBE05A412C872C30056CF2D /* medsel.c */, EBBE05A612C872C30056CF2D /* medwall.c */, EBBE05A812C872C30056CF2D /* mine.c */, EBBE05A912C872C30056CF2D /* objpage.c */, EBBE05AB12C872C30056CF2D /* segment.c */, EBBE05AC12C872C30056CF2D /* seguvs.c */, EBBE05AE12C872C30056CF2D /* texpage.c */, EBBE05B012C872C30056CF2D /* texture.c */, ); path = editor; sourceTree = ""; }; EBBE05FD12C87D250056CF2D /* editor */ = { isa = PBXGroup; children = ( EBBE05FE12C87D250056CF2D /* centers.h */, EBBE05FF12C87D250056CF2D /* editor.h */, EBBE060012C87D250056CF2D /* ehostage.h */, EBBE060112C87D250056CF2D /* eobject.h */, EB6AFF5E170FD98100ED37CB /* esegment.h */, EBBE060212C87D250056CF2D /* eswitch.h */, EBBE060312C87D250056CF2D /* info.h */, EBBE060412C87D250056CF2D /* kdefs.h */, EBBE060512C87D250056CF2D /* kfuncs.h */, EBBE060612C87D250056CF2D /* macro.h */, EBBE060712C87D250056CF2D /* meddraw.h */, EBBE060812C87D250056CF2D /* medlisp.h */, EBBE060912C87D250056CF2D /* medmisc.h */, EBBE060A12C87D250056CF2D /* medrobot.h */, EBBE060B12C87D250056CF2D /* medsel.h */, EBBE060C12C87D250056CF2D /* medwall.h */, EBBE060D12C87D250056CF2D /* objpage.h */, EBBE060E12C87D250056CF2D /* seguvs.h */, EBBE060F12C87D250056CF2D /* texpage.h */, ); path = editor; sourceTree = ""; }; EBC6518D0890CEAE004FCAA3 /* ui */ = { isa = PBXGroup; children = ( EBC651900890CEAE004FCAA3 /* button.c */, EBC651910890CEAE004FCAA3 /* checkbox.c */, EBC651920890CEAE004FCAA3 /* file.c */, EBC651940890CEAE004FCAA3 /* gadget.c */, EBC651960890CEAE004FCAA3 /* icon.c */, EBC651970890CEAE004FCAA3 /* inputbox.c */, EBC651980890CEAE004FCAA3 /* keypad.c */, EBC651990890CEAE004FCAA3 /* keypress.c */, EBC6519A0890CEAE004FCAA3 /* keytrap.c */, EBC6519B0890CEAE004FCAA3 /* listbox.c */, EBC6519E0890CEAE004FCAA3 /* menu.c */, EBC6519F0890CEAE004FCAA3 /* menubar.c */, EBC651A00890CEAE004FCAA3 /* message.c */, EBC651A30890CEAE004FCAA3 /* popup.c */, EBC651A40890CEAE004FCAA3 /* radio.c */, EBC651A50890CEAE004FCAA3 /* scroll.c */, EBC651A60890CEAE004FCAA3 /* ui.c */, EBC651A70890CEAE004FCAA3 /* uidraw.c */, EBC651A80890CEAE004FCAA3 /* userbox.c */, EBC651A90890CEAE004FCAA3 /* dialog.c */, ); path = ui; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ 670E3862066C571F0085B671 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 670E39DA066C59C40085B671 /* libmve.h in Headers */, 670E3A42066C5C420085B671 /* SDLMain.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC1C00668A938007173EB /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 676AC1C20668A938007173EB /* u_mem.h in Headers */, 676AC1C40668A938007173EB /* gr.h in Headers */, 676AC1C50668A938007173EB /* grdef.h in Headers */, 676AC1C60668A938007173EB /* pstypes.h in Headers */, 676AC1C70668A938007173EB /* byteswap.h in Headers */, 676AC1C80668A938007173EB /* rle.h in Headers */, 676AC1CC0668A938007173EB /* makesig.h in Headers */, 676AC1CE0668A938007173EB /* fix.h in Headers */, 676AC1CF0668A938007173EB /* palette.h in Headers */, 676AC1D00668A938007173EB /* pcx.h in Headers */, 676AC1D10668A938007173EB /* 3d.h in Headers */, 676AC1D20668A938007173EB /* texmap.h in Headers */, 676AC1D30668A938007173EB /* interp.h in Headers */, 676AC1D50668A938007173EB /* event.h in Headers */, 676AC1D60668A938007173EB /* joy.h in Headers */, 676AC1D70668A938007173EB /* args.h in Headers */, 676AC1D80668A938007173EB /* console.h in Headers */, 676AC1D90668A938007173EB /* vecmat.h in Headers */, 676AC1DA0668A938007173EB /* timer.h in Headers */, 676AC1DB0668A938007173EB /* key.h in Headers */, 676AC1DC0668A938007173EB /* mouse.h in Headers */, 676AC1DD0668A938007173EB /* rbaudio.h in Headers */, 676AC1DE0668A938007173EB /* maths.h in Headers */, 676AC1E00668A938007173EB /* strutil.h in Headers */, 676AC1E10668A938007173EB /* iff.h in Headers */, 676AC1E40668A938007173EB /* hash.h in Headers */, 676AC1E50668A938007173EB /* strio.h in Headers */, 676AC1E70668A938007173EB /* libmve.h in Headers */, 67F6FED2066B13B400443922 /* SDLMain.h in Headers */, EBAFC23B088E4B2C006329AD /* physfsx.h in Headers */, EBAFC249088E4C17006329AD /* ignorecase.h in Headers */, EBAFC24C088E4C53006329AD /* physfsrwops.h in Headers */, EBAFC26E088E508D006329AD /* conf.h in Headers */, EBC652100890D6B7004FCAA3 /* ui.h in Headers */, EBC652130890D6DF004FCAA3 /* func.h in Headers */, EBB9E5360D8E82B3003466E6 /* bitmap.h in Headers */, EBB9E5370D8E82B3003466E6 /* clip.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC2720668A939007173EB /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( 676AC2730668A939007173EB /* event.h in Headers */, 676AC2740668A939007173EB /* key.h in Headers */, 676AC2750668A939007173EB /* joy.h in Headers */, 676AC2760668A939007173EB /* mouse.h in Headers */, 676AC2770668A939007173EB /* 3d.h in Headers */, 676AC2780668A939007173EB /* args.h in Headers */, 676AC2790668A939007173EB /* byteswap.h in Headers */, 676AC27C0668A939007173EB /* console.h in Headers */, 676AC2800668A939007173EB /* fix.h in Headers */, 676AC2810668A939007173EB /* gr.h in Headers */, 676AC2820668A939007173EB /* grdef.h in Headers */, 676AC2830668A939007173EB /* hash.h in Headers */, 676AC2850668A939007173EB /* iff.h in Headers */, 676AC2860668A939007173EB /* interp.h in Headers */, 676AC2870668A939007173EB /* libmve.h in Headers */, 676AC2880668A939007173EB /* makesig.h in Headers */, 676AC2890668A939007173EB /* maths.h in Headers */, 676AC28C0668A939007173EB /* pcx.h in Headers */, 676AC28D0668A939007173EB /* palette.h in Headers */, 676AC28E0668A939007173EB /* pstypes.h in Headers */, 676AC28F0668A939007173EB /* rbaudio.h in Headers */, 676AC2900668A939007173EB /* rle.h in Headers */, 676AC2910668A939007173EB /* strio.h in Headers */, 676AC2920668A939007173EB /* strutil.h in Headers */, 676AC2930668A939007173EB /* texmap.h in Headers */, 676AC2940668A939007173EB /* timer.h in Headers */, 676AC2960668A939007173EB /* u_mem.h in Headers */, 676AC2970668A939007173EB /* vecmat.h in Headers */, 676AC2980668A939007173EB /* ogl_init.h in Headers */, 67F6FED4066B13B400443922 /* SDLMain.h in Headers */, EBAFC23C088E4B2C006329AD /* physfsx.h in Headers */, EBAFC24A088E4C17006329AD /* ignorecase.h in Headers */, EBAFC24D088E4C53006329AD /* physfsrwops.h in Headers */, EBAFC2C0088E6BC7006329AD /* conf.h in Headers */, EBC652110890D6B7004FCAA3 /* ui.h in Headers */, EBC652140890D6DF004FCAA3 /* func.h in Headers */, EBB9E5340D8E82B3003466E6 /* bitmap.h in Headers */, EBB9E5350D8E82B3003466E6 /* clip.h in Headers */, 179E6ED211F37C1900175C54 /* hmp.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ 670E3866066C571F0085B671 /* MVEPlayer */ = { isa = PBXNativeTarget; buildConfigurationList = EBBAD49A0B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "MVEPlayer" */; buildPhases = ( 670E3862066C571F0085B671 /* Headers */, 670E3863066C571F0085B671 /* Resources */, 670E3864066C571F0085B671 /* Sources */, 670E3865066C571F0085B671 /* Frameworks */, ); buildRules = ( ); dependencies = ( ); name = MVEPlayer; productName = MVEPlayer; productReference = 670E3867066C571F0085B671 /* MVEPlayer.app */; productType = "com.apple.product-type.application"; }; 676AC1BF0668A938007173EB /* d2x */ = { isa = PBXNativeTarget; buildConfigurationList = EBBAD4920B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "d2x" */; buildPhases = ( 676AC1C00668A938007173EB /* Headers */, 676AC1E80668A938007173EB /* Resources */, 676AC1EA0668A938007173EB /* Sources */, 676AC26B0668A938007173EB /* Frameworks */, EB6142BC1501FDEB004E2AE8 /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = d2x; productInstallPath = "$(HOME)/Applications"; productName = d2x; productReference = 676AC26F0668A939007173EB /* d2x.app */; productType = "com.apple.product-type.application"; }; 676AC2710668A939007173EB /* d2xgl */ = { isa = PBXNativeTarget; buildConfigurationList = EBBAD4960B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "d2xgl" */; buildPhases = ( 676AC2720668A939007173EB /* Headers */, 676AC29A0668A939007173EB /* Resources */, 676AC29B0668A939007173EB /* Sources */, 676AC31C0668A939007173EB /* Frameworks */, EBD441C31526B419002FF2BA /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = d2xgl; productName = d2xgl; productReference = 676AC31D0668A939007173EB /* d2xgl.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = EBBAD49E0B2D0F7E00080BBF /* Build configuration list for PBXProject "d2x-rebirth" */; compatibilityVersion = "Xcode 2.4"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 29B97314FDCFA39411CA2CEA /* d2x */; projectDirPath = ""; projectRoot = ""; targets = ( 676AC1BF0668A938007173EB /* d2x */, 676AC2710668A939007173EB /* d2xgl */, 670E3866066C571F0085B671 /* MVEPlayer */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 670E3863066C571F0085B671 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; 676AC1E80668A938007173EB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 676AC1E90668A938007173EB /* InfoPlist.strings in Resources */, 675ED149066B198A00E42AA7 /* d2x-Info.plist in Resources */, EBECB69712C0481A00D660B3 /* d2x-rebirth.icns in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC29A0668A939007173EB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( EBAEB74C0BF4A86F00FC6E13 /* d2x-rebirth.icns in Resources */, EB380D360E16886300EBD9AD /* InfoPlist.strings in Resources */, EBD441921526B3EE002FF2BA /* curve.pad in Resources */, EBD441941526B3EE002FF2BA /* dummy.pad in Resources */, EBD4419D1526B3EE002FF2BA /* group.pad in Resources */, EBD441AB1526B3EE002FF2BA /* lighting.pad in Resources */, EBD441AE1526B3EE002FF2BA /* med.mnu in Resources */, EBD441B51526B3EE002FF2BA /* newobj.pad in Resources */, EBD441B61526B3EE002FF2BA /* object.pad in Resources */, EBD441B71526B3EE002FF2BA /* objmov.pad in Resources */, EBD441B91526B3EE002FF2BA /* pc6x8.fnt in Resources */, EBD441BA1526B3EE002FF2BA /* pc8x16.fnt in Resources */, EBD441BC1526B3EE002FF2BA /* segmove.pad in Resources */, EBD441BD1526B3EE002FF2BA /* segsize.pad in Resources */, EBD441BF1526B3EE002FF2BA /* test.pad in Resources */, EBD441C21526B3EE002FF2BA /* texture.pad in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 670E3864066C571F0085B671 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 670E39B0066C598A0085B671 /* mve_audio.c in Sources */, 670E39B1066C598A0085B671 /* decoder16.c in Sources */, 670E39B3066C598B0085B671 /* decoder8.c in Sources */, 670E39B5066C598B0085B671 /* mveplay.c in Sources */, 670E39BF066C598E0085B671 /* mvelib.c in Sources */, 670E39C5066C59A00085B671 /* mve_main.c in Sources */, 670E3A43066C5C430085B671 /* SDLMain.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC1EA0668A938007173EB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 67F6FED3066B13B400443922 /* SDLMain.m in Sources */, 676AC1EC0668A938007173EB /* 2dsline.c in Sources */, 676AC1ED0668A938007173EB /* bitblt.c in Sources */, 676AC1EE0668A938007173EB /* bitmap.c in Sources */, 676AC1EF0668A938007173EB /* box.c in Sources */, 676AC1F00668A938007173EB /* canvas.c in Sources */, 676AC1F10668A938007173EB /* circle.c in Sources */, 676AC1F20668A938007173EB /* disc.c in Sources */, 676AC1F30668A938007173EB /* font.c in Sources */, 676AC1F40668A938007173EB /* gpixel.c in Sources */, 676AC1F60668A938007173EB /* line.c in Sources */, 676AC1F70668A938007173EB /* palette.c in Sources */, 676AC1F80668A938007173EB /* pcx.c in Sources */, 676AC1F90668A938007173EB /* pixel.c in Sources */, 676AC1FA0668A938007173EB /* poly.c in Sources */, 676AC1FB0668A938007173EB /* rect.c in Sources */, 676AC1FC0668A938007173EB /* rle.c in Sources */, 676AC1FD0668A938007173EB /* scalec.c in Sources */, 676AC1FF0668A938007173EB /* clipper.c in Sources */, 676AC2000668A938007173EB /* draw.c in Sources */, 676AC2010668A938007173EB /* globvars.c in Sources */, 676AC2020668A938007173EB /* instance.c in Sources */, 676AC2030668A938007173EB /* interp.c in Sources */, 676AC2040668A938007173EB /* matrix.c in Sources */, 676AC2050668A938007173EB /* points.c in Sources */, 676AC2060668A938007173EB /* rod.c in Sources */, 676AC2070668A938007173EB /* setup.c in Sources */, 676AC20A0668A938007173EB /* digi.c in Sources */, 676AC20B0668A938007173EB /* event.c in Sources */, 676AC20C0668A938007173EB /* gr.c in Sources */, 676AC20E0668A938007173EB /* joy.c in Sources */, 676AC2100668A938007173EB /* key.c in Sources */, 676AC2110668A938007173EB /* mouse.c in Sources */, 676AC2120668A938007173EB /* rbaudio.c in Sources */, 676AC2130668A938007173EB /* timer.c in Sources */, 676AC2150668A938007173EB /* iff.c in Sources */, 676AC2660668A938007173EB /* decoder16.c in Sources */, 676AC2670668A938007173EB /* decoder8.c in Sources */, 676AC2680668A938007173EB /* mvelib.c in Sources */, 676AC2690668A938007173EB /* mveplay.c in Sources */, 676AC26A0668A938007173EB /* mve_audio.c in Sources */, 676AC2160668A938007173EB /* ai.c in Sources */, 676AC2170668A938007173EB /* ai2.c in Sources */, 676AC2180668A938007173EB /* aipath.c in Sources */, 676AC2190668A938007173EB /* automap.c in Sources */, 676AC21A0668A938007173EB /* bm.c in Sources */, 676AC21C0668A938007173EB /* cntrlcen.c in Sources */, 676AC21D0668A938007173EB /* collide.c in Sources */, 676AC21E0668A938007173EB /* config.c in Sources */, 676AC21F0668A938007173EB /* console.c in Sources */, 676AC2200668A938007173EB /* controls.c in Sources */, 676AC2210668A938007173EB /* credits.c in Sources */, EBAFC290088E67CD006329AD /* digiobj.c in Sources */, 676AC2230668A938007173EB /* effects.c in Sources */, 676AC2240668A938007173EB /* endlevel.c in Sources */, 676AC2250668A938007173EB /* escort.c in Sources */, 676AC2260668A938007173EB /* fireball.c in Sources */, 676AC2270668A938007173EB /* fuelcen.c in Sources */, 676AC2280668A938007173EB /* fvi.c in Sources */, 676AC2290668A938007173EB /* game.c in Sources */, 676AC22A0668A938007173EB /* gamecntl.c in Sources */, 676AC22B0668A938007173EB /* gamefont.c in Sources */, 676AC22C0668A938007173EB /* gamemine.c in Sources */, 676AC22D0668A938007173EB /* gamepal.c in Sources */, 676AC22E0668A938007173EB /* gamerend.c in Sources */, 676AC22F0668A938007173EB /* gamesave.c in Sources */, 676AC2300668A938007173EB /* gameseg.c in Sources */, 676AC2310668A938007173EB /* gameseq.c in Sources */, 676AC2320668A938007173EB /* gauges.c in Sources */, 676AC2330668A938007173EB /* hostage.c in Sources */, 676AC2340668A938007173EB /* hud.c in Sources */, 676AC2350668A938007173EB /* inferno.c in Sources */, 676AC2360668A938007173EB /* kconfig.c in Sources */, 676032FB066B39CE008A67A3 /* kmatrix.c in Sources */, 676AC2380668A938007173EB /* laser.c in Sources */, 676AC2390668A938007173EB /* lighting.c in Sources */, 676AC23A0668A938007173EB /* menu.c in Sources */, 676AC23B0668A938007173EB /* mglobal.c in Sources */, 676AC23C0668A938007173EB /* mission.c in Sources */, 676AC23D0668A938007173EB /* morph.c in Sources */, 676AC23E0668A938007173EB /* movie.c in Sources */, 676032E4066B399A008A67A3 /* multi.c in Sources */, 676032E5066B399A008A67A3 /* multibot.c in Sources */, 676AC23F0668A938007173EB /* newdemo.c in Sources */, 676AC2400668A938007173EB /* newmenu.c in Sources */, 676AC2410668A938007173EB /* object.c in Sources */, 676AC2420668A938007173EB /* paging.c in Sources */, 676AC2430668A938007173EB /* physics.c in Sources */, 676AC2440668A938007173EB /* piggy.c in Sources */, 676AC2450668A938007173EB /* player.c in Sources */, 676AC2460668A938007173EB /* playsave.c in Sources */, 676AC2470668A938007173EB /* polyobj.c in Sources */, 676AC2480668A938007173EB /* powerup.c in Sources */, 676AC2490668A938007173EB /* render.c in Sources */, 676AC24A0668A938007173EB /* robot.c in Sources */, 676AC24B0668A938007173EB /* scores.c in Sources */, 676AC24C0668A938007173EB /* segment.c in Sources */, 676AC24D0668A938007173EB /* slew.c in Sources */, 676AC24E0668A938007173EB /* songs.c in Sources */, 676AC24F0668A938007173EB /* state.c in Sources */, 676AC2500668A938007173EB /* switch.c in Sources */, 676AC2510668A938007173EB /* terrain.c in Sources */, 676AC2520668A938007173EB /* texmerge.c in Sources */, 676AC2530668A938007173EB /* text.c in Sources */, 676AC2540668A938007173EB /* titles.c in Sources */, 676AC2550668A938007173EB /* vclip.c in Sources */, 676AC2560668A938007173EB /* wall.c in Sources */, 676AC2570668A938007173EB /* weapon.c in Sources */, 676AC2580668A938007173EB /* fixc.c in Sources */, 676AC2590668A938007173EB /* rand.c in Sources */, 676AC25A0668A938007173EB /* tables.c in Sources */, 676AC25B0668A938007173EB /* vecmat.c in Sources */, 676AC25C0668A938007173EB /* mem.c in Sources */, 676AC25D0668A938007173EB /* args.c in Sources */, 676AC25F0668A938007173EB /* error.c in Sources */, 676AC2600668A938007173EB /* hash.c in Sources */, EBAFC2B2088E695F006329AD /* ignorecase.c in Sources */, EBAFC2B3088E695F006329AD /* physfsrwops.c in Sources */, 676AC2610668A938007173EB /* strio.c in Sources */, 676AC2620668A938007173EB /* strutil.c in Sources */, 676AC2630668A938007173EB /* ntmap.c in Sources */, 676AC2640668A938007173EB /* scanline.c in Sources */, 676AC2650668A938007173EB /* tmapflat.c in Sources */, EB92BE640CDD693C0045A32C /* digi_audio.c in Sources */, EB92BE650CDD693C0045A32C /* digi_mixer_music.c in Sources */, EB92BE660CDD693C0045A32C /* digi_mixer.c in Sources */, EB92BE670CDD693C0045A32C /* jukebox.c in Sources */, EB92BEA80CDD6A570045A32C /* dl_list.c in Sources */, EB28D9A40ECEAF1C00E68E9B /* init.c in Sources */, EBE8D6EC0FC583B4009D181F /* window.c in Sources */, 17DFA6B910C1A2D100674D11 /* net_udp.c in Sources */, 179E6ECE11F37C0500175C54 /* hmp.c in Sources */, EB1405EA121044B5002B1CC6 /* physfsx.c in Sources */, EB092A8112A25AFB004D9A79 /* messagebox.c in Sources */, EBECB5D312C03E6300D660B3 /* bmread.c in Sources */, EBECB5F912C03F0C00D660B3 /* button.c in Sources */, EBECB5FA12C03F0E00D660B3 /* checkbox.c in Sources */, EBECB5FB12C03F1000D660B3 /* file.c in Sources */, EBECB5FD12C03F1D00D660B3 /* gadget.c in Sources */, EBECB5FE12C03F2700D660B3 /* icon.c in Sources */, EBECB5FF12C03F2C00D660B3 /* inputbox.c in Sources */, EBECB60012C03F3400D660B3 /* keypad.c in Sources */, EBECB60112C03F3500D660B3 /* keypress.c in Sources */, EBECB60212C03F3700D660B3 /* keytrap.c in Sources */, EBECB60312C03F3900D660B3 /* listbox.c in Sources */, EBECB60412C03F4300D660B3 /* menu.c in Sources */, EBECB60512C03F4500D660B3 /* menubar.c in Sources */, EBECB60612C03F4600D660B3 /* message.c in Sources */, EBECB60912C03F7A00D660B3 /* popup.c in Sources */, EBECB60A12C03F7D00D660B3 /* radio.c in Sources */, EBECB60B12C03F7E00D660B3 /* scroll.c in Sources */, EBECB60C12C03F8200D660B3 /* ui.c in Sources */, EBECB60D12C03F8400D660B3 /* uidraw.c in Sources */, EBECB60E12C03F8600D660B3 /* userbox.c in Sources */, EBECB60F12C03F8700D660B3 /* dialog.c in Sources */, EBECB69412C0475900D660B3 /* dumpmine.c in Sources */, EBBE05B112C872C30056CF2D /* autosave.c in Sources */, EBBE05B212C872C30056CF2D /* centers.c in Sources */, EBBE05B412C872C30056CF2D /* curves.c in Sources */, EBBE05B612C872C30056CF2D /* eglobal.c in Sources */, EBBE05B912C872C30056CF2D /* elight.c in Sources */, EBBE05BA12C872C30056CF2D /* eobject.c in Sources */, EBBE05BC12C872C30056CF2D /* eswitch.c in Sources */, EBBE05BE12C872C30056CF2D /* fixseg.c in Sources */, EBBE05BF12C872C30056CF2D /* func.c in Sources */, EBBE05C012C872C30056CF2D /* group.c in Sources */, EBBE05C112C872C30056CF2D /* info.c in Sources */, EBBE05C312C872C30056CF2D /* kbuild.c in Sources */, EBBE05C412C872C30056CF2D /* kcurve.c in Sources */, EBBE05C612C872C30056CF2D /* kfuncs.c in Sources */, EBBE05C812C872C30056CF2D /* kgame.c in Sources */, EBBE05CA12C872C30056CF2D /* khelp.c in Sources */, EBBE05CB12C872C30056CF2D /* kmine.c in Sources */, EBBE05CC12C872C30056CF2D /* ksegmove.c in Sources */, EBBE05CD12C872C30056CF2D /* ksegsel.c in Sources */, EBBE05CE12C872C30056CF2D /* ksegsize.c in Sources */, EBBE05CF12C872C30056CF2D /* ktmap.c in Sources */, EBBE05D012C872C30056CF2D /* kview.c in Sources */, EBBE05D312C872C30056CF2D /* med.c in Sources */, EBBE05D412C872C30056CF2D /* meddraw.c in Sources */, EBBE05D712C872C30056CF2D /* medmisc.c in Sources */, EBBE05D912C872C30056CF2D /* medrobot.c in Sources */, EBBE05DB12C872C30056CF2D /* medsel.c in Sources */, EBBE05DD12C872C30056CF2D /* medwall.c in Sources */, EBBE05DF12C872C30056CF2D /* mine.c in Sources */, EBBE05E012C872C30056CF2D /* objpage.c in Sources */, EBBE05E212C872C30056CF2D /* segment.c in Sources */, EBBE05E312C872C30056CF2D /* seguvs.c in Sources */, EBBE05E512C872C30056CF2D /* texpage.c in Sources */, EBBE05E712C872C30056CF2D /* texture.c in Sources */, EB6AFF60170FD9B400ED37CB /* vers_id.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 676AC29B0668A939007173EB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 67F6FED5066B13B400443922 /* SDLMain.m in Sources */, 676AC29C0668A939007173EB /* 2dsline.c in Sources */, 676AC29D0668A939007173EB /* bitblt.c in Sources */, 676AC29E0668A939007173EB /* bitmap.c in Sources */, 676AC29F0668A939007173EB /* box.c in Sources */, 676AC2A00668A939007173EB /* canvas.c in Sources */, 676AC2A10668A939007173EB /* circle.c in Sources */, 676AC2A20668A939007173EB /* disc.c in Sources */, 676AC2A30668A939007173EB /* font.c in Sources */, 676AC2A40668A939007173EB /* gpixel.c in Sources */, 676AC2A60668A939007173EB /* line.c in Sources */, 676AC2A70668A939007173EB /* palette.c in Sources */, 676AC2A80668A939007173EB /* pcx.c in Sources */, 676AC2A90668A939007173EB /* pixel.c in Sources */, 676AC2AA0668A939007173EB /* poly.c in Sources */, 676AC2AB0668A939007173EB /* rect.c in Sources */, 676AC2AC0668A939007173EB /* rle.c in Sources */, 676AC2AD0668A939007173EB /* scalec.c in Sources */, 676AC2AF0668A939007173EB /* clipper.c in Sources */, 676AC2B00668A939007173EB /* draw.c in Sources */, 676AC2B10668A939007173EB /* globvars.c in Sources */, 676AC2B20668A939007173EB /* instance.c in Sources */, 676AC2B30668A939007173EB /* interp.c in Sources */, 676AC2B40668A939007173EB /* matrix.c in Sources */, 676AC2B50668A939007173EB /* points.c in Sources */, 676AC2B60668A939007173EB /* rod.c in Sources */, 676AC2B70668A939007173EB /* setup.c in Sources */, 676AC2C30668A939007173EB /* gr.c in Sources */, 676AC2C40668A939007173EB /* ogl.c in Sources */, 676AC2BA0668A939007173EB /* digi.c in Sources */, 676AC2BB0668A939007173EB /* event.c in Sources */, 676AC2BD0668A939007173EB /* joy.c in Sources */, 676AC2BF0668A939007173EB /* key.c in Sources */, 676AC2C00668A939007173EB /* mouse.c in Sources */, 676AC2C10668A939007173EB /* rbaudio.c in Sources */, 676AC2C20668A939007173EB /* timer.c in Sources */, 676AC2C70668A939007173EB /* iff.c in Sources */, 676AC2C80668A939007173EB /* decoder16.c in Sources */, 676AC2C90668A939007173EB /* decoder8.c in Sources */, 676AC2CA0668A939007173EB /* mve_audio.c in Sources */, 676AC2CB0668A939007173EB /* mvelib.c in Sources */, 676AC2CC0668A939007173EB /* mveplay.c in Sources */, 676AC2CD0668A939007173EB /* ai.c in Sources */, 676AC2CE0668A939007173EB /* ai2.c in Sources */, 676AC2CF0668A939007173EB /* aipath.c in Sources */, 676AC2D00668A939007173EB /* automap.c in Sources */, 676AC2D10668A939007173EB /* bm.c in Sources */, 676AC2D30668A939007173EB /* cntrlcen.c in Sources */, 676AC2D40668A939007173EB /* collide.c in Sources */, 676AC2D50668A939007173EB /* config.c in Sources */, 676AC2D60668A939007173EB /* console.c in Sources */, 676AC2D70668A939007173EB /* controls.c in Sources */, 676AC2D80668A939007173EB /* credits.c in Sources */, 676AC2DA0668A939007173EB /* effects.c in Sources */, 676AC2DB0668A939007173EB /* endlevel.c in Sources */, 676AC2DC0668A939007173EB /* escort.c in Sources */, 676AC2DD0668A939007173EB /* fireball.c in Sources */, 676AC2DE0668A939007173EB /* fuelcen.c in Sources */, 676AC2DF0668A939007173EB /* fvi.c in Sources */, 676AC2E00668A939007173EB /* game.c in Sources */, 676AC2E10668A939007173EB /* gamecntl.c in Sources */, 676AC2E20668A939007173EB /* gamefont.c in Sources */, 676AC2E30668A939007173EB /* gamemine.c in Sources */, 676AC2E40668A939007173EB /* gamepal.c in Sources */, 676AC2E50668A939007173EB /* gamerend.c in Sources */, 676AC2E60668A939007173EB /* gamesave.c in Sources */, 676AC2E70668A939007173EB /* gameseg.c in Sources */, 676AC2E80668A939007173EB /* gameseq.c in Sources */, 676AC2E90668A939007173EB /* gauges.c in Sources */, 676AC2EA0668A939007173EB /* hostage.c in Sources */, 676AC2EB0668A939007173EB /* hud.c in Sources */, 676AC2EC0668A939007173EB /* inferno.c in Sources */, 676AC2ED0668A939007173EB /* kconfig.c in Sources */, 676AC2EF0668A939007173EB /* laser.c in Sources */, 676AC2F00668A939007173EB /* lighting.c in Sources */, 676AC2F10668A939007173EB /* menu.c in Sources */, 676AC2F20668A939007173EB /* mglobal.c in Sources */, 676AC2F30668A939007173EB /* mission.c in Sources */, 676AC2F40668A939007173EB /* morph.c in Sources */, 676AC2F50668A939007173EB /* movie.c in Sources */, EBAFC291088E67CD006329AD /* digiobj.c in Sources */, 676AC2F60668A939007173EB /* newdemo.c in Sources */, 676AC2F70668A939007173EB /* newmenu.c in Sources */, 676AC2F80668A939007173EB /* object.c in Sources */, 676AC2F90668A939007173EB /* paging.c in Sources */, 676AC2FA0668A939007173EB /* physics.c in Sources */, 676AC2FB0668A939007173EB /* piggy.c in Sources */, 676AC2FC0668A939007173EB /* player.c in Sources */, 676AC2FD0668A939007173EB /* playsave.c in Sources */, 676AC2FE0668A939007173EB /* polyobj.c in Sources */, 676AC2FF0668A939007173EB /* powerup.c in Sources */, 676AC3000668A939007173EB /* render.c in Sources */, 676AC3010668A939007173EB /* robot.c in Sources */, 676AC3020668A939007173EB /* scores.c in Sources */, 676AC3030668A939007173EB /* segment.c in Sources */, 676AC3040668A939007173EB /* slew.c in Sources */, 676AC3050668A939007173EB /* songs.c in Sources */, 676AC3060668A939007173EB /* state.c in Sources */, 676AC3070668A939007173EB /* switch.c in Sources */, 676AC3080668A939007173EB /* terrain.c in Sources */, 676AC3090668A939007173EB /* texmerge.c in Sources */, 676AC30A0668A939007173EB /* text.c in Sources */, 676AC30B0668A939007173EB /* titles.c in Sources */, 676AC30C0668A939007173EB /* vclip.c in Sources */, 676AC30D0668A939007173EB /* wall.c in Sources */, 676AC30E0668A939007173EB /* weapon.c in Sources */, 676AC30F0668A939007173EB /* fixc.c in Sources */, 676AC3100668A939007173EB /* rand.c in Sources */, 676AC3110668A939007173EB /* tables.c in Sources */, 676AC3120668A939007173EB /* vecmat.c in Sources */, 676AC3130668A939007173EB /* mem.c in Sources */, 676AC3140668A939007173EB /* args.c in Sources */, 676AC3160668A939007173EB /* error.c in Sources */, 676AC3170668A939007173EB /* hash.c in Sources */, EBAFC2B4088E695F006329AD /* ignorecase.c in Sources */, EBAFC2B5088E695F006329AD /* physfsrwops.c in Sources */, 676AC3180668A939007173EB /* strio.c in Sources */, 676AC3190668A939007173EB /* strutil.c in Sources */, 676AC31A0668A939007173EB /* ntmap.c in Sources */, 676AC31B0668A939007173EB /* scanline.c in Sources */, EB92BE600CDD693C0045A32C /* digi_audio.c in Sources */, EB92BE610CDD693C0045A32C /* digi_mixer_music.c in Sources */, EB92BE620CDD693C0045A32C /* digi_mixer.c in Sources */, EB92BE630CDD693C0045A32C /* jukebox.c in Sources */, EB92BEA60CDD6A570045A32C /* dl_list.c in Sources */, EB28D9A30ECEAF1C00E68E9B /* init.c in Sources */, EBE8D6EB0FC583B4009D181F /* window.c in Sources */, 17DFA6C410C1A3BA00674D11 /* multi.c in Sources */, 17DFA6C510C1A3BC00674D11 /* multibot.c in Sources */, 17DFA6C610C1A3D400674D11 /* kmatrix.c in Sources */, EB2EEB5810C50CE2005256F2 /* net_udp.c in Sources */, 179E6ECF11F37C0500175C54 /* hmp.c in Sources */, EB1405E9121044B5002B1CC6 /* physfsx.c in Sources */, EB092A8012A25AFB004D9A79 /* messagebox.c in Sources */, EBD441901526B3EE002FF2BA /* autosave.c in Sources */, EBD441911526B3EE002FF2BA /* centers.c in Sources */, EBD441931526B3EE002FF2BA /* curves.c in Sources */, EBD441951526B3EE002FF2BA /* eglobal.c in Sources */, EBD441971526B3EE002FF2BA /* elight.c in Sources */, EBD441981526B3EE002FF2BA /* eobject.c in Sources */, EBD441991526B3EE002FF2BA /* eswitch.c in Sources */, EBD4419A1526B3EE002FF2BA /* fixseg.c in Sources */, EBD4419B1526B3EE002FF2BA /* func.c in Sources */, EBD4419C1526B3EE002FF2BA /* group.c in Sources */, EBD4419E1526B3EE002FF2BA /* info.c in Sources */, EBD4419F1526B3EE002FF2BA /* kbuild.c in Sources */, EBD441A01526B3EE002FF2BA /* kcurve.c in Sources */, EBD441A11526B3EE002FF2BA /* kfuncs.c in Sources */, EBD441A21526B3EE002FF2BA /* kgame.c in Sources */, EBD441A41526B3EE002FF2BA /* khelp.c in Sources */, EBD441A51526B3EE002FF2BA /* kmine.c in Sources */, EBD441A61526B3EE002FF2BA /* ksegmove.c in Sources */, EBD441A71526B3EE002FF2BA /* ksegsel.c in Sources */, EBD441A81526B3EE002FF2BA /* ksegsize.c in Sources */, EBD441A91526B3EE002FF2BA /* ktmap.c in Sources */, EBD441AA1526B3EE002FF2BA /* kview.c in Sources */, EBD441AD1526B3EE002FF2BA /* med.c in Sources */, EBD441AF1526B3EE002FF2BA /* meddraw.c in Sources */, EBD441B01526B3EE002FF2BA /* medmisc.c in Sources */, EBD441B11526B3EE002FF2BA /* medrobot.c in Sources */, EBD441B21526B3EE002FF2BA /* medsel.c in Sources */, EBD441B31526B3EE002FF2BA /* medwall.c in Sources */, EBD441B41526B3EE002FF2BA /* mine.c in Sources */, EBD441B81526B3EE002FF2BA /* objpage.c in Sources */, EBD441BB1526B3EE002FF2BA /* segment.c in Sources */, EBD441BE1526B3EE002FF2BA /* seguvs.c in Sources */, EBD441C01526B3EE002FF2BA /* texpage.c in Sources */, EBD441C11526B3EE002FF2BA /* texture.c in Sources */, EBD441C71526B453002FF2BA /* button.c in Sources */, EBD441C81526B453002FF2BA /* checkbox.c in Sources */, EBD441C91526B453002FF2BA /* dialog.c in Sources */, EBD441CA1526B453002FF2BA /* file.c in Sources */, EBD441CB1526B453002FF2BA /* gadget.c in Sources */, EBD441CC1526B453002FF2BA /* icon.c in Sources */, EBD441CD1526B453002FF2BA /* inputbox.c in Sources */, EBD441CE1526B453002FF2BA /* keypad.c in Sources */, EBD441CF1526B453002FF2BA /* keypress.c in Sources */, EBD441D01526B453002FF2BA /* keytrap.c in Sources */, EBD441D11526B453002FF2BA /* listbox.c in Sources */, EBD441D21526B453002FF2BA /* menu.c in Sources */, EBD441D31526B453002FF2BA /* menubar.c in Sources */, EBD441D41526B453002FF2BA /* message.c in Sources */, EBD441D61526B453002FF2BA /* popup.c in Sources */, EBD441D71526B453002FF2BA /* radio.c in Sources */, EBD441D81526B453002FF2BA /* scroll.c in Sources */, EBD441D91526B453002FF2BA /* ui.c in Sources */, EBD441DA1526B453002FF2BA /* uidraw.c in Sources */, EBD441DB1526B453002FF2BA /* userbox.c in Sources */, EBD441DC1526B4DA002FF2BA /* bmread.c in Sources */, EBD441DD1526B4DA002FF2BA /* dumpmine.c in Sources */, EB6AFF61170FD9B400ED37CB /* vers_id.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( 089C165DFE840E0CC02AAC07 /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ EBBAD4930B2D0F7E00080BBF /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( USE_SDLMIXER, EDITOR, ); HEADER_SEARCH_PATHS = ( include, main, ../physfs, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, ); INFOPLIST_FILE = "d2x-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../physfs/build/Debug\""; PRODUCT_NAME = d2x; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Development; }; EBBAD4940B2D0F7E00080BBF /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( USE_SDLMIXER, EDITOR, NDEBUG, RELEASE, ); HEADER_SEARCH_PATHS = ( include, main, ../physfs, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, ); INFOPLIST_FILE = "d2x-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../physfs/build/Release\""; PRODUCT_NAME = d2x; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Deployment; }; EBBAD4950B2D0F7E00080BBF /* Default */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; INFOPLIST_FILE = "d2x-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", ); LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../physfs/build/Debug\""; LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../physfs/build/Release\""; LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../physfs/build/Debug\""; PRODUCT_NAME = d2x; WARNING_CFLAGS = "-Wall"; }; name = Default; }; EBBAD4970B2D0F7E00080BBF /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( USE_SDLMIXER, OGL, EDITOR, ); HEADER_SEARCH_PATHS = ( include, main, ../physfs, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, ); INFOPLIST_FILE = "d2xgl-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../physfs/build/Debug\""; PRODUCT_NAME = d2xgl; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Development; }; EBBAD4980B2D0F7E00080BBF /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( USE_SDLMIXER, OGL, EDITOR, NDEBUG, RELEASE, ); HEADER_SEARCH_PATHS = ( include, main, ../physfs, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, ); INFOPLIST_FILE = "d2xgl-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/../physfs/build/Release\""; PRODUCT_NAME = d2xgl; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Deployment; }; EBBAD4990B2D0F7E00080BBF /* Default */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = ( "$(HOME)/Library/Frameworks", /Library/Frameworks, "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", ); FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SYSTEM_LIBRARY_DIR)/Frameworks/ApplicationServices.framework/Versions/A/Frameworks\""; GCC_PREPROCESSOR_DEFINITIONS = ( no_cpp_precomp, OGL, NDEBUG, ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ( main, ../physfs, "$(HOME)/Library/Frameworks/SDL.framework/Headers", /Library/Frameworks/SDL.framework/Headers, ); INFOPLIST_FILE = "d2xgl-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2)", "$(LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3)", ); LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/../physfs/build/Debug\""; LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_2 = "\"$(SRCROOT)/../physfs/build/Release\""; LIBRARY_SEARCH_PATHS_QUOTED_FOR_TARGET_3 = "\"$(SRCROOT)/../physfs/build/Debug\""; PRODUCT_NAME = d2xgl; WARNING_CFLAGS = "-Wall"; }; name = Default; }; EBBAD49B0B2D0F7E00080BBF /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; FRAMEWORK_SEARCH_PATHS = /Users/btb/Library/Frameworks; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; HEADER_SEARCH_PATHS = "$(HOME)/Library/Frameworks/SDL.framework/Headers"; INFOPLIST_FILE = "MVEPlayer-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; OTHER_REZFLAGS = ""; PRODUCT_NAME = MVEPlayer; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Development; }; EBBAD49C0B2D0F7E00080BBF /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; FRAMEWORK_SEARCH_PATHS = /Users/btb/Library/Frameworks; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "$(value)", NDEBUG, RELEASE, ); GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; HEADER_SEARCH_PATHS = "$(HOME)/Library/Frameworks/SDL.framework/Headers"; INFOPLIST_FILE = "MVEPlayer-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; OTHER_REZFLAGS = ""; PRODUCT_NAME = MVEPlayer; WARNING_CFLAGS = "-Wall"; ZERO_LINK = NO; }; name = Deployment; }; EBBAD49D0B2D0F7E00080BBF /* Default */ = { isa = XCBuildConfiguration; buildSettings = { FRAMEWORK_SEARCH_PATHS = /Users/btb/Library/Frameworks; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; HEADER_SEARCH_PATHS = "$(HOME)/Library/Frameworks/SDL.framework/Headers"; INFOPLIST_FILE = "MVEPlayer-Info.plist"; INSTALL_PATH = "$(USER_APPS_DIR)"; OTHER_REZFLAGS = ""; PRODUCT_NAME = MVEPlayer; WARNING_CFLAGS = "-Wall"; }; name = Default; }; EBBAD49F0B2D0F7E00080BBF /* Development */ = { isa = XCBuildConfiguration; buildSettings = { GCC_PREFIX_HEADER = arch/carbon/conf.h; GCC_TREAT_WARNINGS_AS_ERRORS = YES; }; name = Development; }; EBBAD4A00B2D0F7E00080BBF /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( i386, ppc, ); GCC_PREFIX_HEADER = arch/carbon/conf.h; GCC_VERSION_i386 = 4.0; GCC_VERSION_ppc = 3.3; MACOSX_DEPLOYMENT_TARGET_i386 = 10.4; MACOSX_DEPLOYMENT_TARGET_ppc = 10.1; SDKROOT = /Developer/SDKs/MacOSX10.3.9.sdk; SDKROOT_i386 = /Developer/SDKs/MacOSX10.4u.sdk; SDKROOT_ppc = /Developer/SDKs/MacOSX10.3.9.sdk; }; name = Deployment; }; EBBAD4A10B2D0F7E00080BBF /* Default */ = { isa = XCBuildConfiguration; buildSettings = { }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ EBBAD4920B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "d2x" */ = { isa = XCConfigurationList; buildConfigurations = ( EBBAD4930B2D0F7E00080BBF /* Development */, EBBAD4940B2D0F7E00080BBF /* Deployment */, EBBAD4950B2D0F7E00080BBF /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; EBBAD4960B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "d2xgl" */ = { isa = XCConfigurationList; buildConfigurations = ( EBBAD4970B2D0F7E00080BBF /* Development */, EBBAD4980B2D0F7E00080BBF /* Deployment */, EBBAD4990B2D0F7E00080BBF /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; EBBAD49A0B2D0F7E00080BBF /* Build configuration list for PBXNativeTarget "MVEPlayer" */ = { isa = XCConfigurationList; buildConfigurations = ( EBBAD49B0B2D0F7E00080BBF /* Development */, EBBAD49C0B2D0F7E00080BBF /* Deployment */, EBBAD49D0B2D0F7E00080BBF /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; EBBAD49E0B2D0F7E00080BBF /* Build configuration list for PBXProject "d2x-rebirth" */ = { isa = XCConfigurationList; buildConfigurations = ( EBBAD49F0B2D0F7E00080BBF /* Development */, EBBAD4A00B2D0F7E00080BBF /* Deployment */, EBBAD4A10B2D0F7E00080BBF /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } dxx-rebirth-0.58.1-d2x/d2x-rebirth.xpm000066400000000000000000004034561217717237500174500ustar00rootroot00000000000000/* XPM */ static char * d2x_rebirth_xpm[] = { "128 128 6223 2", " c None", ". c #000000", "+ c #100F16", "@ c #29292C", "# c #2C2B2C", "$ c #2F2F2F", "% c #26262A", "& c #1A1923", "* c #1F1E26", "= c #29292B", "- c #212027", "; c #242429", "> c #232228", ", c #1C1B24", "' c #201F27", ") c #1E1E25", "! c #1C1B23", "~ c #2C2C2D", "{ c #222126", "] c #232327", "^ c #28272B", "/ c #2A292B", "( c #30302F", "_ c #2F2F2E", ": c #2D2D2D", "< c #2D2D2E", "[ c #202027", "} c #2C2C2C", "| c #31312F", "1 c #232429", "2 c #232227", "3 c #1F1E25", "4 c #1B1B24", "5 c #2B2B2D", "6 c #2A2A2C", "7 c #28282B", "8 c #2E2E2E", "9 c #171717", "0 c #6E6A8E", "a c #F3F2FB", "b c #D6D4E9", "c c #D1CFE7", "d c #CBC9E4", "e c #A4A0CF", "f c #D0CEE7", "g c #F0EFF6", "h c #C4C0E0", "i c #BEBADD", "j c #C6C3E2", "k c #B9B5DB", "l c #B3AFD7", "m c #BDB9DC", "n c #CCC9E4", "o c #B9B6DA", "p c #ABA7D2", "q c #B7B3D9", "r c #D7D5E9", "s c #B6B4D8", "t c #C3BFDF", "u c #F6F6F9", "v c #EEEDF5", "w c #EFEDF5", "x c #F1F0F7", "y c #FBFBFC", "z c #F7F7FA", "A c #F5F5FA", "B c #FCFCFD", "C c #E4E2F2", "D c #C5C2E2", "E c #C7C4E2", "F c #DEDDED", "G c #EEEDF6", "H c #EAEAF4", "I c #EAE9F4", "J c #D9D7EB", "K c #AEA9D3", "L c #BEBBDD", "M c #F4F4FA", "N c #EDEBF5", "O c #D5D3E8", "P c #B2AED5", "Q c #AEABD5", "R c #D9D6EB", "S c #FAFAFC", "T c #F5F5F9", "U c #EBEAF3", "V c #EEEEF5", "W c #EEECF6", "X c #FEFEFD", "Y c #EDECF6", "Z c #E4E2F1", "` c #F8F8F8", " . c #818182", ".. c #83809D", "+. c #FAF9FF", "@. c #B6B1DB", "#. c #938DC7", "$. c #C6C3E6", "%. c #DCD9F1", "&. c #F8F6FF", "*. c #F7F7FD", "=. c #CBC7E9", "-. c #B9B5DE", ";. c #DAD7F0", ">. c #ECEBFA", ",. c #DBD9F2", "'. c #DFDDF3", "). c #EFEDFB", "!. c #D0CCEB", "~. c #CDCAEA", "{. c #E5E3F6", "]. c #C0BCE1", "^. c #BFBCE1", "/. c #F3F1FD", "(. c #FFFFFF", "_. c #D5D3EE", ":. c #DBD9F0", "<. c #F0EFFA", "[. c #F8F8FF", "}. c #F5F5FD", "|. c #F0F0FD", "1. c #E7E4F7", "2. c #F4F2FE", "3. c #D1CDEA", "4. c #DFDCF3", "5. c #BFBAE1", "6. c #CAC6E8", "7. c #F1F0FC", "8. c #FCFBFF", "9. c #DFDCF2", "0. c #D8D6F0", "a. c #C7C2E6", "b. c #F5F5FE", "c. c #FEFEFE", "d. c #878787", "e. c #747191", "f. c #C9C4E9", "g. c #A29ECF", "h. c #AFAAD4", "i. c #CFCCE6", "j. c #F4F3F9", "k. c #E7E6F3", "l. c #BFBCDE", "m. c #BCB8DC", "n. c #DEDCED", "o. c #EFEDF6", "p. c #D5D2EA", "q. c #ECECF5", "r. c #F9F8FB", "s. c #E0DEEF", "t. c #FFFFFE", "u. c #D9D8EC", "v. c #C5C2E1", "w. c #EFEEF6", "x. c #E6E5F2", "y. c #BAB6DB", "z. c #E7E5F2", "A. c #FAFBFC", "B. c #E3E2F1", "C. c #E8E7F4", "D. c #C3BFE0", "E. c #D3D0E7", "F. c #FDFCFD", "G. c #F9F8FC", "H. c #E3E1F0", "I. c #E1E0F0", "J. c #EFEFF7", "K. c #FAFAFD", "L. c #D9D8EB", "M. c #FDFEFE", "N. c #FDFDFE", "O. c #F9F9FC", "P. c #F8F8FB", "Q. c #EDECF5", "R. c #FBFBFD", "S. c #FAFAFA", "T. c #757393", "U. c #CBC7EB", "V. c #DAD9ED", "W. c #DBD9ED", "X. c #F2F0F8", "Y. c #D3D1E8", "Z. c #C1BFDF", "`. c #BEBBDE", " + c #ABA7D1", ".+ c #D1CEE9", "++ c #DCDAED", "@+ c #FDFCFE", "#+ c #FBFAFD", "$+ c #F3F3F8", "%+ c #D3D0E9", "&+ c #D7D5EB", "*+ c #F8F8FC", "=+ c #FCFCFE", "-+ c #DFDDEF", ";+ c #EDEDF6", ">+ c #E0DEF0", ",+ c #D7D4EA", "'+ c #E2E1F0", ")+ c #D9D6EC", "!+ c #F0EFF9", "~+ c #E3E1F1", "{+ c #E1DFEF", "]+ c #ECEBF6", "^+ c #FBFCFD", "/+ c #F1F0F8", "(+ c #F6F6FB", "_+ c #F4F3FA", ":+ c #D7D5EA", "<+ c #F0EEF7", "[+ c #F8F8FA", "}+ c #858684", "|+ c #807E9A", "1+ c #F7F6FE", "2+ c #F0F0F8", "3+ c #D7D4EB", "4+ c #B3AFD6", "5+ c #9893C7", "6+ c #C2BEE0", "7+ c #9E99CB", "8+ c #AAA5D1", "9+ c #C8C5E3", "0+ c #F8F7FC", "a+ c #EFEEF7", "b+ c #E9E9F4", "c+ c #E0DFF0", "d+ c #EDEDF7", "e+ c #EAE8F4", "f+ c #D4D1EA", "g+ c #CBC8E5", "h+ c #C7C4E3", "i+ c #C3C1E1", "j+ c #E1E0F1", "k+ c #E5E3F2", "l+ c #F3F2F9", "m+ c #FEFEFF", "n+ c #F5F3FA", "o+ c #E0DFEE", "p+ c #E9E7F3", "q+ c #FCFBFD", "r+ c #F7F6FC", "s+ c #7B7B7F", "t+ c #86849E", "u+ c #F6F4FE", "v+ c #F6F5FB", "w+ c #ECECF6", "x+ c #CECCE7", "y+ c #C2BEDF", "z+ c #A39ECE", "A+ c #B8B4DB", "B+ c #A09CCC", "C+ c #958FC4", "D+ c #8E88C0", "E+ c #A39ECD", "F+ c #CBC8E4", "G+ c #F0F0F7", "H+ c #F7F7FC", "I+ c #F7F6FB", "J+ c #E4E3F1", "K+ c #F6F6FA", "L+ c #E0E0EF", "M+ c #E8E5F4", "N+ c #CDCBE6", "O+ c #D0CDE7", "P+ c #F5F4FA", "Q+ c #F5F6FA", "R+ c #EBEAF5", "S+ c #F8F6FB", "T+ c #E7E5F3", "U+ c #E0E0F0", "V+ c #C1BDE2", "W+ c #464360", "X+ c #8A88A0", "Y+ c #F4F3FF", "Z+ c #EBEAF4", "`+ c #DDDBED", " @ c #ACA7D3", ".@ c #A5A1D0", "+@ c #8B85BF", "@@ c #7C76B5", "#@ c #8A84BD", "$@ c #B6B2D9", "%@ c #C6C3E3", "&@ c #D8D7ED", "*@ c #D0CDE8", "=@ c #DEDCEE", "-@ c #E8E6F3", ";@ c #FEFDFE", ">@ c #F5F5FB", ",@ c #F7F7FB", "'@ c #FFFEFF", ")@ c #E1DFF0", "!@ c #E6E4F3", "~@ c #E4E3F2", "{@ c #F5F6FB", "]@ c #FAFBFD", "^@ c #F6F5FA", "/@ c #BAB7DC", "(@ c #9992CC", "_@ c #464361", ":@ c #7F7C98", "<@ c #E2E0F5", "[@ c #A099CA", "}@ c #D0CDE6", "|@ c #BDBBDC", "1@ c #B3AED8", "2@ c #C0BDDE", "3@ c #BCB9DC", "4@ c #908AC2", "5@ c #9892C7", "6@ c #9B96C7", "7@ c #8D88BF", "8@ c #8882BC", "9@ c #908AC1", "0@ c #B2AFD6", "a@ c #B3B0D6", "b@ c #FDFDFD", "c@ c #EAEAF5", "d@ c #FBFCFE", "e@ c #E2E0F0", "f@ c #E6E5F3", "g@ c #DBDAEC", "h@ c #EAE9F5", "i@ c #EBEBF5", "j@ c #F0EFF8", "k@ c #A6A1D4", "l@ c #5A596E", "m@ c #6E6B89", "n@ c #EBE8F8", "o@ c #E1DEEF", "p@ c #F3F3F9", "q@ c #D2CFE8", "r@ c #B8B3DA", "s@ c #948FC5", "t@ c #C1BEDE", "u@ c #DEDBEE", "v@ c #A5A1CE", "w@ c #8883BB", "x@ c #8A84BE", "y@ c #6760A6", "z@ c #6760A5", "A@ c #837DB9", "B@ c #8A84BC", "C@ c #6A63A7", "D@ c #9591C4", "E@ c #E5E3F1", "F@ c #FBFBFE", "G@ c #FDFDFF", "H@ c #DCDBEE", "I@ c #ACA8D2", "J@ c #847DB9", "K@ c #A39ECA", "L@ c #ECEBF5", "M@ c #DBD8ED", "N@ c #BAB6E0", "O@ c #57556B", "P@ c #000001", "Q@ c #000002", "R@ c #000004", "S@ c #000008", "T@ c #00000B", "U@ c #00000D", "V@ c #000010", "W@ c #00000E", "X@ c #000007", "Y@ c #6B7099", "Z@ c #E6F1FE", "`@ c #EAF6FF", " # c #E4EFFC", ".# c #E3ECFA", "+# c #E1E7F7", "@# c #CACDE9", "## c #B1B2DA", "$# c #8C88C1", "%# c #948EC5", "&# c #C7C3E2", "*# c #EEEDF7", "=# c #CFCDE5", "-# c #B3AFD5", ";# c #B3AED6", "># c #6D66A8", ",# c #7069AB", "'# c #655EA3", ")# c #8680B9", "!# c #7871AF", "~# c #706AAC", "{# c #AEA9D2", "]# c #E4E3F0", "^# c #D6D3EA", "/# c #E8E7F5", "(# c #817CB1", "_# c #20186A", ":# c #5A5396", "<# c #DFDDEE", "[# c #F0EFF7", "}# c #C7C3E3", "|# c #D2CFEC", "1# c #5A586C", "2# c #000003", "3# c #000016", "4# c #00001D", "5# c #000024", "6# c #00002C", "7# c #000032", "8# c #000038", "9# c #00003E", "0# c #00003D", "a# c #33469D", "b# c #82A7F0", "c# c #92BAF6", "d# c #93B8F3", "e# c #95B8F2", "f# c #98B7EF", "g# c #8CA5E3", "h# c #96ABE3", "i# c #A0B2E4", "j# c #B2BFE9", "k# c #D2DDF5", "l# c #D4DAF1", "m# c #C1C2E2", "n# c #9B98C9", "o# c #918BC2", "p# c #8882BB", "q# c #6B64A7", "r# c #7C75B4", "s# c #8D87BF", "t# c #E6E4F1", "u# c #8983BC", "v# c #6962A8", "w# c #6861A6", "x# c #A9A5CE", "y# c #F2F2F9", "z# c #DFDCEF", "A# c #817CAF", "B# c #403985", "C# c #A7A2CC", "D# c #FEFDFF", "E# c #D6D4EB", "F# c #EDEBF9", "G# c #6F6D79", "H# c #000006", "I# c #00000C", "J# c #000014", "K# c #00001F", "L# c #000145", "M# c #000151", "N# c #00025D", "O# c #00026A", "P# c #000674", "Q# c #070B7D", "R# c #041085", "S# c #031087", "T# c #030D89", "U# c #1136BA", "V# c #2564E2", "W# c #2867E4", "X# c #2A61DC", "Y# c #2D62DA", "Z# c #3B72E2", "`# c #4A82EA", " $ c #5083E5", ".$ c #5783E1", "+$ c #77A4F0", "@$ c #84A9ED", "#$ c #9AB9F0", "$$ c #C4DEFE", "%$ c #B0BFE9", "&$ c #8387C4", "*$ c #6F6DB0", "=$ c #7F7AB7", "-$ c #BBB8DA", ";$ c #ADA9D3", ">$ c #E8E6F4", ",$ c #9C98CA", "'$ c #8681B8", ")$ c #7972B2", "!$ c #A5A0CE", "~$ c #EEEEF6", "{$ c #E9E8F4", "]$ c #DBDAED", "^$ c #F6F4FC", "/$ c #D6D4EA", "($ c #F4F3F8", "_$ c #666574", ":$ c #00000A", "<$ c #000015", "[$ c #000022", "}$ c #000031", "|$ c #000142", "1$ c #000455", "2$ c #000869", "3$ c #000D7D", "4$ c #011893", "5$ c #0430A8", "6$ c #0A4AB9", "7$ c #255EC7", "8$ c #5477D5", "9$ c #518FDD", "0$ c #21A0E3", "a$ c #21A1E8", "b$ c #1D71E9", "c$ c #1669EB", "d$ c #2DA2F2", "e$ c #2292EF", "f$ c #0364E8", "g$ c #0345DA", "h$ c #0740CB", "i$ c #0944CB", "j$ c #0B42CF", "k$ c #124BD2", "l$ c #1C54D9", "m$ c #2A64DF", "n$ c #4079E7", "o$ c #5385E7", "p$ c #6690E6", "q$ c #8AAEEE", "r$ c #93ACE5", "s$ c #98A5DB", "t$ c #BAC1E6", "u$ c #B2B4DC", "v$ c #BDBCDF", "w$ c #ECEAF4", "x$ c #C2C0E0", "y$ c #A39ECB", "z$ c #D7D4E9", "A$ c #FAF9FD", "B$ c #DAD7EC", "C$ c #F5F3F9", "D$ c #79787D", "E$ c #00001B", "F$ c #000141", "G$ c #000357", "H$ c #000972", "I$ c #01168C", "J$ c #011DA1", "K$ c #0124B2", "L$ c #0543CD", "M$ c #0B63E3", "N$ c #138CF4", "O$ c #18B6FE", "P$ c #88FFFF", "Q$ c #70FBFF", "R$ c #0EE9FF", "S$ c #20F3FF", "T$ c #1AC5FF", "U$ c #2CC4FF", "V$ c #B8FFFF", "W$ c #D3FFFF", "X$ c #68CEFF", "Y$ c #0C78EB", "Z$ c #083AC1", "`$ c #082DAB", " % c #0732AE", ".% c #052EAA", "+% c #0124A7", "@% c #032FB6", "#% c #063CC7", "$% c #073AC7", "%% c #1346D0", "&% c #3673E8", "*% c #4D82E9", "=% c #547DDA", "-% c #7898E1", ";% c #8597D6", ">% c #ADB6E2", ",% c #EEF5FC", "'% c #ECEDF7", ")% c #D2D0E8", "!% c #DAD8EB", "~% c #F3F1F9", "{% c #D3D0E8", "]% c #838383", "^% c #00000F", "/% c #00001E", "(% c #000149", "_% c #000668", ":% c #001088", "<% c #011CA5", "[% c #022EBD", "}% c #0544CA", "|% c #0540CA", "1% c #0743C9", "2% c #0A5CD5", "3% c #0D61D6", "4% c #0C5FDB", "5% c #0869E4", "6% c #2AB4F5", "7% c #9CF2FF", "8% c #92F3FF", "9% c #38E4FF", "0% c #5AF8FF", "a% c #83FFFF", "b% c #A6FFFF", "c% c #CBFFFF", "d% c #C9FFFF", "e% c #DCFFFF", "f% c #76E7FF", "g% c #0479EF", "h% c #0333BD", "i% c #0B2FAD", "j% c #0A31AA", "k% c #092A9E", "l% c #08259C", "m% c #082BA6", "n% c #0527A3", "o% c #0225A7", "p% c #0330B9", "q% c #1950D5", "r% c #2E62DB", "s% c #3860CE", "t% c #5D7CD2", "u% c #9EB8EB", "v% c #D1E1FA", "w% c #CDD1EC", "x% c #CFCFE8", "y% c #F1F0F9", "z% c #D2CFE7", "A% c #ECEDF6", "B% c #F8F7FB", "C% c #FAF9FC", "D% c #FBFBFA", "E% c #7D7C80", "F% c #000131", "G% c #00014C", "H% c #00096F", "I% c #001995", "J% c #0226B3", "K% c #0334C8", "L% c #064BD4", "M% c #095BD5", "N% c #094ACA", "O% c #0840C3", "P% c #0944C4", "Q% c #0946C6", "R% c #0843C3", "S% c #0848C7", "T% c #0B4FCC", "U% c #0051D6", "V% c #1598F2", "W% c #A5EEFF", "X% c #F2FFFF", "Y% c #D6FFFF", "Z% c #C6FAFF", "`% c #98E8FF", " & c #34CAFF", ".& c #19C7FF", "+& c #55F5FF", "@& c #E6FFFF", "#& c #74DDFF", "$& c #1F84E8", "%& c #0546C9", "&& c #0F47C2", "*& c #0A37B1", "=& c #0B32A9", "-& c #0C33AA", ";& c #0A2B9F", ">& c #092497", ",& c #072196", "'& c #03229D", ")& c #0226AA", "!& c #0029B4", "~& c #083BC7", "{& c #235EDD", "]& c #538AEE", "^& c #7AA2EB", "/& c #ADC7F3", "(& c #CCDAF4", "_& c #EAF0FA", ":& c #FDFEFF", "<& c #F3F1F8", "[& c #F1EFF7", "}& c #F3F3FA", "|& c #DBD8EC", "1& c #F4F4F9", "2& c #F8F7F8", "3& c #6E6C78", "4& c #000009", "5& c #000017", "6& c #00012C", "7& c #000247", "8& c #00076C", "9& c #001997", "0& c #0237BD", "a& c #044AD1", "b& c #0647D4", "c& c #0746D0", "d& c #0953D0", "e& c #0A57D1", "f& c #0845C9", "g& c #094DCC", "h& c #094DCB", "i& c #094AC7", "j& c #0948C7", "k& c #0A46C5", "l& c #0A47C4", "m& c #0A4BC8", "n& c #004FD4", "o& c #229DF1", "p& c #A6FDFF", "q& c #72D0FC", "r& c #138FF1", "s& c #0B85EB", "t& c #0771EA", "u& c #0E7FF5", "v& c #13C1FD", "w& c #8BFCFF", "x& c #E4FFFF", "y& c #8CF9FF", "z& c #219EF1", "A& c #0344CA", "B& c #0D38B3", "C& c #0E45B7", "D& c #0E40B4", "E& c #092DA4", "F& c #092AA1", "G& c #0929A0", "H& c #09269A", "I& c #072399", "J& c #0529A7", "K& c #073CC2", "L& c #0F4ED5", "M& c #2663E3", "N& c #5C94F3", "O& c #83ABEC", "P& c #ACC2ED", "Q& c #DCE8FB", "R& c #E8EBF9", "S& c #F4F2F9", "T& c #DDDBEE", "U& c #E6E4F2", "V& c #FDFBFE", "W& c #FEFFFF", "X& c #686776", "Y& c #00023D", "Z& c #000561", "`& c #00118C", " * c #0128B7", ".* c #0544D2", "+* c #0751DA", "@* c #074FD7", "#* c #084DD3", "$* c #074DD2", "%* c #084ED2", "&* c #094DD1", "** c #0955D2", "=* c #0A52D0", "-* c #0A4DCB", ";* c #0A4DCA", ">* c #0A4ECA", ",* c #0B51CA", "'* c #0A4EC7", ")* c #0B49C5", "!* c #0864D8", "~* c #10A3F7", "{* c #0C79E6", "]* c #0245CD", "^* c #0C57D1", "/* c #115DD3", "(* c #135CD4", "_* c #1878EA", ":* c #22B5FF", "<* c #4DCBFF", "[* c #6DE9FF", "}* c #9CF3FF", "|* c #167FE7", "1* c #0139C0", "2* c #0E3AB0", "3* c #0D38AF", "4* c #0A2FA7", "5* c #0B34AA", "6* c #0D3DB2", "7* c #0C36AE", "8* c #0B2EA6", "9* c #0A2CA3", "0* c #09279B", "a* c #07259C", "b* c #0328A4", "c* c #0431B8", "d* c #0F47D4", "e* c #3270EB", "f* c #5380E0", "g* c #6B82CC", "h* c #949FD5", "i* c #B7BBE0", "j* c #F2F4FA", "k* c #F1EEF7", "l* c #EAE7F4", "m* c #DDDBEF", "n* c #E9E6F4", "o* c #FBFAFE", "p* c #C6C2E4", "q* c #5E5C6F", "r* c #00012E", "s* c #00024F", "t* c #000C7B", "u* c #0121AB", "v* c #043ACC", "w* c #064BDA", "x* c #0751DB", "y* c #0852DA", "z* c #085BDB", "A* c #0963DC", "B* c #0A6BDE", "C* c #0A5CD9", "D* c #0A58D8", "E* c #0D73DE", "F* c #0C70DC", "G* c #0A59D4", "H* c #0A53D1", "I* c #0A52CE", "J* c #0B56D0", "K* c #0B58CF", "L* c #0B4EC9", "M* c #0B51C8", "N* c #0F65D6", "O* c #0D6EE4", "P* c #0B57D1", "Q* c #0D4EC3", "R* c #0F53C7", "S* c #0E50C7", "T* c #0E49C0", "U* c #1258D5", "V* c #1691FC", "W* c #0BA7FF", "X* c #23BBFF", "Y* c #C6FFFF", "Z* c #B3E9FF", "`* c #0A7FEA", " = c #0732B9", ".= c #0B2FA6", "+= c #0B32A8", "@= c #0C36AB", "#= c #0B31A8", "$= c #0A2EA5", "%= c #0A2CA4", "&= c #0A30A8", "*= c #0B2FA8", "== c #092499", "-= c #062197", ";= c #0223A0", ">= c #0634BD", ",= c #1149D6", "'= c #1842C0", ")= c #2F48AE", "!= c #6F7EC5", "~= c #DAE6F9", "{= c #FBFEFF", "]= c #F3F2FA", "^= c #CFCCE7", "/= c #8983C1", "(= c #403D5D", "_= c #00013A", ":= c #000560", "<= c #001495", "[= c #033FC8", "}= c #064EDC", "|= c #0751DD", "1= c #085EDE", "2= c #0964E1", "3= c #095FDF", "4= c #0A6BE1", "5= c #0A6CE1", "6= c #0A69E0", "7= c #0A5FDC", "8= c #0A5EDB", "9= c #0B67DD", "0= c #0C68DD", "a= c #0B5FDA", "b= c #0B5DD6", "c= c #0B5ED5", "d= c #0B59D2", "e= c #0B56D1", "f= c #0C55CE", "g= c #0C59CE", "h= c #0F66D5", "i= c #1067D6", "j= c #0D55CA", "k= c #0D53C8", "l= c #0F54C8", "m= c #0F50C8", "n= c #0F53CB", "o= c #1157CF", "p= c #156CE2", "q= c #1A88F6", "r= c #199EFD", "s= c #55D8FF", "t= c #CAFFFF", "u= c #6CD5FF", "v= c #035CD8", "w= c #0B33AE", "x= c #0C31A9", "y= c #0C30A8", "z= c #0B2DA5", "A= c #0B2EA4", "B= c #0B2DA3", "C= c #0B2CA2", "D= c #0A2EA6", "E= c #0B36B0", "F= c #0B34AE", "G= c #0A2AA1", "H= c #09279C", "I= c #06259D", "J= c #0428A9", "K= c #0637C3", "L= c #154ACF", "M= c #416AD1", "N= c #92B0E9", "O= c #D7E9FD", "P= c #EEF6FD", "Q= c #DEDEF0", "R= c #D4D2E9", "S= c #D5D4E9", "T= c #F9F8FD", "U= c #D6D5E9", "V= c #9D97CE", "W= c #4B4763", "X= c #000026", "Y= c #000245", "Z= c #000973", "`= c #0120AA", " - c #0440D3", ".- c #0756E1", "+- c #0857E0", "@- c #085AE0", "#- c #0964E2", "$- c #0A69E4", "%- c #0A68E2", "&- c #0B6BE4", "*- c #0B69E3", "=- c #0B67E2", "-- c #0B6FE3", ";- c #0C70E3", ">- c #0A69E1", ",- c #0A69DF", "'- c #0C6DE0", ")- c #0E75E0", "!- c #0F7BE1", "~- c #0D70DC", "{- c #0D6AD9", "]- c #0D5CD2", "^- c #0C5BD1", "/- c #0E5CD0", "(- c #0E5BCE", "_- c #0D56CB", ":- c #0E56C9", "<- c #0E53C9", "[- c #0F52CB", "}- c #1054CD", "|- c #1155CE", "1- c #1153D0", "2- c #155DD8", "3- c #177EF0", "4- c #1FC2FF", "5- c #8FF9FF", "6- c #AFF2FF", "7- c #0F7EE4", "8- c #0934B7", "9- c #0E35AD", "0- c #0C34AB", "a- c #0C31A8", "b- c #0C30A7", "c- c #0B30A6", "d- c #0B35AC", "e- c #0A2FA6", "f- c #0A2BA2", "g- c #08269A", "h- c #07269F", "i- c #0633BB", "j- c #154DD7", "k- c #4276E0", "l- c #8DB2F0", "m- c #C9DEFA", "n- c #CED4EE", "o- c #B1AFD8", "p- c #F2F2F8", "q- c #D4D1E9", "r- c #ABA6D2", "s- c #C3C0E0", "t- c #D8D6EC", "u- c #A19CCB", "v- c #827BB8", "w- c #B6B2D8", "x- c #CDC9E8", "y- c #6C6B76", "z- c #000005", "A- c #000013", "B- c #00012A", "C- c #00034F", "D- c #000C82", "E- c #012ABB", "F- c #064CDC", "G- c #0858E2", "H- c #0859E1", "I- c #095FE3", "J- c #0A65E6", "K- c #0A67E6", "L- c #0A6BE7", "M- c #0A6EE8", "N- c #0B72E8", "O- c #0B76E9", "P- c #0C79E8", "Q- c #0E87EA", "R- c #1090EA", "S- c #1091E9", "T- c #1495E9", "U- c #1191E8", "V- c #0F86E7", "W- c #0F81E4", "X- c #0F7EE2", "Y- c #1181E1", "Z- c #0F6CD9", "`- c #0E63D6", " ; c #0D5ED3", ".; c #0E5BD0", "+; c #0E59CD", "@; c #0E58CB", "#; c #0F57CC", "$; c #1364D2", "%; c #1158CC", "&; c #104FC6", "*; c #114EC7", "=; c #1254D1", "-; c #1579EA", ";; c #41DFFF", ">; c #D0FEFF", ",; c #A6E3FF", "'; c #076DE1", "); c #0D3BBB", "!; c #0E3AB2", "~; c #0E36AE", "{; c #0D34AB", "]; c #0E36AD", "^; c #0E3BB4", "/; c #0F3FB6", "(; c #0D36AD", "_; c #0B2EA5", ":; c #0A2BA1", "<; c #092BA0", "[; c #09289E", "}; c #07259A", "|; c #0428AB", "1; c #0F43D2", "2; c #3C75E6", "3; c #80A9ED", "4; c #B0C7F1", "5; c #C3C9E9", "6; c #EFF1F9", "7; c #FCFCFC", "8; c #DFDCEE", "9; c #F7F5FB", "0; c #C9C6E4", "a; c #E0DDF1", "b; c #A39DCB", "c; c #AFABD1", "d; c #F4F3F7", "e; c #626071", "f; c #00012F", "g; c #000557", "h; c #00108C", "i; c #0233C5", "j; c #0755E1", "k; c #075AE3", "l; c #085DE3", "m; c #0961E5", "n; c #0A6CE9", "o; c #0B71EA", "p; c #0B7AEB", "q; c #0D8AEE", "r; c #1193EF", "s; c #14A4F0", "t; c #1093ED", "u; c #0E80EA", "v; c #0E82E9", "w; c #0E87E9", "x; c #1190EA", "y; c #118AE9", "z; c #0E80E5", "A; c #0F79E2", "B; c #0E77E0", "C; c #0F74DE", "D; c #0F71DC", "E; c #1073DE", "F; c #0E69D7", "G; c #0E60D2", "H; c #0F5DD0", "I; c #0F5BCE", "J; c #1059CD", "K; c #115DCF", "L; c #125ED1", "M; c #1157CB", "N; c #1155CB", "O; c #135DD7", "P; c #157CEB", "Q; c #71E7FF", "R; c #E8FFFF", "S; c #52C6F9", "T; c #075ADC", "U; c #1148C9", "V; c #1141B9", "W; c #0F38B0", "X; c #0E38B0", "Y; c #0E37AE", "Z; c #0E38AE", "`; c #0C34AC", " > c #0C33AB", ".> c #0D37AE", "+> c #0D3AB1", "@> c #0A2CA2", "#> c #0B32AA", "$> c #0A33AC", "%> c #0525A1", "&> c #0B3FCC", "*> c #346FE6", "=> c #6C96E7", "-> c #AAC0ED", ";> c #DCE5F7", ">> c #ECEEF7", ",> c #E6E3F5", "'> c #535268", ")> c #000132", "!> c #00045A", "~> c #001394", "{> c #0338CB", "]> c #0657E2", "^> c #085CE4", "/> c #0A75E9", "(> c #0A71EA", "_> c #0B74EC", ":> c #0C83EF", "<> c #0D85EF", "[> c #0F96F1", "}> c #0F8FF1", "|> c #108DF0", "1> c #1196F1", "2> c #0F8DF0", "3> c #0F8BEF", "4> c #108CED", "5> c #108CEC", "6> c #0F89EB", "7> c #1088E9", "8> c #1085E8", "9> c #0F83E6", "0> c #107FE4", "a> c #0F78DF", "b> c #1070DB", "c> c #106AD7", "d> c #1067D5", "e> c #1064D3", "f> c #1061D3", "g> c #105CD0", "h> c #1158CE", "i> c #1156CB", "j> c #1257CD", "k> c #1258D0", "l> c #0F65E1", "m> c #5CCBFE", "n> c #DBFFFF", "o> c #2DB1F8", "p> c #0969EB", "q> c #1368E7", "r> c #114BC8", "s> c #103DB5", "t> c #0F3BB3", "u> c #0F39B0", "v> c #0F38AF", "w> c #0E38AF", "x> c #0E36AC", "y> c #0C37AD", "z> c #0D39B0", "A> c #0C2FA5", "B> c #0B30A7", "C> c #0B33AC", "D> c #0B34AC", "E> c #092AA2", "F> c #0525A0", "G> c #0A3DCA", "H> c #2A65E3", "I> c #6994E8", "J> c #AFC7F1", "K> c #DAE4F8", "L> c #CCCAE7", "M> c #DEDCEF", "N> c #D1CEE7", "O> c #C8C6E3", "P> c #C4C1E1", "Q> c #00065D", "R> c #001697", "S> c #033AD0", "T> c #075CE5", "U> c #085FE4", "V> c #0968E7", "W> c #0A73EA", "X> c #0B78EC", "Y> c #0B79EE", "Z> c #0C7AF0", "`> c #0D81F1", " , c #0E86F1", "., c #0F8CF2", "+, c #1090F2", "@, c #1193F3", "#, c #1196F2", "$, c #1198F2", "%, c #1199F0", "&, c #1198F1", "*, c #1196F0", "=, c #1094EE", "-, c #1191EB", ";, c #108DEA", ">, c #108AE7", ",, c #1087E7", "', c #1181E4", "), c #107BE0", "!, c #1076DF", "~, c #1172DC", "{, c #106CD8", "], c #1168D6", "^, c #1165D5", "/, c #1160D3", "(, c #115CCF", "_, c #1256CB", ":, c #1253C9", "<, c #0F52CD", "[, c #2688E8", "}, c #A0F1FE", "|, c #ACFFFF", "1, c #7AE5FF", "2, c #58BFFE", "3, c #1878E8", "4, c #0B42C5", "5, c #103BB5", "6, c #103DB4", "7, c #103AB2", "8, c #1040B9", "9, c #0D34A9", "0, c #0C33A9", "a, c #0C32A9", "b, c #0E3FB4", "c, c #0C3AB1", "d, c #0B33AD", "e, c #092DA5", "f, c #09279E", "g, c #0627A4", "h, c #0636C3", "i, c #2A67E5", "j, c #75A4F1", "k, c #BED7FA", "l, c #D1D8F1", "m, c #C8C4E2", "n, c #F1F1F8", "o, c #EEEEF7", "p, c #AEA9D4", "q, c #EAE8F5", "r, c #FCFCFB", "s, c #00055B", "t, c #033DD0", "u, c #0756E4", "v, c #075BE3", "w, c #0860E6", "x, c #0A73EB", "y, c #0B81EE", "z, c #0C7CF0", "A, c #0E84F2", "B, c #0F8BF3", "C, c #1091F5", "D, c #1196F6", "E, c #129BF6", "F, c #139FF6", "G, c #14A0F7", "H, c #14A3F6", "I, c #14A5F4", "J, c #14A6F4", "K, c #15A3F3", "L, c #139EF1", "M, c #149EF0", "N, c #1398EE", "O, c #1293EB", "P, c #128EE9", "Q, c #1187E7", "R, c #127EE2", "S, c #1277DE", "T, c #116EDB", "U, c #116AD8", "V, c #1166D5", "W, c #1263D3", "X, c #1260D2", "Y, c #125BCF", "Z, c #1257CB", "`, c #1254C9", " ' c #134FC7", ".' c #0D4DCC", "+' c #1480E7", "@' c #74CEF8", "#' c #CEECFD", "$' c #E2FFFF", "%' c #77DAFF", "&' c #1179E7", "*' c #1056D0", "=' c #1449C3", "-' c #103FB8", ";' c #1040B8", ">' c #0F3AB2", ",' c #0E38AD", "'' c #0E35AC", ")' c #0D34AA", "!' c #0C31A7", "~' c #0C37AE", "{' c #0F47B9", "]' c #0B35B0", "^' c #0A2EA8", "/' c #092CA4", "(' c #06259E", "_' c #0437C3", ":' c #2B6AE8", "<' c #79A7F2", "[' c #BBD2F6", "}' c #CCD2ED", "|' c #E6E6F3", "1' c #EBE9F5", "2' c #D5D2E9", "3' c #F2F0F9", "4' c #6E6D77", "5' c #001393", "6' c #033CCF", "7' c #085BE4", "8' c #0860E4", "9' c #0861E6", "0' c #0966E9", "a' c #0A75EC", "b' c #0D89F1", "c' c #0D87F2", "d' c #0E87F2", "e' c #1191F5", "f' c #139EF8", "g' c #14A2F8", "h' c #16A9F9", "i' c #18AEF9", "j' c #18ACF9", "k' c #18ADF9", "l' c #18AFF8", "m' c #18AEF7", "n' c #17AAF5", "o' c #17A6F3", "p' c #17A4F2", "q' c #159DF0", "r' c #1497EE", "s' c #1391EB", "t' c #128AE8", "u' c #1285E6", "v' c #1280E4", "w' c #127BE1", "x' c #1274DE", "y' c #126FDB", "z' c #126BD8", "A' c #1266D6", "B' c #1364D5", "C' c #135FD3", "D' c #135BCF", "E' c #1459CE", "F' c #1557CE", "G' c #1552CA", "H' c #104AC9", "I' c #064FD3", "J' c #0071E7", "K' c #6CC3FD", "L' c #96F1FF", "M' c #2AA8F9", "N' c #105BDC", "O' c #1346C0", "P' c #103FB5", "Q' c #103CB2", "R' c #0F3AB1", "S' c #0F37AF", "T' c #0F3FB7", "U' c #0D36AE", "V' c #0F42B7", "W' c #0C37AF", "X' c #0A2EA7", "Y' c #05239E", "Z' c #0537C6", "`' c #3070EB", " ) c #7BA6EF", ".) c #C8DEF9", "+) c #F8FFFF", "@) c #CDCBE5", "#) c #F2F1F7", "$) c #D8D7EC", "%) c #E2DFF0", "&) c #CECBE7", "*) c #565469", "=) c #000123", "-) c #00044E", ";) c #0235CA", ">) c #0754E1", ",) c #085CE1", "') c #0964E6", ")) c #0965E8", "!) c #0A79EC", "~) c #0E96F2", "{) c #0E95F4", "]) c #0E8EF4", "^) c #1098F6", "/) c #139EF7", "() c #15A7F9", "_) c #17A7FA", ":) c #19ACFA", "<) c #19B0FB", "[) c #1CB4FB", "}) c #1CB4FA", "|) c #1CB3FB", "1) c #1BB4FA", "2) c #19B1F9", "3) c #19ADF7", "4) c #18ABF5", "5) c #17A7F3", "6) c #17A1F2", "7) c #169CF1", "8) c #1596EE", "9) c #1490EA", "0) c #138AE8", "a) c #1385E6", "b) c #137FE4", "c) c #1278E0", "d) c #1273DE", "e) c #1370DC", "f) c #136AD9", "g) c #1467D8", "h) c #1463D5", "i) c #135ED2", "j) c #145BD0", "k) c #1558CE", "l) c #1454CA", "m) c #1552C8", "n) c #154DC5", "o) c #1249CF", "p) c #0F64E4", "q) c #53BEF9", "r) c #E0FFFF", "s) c #B3F0FF", "t) c #2082EE", "u) c #0C41C6", "v) c #1242B9", "w) c #1140B7", "x) c #103DB3", "y) c #1242B8", "z) c #1348BF", "A) c #1043BC", "B) c #0F3AB3", "C) c #0C32A7", "D) c #0D36AF", "E) c #0B34AD", "F) c #0A2DA3", "G) c #0D39AD", "H) c #0630AC", "I) c #0840CE", "J) c #3775EB", "K) c #8BB5F3", "L) c #C6D6F4", "M) c #D1D3EC", "N) c #DFDEEF", "O) c #E8E7F3", "P) c #F9FAFC", "Q) c #BFBBDD", "R) c #D1CEE5", "S) c #DEDCF1", "T) c #666472", "U) c #00001C", "V) c #000241", "W) c #000C7E", "X) c #022FC2", "Y) c #0652DE", "Z) c #0755DF", "`) c #0758E2", " ! c #0964E7", ".! c #0A71EB", "+! c #0D8EF0", "@! c #0F9AF4", "#! c #109AF5", "$! c #12A4F7", "%! c #14A6F9", "&! c #15A3FA", "*! c #18A9FB", "=! c #1BAEFA", "-! c #1CB3FC", ";! c #1EB5FB", ">! c #22B7FC", ",! c #23B8FB", "'! c #22B9FB", ")! c #22B8FB", "!! c #20B7FA", "~! c #1EB5F9", "{! c #1CB1F9", "]! c #1AB0F8", "^! c #18ABF6", "/! c #19A7F4", "(! c #18A1F1", "_! c #179AF0", ":! c #1595ED", "~ c #1586E8", ",~ c #1583E6", "'~ c #147BE1", ")~ c #1573DF", "!~ c #156FDD", "~~ c #146BDB", "{~ c #1466D6", "]~ c #1661D5", "^~ c #165DD3", "/~ c #155CD1", "(~ c #1657CF", "_~ c #1655CC", ":~ c #1653CB", "<~ c #1650CA", "[~ c #1750C9", "}~ c #174FCF", "|~ c #0C62E1", "1~ c #45ACF7", "2~ c #A8FBFF", "3~ c #77DDFD", "4~ c #196FE2", "5~ c #144BC6", "6~ c #1345BC", "7~ c #1142B8", "8~ c #103EB5", "9~ c #1243BC", "0~ c #103CB5", "a~ c #1040B7", "b~ c #1142BA", "c~ c #0F3EB6", "d~ c #0A2BA5", "e~ c #0A32AC", "f~ c #0A2AA2", "g~ c #082299", "h~ c #0120A7", "i~ c #0E44D2", "j~ c #5B91EF", "k~ c #B3D1F9", "l~ c #E9F3FE", "m~ c #FCFDFF", "n~ c #C9C5E1", "o~ c #C5C2E0", "p~ c #D6D3E9", "q~ c #DBD9EC", "r~ c #C9C6E2", "s~ c #BBB7DB", "t~ c #EDECF7", "u~ c #A8A3D1", "v~ c #948EC8", "w~ c #4E4B65", "x~ c #00002A", "y~ c #001DA3", "z~ c #0542D2", "A~ c #074FD9", "B~ c #0754DE", "C~ c #0971E6", "D~ c #0D95ED", "E~ c #0C80ED", "F~ c #0D84F0", "G~ c #16AAF6", "H~ c #1BB4F9", "I~ c #16A4FA", "J~ c #17A6FA", "K~ c #1CAFFC", "L~ c #22B6FC", "M~ c #27B9FD", "N~ c #2CBBFD", "O~ c #30BEFD", "P~ c #33BEFD", "Q~ c #34BFFE", "R~ c #34BEFD", "S~ c #31BCFD", "T~ c #2DBBFC", "U~ c #29BAFC", "V~ c #25B8FB", "W~ c #22B5FA", "X~ c #1EB2FA", "Y~ c #1BAFF8", "Z~ c #1AAAF6", "`~ c #19A4F4", " { c #1EADF5", ".{ c #23AFF3", "+{ c #1692EC", "@{ c #1687E8", "#{ c #1683E7", "${ c #167EE3", "%{ c #1678E1", "&{ c #1676DF", "*{ c #1670DD", "={ c #1669DA", "-{ c #1664D7", ";{ c #1762D6", ">{ c #1761D7", ",{ c #195ED5", "'{ c #1757D0", "){ c #1755CD", "!{ c #1752CC", "~{ c #1750CA", "{{ c #1852C9", "]{ c #184ECC", "^{ c #094FD5", "/{ c #2597EF", "({ c #65D2FE", "_{ c #115CE0", ":{ c #164EC9", "<{ c #1345BD", "[{ c #1342BA", "}{ c #1241B8", "|{ c #103FB6", "1{ c #103CB3", "2{ c #0E3AB1", "3{ c #0E42B8", "4{ c #0E41BB", "5{ c #0A32AD", "6{ c #002DB1", "7{ c #0022AD", "8{ c #0020B8", "9{ c #2259E0", "0{ c #76A8F2", "a{ c #C5DBF9", "b{ c #F1F7FE", "c{ c #D8D5EA", "d{ c #B8B4D9", "e{ c #A8A4CF", "f{ c #FDFCFF", "g{ c #BDB9DD", "h{ c #DEDDEF", "i{ c #D2CFE9", "j{ c #CECAE6", "k{ c #5A586D", "l{ c #000347", "m{ c #00108A", "n{ c #0339CA", "o{ c #074ED8", "p{ c #0752DA", "q{ c #0A74E7", "r{ c #0B81EC", "s{ c #0B77EE", "t{ c #0B7CEF", "u{ c #0F90F4", "v{ c #13A4F7", "w{ c #14A3F9", "x{ c #1BAFFB", "y{ c #28BAFD", "z{ c #2DBCFE", "A{ c #35BFFE", "B{ c #3BC0FE", "C{ c #3FC0FE", "D{ c #40C1FF", "E{ c #40C1FD", "F{ c #3CC0FD", "G{ c #36BFFE", "H{ c #2ABAFC", "I{ c #26B7FB", "J{ c #20B4FA", "K{ c #1DB0FA", "L{ c #1BACF8", "M{ c #1AA6F5", "N{ c #1AA0F2", "O{ c #1894EE", "P{ c #168DEA", "Q{ c #1786E8", "R{ c #1680E5", "S{ c #177BE3", "T{ c #1777E1", "U{ c #1772DF", "V{ c #176CDD", "W{ c #1767D9", "X{ c #1864D8", "Y{ c #1862D8", "Z{ c #185FD6", "`{ c #1859D2", " ] c #1756CF", ".] c #1856CF", "+] c #1856D0", "@] c #1854CD", "#] c #1645C2", "$] c #0356D8", "%] c #A0E5FD", "&] c #B3FBFF", "*] c #1985F6", "=] c #1B5BDB", "-] c #1A5FCE", ";] c #1651C2", ">] c #1140B9", ",] c #113FB7", "'] c #0F3AB0", ")] c #0F36AD", "!] c #0E3DB5", "~] c #1044BB", "{] c #0936B6", "]] c #0F4CCF", "^] c #4DB9F1", "/] c #60CDEF", "(] c #288BE1", "_] c #013ED5", ":] c #376AE4", "<] c #94BCF4", "[] c #D7E6FB", "}] c #EFF1FA", "|] c #ECE9F5", "1] c #E9E8F3", "2] c #D8D6EB", "3] c #D0CEE6", "4] c #BDB8DD", "5] c #CDCAE6", "6] c #CAC7E9", "7] c #605E71", "8] c #000012", "9] c #000971", "0] c #0127B7", "a] c #0646D3", "b] c #074ED7", "c] c #0758DC", "d] c #085FE1", "e] c #0967E5", "f] c #0A70E9", "g] c #0C85F2", "h] c #0F93F4", "i] c #119CF7", "j] c #14A2F9", "k] c #1AACFB", "l] c #1FB4FC", "m] c #25B9FD", "n] c #2DBBFD", "o] c #46C3FE", "p] c #4AC4FE", "q] c #4DC4FE", "r] c #4CC5FE", "s] c #46C3FF", "t] c #3FC1FE", "u] c #37BFFE", "v] c #2FBBFD", "w] c #28B8FC", "x] c #23B5FA", "y] c #1FB1FA", "z] c #1CAEF8", "A] c #1BA8F6", "B] c #19A2F4", "C] c #179BF1", "D] c #1895EF", "E] c #1890EC", "F] c #1789EA", "G] c #1782E8", "H] c #177DE6", "I] c #1777E3", "J] c #1774E0", "K] c #176FDE", "L] c #1869DC", "M] c #1866D9", "N] c #1861D7", "O] c #185ED5", "P] c #185BD4", "Q] c #1A5BD4", "R] c #1A5CD6", "S] c #1956D1", "T] c #1850CB", "U] c #184CC6", "V] c #0F48CC", "W] c #4EA8F4", "X] c #DDFBFF", "Y] c #35A7FB", "Z] c #1757DC", "`] c #1B59D0", " ^ c #164EC3", ".^ c #1242BA", "+^ c #113FB6", "@^ c #0D36B4", "#^ c #0435BE", "$^ c #0B4ED0", "%^ c #37BDF7", "&^ c #79FFFF", "*^ c #58CDFF", "=^ c #41D0FD", "-^ c #2DC5F9", ";^ c #1972E7", ">^ c #5485EA", ",^ c #AAC6F4", "'^ c #DFE7F8", ")^ c #F0F1F9", "!^ c #C8C5E2", "~^ c #AEAAD1", "{^ c #7972B3", "]^ c #A29DCD", "^^ c #D3CFE9", "/^ c #B5B1D9", "(^ c #AAA6D2", "_^ c #B5B1DA", ":^ c #AEA8D9", "<^ c #5D5A6F", "[^ c #00189E", "}^ c #053CCC", "|^ c #0749D2", "1^ c #0750D7", "2^ c #095FDE", "3^ c #0A6CE4", "4^ c #0A74EA", "5^ c #0C7FEE", "6^ c #0E8EF2", "7^ c #1098F5", "8^ c #13A7F9", "9^ c #18AFFA", "0^ c #1BB1FB", "a^ c #21B5FC", "b^ c #3CC0FE", "c^ c #47C3FE", "d^ c #51C5FE", "e^ c #56C7FE", "f^ c #59C8FE", "g^ c #57C8FE", "h^ c #51C7FF", "i^ c #48C3FE", "j^ c #3DC0FD", "k^ c #33BCFD", "l^ c #2CB9FC", "m^ c #26B6FB", "n^ c #21B3FA", "o^ c #1EAFF9", "p^ c #1CAAF7", "q^ c #1AA5F5", "r^ c #199FF2", "s^ c #1998F0", "t^ c #1892EE", "u^ c #188CEB", "v^ c #1886E9", "w^ c #187FE7", "x^ c #1879E5", "y^ c #1875E2", "z^ c #1870DF", "A^ c #186CDE", "B^ c #1867DC", "C^ c #1863D9", "D^ c #1960D6", "E^ c #195DD5", "F^ c #195BD5", "G^ c #195AD4", "H^ c #1958D3", "I^ c #1954CF", "J^ c #1953D0", "K^ c #1C5DD3", "L^ c #1853D1", "M^ c #298FF0", "N^ c #ADF9FF", "O^ c #3EB0FC", "P^ c #1658DE", "Q^ c #1954D1", "R^ c #174CC9", "S^ c #1447BF", "T^ c #1343BA", "U^ c #1140B8", "V^ c #0F3CBA", "W^ c #1165D8", "X^ c #4BACF0", "Y^ c #55DAFB", "Z^ c #27B3F1", "`^ c #1F77DC", " / c #0C49CE", "./ c #104FCF", "+/ c #1B7EE0", "@/ c #0A67E8", "#/ c #2564E6", "$/ c #75A0EC", "%/ c #B2C4EC", "&/ c #DDDFF2", "*/ c #DDDAED", "=/ c #D1CDE7", "-/ c #B2AFD7", ";/ c #A7A3CF", ">/ c #A8A3D0", ",/ c #BAB6DC", "'/ c #B8B4DA", ")/ c #9691C6", "!/ c #A6A1D5", "~/ c #5D5C6F", "{/ c #00023E", "]/ c #000C80", "^/ c #022EBE", "// c #0744CF", "(/ c #074FD4", "_/ c #0753D8", ":/ c #085ADD", "( c #000028", ",( c #00065F", "'( c #011DA8", ")( c #053CCA", "!( c #0746CD", "~( c #074FD3", "{( c #0856D8", "]( c #095EDD", "^( c #0A77E5", "/( c #0B7EE9", "(( c #0B77EB", "_( c #1093F3", ":( c #119CF5", "<( c #14A6F8", "[( c #1DB3FB", "}( c #24B6FC", "|( c #2DB9FD", "1( c #37BCFE", "2( c #45C1FE", "3( c #53C6FE", "4( c #5DC9FE", "5( c #66CDFF", "6( c #69CEFF", "7( c #65CCFF", "8( c #52C5FE", "9( c #45C1FD", "0( c #3ABFFD", "a( c #31BBFD", "b( c #29B6FB", "c( c #24B3FB", "d( c #1FB0FA", "e( c #1DACF8", "f( c #1BA1F3", "g( c #1A9BF2", "h( c #1995F0", "i( c #198FEC", "j( c #1A8EED", "k( c #1A8BED", "l( c #1981E8", "m( c #1979E5", "n( c #1973E3", "o( c #1A6EE0", "p( c #1A6BDF", "q( c #1A67DE", "r( c #1A63DB", "s( c #1B5ED7", "t( c #1B5CD5", "u( c #1A58D3", "v( c #1B59D4", "w( c #1B59D5", "x( c #1A57D2", "y( c #1A55D4", "z( c #1D76EE", "A( c #6AE1FF", "B( c #5CDDFE", "C( c #166CEA", "D( c #184ECD", "E( c #164BC5", "F( c #1445BD", "G( c #1447C0", "H( c #164BC3", "I( c #1551D3", "J( c #1E7FEE", "K( c #6ED4FD", "L( c #BCFAFF", "M( c #65CFF8", "N( c #094CC8", "O( c #0D39BB", "P( c #0E3BB6", "Q( c #0F41BD", "R( c #0A2DA8", "S( c #0A299F", "T( c #0329B0", "U( c #1951D7", "V( c #5D89E2", "W( c #9BA9DE", "X( c #C7C9E6", "Y( c #DAD7ED", "Z( c #F2F1F9", "`( c #D9D7EC", " _ c #DAD8ED", "._ c #B9B5DA", "+_ c #C0BBDE", "@_ c #A39ECC", "#_ c #A5A0CD", "$_ c #C1BCE3", "%_ c #000240", "&_ c #000E86", "*_ c #032EBF", "=_ c #0742C9", "-_ c #0750D1", ";_ c #0751D4", ">_ c #0853D7", ",_ c #0B6DE0", "'_ c #0D89E9", ")_ c #0B77E7", "!_ c #0B7BEB", "~_ c #0E89F0", "{_ c #0F97F2", "]_ c #11A1F7", "^_ c #14A8F9", "/_ c #18AEFA", "(_ c #25B6FC", "__ c #2DB9FE", ":_ c #46C1FE", "<_ c #52C4FE", "[_ c #5EC9FE", "}_ c #66CCFF", "|_ c #69CCFF", "1_ c #47C2FE", "2_ c #29B7FC", "3_ c #24B4FB", "4_ c #1BA7F6", "5_ c #1BA0F4", "6_ c #1B9CF2", "7_ c #1A97F0", "8_ c #1A90EE", "9_ c #1A8DEE", "0_ c #1B89EE", "a_ c #1A82EA", "b_ c #1A7CE7", "c_ c #1A75E4", "d_ c #1B71E2", "e_ c #1B6DE0", "f_ c #1A69DE", "g_ c #1B66DD", "h_ c #1B62DA", "i_ c #1B60D8", "j_ c #1B5DD7", "k_ c #1B5BD6", "l_ c #1C5BD6", "m_ c #1C5DD8", "n_ c #1C5CD7", "o_ c #1F65E5", "p_ c #26A1FA", "q_ c #9FEBFE", "r_ c #0F6FE9", "s_ c #184DCC", "t_ c #174EC7", "u_ c #1649C2", "v_ c #1649C4", "w_ c #1851CB", "x_ c #0A54DE", "y_ c #57CCFB", "z_ c #D7FFFF", "A_ c #65C9F8", "B_ c #1158D3", "C_ c #0E35B0", "D_ c #0E37AD", "E_ c #0D35AC", "F_ c #0D39B1", "G_ c #0D3BB3", "H_ c #0A29A0", "I_ c #06239B", "J_ c #0738C6", "K_ c #3568DC", "L_ c #6F87D5", "M_ c #ADB4DE", "N_ c #E2E2F1", "O_ c #E5E4F2", "P_ c #B2AED6", "Q_ c #C4C1E0", "R_ c #AFAAD8", "S_ c #524E68", "T_ c #000027", "U_ c #000660", "V_ c #011DA9", "W_ c #084BCA", "X_ c #095CD4", "Y_ c #0955D5", "Z_ c #0957D8", "`_ c #0A6AE0", " : c #0C74E4", ".: c #0B72E6", "+: c #0B7EEA", "@: c #0E8CEF", "#: c #109FF3", "$: c #12A4F5", "%: c #15A7F8", "&: c #18AEFB", "*: c #2CB9FD", "=: c #35BBFD", "-: c #41BFFE", ";: c #4EC2FE", ">: c #58C7FE", ",: c #60CAFF", "': c #63CBFF", "): c #5FC9FF", "!: c #4EC3FE", "~: c #43C1FE", "{: c #38BDFD", "]: c #2FB8FD", "^: c #28B6FC", "/: c #23B2FB", "(: c #1FAFFA", "_: c #1EACF8", ":: c #1CA7F7", "<: c #1BA2F5", "[: c #1B9EF4", "}: c #1B98F1", "|: c #1A85EB", "1: c #177DE9", "2: c #1977E7", "3: c #1A76E6", "4: c #1B73E4", "5: c #1B6EE2", "6: c #1B6BE0", "7: c #1B67DF", "8: c #1C64DD", "9: c #1C62DC", "0: c #1D60DB", "a: c #1C5DD9", "b: c #1D60DC", "c: c #1E62DF", "d: c #1F60DD", "e: c #1A5EE3", "f: c #339BF8", "g: c #D9FFFF", "h: c #87E0FD", "i: c #0E62DF", "j: c #184EC9", "k: c #1952CB", "l: c #184FC9", "m: c #174CC6", "n: c #174BC5", "o: c #0A45CC", "p: c #4FC4F4", "q: c #A6FEFF", "r: c #2F8EED", "s: c #1141B6", "t: c #0C32AA", "u: c #0C35AE", "v: c #557BD9", "w: c #98A6DC", "x: c #CCCBE8", "y: c #E0DEEE", "z: c #D1CEE8", "A: c #E9E8F5", "B: c #C7C4E1", "C: c #C1BDDF", "D: c #AAA6D5", "E: c #676675", "F: c #00023C", "G: c #000E82", "H: c #022BBC", "I: c #073DC3", "J: c #0743C7", "K: c #0850CF", "L: c #0953D3", "M: c #0958D7", "N: c #0A66DE", "O: c #0A6BE2", "P: c #0B75E7", "Q: c #0C80EA", "R: c #0D8CEE", "S: c #119BF2", "T: c #11A2F5", "U: c #14A8F8", "V: c #22B3FC", "W: c #29B6FD", "X: c #31B9FD", "Y: c #3BBDFE", "Z: c #46C0FE", "`: c #55C6FE", " < c #57C6FE", ".< c #55C5FE", "+< c #50C3FE", "@< c #47C1FE", "#< c #3CBDFD", "$< c #33BAFD", "%< c #2CB7FD", "&< c #27B4FC", "*< c #22B1FB", "=< c #1FAEFA", "-< c #1DABF8", ";< c #1DA6F6", ">< c #1CA1F5", ",< c #1C9FF3", "'< c #1B98F2", ")< c #1A91F0", "!< c #1B8CEE", "~< c #1A86EC", "{< c #1F87EC", "]< c #1F88EB", "^< c #1B79EA", "/< c #1B71E6", "(< c #1D70E4", "_< c #1E6EE3", ":< c #1D69E1", "<< c #1D67E0", "[< c #1D65DE", "}< c #1D62DC", "|< c #1D5EDA", "1< c #1E5ED9", "2< c #1E63DF", "3< c #1F62E4", "4< c #2065EA", "5< c #1C7DF7", "6< c #5CDBFF", "7< c #F4FFFF", "8< c #59C6FC", "9< c #1059DF", "0< c #194EC9", "a< c #1952CC", "b< c #1850CA", "c< c #164AC4", "d< c #1648C0", "e< c #1746C5", "f< c #0D7AE9", "g< c #8BF2FE", "h< c #78DBFA", "i< c #0F57D1", "j< c #1246BA", "k< c #0F37AC", "l< c #0D38B1", "m< c #062399", "n< c #0736C4", "o< c #4174E2", "p< c #98B4EC", "q< c #D8DFF4", "r< c #E0DDEF", "s< c #E2E0F1", "t< c #CECCE6", "u< c #CECBE6", "v< c #B6B2DD", "w< c #656374", "x< c #000021", "y< c #011BA2", "z< c #0536C3", "A< c #083DBF", "B< c #0741C5", "C< c #0745C9", "D< c #094FD0", "E< c #0958D6", "F< c #0B6EDF", "G< c #0C77E4", "H< c #0B73E5", "I< c #0C80E9", "J< c #0E8CED", "K< c #1096F1", "L< c #11A0F4", "M< c #13A8F8", "N< c #17ACFA", "O< c #1AAEFB", "P< c #1FB2FB", "Q< c #26B5FC", "R< c #2DB7FD", "S< c #34B9FE", "T< c #3DBDFE", "U< c #44BFFE", "V< c #49C1FE", "W< c #4AC2FE", "X< c #46C2FE", "Y< c #3EBFFD", "Z< c #36BAFD", "`< c #29B6FC", " [ c #22B0FB", ".[ c #1FADFA", "+[ c #1DAAF9", "@[ c #1CA7F8", "#[ c #1DA2F6", "$[ c #1B9DF3", "%[ c #1C97F1", "&[ c #1D91F0", "*[ c #1684EF", "=[ c #1F96F4", "-[ c #5FCDFC", ";[ c #4DEAFD", ">[ c #2BB0F9", ",[ c #1775EE", "'[ c #156BE7", ")[ c #1B69E3", "![ c #1E69E1", "~[ c #1E66DF", "{[ c #1E63DE", "][ c #1E61DC", "^[ c #1D61DC", "/[ c #2167E6", "([ c #207EF3", "_[ c #209FFD", ":[ c #3BD9FF", "<[ c #9EFEFF", "[[ c #F7FEFF", "}[ c #72D2FE", "|[ c #0F62E6", "1[ c #194DC9", "2[ c #184DC8", "3[ c #184CC7", "4[ c #164AC2", "5[ c #1747C1", "6[ c #0A4ED9", "7[ c #5FDCFD", "8[ c #89F1FD", "9[ c #0F55D0", "0[ c #113EB8", "a[ c #113CB0", "b[ c #1145B9", "c[ c #0C33A8", "d[ c #0C3AAC", "e[ c #042DB2", "f[ c #2662E2", "g[ c #87B2F4", "h[ c #CDDCF7", "i[ c #F1F2FA", "j[ c #FBFAFC", "k[ c #F6F7FB", "l[ c #F1F1F7", "m[ c #C2BFE1", "n[ c #A9A4D1", "o[ c #B1ACD9", "p[ c #5A576D", "q[ c #000B75", "r[ c #0228B9", "s[ c #073BC1", "t[ c #073CBD", "u[ c #0742C5", "v[ c #0949CA", "w[ c #0B61D8", "x[ c #0B70DF", "y[ c #0B6FE0", "z[ c #0B75E5", "A[ c #0C80E8", "B[ c #0E8CEB", "C[ c #0F96F0", "D[ c #119DF2", "E[ c #13A5F5", "F[ c #16A9F8", "G[ c #18ADFA", "H[ c #21B3FC", "I[ c #28B5FD", "J[ c #2EB7FD", "K[ c #33B9FD", "L[ c #39BBFE", "M[ c #3CBCFE", "N[ c #3FBEFE", "O[ c #41C0FE", "P[ c #3DBEFE", "Q[ c #34BAFD", "R[ c #2AB6FD", "S[ c #26B4FC", "T[ c #22B2FA", "U[ c #1EADF9", "V[ c #1EA9F8", "W[ c #1DA6F7", "X[ c #1EA2F6", "Y[ c #1B9BF2", "Z[ c #1B93F1", "`[ c #158BF2", " } c #0D89F4", ".} c #2BCCFC", "+} c #4AD1FE", "@} c #3CC6FD", "#} c #3EE5FF", "$} c #4BC3FD", "%} c #3DA4F6", "&} c #1C77ED", "*} c #1466E7", "=} c #1E66E1", "-} c #1E65DE", ";} c #1E64DF", ">} c #2065DF", ",} c #2063E2", "'} c #1E7DF6", ")} c #4FD0FF", "!} c #80F9FF", "~} c #99FFFF", "{} c #F7FFFF", "]} c #7FE2FD", "^} c #0E61E2", "/} c #1A4FCE", "(} c #194FCA", "_} c #194DC8", ":} c #184EC8", "<} c #174CC5", "[} c #1749C4", "}} c #144DD0", "|} c #2F9DF3", "1} c #A4F6FF", "2} c #2B97E7", "3} c #1042C0", "4} c #0F3BB2", "5} c #0F41BA", "6} c #0E3BB3", "7} c #0F3DB1", "8} c #0F42B2", "9} c #092A9F", "0} c #0628A2", "a} c #0E46D2", "b} c #5C91EC", "c} c #A9BEED", "d} c #E2E6F5", "e} c #E2E0EF", "f} c #AAA4D5", "g} c #666373", "h} c #000346", "i} c #00138F", "j} c #0434C1", "k} c #0841C0", "l} c #073DBE", "m} c #0842C3", "n} c #094AC9", "o} c #094FCF", "p} c #0B61D7", "q} c #0B68DC", "r} c #0B69DD", "s} c #0C75E3", "t} c #0C80E6", "u} c #0E8BEB", "v} c #0F95EF", "w} c #109BF2", "x} c #12A2F4", "y} c #15A7F6", "z} c #18ABF9", "A} c #1DB0FC", "B} c #22B3FB", "C} c #27B5FD", "D} c #2BB5FD", "E} c #2FB7FD", "F} c #31B8FD", "G} c #34BAFE", "H} c #34BBFE", "I} c #31B8FE", "J} c #25B4FC", "K} c #23B2FA", "L} c #21AFFA", "M} c #1EAEFA", "N} c #1EAAFA", "O} c #1DA4F6", "P} c #1EA0F5", "Q} c #1B9BF5", "R} c #179AF8", "S} c #26ABFA", "T} c #69D1FD", "U} c #53C7FD", "V} c #1884F9", "W} c #2FB3FB", "X} c #6FE9FF", "Y} c #7AE8FF", "Z} c #75D9FE", "`} c #439FF7", " | c #0E68EC", ".| c #1E65E6", "+| c #2065E0", "@| c #1F5FDF", "#| c #206CF0", "$| c #30B1FF", "%| c #BBFDFF", "&| c #FAFFFF", "*| c #D8FEFF", "=| c #51D1FE", "-| c #1962E9", ";| c #1B56D3", ">| c #1A54CF", ",| c #174DC7", "'| c #1848C4", ")| c #074DD9", "!| c #91DFFD", "~| c #54C8F7", "{| c #0C41BF", "]| c #113CB2", "^| c #0E3AB3", "/| c #0D39B2", "(| c #0C30A6", "_| c #0A2DA5", ":| c #08289F", "<| c #0634C0", "[| c #3772E6", "}| c #8DADEA", "|| c #C9D1EE", "1| c #DCD9ED", "2| c #8881BC", "3| c #8982BD", "4| c #A19BCF", "5| c #666473", "6| c #000023", "7| c #00075C", "8| c #011BA3", "9| c #0636BE", "0| c #083FBC", "a| c #0943C3", "b| c #0948C8", "c| c #0A50CD", "d| c #0A60D6", "e| c #0B61D9", "f| c #0B6ADD", "g| c #0C74E1", "h| c #0D7EE5", "i| c #0E88E9", "j| c #0F92ED", "k| c #1098F1", "l| c #119FF3", "m| c #13A3F4", "n| c #17A9F7", "o| c #19ADFA", "p| c #1BAFFA", "q| c #1EB0FB", "r| c #21B2FB", "s| c #25B3FC", "t| c #27B4FD", "u| c #29B4FD", "v| c #2AB5FE", "w| c #29B5FC", "x| c #27B5FC", "y| c #25B2FC", "z| c #23B1FA", "A| c #20AFFA", "B| c #1DA9F8", "C| c #1C9DF6", "D| c #25ADFD", "E| c #44D7FF", "F| c #74F8FF", "G| c #E3FFFF", "H| c #97FEFF", "I| c #26A0FB", "J| c #1C7AF1", "K| c #298AF3", "L| c #3796F6", "M| c #6AD1FF", "N| c #94F1FF", "O| c #74C7FC", "P| c #3098F9", "Q| c #2275F1", "R| c #2773EF", "S| c #0E80FC", "T| c #78DAFF", "U| c #F6FFFE", "V| c #EEF7FD", "W| c #6DFBFF", "X| c #2FB7FF", "Y| c #2472F7", "Z| c #1F63E0", "`| c #1B5AD5", " 1 c #1A56D0", ".1 c #1A53CF", "+1 c #1951CA", "@1 c #1343C4", "#1 c #B2EDFE", "$1 c #50AEF5", "%1 c #0C40C0", "&1 c #113EB5", "*1 c #0E3CB2", "=1 c #0F40B4", "-1 c #0B31A7", ";1 c #0B35AD", ">1 c #0A2EA4", ",1 c #092BA2", "'1 c #042BAF", ")1 c #1D57DD", "!1 c #739EEA", "~1 c #B9C7ED", "{1 c #DFE0F0", "]1 c #D7D6EC", "^1 c #EAEAF6", "/1 c #928CC4", "(1 c #A09ACD", "_1 c #D7D5EE", ":1 c #7A797E", "<1 c #0325B4", "[1 c #0735B6", "}1 c #0737B5", "|1 c #093DBC", "11 c #0945C4", "21 c #0948C6", "31 c #0A4FCC", "41 c #0C6BD9", "51 c #0B63D7", "61 c #0B68DB", "71 c #0C72E0", "81 c #0D7CE4", "91 c #0F88E9", "01 c #108FEB", "a1 c #1093EE", "b1 c #119AF1", "c1 c #129FF3", "d1 c #15A4F6", "e1 c #17A8F8", "f1 c #19ACF9", "g1 c #1BADFA", "h1 c #1DAFFA", "i1 c #20B4FC", "j1 c #22B2FB", "k1 c #23B1FC", "l1 c #24B2FB", "m1 c #21B0FA", "n1 c #1EADFA", "o1 c #1DABFA", "p1 c #1DA8F8", "q1 c #1DA6F8", "r1 c #1DA4F7", "s1 c #1D9EF5", "t1 c #1C9CF7", "u1 c #3ACCFE", "v1 c #55E2FE", "w1 c #42BEFC", "x1 c #79E7FF", "y1 c #6DCCFC", "z1 c #3DB0FA", "A1 c #2490F6", "B1 c #207CEE", "C1 c #1D72EC", "D1 c #186CEB", "E1 c #1C7EF5", "F1 c #8DE3FF", "G1 c #CDFFFF", "H1 c #28AEFF", "I1 c #1C8BFF", "J1 c #2FB3FF", "K1 c #54CAFF", "L1 c #DAF7FF", "M1 c #FFFEFE", "N1 c #E8F8FE", "O1 c #EEFEFF", "P1 c #74FFFF", "Q1 c #3DF4FF", "R1 c #2EA3FF", "S1 c #2B89FA", "T1 c #2475E8", "U1 c #1A50D5", "V1 c #184DCF", "W1 c #1B54D1", "X1 c #1C5AD4", "Y1 c #194FD2", "Z1 c #0A5ADE", "`1 c #78CBFB", " 2 c #BEFDFF", ".2 c #2383E6", "+2 c #1143C1", "@2 c #1040B5", "#2 c #1146B8", "$2 c #0E43B6", "%2 c #0A30A7", "&2 c #09289D", "*2 c #1048D4", "=2 c #598DEC", "-2 c #B1C8F1", ";2 c #F1F6FC", ">2 c #BAB7DB", ",2 c #9A95CA", "'2 c #A8A2D1", ")2 c #BFBBDE", "!2 c #6A6876", "~2 c #00138C", "{2 c #0432C0", "]2 c #0735B4", "^2 c #0734B2", "/2 c #0943C0", "(2 c #0A47C5", "_2 c #0A48C5", ":2 c #0C63D6", "<2 c #0B61D6", "[2 c #0B66D9", "}2 c #0C70DF", "|2 c #0E7BE3", "12 c #0F87E9", "22 c #108AEA", "32 c #118FEC", "42 c #1196EF", "52 c #139CF2", "62 c #14A1F4", "72 c #18A6F8", "82 c #18A9F9", "92 c #1AACF9", "02 c #1CB1FC", "a2 c #1DB1FB", "b2 c #1DAFFB", "c2 c #1EAFFA", "d2 c #1EAFFB", "e2 c #1EAEFB", "f2 c #1DAEFA", "g2 c #1DA9F9", "h2 c #1DA5F8", "i2 c #1EA4F8", "j2 c #1DA1F6", "k2 c #1D9BF6", "l2 c #21A3F9", "m2 c #36D4FE", "n2 c #2FBAFB", "o2 c #1686F7", "p2 c #1FA1FA", "q2 c #188FF5", "r2 c #197DF1", "s2 c #2280F1", "t2 c #237FF0", "u2 c #247AEE", "v2 c #2075EC", "w2 c #227AF0", "x2 c #9CDEFF", "y2 c #92ECFF", "z2 c #77DCFF", "A2 c #63E7FF", "B2 c #8EF8FF", "C2 c #C2FDFF", "D2 c #F8FEFE", "E2 c #FCF9FE", "F2 c #F8FEFF", "G2 c #A8FFFF", "H2 c #60F0FF", "I2 c #2DB1FF", "J2 c #1987FD", "K2 c #1C87F6", "L2 c #187FEE", "M2 c #116EE6", "N2 c #0B59DE", "O2 c #0E4FD8", "P2 c #0367EB", "Q2 c #55C4FC", "R2 c #4EB3F8", "S2 c #1157D6", "T2 c #1548C2", "U2 c #1142BB", "V2 c #1042B7", "W2 c #0C33AC", "X2 c #0E3FB6", "Y2 c #0C33AD", "Z2 c #072499", "`2 c #0837C1", " 3 c #3F79EA", ".3 c #9AB9EF", "+3 c #EBF2FC", "@3 c #E3E1F2", "#3 c #E3E0F1", "$3 c #C6C3E1", "%3 c #CAC6E9", "&3 c #55536A", "*3 c #000453", "=3 c #01189E", "-3 c #052EB8", ";3 c #0832AD", ">3 c #0938B5", ",3 c #0940BB", "'3 c #0A45C1", ")3 c #0A49C4", "!3 c #0B4FCA", "~3 c #0C5DD1", "{3 c #0B5DD4", "]3 c #0C64D8", "^3 c #0C6DDC", "/3 c #0E78E1", "(3 c #0F82E6", "_3 c #1086E9", ":3 c #118DEB", "<3 c #1191EE", "[3 c #1297F0", "}3 c #139BF2", "|3 c #149FF3", "13 c #17A3F5", "23 c #17A6F8", "33 c #18A8F8", "43 c #19AAF9", "53 c #1AABF9", "63 c #1BABF9", "73 c #1BACFA", "83 c #1CACFA", "93 c #1DABF9", "03 c #1EA7F9", "a3 c #1EA2F7", "b3 c #1E9EF6", "c3 c #1D9AF6", "d3 c #21A0F9", "e3 c #2BBAFE", "f3 c #24A2FA", "g3 c #208AF4", "h3 c #2089F4", "i3 c #2286F3", "j3 c #2384F1", "k3 c #2480F1", "l3 c #247EF1", "m3 c #247BF0", "n3 c #2377F0", "o3 c #2476EE", "p3 c #45A0F7", "q3 c #62BFFC", "r3 c #65B6FA", "s3 c #69D1F9", "t3 c #47ABF6", "u3 c #2C8AF9", "v3 c #4FD5FF", "w3 c #DFFFFF", "x3 c #DCFDFF", "y3 c #B2F7FF", "z3 c #8AEBFF", "A3 c #75EAFF", "B3 c #86EFFF", "C3 c #A3EBFE", "D3 c #81CCFA", "E3 c #53AEF9", "F3 c #71DDFE", "G3 c #208CF2", "H3 c #1349CA", "I3 c #1347BE", "J3 c #1244BC", "K3 c #103AB1", "L3 c #0A30A9", "M3 c #09289C", "N3 c #042BB1", "O3 c #2965E4", "P3 c #83AAED", "Q3 c #D4DFF6", "R3 c #E7E7F4", "S3 c #D6D5EB", "T3 c #DCD9F0", "U3 c #636172", "V3 c #000864", "W3 c #011DA7", "X3 c #0734B8", "Y3 c #0A3BB5", "Z3 c #093AB7", "`3 c #093CB9", " 4 c #0A40BC", ".4 c #0A46C1", "+4 c #0B52CB", "@4 c #0D5FD4", "#4 c #0B5BD1", "$4 c #0C62D5", "%4 c #0C6ADA", "&4 c #0E73DE", "*4 c #0F7CE2", "=4 c #0F81E5", "-4 c #108CE9", ";4 c #1292EE", ">4 c #1396F0", ",4 c #149BF1", "'4 c #169EF3", ")4 c #16A1F4", "!4 c #17A4F5", "~4 c #18A5F7", "{4 c #19A6F8", "]4 c #19A7F8", "^4 c #1AA7F9", "/4 c #1AA8F8", "(4 c #1BA8F8", "_4 c #1CA6F8", ":4 c #1DA7F8", "<4 c #1DA4F8", "[4 c #20A9F9", "}4 c #21A8F9", "|4 c #1E9FF7", "14 c #1E9CF6", "24 c #1F99F8", "34 c #22A1FC", "44 c #2AB0FF", "54 c #2599F9", "64 c #228AF4", "74 c #238AF4", "84 c #2488F4", "94 c #2485F3", "04 c #2582F3", "a4 c #257FF1", "b4 c #257CF1", "c4 c #2679F0", "d4 c #2677EF", "e4 c #2272EF", "f4 c #2170EE", "g4 c #236DEC", "h4 c #2470EA", "i4 c #236CE8", "j4 c #1F64EC", "k4 c #2A95F9", "l4 c #5FD2FF", "m4 c #83EBFF", "n4 c #62E3FF", "o4 c #65D2FF", "p4 c #8AE5FF", "q4 c #9AF9FF", "r4 c #9FFCFF", "s4 c #9CF6FF", "t4 c #99E2FF", "u4 c #75CCFB", "v4 c #39ACF4", "w4 c #1B65DE", "x4 c #164AC5", "y4 c #113FB5", "z4 c #103BB1", "A4 c #103EB6", "B4 c #0A2FA8", "C4 c #0633B4", "D4 c #1953DB", "E4 c #6692E6", "F4 c #BBCAEE", "G4 c #EBEBF6", "H4 c #E5E4F3", "I4 c #F8F7FA", "J4 c #7C7B7F", "K4 c #000C75", "L4 c #0224B2", "M4 c #0937B3", "N4 c #0A42BA", "O4 c #0939B5", "P4 c #0A40BB", "Q4 c #0A43BF", "R4 c #0B4FC8", "S4 c #0D5DD1", "T4 c #0C59CF", "U4 c #0C5FD3", "V4 c #0C68D8", "W4 c #0E71DD", "X4 c #0F76E0", "Y4 c #0F7CE3", "Z4 c #1082E7", "`4 c #1087E9", " 5 c #128DEB", ".5 c #1390EE", "+5 c #1394F0", "@5 c #1498F1", "#5 c #169CF2", "$5 c #179EF3", "%5 c #17A0F4", "&5 c #19A4F6", "*5 c #1AA4F6", "=5 c #1AA6F8", "-5 c #1BA6F8", ";5 c #1CA4F7", ">5 c #1CA3F7", ",5 c #1DA2F7", "'5 c #1FA0F8", ")5 c #1E9BF6", "!5 c #1E98F7", "~5 c #25AEFC", "{5 c #36CCFF", "]5 c #2EB4FF", "^5 c #2393FA", "/5 c #238BF5", "(5 c #248AF5", "_5 c #2587F5", ":5 c #2585F4", "<5 c #2682F4", "[5 c #267FF3", "}5 c #267DF2", "|5 c #277AF1", "15 c #2778F1", "25 c #2774EF", "35 c #2672ED", "45 c #2570EC", "55 c #246CEA", "65 c #266CE9", "75 c #256CEB", "85 c #2372F1", "95 c #268EFC", "05 c #44C0FF", "a5 c #C9F6FF", "b5 c #B8F6FF", "c5 c #2DAFFF", "d5 c #2383FC", "e5 c #2E99FB", "f5 c #2893F8", "g5 c #2280F2", "h5 c #2E91F1", "i5 c #2680E6", "j5 c #1960DA", "k5 c #1454D4", "l5 c #144DCB", "m5 c #164AC3", "n5 c #1445BC", "o5 c #0F3CB4", "p5 c #0D37AF", "q5 c #0A2FA5", "r5 c #082EAB", "s5 c #0E43CF", "t5 c #5386E7", "u5 c #9FB3E6", "v5 c #C4C4E3", "w5 c #CCCAE5", "x5 c #B7B3DA", "y5 c #D4D0EA", "z5 c #808181", "A5 c #00023B", "B5 c #001083", "C5 c #0328B5", "D5 c #082FAA", "E5 c #0931AE", "F5 c #0934AF", "G5 c #0A3CB7", "H5 c #0A43BE", "I5 c #0B43BF", "J5 c #0B49C3", "K5 c #0C58CC", "L5 c #0C57CD", "M5 c #0C5ED1", "N5 c #0D65D6", "O5 c #0F6EDB", "P5 c #0F73DF", "Q5 c #1078E1", "R5 c #107EE4", "S5 c #1287E9", "T5 c #128BEB", "U5 c #138EEC", "V5 c #1493F0", "W5 c #1596F1", "X5 c #1699F2", "Y5 c #179AF3", "Z5 c #179DF4", "`5 c #189EF4", " 6 c #199FF5", ".6 c #1AA0F5", "+6 c #1BA2F6", "@6 c #1CA2F7", "#6 c #1BA0F6", "$6 c #1C9FF6", "%6 c #1D9DF5", "&6 c #1D9CF6", "*6 c #1E9AF6", "=6 c #1E98F6", "-6 c #1B99F7", ";6 c #52D2FF", ">6 c #B1FEFF", ",6 c #44CDFE", "'6 c #1A8BF9", ")6 c #248AF6", "!6 c #258AF7", "~6 c #2688F6", "{6 c #2686F5", "]6 c #2783F5", "^6 c #277FF4", "/6 c #277DF4", "(6 c #277AF2", "_6 c #2779F1", ":6 c #2776F1", "<6 c #2771ED", "[6 c #276EEB", "}6 c #2871EC", "|6 c #2872EE", "16 c #266EEC", "26 c #256AE7", "36 c #256DED", "46 c #1F6DF4", "56 c #43ABFA", "66 c #DBFDFF", "76 c #A4ECFF", "86 c #1F85F7", "96 c #1B5DE6", "06 c #1E5FE1", "a6 c #1C5BDA", "b6 c #1954D3", "c6 c #1750CF", "d6 c #1850CD", "e6 c #174FCA", "f6 c #1648C1", "g6 c #1344BD", "h6 c #1045BB", "i6 c #0C32A8", "j6 c #0938C3", "k6 c #437AE7", "l6 c #88A0DF", "m6 c #BBBCE1", "n6 c #DAD7EB", "o6 c #D9D8ED", "p6 c #DCDAEE", "q6 c #7F7E80", "r6 c #00148F", "s6 c #042AB3", "t6 c #082EA7", "u6 c #0932AE", "v6 c #0A35B0", "w6 c #0A39B5", "x6 c #0B40BA", "y6 c #0B43BE", "z6 c #0B48C1", "A6 c #0F5ECE", "B6 c #0D57CD", "C6 c #0D5ACE", "D6 c #0E62D4", "E6 c #0F69D9", "F6 c #106EDD", "G6 c #1073DF", "H6 c #1077E1", "I6 c #107CE4", "J6 c #1284E8", "K6 c #148DEB", "L6 c #138CEB", "M6 c #148CEC", "N6 c #158FEE", "O6 c #1693F0", "P6 c #1795F0", "Q6 c #1797F2", "R6 c #1899F2", "S6 c #199AF3", "T6 c #199CF4", "U6 c #1B9CF4", "V6 c #1B9CF5", "W6 c #1B9AF5", "X6 c #1C9AF5", "Y6 c #1D98F5", "Z6 c #1E96F5", "`6 c #1E95F5", " 7 c #1A90F6", ".7 c #2EB1FC", "+7 c #CCF5FF", "@7 c #22B0FE", "#7 c #2088F8", "$7 c #2589F8", "%7 c #2787F7", "&7 c #2785F7", "*7 c #2883F6", "=7 c #2881F6", "-7 c #287FF5", ";7 c #287CF3", ">7 c #2979F2", ",7 c #2877F1", "'7 c #2875F1", ")7 c #2873EE", "!7 c #2770EC", "~7 c #276EEA", "{7 c #256CE9", "]7 c #256BE8", "^7 c #2468E5", "/7 c #2465E6", "(7 c #1E77F2", "_7 c #51C1FE", ":7 c #D2F5FF", "<7 c #A1E8FF", "[7 c #2483F0", "}7 c #175ADF", "|7 c #1D5AD7", "17 c #1B56D2", "27 c #1A54D0", "37 c #1952CD", "47 c #1548BF", "57 c #1245BA", "67 c #134BBE", "77 c #0B2FA5", "87 c #07259B", "97 c #0732BA", "07 c #3772E9", "a7 c #C0C4E7", "b7 c #CFCAE6", "c7 c #E5E4F1", "d7 c #D4D2EA", "e7 c #00001A", "f7 c #000450", "g7 c #011C9B", "h7 c #0736BC", "i7 c #0D40B3", "j7 c #0C3FB6", "k7 c #0A34B0", "l7 c #0A37B2", "m7 c #0B3DB7", "n7 c #0C48C1", "o7 c #0B47C0", "p7 c #0D53CA", "q7 c #0E58CC", "r7 c #0E5FD2", "s7 c #1065D5", "t7 c #106BDB", "u7 c #1177E2", "v7 c #1588EA", "w7 c #1790ED", "x7 c #1487EB", "y7 c #1487EA", "z7 c #168BEC", "A7 c #178DEC", "B7 c #178FEE", "C7 c #1892F0", "D7 c #1894F1", "E7 c #1995F1", "F7 c #1B97F3", "G7 c #1B96F4", "H7 c #1C96F4", "I7 c #1D96F4", "J7 c #1E96F4", "K7 c #1E98F8", "L7 c #1A98F9", "M7 c #40BFFD", "N7 c #ABEFFF", "O7 c #149FFD", "P7 c #2486F9", "Q7 c #278AF8", "R7 c #2788F9", "S7 c #2887F9", "T7 c #2885F8", "U7 c #2983F9", "V7 c #2982F8", "W7 c #2A7FF6", "X7 c #2A7CF5", "Y7 c #2A7AF4", "Z7 c #2978F2", "`7 c #2975F1", " 8 c #2973F0", ".8 c #2771EE", "+8 c #2568E7", "@8 c #2466E3", "#8 c #2467E5", "$8 c #2875EE", "%8 c #1E71F4", "&8 c #318CF6", "*8 c #A9EDFE", "=8 c #A7F1FF", "-8 c #2484F2", ";8 c #1557DE", ">8 c #1D58D3", ",8 c #1A51CD", "'8 c #1A52CE", ")8 c #1955D0", "!8 c #1647C1", "~8 c #1445BE", "{8 c #1346BD", "]8 c #1143B9", "^8 c #1142B9", "/8 c #092EA5", "(8 c #062DB1", "_8 c #235BDD", ":8 c #7B9EE5", "<8 c #CCD5F0", "[8 c #BCB7DB", "}8 c #BBB6DB", "|8 c #78787D", "18 c #000657", "28 c #0122A4", "38 c #0839B9", "48 c #1146B5", "58 c #0D3FB6", "68 c #0931AF", "78 c #0A38B2", "88 c #0B3DB6", "98 c #0C43BC", "08 c #0C45BE", "a8 c #0E55CA", "b8 c #0F5BD0", "c8 c #1061D4", "d8 c #1068D8", "e8 c #106BDA", "f8 c #116FDD", "g8 c #1274DF", "h8 c #1686E8", "i8 c #1586EA", "j8 c #147EE7", "k8 c #1581E8", "l8 c #1685E9", "m8 c #1689EB", "n8 c #178AEC", "o8 c #178CEE", "p8 c #198FEF", "q8 c #1990F0", "r8 c #1B92F1", "s8 c #1B91F1", "t8 c #1B92F2", "u8 c #1D92F3", "v8 c #1D8FF3", "w8 c #209AF5", "x8 c #2FB8F9", "y8 c #4ED2FE", "z8 c #5EDFFF", "A8 c #59E7FF", "B8 c #8DE4FF", "C8 c #64D9FF", "D8 c #1F99FC", "E8 c #2586F8", "F8 c #278AFA", "G8 c #2788FA", "H8 c #2987F9", "I8 c #2985F9", "J8 c #2A84FA", "K8 c #2B81F9", "L8 c #2A7FF8", "M8 c #2A7DF6", "N8 c #2A7BF5", "O8 c #2A79F4", "P8 c #2A76F2", "Q8 c #2A74F1", "R8 c #2973EF", "S8 c #266CEA", "T8 c #2569E7", "U8 c #2567E4", "V8 c #266FEB", "W8 c #256DE9", "X8 c #165DE5", "Y8 c #2486F2", "Z8 c #BEF5FF", "`8 c #AFE1FF", " 9 c #2384F5", ".9 c #1A5FE1", "+9 c #1C55D1", "@9 c #1A54CE", "#9 c #1B5BD7", "$9 c #1950CC", "%9 c #1649C3", "&9 c #1546BF", "*9 c #1446BF", "=9 c #1240B7", "-9 c #0A2DA4", ";9 c #0B3DB1", ">9 c #2058DC", ",9 c #739AE6", "'9 c #B3BDE5", ")9 c #A39CCB", "!9 c #B8B2D8", "~9 c #FAF9F9", "{9 c #78797D", "]9 c #00075E", "^9 c #0120A6", "/9 c #0830B0", "(9 c #0932AC", "_9 c #0931AC", ":9 c #0B39B2", "<9 c #0D43BC", "[9 c #0C47C0", "}9 c #0C48BF", "|9 c #0E4CC4", "19 c #105ACF", "29 c #105FD3", "39 c #1163D5", "49 c #1067D7", "59 c #116BDB", "69 c #116EDD", "79 c #1374E1", "89 c #1378E3", "99 c #1479E4", "09 c #157CE7", "a9 c #167FE8", "b9 c #1783E9", "c9 c #1786EB", "d9 c #198AED", "e9 c #198BEE", "f9 c #198BEF", "g9 c #1B8CEF", "h9 c #1B8CF0", "i9 c #1B8CF2", "j9 c #1D8EF2", "k9 c #1D8CF2", "l9 c #1E94F4", "m9 c #31AFF9", "n9 c #6FD1FC", "o9 c #85DDFD", "p9 c #26A3FC", "q9 c #1294FC", "r9 c #22A6FF", "s9 c #2C93FD", "t9 c #2787FA", "u9 c #2A89FA", "v9 c #2A88FA", "w9 c #2A87FA", "x9 c #2B85FA", "y9 c #2C83FA", "z9 c #2C82FA", "A9 c #2C81FA", "B9 c #2C7FF9", "C9 c #2B7CF7", "D9 c #2B7AF4", "E9 c #2A78F1", "F9 c #2A73F2", "G9 c #2972F0", "H9 c #2871EE", "I9 c #266DEA", "J9 c #2568E4", "K9 c #2567E5", "L9 c #256CE8", "M9 c #2467E4", "N9 c #2363E3", "O9 c #1664E8", "P9 c #50B3FC", "Q9 c #E9FFFF", "R9 c #8CDFFF", "S9 c #1677EE", "T9 c #1A52D5", "U9 c #1951CC", "V9 c #1A52CF", "W9 c #194FCB", "X9 c #174AC3", "Y9 c #1646C0", "Z9 c #1243B9", "`9 c #0E39AF", " 0 c #0E37AF", ".0 c #0A32A8", "+0 c #0428AA", "@0 c #215DE0", "#0 c #7AA9F3", "$0 c #A5B0E0", "%0 c #C1BCDE", "&0 c #E7E6F2", "*0 c #F7F6FA", "=0 c #828282", "-0 c #072BAA", ";0 c #0929A1", ">0 c #092DA6", ",0 c #0931AA", "'0 c #0B35AE", ")0 c #0B38B0", "!0 c #0D41B9", "~0 c #0D45BE", "{0 c #0E47BD", "]0 c #0E4BC2", "^0 c #0F50C7", "/0 c #1057CC", "(0 c #115CD1", "_0 c #115ED2", ":0 c #1162D5", "<0 c #1167D8", "[0 c #136BDB", "}0 c #136DDD", "|0 c #1371DF", "10 c #1475E1", "20 c #1678E5", "30 c #167BE6", "40 c #177DE8", "50 c #1780E9", "60 c #1984EB", "70 c #1985EC", "80 c #1985ED", "90 c #1B87ED", "00 c #1B88EF", "a0 c #1C89F0", "b0 c #1D8AF1", "c0 c #1F8BF2", "d0 c #1F89F2", "e0 c #1C83F4", "f0 c #1B87F5", "g0 c #2289F7", "h0 c #2082F6", "i0 c #2588F8", "j0 c #288CFB", "k0 c #298AFA", "l0 c #2988FA", "m0 c #2A89FC", "n0 c #2C87FB", "o0 c #2C86FB", "p0 c #2D85FB", "q0 c #2D84FB", "r0 c #2D83FB", "s0 c #2E85FC", "t0 c #2E82FB", "u0 c #2C7EF9", "v0 c #2B7AF7", "w0 c #2B79F6", "x0 c #2C7CF9", "y0 c #2E81FB", "z0 c #2D7EFA", "A0 c #2A74F4", "B0 c #2873EF", "C0 c #2567E6", "D0 c #2364E1", "E0 c #2362E1", "F0 c #2366E3", "G0 c #1F63E7", "H0 c #1C88F5", "I0 c #A4F1FF", "J0 c #C3FAFF", "K0 c #208DF3", "L0 c #154ED6", "M0 c #1A50CC", "N0 c #184DC7", "O0 c #174BC4", "P0 c #1648C2", "Q0 c #1446BD", "R0 c #103FB7", "S0 c #0E36AF", "T0 c #0A2AA0", "U0 c #09269B", "V0 c #0425A3", "W0 c #1951D9", "X0 c #6F9FEF", "Y0 c #BBCBEF", "Z0 c #C2BFDF", "`0 c #DAD8EC", " a c #EFEEF8", ".a c #E8E5F7", "+a c #000029", "@a c #000968", "#a c #0123AE", "$a c #082FAC", "%a c #092AA0", "&a c #0A31AB", "*a c #0B36AF", "=a c #0C3BB3", "-a c #0D3FB7", ";a c #0E46BD", ">a c #0F49BF", ",a c #0F4CC4", "'a c #1052C7", ")a c #115ACE", "!a c #125DD2", "~a c #1262D5", "{a c #1267D8", "]a c #156DDE", "^a c #166FDF", "/a c #1673E1", "(a c #1676E4", "_a c #1779E6", ":a c #187BE7", "b c #1A7EEA", ",b c #1B7FEB", "'b c #1C7FED", ")b c #1E81EF", "!b c #1E81F0", "~b c #1F82F1", "{b c #2284F1", "]b c #2385F2", "^b c #2485F4", "/b c #2586F5", "(b c #2686F7", "_b c #2785F8", ":b c #2886F9", "c c #2B85FB", ",c c #2E87FF", "'c c #3087FF", ")c c #3083FD", "!c c #328BFF", "~c c #389FFF", "{c c #4AD5FF", "]c c #5CFCFF", "^c c #53F4FF", "/c c #3EC4FF", "(c c #3497FF", "_c c #2C79F9", ":c c #276FEC", "d c #4FD9FF", ",d c #E9FEFF", "'d c #CFF9FF", ")d c #319AF2", "!d c #124DD5", "~d c #1A50CD", "{d c #1647C0", "]d c #1443BB", "^d c #1241BA", "/d c #154FC2", "(d c #1245BC", "_d c #0C34AA", ":d c #0D38AE", "e c #000863", ",e c #0326AB", "'e c #0A3CB8", ")e c #0B2FA9", "!e c #0B30A8", "~e c #0D35AD", "{e c #0E3BB2", "]e c #1042B9", "^e c #1146BE", "/e c #124AC2", "(e c #124CC5", "_e c #134EC7", ":e c #1451C9", "f c #1D6BE3", ",f c #1E6DE5", "'f c #206FE7", ")f c #2272E9", "!f c #2374EB", "~f c #2475ED", "{f c #2577EF", "]f c #2678F1", "^f c #277AF3", "/f c #287AF3", "(f c #297AF3", "_f c #2A7CF4", ":f c #2A7CF6", "g c #2F85FF", ",g c #2F84FF", "'g c #308AFF", ")g c #37A7FF", "!g c #38C5FF", "~g c #5DE9FF", "{g c #89F7FF", "]g c #69ECFF", "^g c #99F7FE", "/g c #BADAF8", "(g c #5DA1EC", "_g c #1767DE", ":g c #1C53D5", "h c #A1A6D7", ",h c #B0ABD3", "'h c #A6A2D0", ")h c #ABA6D3", "!h c #B9B4DA", "~h c #D3D1EA", "{h c #EFEDF7", "]h c #75747C", "^h c #01148E", "/h c #0A3BBD", "(h c #0C36A7", "_h c #092BA3", ":h c #0C38B3", "i c #2165E1", ",i c #2369E4", "'i c #246BE7", ")i c #256DE8", "!i c #266EE9", "~i c #2670EB", "{i c #2874EF", "]i c #2974F1", "^i c #2B78F3", "/i c #2C7AF7", "(i c #2D7BFA", "_i c #288EFF", ":i c #55D5FF", "j c #2A7AF7", ",j c #2B7DFC", "'j c #28A1FF", ")j c #75ECFF", "!j c #C7E5FB", "~j c #2472E4", "{j c #1D59D8", "]j c #1E5BD6", "^j c #1C56D2", "/j c #1B55D1", "(j c #1C5AD6", "_j c #1C5FDB", ":j c #1852CE", "k c #255CC2", ",k c #052AAB", "'k c #1447D1", ")k c #5074D4", "!k c #6E77BF", "~k c #9D98C9", "{k c #B9B6DB", "]k c #DAD9EC", "^k c #EFEFF8", "/k c #F8F8F9", "(k c #818082", "_k c #000451", ":k c #001698", "l c #2886FE", ",l c #2B76F5", "'l c #2971EF", ")l c #276CE9", "!l c #266CE8", "~l c #1A69F2", "{l c #5ED2FF", "]l c #42BAFE", "^l c #226FF5", "/l c #236CEA", "(l c #1E5ADD", "_l c #1C55DD", ":l c #124FDA", "m c #1145D1", ",m c #5484E5", "'m c #8192D3", ")m c #9693C8", "!m c #AFAAD5", "~m c #CDCAE5", "{m c #EEECF8", "]m c #00065C", "^m c #011AA1", "/m c #0628A9", "(m c #09299C", "_m c #0A2FA9", ":m c #0B31AA", "n c #C0FDFF", ",n c #9CFFFF", "'n c #53FCFF", ")n c #9BFFFF", "!n c #9BE6FF", "~n c #2888ED", "{n c #1052D4", "]n c #0F4CCB", "^n c #1148C7", "/n c #1142C3", "(n c #1048C8", "_n c #0F48C7", ":n c #0F44C4", "o c #E8FDFF", ",o c #83D3F8", "'o c #0C56DB", ")o c #174CCB", "!o c #1344BB", "~o c #1043BA", "{o c #0D35AE", "]o c #052DB4", "^o c #1D51D4", "/o c #5B7AD2", "(o c #9EA9DC", "_o c #938FC5", ":o c #C5C1E0", "p c #61CDFF", ",p c #B5F9FF", "'p c #309FF6", ")p c #1A5BDE", "!p c #1E5CD7", "~p c #1E57D5", "{p c #1556D9", "]p c #63D0F8", "^p c #9AEFFE", "/p c #156AE9", "(p c #1649C1", "_p c #1646BF", ":p c #0C39AD", "

q c #4B5CB4", ",q c #8486C4", "'q c #D8D5EB", ")q c #B4B1D7", "!q c #CAC6E3", "~q c #DAD9EB", "{q c #706E78", "]q c #000351", "^q c #00179D", "/q c #0529AF", "(q c #09299D", "_q c #0E3CB3", ":q c #1146BD", "r c #319AF7", ",r c #B1F2FF", "'r c #A9F8FF", ")r c #3094F0", "!r c #134AC9", "~r c #1343BC", "{r c #0D34AC", "]r c #0E42B6", "^r c #0B30AA", "/r c #0326A8", "(r c #0839C7", "_r c #3A64CF", ":r c #8195D7", "s c #1A4FCA", ",s c #1348CB", "'s c #1452D2", ")s c #3990EC", "!s c #8DF1FF", "~s c #BCF2FD", "{s c #96DCF7", "]s c #50ADF0", "^s c #1952DF", "/s c #035ADF", "(s c #58B4F5", "_s c #CCFFFF", ":s c #7CD4FE", "t c #DAFBFF", ",t c #2EBAFB", "'t c #1358DD", ")t c #134BC8", "!t c #0D50D5", "~t c #1E77E8", "{t c #A1E0FE", "]t c #68F7FF", "^t c #E7FFFF", "/t c #81F5FF", "(t c #1C9BF8", "_t c #1451D4", ":t c #1448C1", "u c #98E5FF", ",u c #DEFDFF", "'u c #349FF4", ")u c #0C58DB", "!u c #174ECC", "~u c #1348C2", "{u c #0F3BB4", "]u c #0C2FA6", "^u c #0A2DA6", "/u c #0629A6", "(u c #0839C6", "_u c #275AD7", ":u c #6689D9", "v c #0A39BB", ",v c #103FB4", "'v c #0F40B8", ")v c #123FB0", "!v c #1F53BE", "~v c #1249BB", "{v c #0A33AA", "]v c #0732AF", "^v c #083ACA", "/v c #275EDB", "(v c #688FDE", "_v c #AEC4EE", ":v c #ABAFD8", "w c #71F1FF", ",w c #6FD0FB", "'w c #0562DC", ")w c #103FBC", "!w c #082EA8", "~w c #0226A8", "{w c #0E43D1", "]w c #3E7CED", "^w c #86B2F3", "/w c #C2D8F9", "(w c #DCE3F4", "_w c #EDEBF6", ":w c #F4F5F9", "x c #ABFFFF", ",x c #40B0F7", "'x c #074AD6", ")x c #1040BB", "!x c #08259A", "~x c #02219F", "{x c #0332C0", "]x c #215FE5", "^x c #5D95F1", "/x c #9ABDF4", "(x c #CEDEF8", "_x c #F0F5FE", ":x c #E8E9F4", "y c #0A30AA", ",y c #092799", "'y c #052296", ")y c #0022A3", "!y c #0534C3", "~y c #1F5BE1", "{y c #518BF0", "]y c #8DB7F6", "^y c #C0D7F9", "/y c #E3EEFC", "(y c #F8FBFF", "_y c #F9FAFD", ":y c #F9F9FB", "z c #3672E9", ",z c #669BF2", "'z c #99C0F6", ")z c #C6DCF9", "!z c #E4EEFD", "~z c #F3F6FC", "{z c #D9D8E8", "]z c #CAC8DF", "^z c #E0DDF0", "/z c #858484", "(z c #000865", "_z c #000E85", ":z c #081BA8", "A c #00034D", ",A c #000866", "'A c #000E80", ")A c #001696", "!A c #011DA6", "~A c #0222B1", "{A c #093FC4", "]A c #0E5CD8", "^A c #0933BC", "/A c #092FAD", "(A c #0B3EB8", "_A c #0B3CB6", ":A c #0A30AD", "B c #B1C3EE", ",B c #D6E5FA", "'B c #E7EFFC", ")B c #EAEEF8", "!B c #F6F6FC", "~B c #FAF8FC", "{B c #FBFAFA", "]B c #00002F", "^B c #000034", "/B c #000035", "(B c #303F93", "_B c #647FD3", ":B c #6680D0", "C c #E1DEF1", ",C c #DFDDF0", "'C c #C0BCDE", ")C c #CCCAE6", "!C c #D5D1EF", "~C c #6D6B77", "{C c #65618A", "]C c #D4D1F0", "^C c #DEDAEE", "/C c #E1DFF2", "(C c #D5D2EE", "_C c #737179", ":C c #615D89", " , , ' - ) ! * ~ { ] ~ ^ / ( ( _ _ : < ^ - [ > } | < ~ 1 2 ~ / ' 3 4 5 ( 6 % 7 6 ~ _ 5 % 8 : 9 . . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 a b c d e f g h i j k l m n o p q r s t u v w x y x z A B C D E F G H I J K L M N O P Q R S T U V W z X Y Z y ` .. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(.(.(._.:.%.<.[.}.|.1.2.(.3.@.%.4.5.6.7.8.(.9.0.a.b.(.(.(.(.(.(.[.(.(.c.d.. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e.f.g.h.i.c.j.k.l.m.n.o.p.q.r.s.o.t.u.v.w.c.(.(.x.y.m z.A.B.B.z.c.C.D.E.F.G.H.I.J.K.(.(.j.L.M.N.O.P.(.P.K.O.Q.R.S. .. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . T.U.E V.W.P.X.Y.Z.`. +t .+j ++@+#+$+k.%+&+(.(.*+=+C -+++;+*+>+,+'+)+!+~+{+]+O.B ^+(.(.(.R.z (.#+/+(+(._+N.(.:+<+[+}+. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . |+1+O.<+2+3+>+4+5+6+7+8+9+k R 0+(.B M R.a+b+c.O.G._+c+J d+e+f+g+h+i+O.I V.j+k+l+K.m+(.(.(.(.N.O.Y n+G.N.K.o+p+q+r+s+. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . t+u+m+v+w+x+u.y+z+A+B+C+D+E+F+G+H+I+=+(.r.J+m+(.m+K+L+*+N.&+M+k+f N+O+P+N.Q+j.R.(.(.(.(.(.I+R+N.N.S+l+N.T+U+P+]+V+W+. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X+Y+Z+`+k.:+Y.m. @.@+@@@#@$@%@&@*@=@(.@+-@B (.(.B ;@P.c+>@,@'@(.)@!@++~@(.{@]@(.(.(.(.(.(.B P.(.(.N.@+N.^@m+O./@(@_@. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . :@<@[@}@K.x.|@1@2@3@K 4@5@6@7@8@9@i J 0@a@(.(.(.m+(.b@c@K.(.d@e@f@R.g@6+h@i@G.(.(.(.(.(.(.(.(.R.B (.(.(.(.l+j@%+k@l@. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m@n@o@p@(.B q@r@K s@t@u@v@w@x@y@z@A@B@C@D@E@(.(.m+B F@G@c.S O.H@I j.I@J@K@a+'@(.(.(.(.(.(.(.(.m+m+(.(.(.(.L@R+M@N@O@. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P@Q@R@S@T@U@V@W@X@Y@Z@`@ #.#+#@###$#%#&#*#=#-#;#J@>#,#'#)#!#~#{#]#N.(.b@=+(.m+(.I+^#/#(#_#:#<#(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.c.[#}#|#1#. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2#S@W@3#4#5#6#7#8#9#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#:+t#u#v#w#x#y#(.(.(.(.(.m+(+z#A#B#C#D#(.(.B N.(.(.(.(.(.(.(.(.(.(.(.(.O.E#F#G#. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P@H#I#J#K#6#8#L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#`# $.$+$@$#$$$%$&$*$=$-$;$P b >$,$'$)$!$~$G.S B R.m+{$]$^$/$G+(.(.(.m+(.(.(.(.(.(.(.(.(.(.m+(.(.m+(.($_$. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R@:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$O w$x$>$Y.y$z$2+;+q+G.(.A$p@A 0+R.c.(.(.(.(.N.(.(.(.(.(.(.=+]+B$/+(.B N.C$D$. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P@H#W@E$6#F$G$H$I$J$K$L$M$N$O$P$(.Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%#%$%%%&%*%=%-%;%>%,%'%)%!%*+(.x.A /$~%t.(.N.(.K.=+N.b@(.(.(.(.b@(.(.(.(.(.(.,@{%y.<#c.;@O.^@]%. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Q@H#^%/%}$(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%d%e%f%g%h%i%j%k%l%m%n%o%p%$%q%r%s%t%u%v%w%x%y%(.g ]+z%A%~$;@N.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.m+B%*+m+C%(.D%E%. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2#U@4#F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&;&>&,&'&)&!&~&{&]&^&/&(&_&:&<&B [&}&|&1&(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.m+(.2&3&. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Q@4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F&G&k%H&I&J&K&L&M&N&O&P&Q&R&f@S&-@T&U&(.A$*#l+(.N.c.=+m+V&(.(.(.(.(.(.(.(.(.(.(.(.W&R.0+X&. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R@V@[$Y&Z&`& *.*+*@*#*$*%*&***2%=*-*;*>*,*'*)*!*~*{*]*^*/*(*_*:*<*[*}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*e*f*g*h*i*j*k*l*M F@<+m*n*c.N.m+@+K.N.(.(.(.(.(.(.(.(.(.(.(.(.o*>+p*q*. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Q@S@3#r*s*t*u*v*w*x*y*z*A*B*C*D*E*F*G*H*I*J*K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z*`* =.=.=+=@=#=$=%=&=*===-=;=>=,='=)=!=~={=F@G.v+,@A ]=,@(.(.(.(.N.m+(.(.(.(.(.(.(.(.(.(.(.(.^=/=(=. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2#I#/%_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=0=a=b=c=d=e=f=g=h=i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=K=L=M=N=O=P=Q=R=T+F@K.P+=+@+a+n S=N.(.(.(.(.(.(.(.(.(.N.T=U=E+V=W=. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . R@V@X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-,-'-)-!-~-{-]-^-/-(-_-:-<-[-}-|-1-2-3-4-5-6-7-8-9-0-a-b-c-.=A=.=d-e-f-f-g-h-i-j-k-l-m-n-o-O+p-n.q-Y G.~@r-s-R.(.(.(.(.(.(.(.(.(.t-u-v-w-x-y-. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . z-A-B-C-D-E-F-G-H-I-J-K-L-M-N-O-P-Q-R-S-T-U-V-W-X-Y-Z-`- ;.;+;@;#;$;%;&;*;=;-;;;>;,;';);!;~;{;];^;/;(;_;B=_;_;:;<;[;};|;1;2;3;4;5;6;7;Z O+8;9;{$&+0;/+c.(.(.(.(.(.(.(._+a;b;c;P.d;e;. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . z-J#f;g;h;i;j;k;l;m;n;o;o;p;q;r;s;t;u;v;w;x;y;z;A;B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;~;Y;Z;`; >.>+>$=@>#>$>4*0*%>&>*>=>->;>>>T+~%*+/+z.P.1&o*N.r.(.(.(.(.(.(.I+]$:+W /+,>'>. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . z-3#)>!>~>{>]>^>m;/>(>_>:><>[>}>|>1>2>3>4>5>6>7>8>9>0>!-a>C;b>c>d>e>f>g>h>i>j>k>l>m>n>o>p>q>r>s>t>u>v>w>x>0-y>z> >A>B>C>D>E>0*F>G>H>I>J>K>L>z.a+M>N>[#m+P.N.C%(.(.(.(.(.(.P.h O>P>h+_+ .. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . R@J#F%Q>R>S>T>U>V>W>X>Y>Z>`> ,.,.,+,@,#,$,%,&,*,=,-,;,>,,,',),!,~,{,],^,/,(,%;_,:,<,[,},|,1,2,3,4,5,6,7,s>8,Y;9,0,a,.=0-b,c,d,e,f,g,h,i,j,k,l,i+m,8;H.n,A Y #+K.(.(.(.m+#+o,t@p,=@q,p+r,}+. . . ", " . . . . . . . . . . . . . . . . . . . . . . . R@A-r*s,R>t,u,v,w,x,y,Y>z,A,B,C,D,E,F,G,H,H,I,J,K,L,M,N,O,P,Q,',R,S,T,U,V,W,X,Y,Z,`, '.'+'@'#'$'%'&'*'='-'6,;'>',''')'0,!'_;~'{']'^'/'('_':'<'['}'|'Z+p+L@o,A$n*-@m+(.(.1'2'}@J+@+*+(.3'U 4'. . . ", " . . . . . . . . . . . . . . . . . . . . . . 2#^%B-1$5'6'7'8'9'0'a'b'c'd'e'E,f'g'h'i'j'j'k'l'm'n'o'p'q'r's't'u'v'w'x'y'z'A'B'C'D'E'F'G'H'I'J'K'Y%L'M'N'O'P'Q'Q'R'S'W;T'U'.=A=V'W'D=$=X'Y'Z'`' ).)+)T&@)~+1&K.l+F@(.m+#)J $){$v+1&(.(.%)&)*). . . ", " . . . . . . . . . . . . . . . . . . . . . P@T@=)-)`&;)>),)')))!)~){)])^)/)()_):)<)[)})|)[)1)2)3)4)5)6)7)8)9)0)a)b)c)d)e)f)g)h)i)j)k)l)m)n)o)p)q)r)s)t)u)v)w)x)Q'y)z)A)B)(;C)D)E)F)9*j%G)H)I)J)K)L)M)N)D#(.(.(.(.(.(.G O)P)p@++Q)@)R)U&S)T). . . ", " . . . . . . . . . . . . . . . . . . . . . X@U)V)W)X)Y)Z)`) !.!+!@!#!$!%!&!*!=!-!;!>!,!'!)!!!~!{!]!^!/!(!_!:!~,~'~)~!~~~{~]~^~/~(~_~:~<~[~}~|~1~2~3~4~5~6~7~8~w)9~0~a~b~c~3*#>#=d~e~f~g~h~i~j~k~l~m~(.t.a+,@n~o~p~q~r~s~~+t~f s~u~v~w~. . . ", " . . . . . . . . . . . . . . . . . . . P@I#x~s,y~z~A~B~C~D~E~F~{)G~H~I~J~K~L~M~N~O~P~Q~R~S~T~U~V~W~X~Y~Z~`~ {.{+{@{#{${%{&{*{={-{;{>{,{'{){!{~{{{]{^{/{c%({_{:{<{[{}{|{1{7~P'2{/;+>`;3{4{5{6{7{8{9{0{a{b{q+c{E d{e{'@f{E@I J g{h{Y i{j{=.k{. . . ", " . . . . . . . . . . . . . . . . . . . H#/%l{m{n{o{p{@-q{r{s{t{u{v{w{J~x{V!y{z{A{B{C{D{E{F{G{S~H{I{J{K{L{M{`~N{O{P{Q{R{S{T{U{V{W{X{Y{Z{`{ ].]+]@][~#]$]%]&]*]=]-];]>],]x)Q''])]R'!]z>~]{]]]^]/](]_]:]<][]}]|]$)d{|&1]c;2@N>m,g+2]3]4]5]6]7]. . . ", " . . . . . . . . . . . . . . . . . . Q@8]G!9]0]a]b]c]d]e]f]Y>g]h]i]j]k]l]m]n]A{C{o]p]q]r]s]t]u]v]w]x]y]z]A]B]C]D]E]F]G]H]I]J]K]L]M]N]O]P]`{Q]R]S]T]U]V]W]X]Y]Z]`] ^h!.^+^x)l!W;)]R'@^#^$^%^&^*^=^-^;^>^,^'^)^!^m t~~^{^]^w-^^|&^=/^(^_^:^<^. . . ", " . . . . . . . . . . . . . . . . . . 4&X=G$[^}^|^1^2^3^q{4^5^6^7^8^9^0^a^ ~S~b^c^d^e^f^g^h^i^j^k^l^m^n^o^p^q^r^s^t^u^v^w^x^y^z^A^B^C^D^E^F^G^H^I^J^K^L^M^N^O^P^Q^R^S^6~T^U^8~1{l!V^W^X^Y^Z^`^ /./+/@/#/$/%/&/*/q@d+=/-/;/>/,/!%Y '/)/%#!/~/. . . ", " . . . . . . . . . . . . . . . . . 2#3#{/]/^///(/_/:/(,('()(!(~({(](^(/(((|/_(:(<(9^[(}(|(1(2(3(4(5(6(7(4(8(9(0(a(b(c(d(e(k/f(g(h(i(j(k(l(m(n(o(p(q(r(x/s(t(u(v(w(x(y(z(A(R;B(C(D(E(F(G(H(I(J(K(L(M(N(O(P(Q(7*F)R(S(T(U(V(W(X(~@Y(v+Z(`( _++ _._+_@_#_$_k{. . . ", " . . . . . . . . . . . . . . . . Q@3#%_&_*_=_-_;_>_,_'_)_!_~_{_]_^_/_[((___1(:_<_[_}_|_7(4(d^1_b^a(2_3_d(e(4_5_6_7_8_9_0_a_b_c_d_e_f_g_h_i_j_k_l_m_n_n_o_p_t=q_r_s_t_u_v_w_x_y_z_A_B_C_D_E_F_G_.=$=H_I_J_K_L_M_N_{%2]a+W.O_|'P_Q_3+;#P_R_S_. . . ", " . . . . . . . . . . . . . . . . S@T_U_V_Z'W_X_Y_Z_`_ :.:+:@:#:$:%:&:|)}(*:=:-:;:>:,:':):>:!:~:{:]:^:/:(:_:::<:[:}:8_k(|:1:2:3:4:5:6:7:8:9:0:a:n_b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:*;s:9-{;t:u:#>e-j%H=|;%%v:w:x:y:z:-+H@A:!+B:9+&(P>C:D:E:. . . ", " . . . . . . . . . . . . . . . Q@A-F:G:H:I:J:K:L:M:N:O:P:Q:R:S:T:U:/_U!V:W:X:Y:Z:!:`: <.<+<@<#<$<%<&<*<=<-<;<><,<'<)[,['[)[![![~[{[][^[/[([_[:[<[[[}[|[1[2[3[n:4[5[6[7[8[9[0[7,Z;a[b[3*F&c[d[H&e[f[g[h[i[(.j[k[B l[`+i.=@m[n[o[p[. . . ", " . . . . . . . . . . . . . . . I#7#q[r[s[t[u[v[D},}'})}!}~}{}(.]}^}/}(}_}:}<}[}}}|}1}2}3}4}v>3*5}6}@>7}8}9}0}a}b}c}d}B%m+*+N.c.e}O+>+;/4@f}g}. . . ", " . . . . . . . . . . . . . . Q@5&h}i}j}k}l}m}n}o}p}q}r}s}t}u}v}w}x}y}z}x{A}B}C}D}E}F}G}H}I}%<`|j::}l:,|'|)|!|~|{|]|R'S'^|/|(|a-_|<;:|<|[|}|||B.(.O.Z((+;+1|=(2|3|4|5|. . . ", " . . . . . . . . . . . . . . z-6|7|8|9|0|t[a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|x|y|z|A|=<.[B|B|#[C|D|E|F|G|(.H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|'@Y%W|X|Y|Z|`| 1K/.1+1@1l>#1$1%1&1l!)]*1=1-1q!;1>1,1'1)1!1~1{1(.@+R+]1^1B:/15+(1_1:1. . . ", " . . . . . . . . . . . . . . T@)>q[<1[1}1|111213141516171819101a1b1c1d1e1f1g1h1i1V:j1k1l1/: [m1(:n1o1p1q1r1s1t1u1v1w1x1y1z1A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V1W1X1Y1Z1`1 2.2+2,]1{~;@2#2a--1$2%2&2F>*2=2-2;2#+#+P+T&e@>2,2'2)24.!2. . . ", " . . . . . . . . . . . . . P@A-V)~2{2]2^2/2(2_2>*:2<2[2}2|2122232425262d172829202a2b2c2c2d2e2f2M}M}g2h2i2j2k2l2m2n2o2p2q2r2s2t2u2v2w2x2e%y2z2A2B2C2D2E2F2G2H2I2J2K2L2M2N2O2P2Q2@&R2S2T2U2Q'v>|{V2a-W2X2Y2F&Z2`2 3.3+3N.(.*+@3#3)%$3}@I.%3&3. . . ", " . . . . . . . . . . . . . Q@4#*3=3-3;3>3,3'3)3!3~3{3]3^3/3(3_3:3<3[3}3|31323334353637373838393U[B|q103a3b3c3d3e3f3g3h3i3j3k3l3m3n3o3p3q3r3s3t3u3v3w3(.(.&|x3y3z3A3B3C3D3E3F3x&G1G3H3I3J3x)K3R'4}{;t:D>L3_|M3N3O3P3Q3(.v+k.I.R3*+R.v+S3T3U3. . . ", " . . . . . . . . . . . . . z->(V3W3X3Y3Z3`3 4.4+4@4#4$4%4&4*4=4,,-4;4>4,4'4)4!4~4{4]4^4/4(4(4_4:4<4[4}4|414243444546474849404a4b4c4d4e4f4g4h4i4j4k4l4m4e%*|n4o4p4q4r4s4c%q:t4u4v4w4x46~O/y4z4v>A4>'a,c-F)L3B4C4D4E4F4G48;H4a+A:C.R.e@3+I4J4. . . ", " . . . . . . . . . . . . . T@F%K4L4M4N4M4O4P4Q4R4S4T4U4V4W4X4Y4Z4`4 5.5+5@5#5$5%5&5&5&5*5=5-5;5>5,5i2'5)5!5~5{5]5^5/5(5_5:5<5[5}5|51525354555556575859505a5b5c5d5e5f5g5h5i5j5k5l5m5m5n5M/w)Q'R'o5p5y=B>q5%=X'r5s5t5u5v5w5O+0;x.P+X.J+x5y5z5. . . ", " . . . . . . . . . . . . . ^%A5B5C5D5E5F5G5H5I5J5K5L5M5N5O5P5Q5R5Z4S5T5U5V5W5X5Y5Z5`5 6.6+6@6#6$6%6&6*6=6-6;6>6,6'6)6!6~6{6]6^6/6(6_6:625<6[6}6|616263646566676869606a6b6c6d6e6n:u_f6F(g6U^l!y4h63*i6n!a-G=F&I=j6k6l6m6n6T&^=o6k+q~&+p6~+q6. . . ", " . . . . . . . . . . . . . <$l{r6s6t6u6v6w6x6y6z6A6B6C6D6E6F6G6H6I6J6K6L6M6N6O6P6Q6R6S6T6U6V6W6X6Y6Z6`6 7.7t=+7@7#7!6$7%7&7*7=7-7;7>7,7'7)7!7~765{7]7^7/7(7_7:7<7[7}7|717>|2737,|u_47F(<{7~4}5767Y;i6a,77D=4*879707}|a7b7R=c7]+d7j c+^$[+]%. . . ", " . . . . . . . . . . . . P@e7f7g7h7i7j7k7l7m7n7o7S*p7q7r7s7t7F6G6u7v7w7x7y7z7A7B7C7D7E7F7F7G7H7I7J7Z6K7L7M7w3N7O7P7Q7R7S7T7U7V7W7X7Y7Z7`7 8.8[665]7+8@8#8$8%8&8*8=8-8;8>8,8'8)8:}u_!8~8{8v)6,]8^8];i6c-F)d-C>/8(8_8:8<8[8}8H q+^@]+c+C A |8. . . ", " . . . . . . . . . . . . P@/%18283848586878889808n7S*a8b8c8d8e8f8g8h8i8j8k8l8m8n8o8p8q8r8s8t8u8v8w8x8y8z8A8B8C8D8E8F8G8H8I8J8K8L8M8N8O8P8Q8R8!7[6S8T8U8#8V8W8X8Y8Z8`8 9.9+9@9#9$9%9u_&9*9=9y4w)4}E_{;#=A=p!-9;9'1>9,9'9)9!9G (.(.(.*+>@~9{9. . . ", " . . . . . . . . . . . . 2#6|]9^9/94*(9_9v6:9<9[9}9|9<-19293949596979899909a9b9c9d9e9f9g9h9i9j9k9l9m9n9o9p9q9r9s9t9u9v9w9x9y9z9A9B9C9D9E9P8F9G9H9!7I9J9K9L9M9N9O9P9Q9R9S9T9U9V9W9X9d_;@>G=.0+0@0#0$0r-%0&0m+*#A (.m+*0=0. . . ", " . . . . . . . . . . . . z-X=V3'(-0;0>0,0'0)0!0~0{0]0^0/0(0_0:0<0[0}0|010203040506070809000a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p0q0r0s0t0u0v0w0x0y0z0A0B0I9C0@8D0E0F0G0H0I0J0K0L0M0j:N0O0P0P0Q0J3R0Q'u>Y;S0a,_;F)T0U0V0W0X0Y0Z0%(G@R.u<`0S a.a3&. . . ", " . . . . . . . . . . . . z-+a@a#a$a%a/8B4&a*a=a-a;a>a,a'a/0)a!a~a{a~~]a^a/a(a_a:aGaHaIa&(2'_+}&L@*#JaKaLaMa. . . ", " . . . . . . . . . . . . H#NaOaPaQaRaSaTaUaX2VaWaXaYaZa&;`a%; b.b+b@b#b$b%b&b*b=b-b;b>b,b'b)b!b~b{b]b^b/b(b_b:bc}b,cna'cia)cja3b!c~c{c]c^c/c(c_c:c-&acbc;1T0H=ccdcecfcgcz%{$`0h@}&p@{$hcic. . . ", " . . . . . . . . . . . . H#Najckclcmce~L3ncocc,pcqcNbrcNbsctcucvcvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcy9ScTcUc'cVcWcXcYcZc`c d.dP1+d@d#d$d%d&d*d*d=d-d;d>d,d'd)d!d~d+1N0mbO0{d]d^dv)/d(d 0_d:dbc#=f-4*(5d6d7d8d$=_|E)Va9d6}T'0dadbdcdddeducfdgdhdidC^jdkdldmdndodpdqdrdsdtdudvd}5wd-7xdydK8z9zdjaAdBd3bCdDdEdFdGd>6Hd7e,e'eE))e!eB> >~e{e/;]e^e/e(e_e:eNep5Oe$=G=E>-aPeQeRem.Sep.h@t-i.q-G4TeUe. . . ", " . . . . . . . . . . . . 2#[$VeWe>3XeYed,~'W'Ze!;`e f~].f+f@f#f$f%f ]&f*f,{=fr(-f7:;f>f,f'f)f!f~f{f]f^f/f(f_f:fz=:;4*qfrfsftfufvf$eN+wfq )+xfZ(yf. . . ", " . . . . . . . . . . . . Q@K#g;zfAfBfCf]'DfEfFf^;o5 fGfHf.fIf<~JfKfLfMfNfOfPfQfRf-fSfTfUfVfWfXfYfZf`f g15Z7Y7N8.g+gVc@g#g$g%g&g*g=g-g;g>g,g'g)g!g~g>;ve{g]g^g/g(g_g:g'.>_d-& >1g:;2g3g4g5g6g7g8g>2'/wfW.B$!+9g0g. . . ", " . . . . . . . . . . . . P@agbgcgdgegH_fgD>b-U'6}gghgIfigjgkglgmgmgngogpgqgrgsgz/tg~[ugvgwgxgygzgAgBgCgDgEgFgGgHgIgJg1fKgLgMgG|NgOgPgQgRgSg>gTgUgVgWgXgYgZg`g h.h+h@h#h$h[g(}T]:}u_f6f6*9|gU^T'%hpf)'&h*hW'#=&2=h-h;h>h,h(^u~'h)h!h2'~h{h]h. . . ", " . . . . . . . . . . . . P@J#Y=^h/h(h_h:h-&77a,`hR0 i.i+iof@i#i$i%il:&i@]*iu(v(l_=i-ic:;i>i,i'i)i!i~i<6B0{i]i^i/i(i_i:iz_j,j'j)j!j~j{j]jei^j/j(j_jw(:jljo!.=b-{;W;B)6,pbV;g6ck,k'k)k!k~ki.{kufP>]k~+^k2+/k(k. . . ", " . . . . . . . . . . . . . Q@E$_k:k|27177k8k9k0kd:akbkckF0yj]7Vi<6dk*jekfkgkG|hkikjkF93iIjkksalkR8*j:c65I9mknk@&okpkqkrk+9sktkukvkwkxkykzkAkBkCkDkEkFkGkHkIkJkKkLkMkNkOkPkQkRkuB>a,pfpfR'1{V;VkWkXkdl,l'lIjab)lu>l!U^#itlF(ul%9%iN0l:(}vloj17wlrkxldiylzlAlF0Bl@8ClT8&lDlElFlG|GlHlIlJlKlI9*dLlT8ClU8MlNl26@8OlPlQlRlSlTlUlVlWlXlYlt=Zl`l md%.m+m@m#m$m%m&m*m=m-mB4&2;m>m,m'm)mP_!ml ]$++~mN Jav+{m]%. . . ", " . . . . . . . . . . . . . . H#[$]m^m/m(m_m:mA=(|-&''v>R'6,Q'9~OmN/g6Pmdn,n'n)nZg!n~n{n]n^n/n(n_n:n^|~eHi@>d-[n}n|n1n2n3nB$I+f 4nc7O.W.gcz+5n6ne;. . . ", " . . . . . . . . . . . . . . . I#nl7n8n9n0n!eq5*ht:3*R'Ii']6,anN/h!&9P0O0n:l:bnRm[g.1^jcndnenfngnhninjnBlknlnmnnnG|onpnqnrn]7yjyjyj7mAlak&nsntnungn2mvnwn n&|x&5fxnynznAnBn5kCn<{|gDn+^R'Ent>m!`;F)T0&ae,F>FnGnHnInJn]$Kns-y#T=`02dImLnMnNn. . . ", " . . . . . . . . . . . . . . . z-K#OnPnQnRn'0L3B=Sn/;6}-'Enl!A4^8ofG(%9u_Tnm:l:vlWd,8'8UnVnWnXn2mYn+lZnVm`n o.o+o@o{}#o`i$oTiD07mM9D0Vm%oUm3mdixl&ofn*o=o-o;oId>o,o'o)oO0Fh&9M/!o2k8~K3u>^8~o{oa,9*T0/'%a]o^o/o(o_o,hQ.:oq~=+O.B =+_+)@177.>0-2{4}']x)w)v)J3G({du_m:N0l:Ba(},8'85o;|eiBh&ogntnUm6o7o8o9o0oao*gbocodoVmVm5meofo3mhngngnxleiUjgohoiojoM~kolomonou_u_oo<{N/+^1{Env>>'n!!eq59*G=poqorosotouow5q~C%C%n,p@B (.(.>@vowoxo. . . ", " . . . . . . . . . . . . . . . . X@5#Q>yozo&2>1F)A=77a,{;Y;']1{0cpb!oAo%9Cau_mbm::}BoWd}m'85oCoDo&o8kYnEohnZn6mFoGoHo7F)q5Uo<;VoWoXoYoZoB (.(.(.*+0+(.(.=+)@`o p.p. . . ", " . . . . . . . . . . . . . . . . Q@<$+p@p#p$pH=%psl77_dac`hS'En&p7~=9M/KiCaf6mbj:bnU]2[*p[gV9m_=pBhBh&o&o|7tj#l-p;p>p7<,p'p)pAhgn!p2m2mYnTm~pMo^j17/jW1{p]p^p/pJ^j:nf(p_pF(!ov)6, e571kD__d >D>f--1:pC.t-Bp. . . ", " . . . . . . . . . . . . . . . . . Q@A-Cp3$DpEpFp9*C=.=i6a-Y;o5GpHp,]2k}{Ip<{Ghu_JpKpWdb<]{LpMpNpOp8kPpWj.lQpRpSpTpUpqe(.(.VpWpXpei7kMoCofi5oYpZp'8'8@h`p q.q+q@q{d#qIp6~9~$q1{.f%q&q~;U'.=*h*q,1=qub-q;q>q,q`o'q^#O))@)+*+xf~+%+^=)q!q~q{q. . . ", " . . . . . . . . . . . . . . . . . . X@x<]q^q/q(q=q@>sl_|B4_q:ql!Kqw)T^6~O/T2P0LqMqNqOqPqQqRqSqTqUqVqWqXqYqZqwe`q r.r+r@r#r$r%r&r*r(}DhU9=r-r;r>r,r'r)r!rd<<{!o~r2kKqQ'pfS'];{rc-i6]r;1^r%p/r(r_r:ruo'!;ac_;4oVaHrz=IrJrKrLrMrNrd{OrL@p@>@v+m+B j.K.S (.'@ aPr3p. . . ", " . . . . . . . . . . . . . . . . . . . . T@X=g;QrRr9*Sr']TrUrA=o!VrWrXrX;Q'+^V;y)v)YrZr`r s.s+s@scs,s's)s!s~s{s]swm^s/s(s_s:s6,U2w)w)Z9jskslsmsns5oR^ospsqsrssstsusvswsxsnj0Df{rG_3*];1ku>0c6,h! t.t+t@t#t$t%t&t*t=t-t;t>tz_,t'tnfn:<}3[N0U]Eh3[)t!t~t{tZl]t^t/t(t_t:{:tli+^6,}tF_ac-177F)_|_mSa|t1t2t3t4t5t6t7t8tz%1]9t'/q~(.0t}&m+r+J.-+%+atbt. . . ", " . . . . . . . . . . . . . . . . . . . . . . :$ctdtetft2r9*E):;%2 >(|0,acY;v>v>4} fgthtitjtktltmtntotptqtrtW$stttutf6u_4[H(E(<}mjZkU]vt!twt mYgxto1ytztAtHf+^8~obZ9Bt];4}Cta,y=779*G=@>L3DtEtFtGtHtItJt~ku-Ktp6LtMtC:5]R=NtI (.#+n,Y q,Ot3p. . . ", " . . . . . . . . . . . . . . . . . . . . . . Q@U@Pt_kQtDpRtSt*=TtF)-1|k >NeE_Y;MeUtVtWtXtYtZt`t u.u+u@u#u$u%u&u*uX9ululf6m5<}T]T]w_=u-uNo;u>u,u'u)u!u5~~uobl!w)[h~;w>{u(;]u.=_;@>H_E>^u/u(u_u:uauW'.=!'i6Y;k!bucu[edueufuguhuiu60juku!rlu0pGhmu%9nuAoAoc<+]%ioupuqurusutuuuvuwuxuyuanx)']v>v>!]zum!a,AuBu#=77Hi0,EfVuWuXuYuZu`u v.v+v@v#v(dS^oo{8M/{8Ip:t2h{8Q0S^$v%v&v*vir=va%-v;v>v e,v1{R'']v>''Au'v2{%=)v!v~vL3E>{v]v^v/v(v_v:v'mvw)$q,]w)+^nv9~h!ofovpvOmOmqvrvsvt=(.tvuvvvwvl!R'v>pfR'xvyv`;}kt:-9zvAv5*&2BvCvDvEvFvGvHvz.U&IvJvKv`0~+LvMv1'++5vNvz!OvO>2@PvQvs~r-RvSv. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . z-}ox~_kh;TvUvrl&2H_$='8~^8+w@w#w$w%w&w&w*w=w-w;w>wr),w'w)wQ'v> 0];X;!;-&a-W2|kB>[k>0!w0nI&~w{w]w^w/w(w(.(.j@_wn,:w@+T=S0E_E_p5xw|kb-$=A=f-G=^uFpubywzwAwBwCw+#Dw[&|&EwZ(p@FwZ (.(.w.R.=+T @+D#GwHwl+}@Iwy+JwKwLw. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2#U@xx,x'x)xY;~ea,a--1(|#=>1F)F&G=S(!x~x{x]x^x/x(x_x:xR.a+/$1]/+N)2xpl3xG&M3_|4x5xH[6x7x8x9x0xi6{r.>axbxcxdxexfxgxhxueixjxkxlxmxnxoxpxqxrx^;0,c-77p!sx@>G=F)f-[;txuxvxwxxxyxzxAxBxd@l+=+(.(.G.p@Y CxDxExN.=+c.FxGxj@p@(.j@3@=(q-t-N.HxIx. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X@J#+aJxKxLxMxNxH=OxPxQxmhRxSxD_Tx`;}kDfUxVxWxc%XxYxZx`x y.y+y@y#yd1>b$y%y&y*y=y-yA=;yG=_|D=>ye-,y'y)y!y~y{y]y^y/y(y_y:yv+z,z'z)z!z~z^+R.;@N.{z]z#+l+{$~+]=M.K.S W&F.(.(.N.(.(.m+m+(.Q.c@P.2+^zS./z. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R@T@ag6#h}(z_z:z@]@(.(.(.(.3dp@W&L@xzp~=+yz aq6. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P@H#U@ag6#Fys,zzAzBzRuCzDzEzFzGzHzIzJzKzB4&aLzMz:9NzOzPzQzRzSzHkTzUzVzgsWzXzYzZz`z A.A+A@A#A$A(.(.,@P+c.(.(.=+N.(.(.(.(.(.'q%AK.sA,A'A)A!A~A{A]A^A/A(A_A:A&a_mwqE&B,B'B)B!Bq+G.G.N.S 3uO.,@P+j[(.c.(.(.(.(.(.(.(.(.(.#+*+F.(.m+N.;@(.(.OuO+M>iAw$I+{+k.~B{B-A. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . P@z-:$V@5&K#;eB-]B1x^B/B(B_B:B`+1&O.O.(.(+uBP.(.(.(.(.(+c.(.(.(.(.(.(.p-vBwBaBN.(.(.(.(.O.=@9+M@,@d@xBB$t+K+x (.N.e}4u(.A$@3PBtB$3N)>$GwQB(.(.m+(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.O.=+(.K._wV.2];@;@)+lASARB-+SBTBUB. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . VBWBj ~ml+N.m+CBG@B A G.l+<#XBt@~+JvP./+w+c.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.N.Jac.3u<+4uW&x.&C1d0;5]MtQv*C=C. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -C;C>CR.Z+Z+(.(.(.(.(.(.=+Z ,CK.i@vfl+R.K.(.@+O.c.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.K.N.O.uBj.e+W.9+!m'CE YB)C!C~C. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . {C]Cp6E@Z+F@(.(.(.(.(.N.;@_+1'=+,@T&*+(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.(.m+B Y k+-+^C5ve@4u++/C(C_C. . . ", " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . :C Set maximum framerate to (default: 1000, availble: 1-1000) ;-hogdir set shared data directory to ;-nohogdir don't try to use shared data directory ;-use_players_dir put player files and saved games in Players subdirectory ;-lowmem Lowers animation detail for better performance with low memory ;-pilot Select pilot automatically ;-autodemo Start in demo mode ;-window Run the game in a window ;-noborders Do not show borders in window mode ;-nomovies Don't play movies Controls: ;-nocursor Hide mouse cursor ;-nomouse Deactivate mouse ;-nojoystick Deactivate joystick ;-nostickykeys Make CapsLock and NumLock non-sticky Sound: ;-nosound Disables sound output ;-nomusic Disables music output ;-sound11k Use 11KHz sounds ;-nosdlmixer Disable Sound output via SDL_mixer Graphics: ;-lowresfont Force to use LowRes fonts ;-lowresgraphics Force to use LowRes graphics ;-lowresmovies Play low resolution movies if available (for slow machines) ;-gl_fixedfont Do not scale fonts to current resolution Multiplayer: ;-udp_hostaddr Use IP address/Hostname for manual game joining (default: localhost) ;-udp_hostport Use UDP port for manual game joining (default: 42424) ;-udp_myport Set my own UDP port to (default: 42424) ;-tracker_hostaddr Address of Tracker server to register/query games to/from (default: dxxtracker.reenigne.net) ;-tracker_hostport Port of Tracker server to register/query games to/from (default: 42420) Debug (use only if you know what you're doing): ;-debug Enable debugging output. ;-verbose Enable verbose output. ;-safelog Write gamelog.txt unbuffered. Use to keep helpful output to trace program crashes. ;-norun Bail out after initialization ;-renderstats Enable renderstats info by default ;-text Specify alternate .tex file ;-tmap Select texmapper to use (default: c, available: c, fp, quad, i386) ;-showmeminfo Show memory statistics ;-nodoublebuffer Disable Doublebuffering ;-bigpig Use uncompressed RLE bitmaps ;-16bpp Use 16Bpp instead of 32Bpp ;-gl_oldtexmerge Use old texmerge, uses more ram, but might be faster ;-gl_intensity4_ok Override DbgGlIntensity4Ok (default: 1) ;-gl_luminance4_alpha4_ok Override DbgGlLuminance4Alpha4Ok (default: 1) ;-gl_rgba2_ok Override DbgGlRGBA2Ok (default: 1) ;-gl_readpixels_ok Override DbgGlReadPixelsOk (default: 1) ;-gl_gettexlevelparam_ok Override DbgGlGetTexLevelParamOk (default: 1) dxx-rebirth-0.58.1-d2x/d2xgl-Info.plist000066400000000000000000000014331217717237500175430ustar00rootroot00000000000000 CFBundleDevelopmentRegion English CFBundleExecutable d2xgl CFBundleIconFile d2x-rebirth CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature DCT2 CFBundleVersion 0.57.3 CSResourcesFileMapped LSPrefersCarbon NSMainNibFile MainMenu NSPrincipalClass NSApplication dxx-rebirth-0.58.1-d2x/debian/000077500000000000000000000000001217717237500157765ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/debian/changelog000066400000000000000000000004231217717237500176470ustar00rootroot00000000000000d2x-rebirth (0.56-1) maverick; urgency=low * Keeping up to date. -- zico Thu, 05 May 2011 01:22:39 +0100 d2x-rebirth (0.55-1) intrepid; urgency=low * Package creation. -- MD2211 Tue, 30 Dec 2008 16:18:17 +0100 dxx-rebirth-0.58.1-d2x/debian/control000066400000000000000000000011621217717237500174010ustar00rootroot00000000000000Source: d2x-rebirth Section: games Priority: optional Maintainer: zico Standards-Version: 3.6.1 Package: d2x-rebirth Build-Depends: libsdl1.2-dev, libsdl-mixer1.2-dev, libphysfs-dev, scons Recommends: timidity, freepats Architecture: any Depends: ${shlibs:Depends} Description: Port of the 1996 classic game Descent 2: Counterstrike! DXX-Rebirth is a Source Port of the Descent & Descent ][ Engines and provides classical Gameplay combined with OpenGL graphics and effects, a bunch of improvements and new features. . For more information please visit the web site: http://www.dxx-rebirth.com/ dxx-rebirth-0.58.1-d2x/debian/copyright000066400000000000000000000005461217717237500177360ustar00rootroot00000000000000This software was packaged by zico Thu, 05 May 2011 01:22:39 +0100 It was downloaded from: http://www.dxx-rebirth.com/ Original authors: * Descent 2 by Interplay / Parallax Software * D2X by Bradley Bell (http://icculus.org/~btb/) * DXX-Rebirth by Zico License: Please see COPYING file for details dxx-rebirth-0.58.1-d2x/debian/patches/000077500000000000000000000000001217717237500174255ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/debian/patches/00games_as_bindir.diff000066400000000000000000000005361217717237500235310ustar00rootroot00000000000000--- SConstruct 2008-12-30 21:47:01.000000000 +0100 +++ SConstruct.new 2008-12-30 21:47:44.000000000 +0100 @@ -15,7 +15,7 @@ # installation path PREFIX = str(ARGUMENTS.get('prefix', '/usr/local')) -BIN_SUBDIR = '/bin' +BIN_SUBDIR = '/games' DATA_SUBDIR = '/share/games/d2x-rebirth' BIN_DIR = PREFIX + BIN_SUBDIR DATA_DIR = PREFIX + DATA_SUBDIR dxx-rebirth-0.58.1-d2x/debian/postinst000077500000000000000000000000151217717237500176030ustar00rootroot00000000000000#! /bin/bash dxx-rebirth-0.58.1-d2x/debian/prerm000077500000000000000000000000151217717237500170450ustar00rootroot00000000000000#! /bin/bash dxx-rebirth-0.58.1-d2x/debian/rules000077500000000000000000000041101217717237500170520ustar00rootroot00000000000000#! /usr/bin/make -f # # debian/rules file for d2x-rebirth # zico # Thu, 05 May 2011 01:22:39 +0100 # package = d2x-rebirth SCONS = scons -Q SCONSFLAGS = prefix=/usr BINARY = d2x-rebirth PREFIX = /usr BIN_DIR = $(PREFIX)/games SHARE_DIR = $(PREFIX)/share DATA_DIR = $(SHARE_DIR)/games/$(package) DEBIAN_TMP = debian/tmp patch: patch-stamp patch-stamp: test -d debian/patches @for patch in debian/patches/*.diff; do \ echo "Applying $$patch"; \ patch < $$patch; \ done touch $@ build: patch build-stamp build-stamp: $(SCONS) $(SCONSFLAGS) strip $(BINARY) touch $@ clean: $(SCONS) -c rm -rf patch-stamp build-stamp *~ $(DEBIAN_TMP) debian/*~ debian/files* debian/substvars binary-indep: checkroot build $(checkdir) # There are no architecture-independent files to be uploaded # generated by this package. If there were any they would be # made here. TMP_BIN_DIR = $(DEBIAN_TMP)/$(BIN_DIR) TMP_SHARE_DIR = $(DEBIAN_TMP)/$(SHARE_DIR) TMP_DATA_DIR = $(DEBIAN_TMP)/$(DATA_DIR) binary-arch: checkroot build $(checkdir) rm -rf $(DEBIAN_TMP) install -d $(DEBIAN_TMP)/DEBIAN $(TMP_BIN_DIR) $(TMP_DATA_DIR) install -d $(TMP_DATA_DIR)/missions $(TMP_DATA_DIR)/demos $(TMP_DATA_DIR)/screenshots $(TMP_DATA_DIR)/Music install -d $(TMP_SHARE_DIR)/applications $(TMP_SHARE_DIR)/pixmaps install -m 755 debian/postinst debian/prerm $(DEBIAN_TMP)/DEBIAN install -m 755 $(BINARY) $(TMP_BIN_DIR) install -m 644 d2x.ini $(TMP_DATA_DIR) install -m 644 CHANGELOG.txt $(TMP_DATA_DIR) install -m 644 COPYING.txt $(TMP_DATA_DIR) install -m 644 README.txt $(TMP_DATA_DIR) install -m 644 d2x-rebirth.desktop $(TMP_SHARE_DIR)/applications install -m 644 d2x-rebirth.xpm $(TMP_SHARE_DIR)/pixmaps dpkg-shlibdeps $(TMP_BIN_DIR)/$(BINARY) dpkg-gencontrol -isp chown -R root:root $(DEBIAN_TMP) chmod -R u+w,go=rX $(DEBIAN_TMP) dpkg --build $(DEBIAN_TMP) .. define checkdir test -f SConstruct -a -f debian/rules endef binary: binary-indep binary-arch checkroot: $(checkdir) test $$(id -u) = 0 .PHONY: binary binary-arch binary-indep clean checkroot dxx-rebirth-0.58.1-d2x/editor/000077500000000000000000000000001217717237500160425ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/editor/autosave.c000066400000000000000000000103541217717237500200400ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Autosave system: * Saves current mine to disk to prevent loss of work, and support undo. * */ #include #include #include #include #include #include #include "dxxerror.h" #include "inferno.h" #include "editor.h" #include "u_mem.h" #include "ui.h" #include "strutil.h" #define AUTOSAVE_PERIOD 5 // Number of minutes for timed autosave int Autosave_count; int Autosave_numfiles; int Autosave_total; int undo_count; int original; int Timer_save_flag=0; int Autosave_flag; int save_second=-1; char undo_status[10][100]; void init_autosave(void) { // int i; Autosave_count = 0; Autosave_numfiles = 0; Autosave_flag = 0; undo_count = 0; //MALLOC( undo_status, char *, 10 ); //for (i=0; i<10; i++) // MALLOC( undo_status[i], char, 100 ); autosave_mine(mine_filename); } void close_autosave(void) { int i; char *delname, *ext; for (i=0;i 0) undo_count--; if (Autosave_count > 9) Autosave_count -= 10; if (Autosave_numfiles < 10) Autosave_numfiles++; if (Autosave_total < 10) Autosave_total++; d_free(savename); } } void print_clock( int seconds, char message[10] ) { int w,h,aw; char *p; // Make colon flash if (seconds & 1) if ((p = strchr(message, ':')) != NULL) *p = ' '; gr_set_current_canvas( NULL ); gr_set_fontcolor( CBLACK, CGREY ); gr_get_string_size( message, &w, &h, &aw ); gr_setcolor( CGREY ); gr_rect( 700, 0, 799, h+1 ); gr_string( 700, 0, message ); gr_set_fontcolor( CBLACK, CWHITE ); } static char the_time[14]; // changed from 10, I don't think that was long enough void clock_message( int seconds, char *format, ... ) { va_list ap; va_start(ap, format); vsprintf(the_time, format, ap); va_end(ap); print_clock(seconds, the_time); } struct tm Editor_time_of_day; void set_editor_time_of_day() { time_t ltime; time( <ime ); Editor_time_of_day = *localtime( <ime ); } void TimedAutosave(char *name) { int month,day,hour,minute,second; month = (Editor_time_of_day.tm_mon) + 1; day = Editor_time_of_day.tm_mday; minute = Editor_time_of_day.tm_min; hour = Editor_time_of_day.tm_hour; second = Editor_time_of_day.tm_sec; if (hour > 12) hour-=12; //if (second!=save_second) { save_second = second; clock_message(second, "%d/%d %d:%02d", month, day, hour, minute); } #ifndef DEMO if (minute%AUTOSAVE_PERIOD != 0) Timer_save_flag = 1; if ((minute%AUTOSAVE_PERIOD == 0) && (Timer_save_flag)) { time_t ltime; autosave_mine(name); Timer_save_flag = 0; time( <ime ); diagnostic_message_fmt("Mine Autosaved at %s\n", ctime(<ime)); } #endif } int undo( void ) { Int3(); return 2; } dxx-rebirth-0.58.1-d2x/editor/centers.c000066400000000000000000000156431217717237500176620ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Dialog box stuff for control centers, material centers, etc. * */ #include #include #include #include #include "fuelcen.h" #include "screens.h" #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "timer.h" #include "objpage.h" #include "fix.h" #include "dxxerror.h" #include "kdefs.h" #include "object.h" #include "polyobj.h" #include "game.h" #include "powerup.h" #include "ai.h" #include "hostage.h" #include "eobject.h" #include "medwall.h" #include "eswitch.h" #include "ehostage.h" #include "key.h" #include "medrobot.h" #include "bm.h" #include "centers.h" //------------------------------------------------------------------------- // Variables for this module... //------------------------------------------------------------------------- static UI_DIALOG *MainWindow = NULL; typedef struct centers_dialog { UI_GADGET_BUTTON *quitButton; UI_GADGET_RADIO *centerFlag[MAX_CENTER_TYPES]; UI_GADGET_CHECKBOX *robotMatFlag[MAX_ROBOT_TYPES]; int old_seg_num; } centers_dialog; char center_names[MAX_CENTER_TYPES][CENTER_STRING_LENGTH] = { "Nothing", "FuelCen", "RepairCen", "ControlCen", "RobotMaker" }; int centers_dialog_handler(UI_DIALOG *dlg, d_event *event, centers_dialog *c); //------------------------------------------------------------------------- // Called from the editor... does one instance of the centers dialog box //------------------------------------------------------------------------- int do_centers_dialog() { centers_dialog *c; int i; // Only open 1 instance of this window... if ( MainWindow != NULL ) return 0; // Close other windows. close_trigger_window(); hostage_close_window(); close_wall_window(); robot_close_window(); MALLOC(c, centers_dialog, 1); if (!c) return 0; // Open a window with a quit button MainWindow = ui_create_dialog( 20, TMAPBOX_Y+20, 740, 545-TMAPBOX_Y, DF_DIALOG, (int (*)(UI_DIALOG *, d_event *, void *))centers_dialog_handler, c ); c->quitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL ); // These are the checkboxes for each door flag. i = 40; c->centerFlag[0] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "NONE" ); i += 24; c->centerFlag[1] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "FuelCen" ); i += 24; c->centerFlag[2] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "RepairCen" ); i += 24; c->centerFlag[3] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "ControlCen" ); i += 24; c->centerFlag[4] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "RobotCen" ); i += 24; c->centerFlag[5] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "Blue Goal" ); i += 24; c->centerFlag[6] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "Red Goal" ); i += 24; // These are the checkboxes for each robot flag. for (i=0; irobotMatFlag[i] = ui_add_gadget_checkbox( MainWindow, 128 + (i%6)*92, 20+(i/6)*24, 16, 16, 0, Robot_names[i]); c->old_seg_num = -2; // Set to some dummy value so everything works ok on the first frame. return 1; } void close_centers_window() { if ( MainWindow!=NULL ) { ui_close_dialog( MainWindow ); MainWindow = NULL; } } int centers_dialog_handler(UI_DIALOG *dlg, d_event *event, centers_dialog *c) { int i; // int robot_flags; int keypress = 0; int rval = 0; Assert(MainWindow != NULL); if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); //------------------------------------------------------------ // Call the ui code.. //------------------------------------------------------------ ui_button_any_drawn = 0; //------------------------------------------------------------ // If we change centers, we need to reset the ui code for all // of the checkboxes that control the center flags. //------------------------------------------------------------ if (c->old_seg_num != Cursegp-Segments) { for (i = 0; i < MAX_CENTER_TYPES; i++) ui_radio_set_value(c->centerFlag[i], 0); Assert(Curseg2p->special < MAX_CENTER_TYPES); ui_radio_set_value(c->centerFlag[Curseg2p->special], 1); // Read materialization center robot bit flags for (i = 0; i < N_robot_types; i++) ui_checkbox_check(c->robotMatFlag[i], RobotCenters[Curseg2p->matcen_num].robot_flags[i >= 32 ? 1 : 0] & (1 << (i % 32))); } //------------------------------------------------------------ // If any of the radio buttons that control the mode are set, then // update the corresponding center. //------------------------------------------------------------ for ( i=0; i < MAX_CENTER_TYPES; i++ ) { if ( GADGET_PRESSED(c->centerFlag[i]) ) { if ( i == 0) fuelcen_delete(Cursegp); else if (Curseg2p->special != i) { fuelcen_delete(Cursegp); Update_flags |= UF_WORLD_CHANGED; fuelcen_activate( Cursegp, i ); } rval = 1; } } for (i = 0; i < N_robot_types; i++) { if ( GADGET_PRESSED(c->robotMatFlag[i]) ) { if (c->robotMatFlag[i]->flag) RobotCenters[Curseg2p->matcen_num].robot_flags[i >= 32 ? 1 : 0] |= (1 << (i % 32)); else RobotCenters[Curseg2p->matcen_num].robot_flags[i >= 32 ? 1 : 0] &= ~(1 << (i % 32)); rval = 1; } } //------------------------------------------------------------ // If anything changes in the ui system, redraw all the text that // identifies this wall. //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { // int i; // char temp_text[CENTER_STRING_LENGTH]; ui_dprintf_at( dlg, 12, 6, "Seg: %3ld", Cursegp-Segments ); // for (i=0; ispecial < MAX_CENTER_TYPES); // strncpy(temp_text, Center_names[Curseg2p->special], strlen(Center_names[Curseg2p->special])); // ui_dprintf_at( dlg, 12, 23, " Type: %s", temp_text ); } if (c->old_seg_num != Cursegp-Segments) Update_flags |= UF_WORLD_CHANGED; if (event->type == EVENT_WINDOW_CLOSE) { d_free(c); MainWindow = NULL; return 0; // we're not cancelling the close } if ( GADGET_PRESSED(c->quitButton) || (keypress==KEY_ESC) ) { close_centers_window(); return 1; } c->old_seg_num = Cursegp-Segments; return rval; } dxx-rebirth-0.58.1-d2x/editor/curves.c000066400000000000000000000333261217717237500175240ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * curve generation stuff * */ #include #include #include #include #include #include #include "inferno.h" #include "vecmat.h" #include "gr.h" #include "key.h" #include "editor.h" #include "editor/esegment.h" #include "gameseg.h" #include "console.h" #define ONE_OVER_SQRT2 F1_0 * 0.707106781 #define CURVE_RIGHT 1 #define CURVE_UP 2 segment *OriginalSeg; segment *OriginalMarkedSeg; int OriginalSide; int OriginalMarkedSide; segment *CurveSegs[MAX_SEGMENTS]; int CurveNumSegs; const fix Mh[4][4] = { { 2*F1_0, -2*F1_0, 1*F1_0, 1*F1_0 }, {-3*F1_0, 3*F1_0, -2*F1_0, -1*F1_0 }, { 0*F1_0, 0*F1_0, 1*F1_0, 0*F1_0 }, { 1*F1_0, 0*F1_0, 0*F1_0, 0*F1_0 } }; void generate_banked_curve(fix maxscale, vms_equation coeffs); void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs) { // Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t~3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4 coeffs->n.x3 = fixmul(2*F1_0,p1->x) - fixmul(2*F1_0,p4->x) + r1->x + r4->x; coeffs->n.x2 = fixmul(-3*F1_0,p1->x) + fixmul(3*F1_0,p4->x) - fixmul(2*F1_0,r1->x) - fixmul(1*F1_0,r4->x); coeffs->n.x1 = r1->x; coeffs->n.x0 = p1->x; coeffs->n.y3 = fixmul(2*F1_0,p1->y) - fixmul(2*F1_0,p4->y) + r1->y + r4->y; coeffs->n.y2 = fixmul(-3*F1_0,p1->y) + fixmul(3*F1_0,p4->y) - fixmul(2*F1_0,r1->y) - fixmul(1*F1_0,r4->y); coeffs->n.y1 = r1->y; coeffs->n.y0 = p1->y; coeffs->n.z3 = fixmul(2*F1_0,p1->z) - fixmul(2*F1_0,p4->z) + r1->z + r4->z; coeffs->n.z2 = fixmul(-3*F1_0,p1->z) + fixmul(3*F1_0,p4->z) - fixmul(2*F1_0,r1->z) - fixmul(1*F1_0,r4->z); coeffs->n.z1 = r1->z; coeffs->n.z0 = p1->z; } vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t) { fix t2, t3; vms_vector coord; if (degree!=3) con_printf(CON_CRITICAL," for Hermite Curves degree must be 3\n"); t2 = fixmul(t,t); t3 = fixmul(t2,t); coord.x = fixmul(coeffs->n.x3,t3) + fixmul(coeffs->n.x2,t2) + fixmul(coeffs->n.x1,t) + coeffs->n.x0; coord.y = fixmul(coeffs->n.y3,t3) + fixmul(coeffs->n.y2,t2) + fixmul(coeffs->n.y1,t) + coeffs->n.y0; coord.z = fixmul(coeffs->n.z3,t3) + fixmul(coeffs->n.z2,t2) + fixmul(coeffs->n.z1,t) + coeffs->n.z0; return coord; } fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist) { vms_vector coord; fix t, diff; if (degree!=3) con_printf(CON_CRITICAL," for Hermite Curves degree must be 3\n"); for (t=t0;t<1*F1_0;t+=0.001*F1_0) { coord = evaluate_curve(coeffs, 3, t); diff = dist - vm_vec_dist(&coord, p0); if (diff-ACCURACY)) return t; } return -1*F1_0; } void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) { fix t2; if (degree!=3) con_printf(CON_CRITICAL," for Hermite Curves degree must be 3\n"); t2 = fixmul(t0,t0); dir->x = fixmul(3*F1_0,fixmul(coeffs->n.x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.x2,t0)) + coeffs->n.x1; dir->y = fixmul(3*F1_0,fixmul(coeffs->n.y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.y2,t0)) + coeffs->n.y1; dir->z = fixmul(3*F1_0,fixmul(coeffs->n.z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.z2,t0)) + coeffs->n.z1; vm_vec_normalize( dir ); } void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t) { vms_vector coord, dcoord; fix t, dt; gr_setcolor(15); gr_box( 75, 40, 325, 290 ); gr_box( 75, 310, 325, 560 ); gr_box( 475, 310, 725, 560 ); //gr_pal_fade_in( grd_curscreen->pal ); for (t=min_t;t fixmul( nextdist, 1.5*F1_0 )) { vms_matrix rotmat,rotmat2; vms_vector tdest; if (firstsegflag==1) firstsegflag=0; else extract_forward_vector_from_segment(Cursegp, &tvec); nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point t = curve_dist(&coeffs, 3, t, &prev_point, nextdist); // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve) coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point)); vm_vec_normalized_dir(&vec_dir, &coord, &prev_point); if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) { med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp vec_dir = tdest; vm_vector_2_matrix(&rotmat2,&vec_dir,NULL,NULL); med_rotate_segment( Cursegp, &rotmat2 ); prev_point = coord; Curside = Side_opposite[AttachSide]; CurveSegs[CurveNumSegs]=Cursegp; CurveNumSegs++; } else return 0; } extract_up_vector_from_segment( Cursegp,&tvec ); uangle = vm_vec_delta_ang( &tvec, &r4t, &r4 ); if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; extract_right_vector_from_segment( Cursegp,&tvec ); rangle = vm_vec_delta_ang( &tvec, &r4t, &r4 ); if (rangle >= F1_0/8) rangle -= F1_0/4; if (rangle >= F1_0/8) rangle -= F1_0/4; if (rangle <= -F1_0/8) rangle += F1_0/4; if (rangle <= -F1_0/8) rangle += F1_0/4; if ((uangle != 0) && (rangle != 0)) { maxscale = CurveNumSegs*F1_0; generate_banked_curve(maxscale, coeffs); } if (CurveNumSegs) { med_form_bridge_segment( Cursegp, Side_opposite[AttachSide], Markedsegp, Markedside ); CurveSegs[CurveNumSegs] = &Segments[ Markedsegp->children[Markedside] ]; CurveNumSegs++; } Cursegp = OriginalSeg; Curside = OriginalSide; med_create_new_segment_from_cursegp(); //warn_if_concave_segments(); if (CurveNumSegs) return 1; else return 0; } void generate_banked_curve(fix maxscale, vms_equation coeffs) { vms_vector vec_dir, tvec, b4r4t; vms_vector coord,prev_point; fix enddist, nextdist; int firstsegflag; fixang rangle, uangle, angle, scaled_ang=0; fix t; if (CurveNumSegs) { extract_up_vector_from_segment( Cursegp,&b4r4t ); uangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 ); if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; extract_right_vector_from_segment( Cursegp,&b4r4t ); rangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 ); if (rangle >= F1_0/8) rangle -= F1_0/4; if (rangle >= F1_0/8) rangle -= F1_0/4; if (rangle <= -F1_0/8) rangle += F1_0/4; if (rangle <= -F1_0/8) rangle += F1_0/4; angle = uangle; if (abs(rangle) < abs(uangle)) angle = rangle; delete_curve(); coord = prev_point = p1; #define MAGIC_NUM 0.707*F1_0 if (maxscale) scaled_ang = fixdiv(angle,fixmul(maxscale,MAGIC_NUM)); t=0; tvec = r1save; firstsegflag = 1; enddist = F1_0; nextdist = 0; while ( enddist > fixmul( nextdist, 1.5*F1_0 )) { vms_matrix rotmat,rotmat2; vms_vector tdest; if (firstsegflag==1) firstsegflag=0; else extract_forward_vector_from_segment(Cursegp, &tvec); nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point t = curve_dist(&coeffs, 3, t, &prev_point, nextdist); // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve) coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point)); vm_vec_normalized_dir(&vec_dir, &coord, &prev_point); if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) { med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp vec_dir = tdest; vm_vec_ang_2_matrix(&rotmat2,&vec_dir,scaled_ang); med_rotate_segment( Cursegp, &rotmat2 ); prev_point = coord; Curside = Side_opposite[AttachSide]; CurveSegs[CurveNumSegs]=Cursegp; CurveNumSegs++; } } } } void delete_curve() { int i; for (i=0; isegnum != -1) med_delete_segment(CurveSegs[i]); } Markedsegp = OriginalMarkedSeg; Markedside = OriginalMarkedSide; Cursegp = OriginalSeg; Curside = OriginalSide; med_create_new_segment_from_cursegp(); CurveNumSegs = 0; //editor_status(""); //warn_if_concave_segments(); } dxx-rebirth-0.58.1-d2x/editor/data/000077500000000000000000000000001217717237500167535ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/editor/data/curve.pad000066400000000000000000000020471217717237500205700ustar00rootroot00000000000000Curve Forming Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ * ³ - ³ ³ Lock ³ ³ ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³Decrease³ 8 ³Increase³ ³ ³ R1 ³  ³ R1 ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ + ³ ³Decrease³ 5 ³Increase³ ³ ³ R4 ³ ³ R4 ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 1 ³ 2 ³ 3 ³ ³ ³ End ³  ³ PgDn ³ ³ ³ ³ ³ ³ Create ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Curve ³ ³ Set ³ Delete ³ ³ ³ Curve ³ Curve ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{PadEnter} med-curve-generate {Ctrl}{Pad.} med-curve-delete {Ctrl}{Pad7} med-curve-decrease-r1 {Ctrl}{Pad9} med-curve-increase-r1 {Ctrl}{Pad4} med-curve-decrease-r4 {Ctrl}{Pad6} med-curve-increase-r4 {Ctrl}{Pad0} med-curve-set dxx-rebirth-0.58.1-d2x/editor/data/dummy.pad000066400000000000000000000000251217717237500205710ustar00rootroot00000000000000this is a test file dxx-rebirth-0.58.1-d2x/editor/data/group.pad000066400000000000000000000023111217717237500205720ustar00rootroot00000000000000Group Editing Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ Load ³ Save ³ Prev ³ ³ Lock ³ Group ³ Group ³ Group ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Move ³ 8 ³ Group ³ ³ ³ Group ³  ³Segment ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ Copy ³ 5 ³Ungroup ³ Group ³ ³ Group ³ ³Segment ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Rotate ³ 2 ³Degroup ³ ³ ³ Group ³  ³(Group) ³ ³ ³ ³ ³ ³ Create ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Group ³ ³ Mark Group ³ Delete ³ ³ ³ Segment ³ Group ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad/} med-group-load {Ctrl}{Pad*} med-group-save {Ctrl}{Pad-} med-prev-group {Ctrl}{Pad+} med-next-group {Ctrl}{Pad7} med-move-group {Ctrl}{Pad4} med-copy-group {Ctrl}{Pad1} med-rotate-group {Ctrl}{Pad9} med-group-segment {Ctrl}{Pad6} med-ungroup-segment {Ctrl}{Pad3} med-degroup-group {Ctrl}{Pad0} med-mark-groupseg {Ctrl}{Pad.} med-delete-group {Ctrl}{PadEnter} med-create-group dxx-rebirth-0.58.1-d2x/editor/data/lighting.pad000066400000000000000000000027271217717237500212560ustar00rootroot00000000000000Lighting Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³Smooth ³ Smooth ³ Quick ³ ³ Lock ³Lighting³Lighting³Lighting³ ³ ³on side ³ on All ³ on All ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³Decrease³Set ³Increase³ ³ ³Light/ ³Maximum ³Light/ ³Assign ³ ³Vertex ³Lighting³Vertex ³Default ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´Lighting³ ³Decrease³Set ³Increase³to All ³ ³Light/ ³Default ³Light/ ³ ³ ³Side ³Lighting³Side ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³Decrease³ 2 ³Increase³ ³ ³Light/ ³  ³Light/ ³ ³ ³Segment ³ ³Segment ³ Select ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ Copy Current ³ Copy to³ Vertex ³ ³ Intensity to ³ Whole ³ ³ ³ Whole Side ³ Segment³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{PadEnter} med-light-select-next-vertex {Ctrl}{Pad7} med-light-decrease-light-vertex {Ctrl}{Pad9} med-light-increase-light-vertex {Ctrl}{Pad4} med-light-decrease-light-side {Ctrl}{Pad5} med-light-set-default {Ctrl}{Pad6} med-light-increase-light-side {Ctrl}{Pad1} med-light-decrease-light-segment {Ctrl}{Pad3} med-light-increase-light-segment {Ctrl}{Pad0} med-light-copy-intensity-side {Ctrl}{Pad8} med-light-set-maximum {Ctrl}{Pad.} med-light-copy-intensity-segment {Ctrl}{Pad+} med-light-assign-default-all {Ctrl}{Pad-} med-seguvs-smooth-lighting-all-quick {Ctrl}{Pad*} med-seguvs-smooth-lighting-all {Ctrl}{Pad/} med-seguvs-smooth-lighting dxx-rebirth-0.58.1-d2x/editor/data/med.mnu000066400000000000000000000214421217717237500202440ustar00rootroot00000000000000;========================================================= 0, 0, &File, {}, , 0, 1, &Segment, {}, , 0, 2, &Group, {}, , 0, 3, &Build, {}, , 0, 4, &Texture, {}, , 0, 5, &Object, {}, , 0, 6, &Wall, {}, , 0, 7, &View, {}, , ;0, 8, &Macro, {}, , 0, 8, Oth&er, {}, , 0, 9, &Help, {}, , ;================= FILE MENU ============================ 1, 0, &New Mine, {}, med-mine-create-new, 1, 1, &Load Mine, {}, med-game-load, 1, 2, &Save Mine, {}, med-game-save, 1, 3, -, {}, , 1, 4, Save &compiled versions of all levels, {}, , 1, 5, Loa&d all levels (to regenerate PIGs), {}, , 1, 6, -, {}, , 1, 7, &Undo ^U, {Ctrl}{U}, med-autosave-undo, 1, 8, -, {}, , 1, 9, &Play in 320x200, {}, med-goto-game-screen, 1, 10, Go to &Main Menu, {}, med-goto-main-menu, 1, 11, -, {}, , 1, 12, &Autosave Toggle _A, {Shift}{A}, med-autosave-toggle, 1, 13, &Restore Game State, {}, med-restore-game-state, 1, 14, -, {}, , 1, 15, E&xit, {}, med-editor-exit, ;================= SEGMENT MENU =========================== 2, 0, &Add ^A, {Ctrl}{A}, med-segment-add, 2, 1, Add D&efault _E, {Shift}{E}, med-create-default-new-segment, 2, 2, &Delete ^D, {Ctrl}{D}, med-segment-delete, 2, 3, -, {}, , 2, 4, &Mark ^M, {Ctrl}{M}, med-segsel-set-marked, 2, 5, E&xchange Marked, {}, med-segment-exchange, 2, 6, -, {}, , 2, 7, Select next side &] ^F, {Ctrl}{F}, med-segsel-next-side, 2, 8, Select prev side &[ ^_F, {Ctrl}{Shift}{F}, med-segsel-prev-side, 2, 9, Select &next segment ^S, {Ctrl}{S}, med-segsel-next-segment, 2, 10, Select &previous segment ^_S, {Ctrl}{Shift}{S}, med-segsel-prev-segment, 2, 11, Select next found seg. &=, {}, med-select-next-found-seg, 2, 12, Select previous found seg. &-, {}, med-select-prev-found-seg, 2, 13, Select segment by n&umber, {}, , 2, 14, Select segment w/p&owerup, {}, , 2, 15, -, {}, , 2, 16, &Clear Selected List ^C, {Ctrl}{C}, med-clear-selected-list, 2, 17, &Sort Selected List, {}, med-sort-selected-list, 2, 18, Make Curside &Bottom ^B, {Ctrl}{B}, med-segment-bottom, 2, 19, Toggle Bottom, {}, med-segment-show-bottom, 2, 20, -, {}, , 2, 21, Make Refueling Center, {}, med-fuelcen-create, 2, 22, Make Control Center, {}, med-controlcen-create, 2, 23, Make Robot Materializator, {}, med-robotmaker-create, 2, 24, Reset all centers, {}, med-fuelcen-reset-all, 2, 25, Delete Center from Curseg, {}, med-fuelcen-delete, 2, 26, Do Centers Dialog _C, {Shift}{C}, do-centers-dialog, 2, 27, -, {}, , 2, 28, Make Blue Goal, {}, , 2, 29, Make Red Goal, {}, , 2, 30, Set Secret &Level Return Location, {}, , 2, 31, Synchronize Wall/Segment Info, {}, , ;================== GROUP MENU =============================== 3, 0, Select &Next Group ^N, {Ctrl}{N}, med-next-group, 3, 1, Select &Previous Group ^P, {Ctrl}{P}, med-prev-group, 3, 2, -, {}, , 3, 3, Show Names of all groups, {}, , 3, 4, Save selected segs as Group, {}, , 3, 5, -, {}, , 3, 6, &Add (Create) Group ^G, {Ctrl}{G}, med-create-group, 3, 7, Mo&ve Group ^_G, {Ctrl}{Shift}{G}, med-move-group, 3, 8, &Copy Group, {}, med-copy-group, 3, 9, &Rotate (and move) Group ^R, {Ctrl}{R}, med-rotate-group, 3, 10, -, {}, , 3, 11, &Ungroup Segment, {}, med-ungroup-segment, 3, 12, &Group Segment, {}, med-group-segment, 3, 13, &Degroup (Group), {}, med-degroup-group, 3, 14, -, {}, , 3, 15, &Load Group, {}, med-group-load, 3, 16, &Save Group, {}, med-group-save, 3, 17, &Mark Group Segment, {}, med-mark-groupseg, 3, 18, &X Delete Group, {}, med-delete-group, 3, 19, Su&btract From Group, {}, med-subtract-from-group, ;================= BUILD MENU =========================== 4, 0, &Bridge ^B, {Ctrl}{B}, med-build-bridge, 4, 1, &Joint ^J, {Ctrl}{J}, med-build-joint, 4, 2, -, {}, , 4, 3, Join Adj &Wall, {}, med-build-adj-joint, 4, 4, Join Adj &Segment, {}, med-build-adj-joints-segment, 4, 5, Join &All Adj Segments ^_A, {Ctrl}{Shift}{A}, med-build-adj-joints-all, 4, 6, -, {}, , 4, 7, &Punch a sloppy connection _P, {Shift}{P}, med-build-sloppy-adj-joint, 4, 8, P&unch all sloppy in group, {}, med-build-sloppy-adj-joint-group, ;================= TMAP Menu ================================ 5, 0, Assign Texture &1 _1, {Shift}{1}, med-tmap-assign, 5, 1, Assign Texture &2 _2, {Shift}{2}, med-tmap-assign2, 5, 2, Clear Texture 2 (&0) _0, {Shift}{0}, med-tmap-clear2, 5, 3, &Propagate, {}, med-tmap-propogate, 5, 4, &Move and Propagate, {}, med-tmap-propogate-move, 5, 5, Propagate &Textures Only, {}, med-tmap-propogate-uvs, 5, 6, Move Propagate &Textures Only, {}, med-tmap-propogate-move-uvs, 5, 7, Propagate &Selected, {}, med-tmap-propogate-selected, ;===================== OBJECT MENU ==================================== 6, 0, &Place Object, {}, med-obj-place-object, 6, 1, P&lace Object/Cur Tmap, {}, med-obj-place-object-tmap, 6, 2, &Delete Object, {}, med-obj-delete-object, 6, 3, &Set Player Position, {}, med-obj-set-player, 6, 4, -, {}, , 6, 5, &AI Properties..., {Shift}{R}, do-robot-dialog, 6, 6, &Object Editor..., {Shift}{O}, do-object-dialog, 6, 7, &Make Object COOP, {}, med-obj-make-coop, ;===================== WALL MENU ==================================== 7, 0, Add &Blastable Wall, {}, med-wall-add-blastable, 7, 1, Add &Door, {}, med-wall-add-door, 7, 2, Add &Illusory Wall, {}, med-wall-add-illusion, 7, 3, Add &Closed Wall, {}, med-wall-add-closed, 7, 4, Add &External Wall, {}, med-wall-add-external, 7, 5, -, {}, , 7, 6, Restore &All Walls, {}, med-wall-restore-all, 7, 7, &Remove Wall, {}, med-wall-remove, 7, 8, -, {}, , 7, 9, &Link doors, {}, med-link-doors, 7, 10, &Unlink door, {}, med-unlink-door, 7, 11, -, {}, , 7, 12, Do &Wall Dialog, {Shift}{W}, do-wall-dialog, 7, 13, Do &Trigger Dialog, {Shift}{T}, do-trigger-dialog, 7, 14, -, {}, , 7, 15, Delete ALL Walls, {}, delete-all-walls, 7, 16, Check Walls, {}, check-walls, 7, 17, -, {}, , 7, 18, Delete ALL Control Center Trigges, {}, , ;===================== VIEW MENU ==================================== 8, 0, Zoom &In, {}, med-view-zoom-in, 8, 1, Zoom &Out, {}, med-view-zoom-out, 8, 2, -, {}, , 8, 3, Move &Closer, {}, med-view-move-closer, 8, 4, Move &Away, {}, med-view-move-away, 8, 5, -, {}, , 8, 6, Show &More Segments, {}, med-increase-draw-depth, 8, 7, Show &Less Segments, {}, med-decrease-draw-depth, 8, 8, -, {}, , 8, 9, Lean a&gainst CurSide ^_C, {Ctrl}{Shift}{C}, med-set-player-from-curseg, 8, 10, &Face Curside, {}, med-set-player-from-curseg-minus-one, ;;;===================== MACRO MENU =================================== ;;9, 0, Play &fast, {}, med-macro-play-fast, ;;9, 1, Play &normal, {}, med-macro-play-normal, ;;9, 2, -, {}, , ;;9, 3, Record &All, {}, med-macro-record-all, ;;9, 4, Record &Keystrokes, {}, med-macro-record-keys, ;;9, 5, -, {}, , ;;9, 6, &Save macro, {}, med-macro-save, ;;9, 7, &Load macro, {}, med-macro-load, ;====================== OTHER MENU =================================== 9, 0, &Clear Selected list, {}, , 9, 1, -, {}, , 9, 2, &Flag concave segments, {}, med-find-concave-segs, 9, 3, Flag &Intersecting segments, {}, , 9, 4, -, {}, , 9, 5, Make Curside &planar, {}, , 9, 6, &All sides in Cursegp planar, {}, , 9, 7, -, {}, , 9, 8, &Update Screen, {}, med-update, 9, 9, -, {}, , 9, 10, &Mark Start _M, {Shift}{M}, med-mark-start, 9, 11, Mark &End ^_M, {Ctrl}{Shift}{M}, med-mark-end, 9, 12, -, {}, , 9, 13, &Rename level, {}, rename-level, 9, 14, -, {}, , 9, 15, &Select palette, {}, , 9, 16, -, {}, , 9, 17, Set reactor explode &time, {}, , 9, 18, Set reactor stren>h, {}, , 9, 19, -, {}, , 9, 20, Fix &Bogus uvs on side, {}, med-seguvs-fix-bogus-uvs-on-side, 9, 21, Fix Bogus uvs All _B, {Shift}{B}, med-seguvs-fix-bogus-uvs-all, 9, 22, -, {}, , 9, 23, Assign Lava &Volatility, {}, , 9, 24, -, {}, , 9, 25, Set Flickering &Light, {}, , ;======================== Help Index ================================= 10, 0, &About MED, {}, med-about, ;======================== END ================================= dxx-rebirth-0.58.1-d2x/editor/data/newobj.pad000066400000000000000000000030041217717237500207220ustar00rootroot00000000000000Object Placement Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ Next ³ Make ³ ³ Lock ³ ³ Obj in ³ Smaller³ ³ ³ ³ Segment³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 7 ³ Move ³ Move ³ ³ ³ Home ³ Forward³ Up ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Make ³ ³ Move ³ Set ³ Move ³ Larger ³ ³ Left ³ Default³ Right ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 1 ³ Move ³ Move ³ ³ ³ End ³ Back ³ Down ³ ³ ³ ³ ³ ³ Select ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ Place ³ Delete ³ Object ³ ³ Object ³ Object ³ Type ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad*} med-obj-select-next-in-segment {Ctrl}{Pad-} med-obj-make-smaller {Ctrl}{Pad+} med-obj-make-larger {Ctrl}{Pad8} med-obj-move-forward {Ctrl}{Pad9} med-obj-move-up {Ctrl}{Pad4} med-obj-move-left {Ctrl}{Pad5} med-obj-set-default {Ctrl}{Pad6} med-obj-move-right {Ctrl}{Pad2} med-obj-move-back {Ctrl}{Pad3} med-obj-move-down {Ctrl}{PadEnter} med-obj-select-next-type {Ctrl}{Pad0} med-obj-place-object {Ctrl}{Pad.} med-obj-delete-object {Shift}{Pad1} med-obj-decrease-bank {Shift}{Pad3} med-obj-increase-bank {Shift}{Pad2} med-obj-decrease-pitch {Shift}{Pad8} med-obj-increase-pitch {Shift}{Pad4} med-obj-decrease-heading {Shift}{Pad6} med-obj-increase-heading {Shift}{Pad5} med-obj-reset dxx-rebirth-0.58.1-d2x/editor/data/object.pad000066400000000000000000000024001217717237500207030ustar00rootroot00000000000000Object Placement Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ Next ³ Move ³ ³ Lock ³ ³ Obj in ³ Away on³ ³ ³ ³ Segment³ Vector ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 7 ³ Move ³ Move ³ ³ ³ Home ³ Forward³ Up ³ ³ ³ ³ ³ ³ Move ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Nearer ³ ³ Move ³ Set ³ Move ³ on ³ ³ Left ³ Default³ Right ³ Vector ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 1 ³ Move ³ Move ³ ³ ³ End ³ Back ³ Down ³ ³ ³ ³ ³ ³ Select ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ Place ³ Delete ³ Object ³ ³ Object ³ Object ³ Type ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad*} med-obj-select-next-in-segment {Ctrl}{Pad-} med-obj-move-further {Ctrl}{Pad+} med-obj-move-nearer {Ctrl}{Pad8} med-obj-move-forward {Ctrl}{Pad9} med-obj-move-up {Ctrl}{Pad4} med-obj-move-left {Ctrl}{Pad5} med-obj-set-default {Ctrl}{Pad6} med-obj-move-right {Ctrl}{Pad2} med-obj-move-back {Ctrl}{Pad3} med-obj-move-down {Ctrl}{PadEnter} med-obj-select-next-type {Ctrl}{Pad0} med-obj-place-object {Ctrl}{Pad.} med-obj-delete-object dxx-rebirth-0.58.1-d2x/editor/data/objmov.pad000066400000000000000000000030121217717237500207310ustar00rootroot00000000000000Object Rotation Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ Next ³ - ³ ³ Lock ³ ³ Obj in ³ ³ ³ ³ ³ Segment³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Flip ³Increase³ 9 ³ ³ ³ Object ³ Pitch ³ PgUp ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ + ³ ³Decrease³ Reset ³Increase³ ³ ³Heading ³ Object ³Heading ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³Decrease³Decrease³Increase³ ³ ³ Bank ³ Pitch ³ Bank ³ ³ ³ ³ ³ ³ Select ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ Place ³ Delete ³ Object ³ ³ Object ³ Object ³ Type ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad*} med-obj-select-next-in-segment {Ctrl}{Pad1} med-obj-decrease-bank {Ctrl}{Pad3} med-obj-increase-bank {Ctrl}{Pad2} med-obj-decrease-pitch {Ctrl}{Pad8} med-obj-increase-pitch {Ctrl}{Pad4} med-obj-decrease-heading {Ctrl}{Pad6} med-obj-increase-heading {Ctrl}{Pad7} med-obj-flip {Ctrl}{Pad5} med-obj-reset {Ctrl}{PadEnter} med-obj-select-next-type {Ctrl}{Pad0} med-obj-place-object {Ctrl}{Pad.} med-obj-delete-object {Ctrl}{Shift}{Pad1} med-obj-decrease-bank-big {Ctrl}{Shift}{Pad3} med-obj-increase-bank-big {Ctrl}{Shift}{Pad2} med-obj-decrease-pitch-big {Ctrl}{Shift}{Pad8} med-obj-increase-pitch-big {Ctrl}{Shift}{Pad4} med-obj-decrease-heading-big {Ctrl}{Shift}{Pad6} med-obj-increase-heading-big dxx-rebirth-0.58.1-d2x/editor/data/pc6x8.fnt000066400000000000000000000040441217717237500204360ustar00rootroot00000000000000PSFNÿpø¨øØˆppø¨øˆØpPøøøp pøøp pPø¨ø p pøøø p pp øøØˆˆØøø PP øøØ¨¨Øøø8h  @pˆˆp ø xHx@@@ÀxHxHHXÀ ¨pØØp¨ €ÀðøðÀ€xøx p¨ ¨p ØØØØØØx¨¨h(((0HP(HH0üü p¨ ¨p ø p¨ ¨p ø @ø@ €€€øPøøP pøøøøp PPPPPøPøPP x p(ð ÀÈ @˜@  @¨h00 @ @@@ @  @ ¨pøp¨ ø 00 @ø00 @€pˆ˜¨Èˆp ` ppˆp€€øø0ˆp0Pøø€ðˆp8@€ðˆˆpø @€pˆˆpˆˆppˆˆxà @ @ øø@  @pˆ0 pˆ¨¸°€x Pˆˆøˆˆðˆˆðˆˆðpˆ€€€ˆpðˆˆˆˆˆðø€€ð€€øø€€ð€€€xˆ€€˜ˆxˆˆˆøˆˆˆp p8`ˆ À ˆ€€€€€€øˆØ¨¨¨ˆˆˆˆÈ¨˜ˆˆpˆˆˆˆˆpðˆˆð€€€pˆˆˆ¨hðˆˆð ˆpˆ€pˆpø¨ ˆˆˆˆˆˆpˆˆˆˆˆP ˆˆˆ¨¨¨PˆˆP PˆˆˆˆP øp@€øx@@@@@x€@ xx Pˆø`` `px€€°ÈˆÈ°pˆ€ˆph˜ˆ˜hpˆø€p( p p˜˜hp€€°Èˆˆˆ ` p`€€ À ` pШ¨¨¨°Èˆˆˆpˆˆˆp°ÈȰ€€h˜˜h°È€€€x€pð ø (ˆˆˆ˜hˆˆˆP ˆˆ¨¨PˆP Pˆˆˆxˆpø @ø @  @  @@¨ p؈ˆøpˆ€€ˆp`ˆˆˆ˜hpˆø€xø`pxˆ`pxÀ`px0`pxxÀÀx0øpˆø€xˆpˆø€xÀpˆø€x(080H08`08P Pˆøˆˆ Pˆøˆˆ0ð€à€ð|x|þ><~~<fffffffffÛÛÛ{|Æ`8lÆÆl8 Æ|þþþþ<~~<~<~~< þ 0`þ`0ÀÀÀþ(lþl(88||þþþþ||88<<<fff$llþlllþll|ÆÂÀ|†Æ|ÂÆ 0`Ɔ8ll8vÜÌÌÌv000` 000000 0 0f<ÿlÌÌþÌÌÌÌÎ8l|ÆÆÆÆÆ|Æ|ÆÆÆÆÆ|`0|ÆÆÆÆÆ|0xÌÌÌÌÌÌÌv`0ÌÌÌÌÌÌvÆÆÆÆÆÆÆ~ xÆ|ÆÆÆÆÆÆÆ|ÆÆÆÆÆÆÆÆÆ|~8ll8|0000`ÀÆÆ|þÀÀÀÀþÀÀÂÆÌ0`܆ >ÀÀÂÆÌ0fΞ><<<6lØl6Øl6lØDDDDDDDDUªUªUªUªUªUªUªUªÝwÝwÝwÝwÝwÝwÝwÝwøøø6666666ö66666666þ66666666øø66666öö666666666666666666666666þö6666666666666öþ6666666þøøøÿÿÿÿ66666667666666666666670??076666666666666÷ÿÿ÷666666666666670766666666ÿÿ66666÷÷66666666ÿÿ6666666ÿÿÿÿ666666666666666??666666666666666ÿ66666666ÿÿøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿððððððððððððððððÿÿÿÿÿÿÿvÜØØØÜvxÌÌÌØÌÆÆÆÌþÆÆÀÀÀÀÀÀÀþlllllllþÆ`00`Æþ~ØØØØØpfffff|``ÀvÜ~ffff<~ÛÛÛ~~ÛÛó~`À0``|```0|ÆÆÆÆÆÆÆÆþþþ~ÿ0  0~ 0`0 ~ØØØp~vÜvÜ8ll8 ìll<ØlllllpØ0`Èø|||||||dxx-rebirth-0.58.1-d2x/editor/data/segmove.pad000066400000000000000000000020521217717237500211050ustar00rootroot00000000000000Segment rotation ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ * ³ - ³ ³ Lock ³ ³ ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 7 ³ Pitch ³ 9 ³ ³ ³ Home ³ Forward³ PgUp ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ + ³ ³ Rotate ³ 5 ³ Rotate ³ ³ ³ Left ³ ³ Right ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Bank ³ Pitch ³ Bank ³ ³ ³ Left ³Backward³ Right ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Enter ³ ³ 0 ³ . ³ ³ ³ Ins ³ Del ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad8} med-segmove-increase-pitch {Ctrl}{Pad2} med-segmove-decrease-pitch {Ctrl}{Pad4} med-segmove-decrease-heading {Ctrl}{Pad6} med-segmove-increase-heading {Ctrl}{Pad1} med-segmove-decrease-bank {Ctrl}{Pad3} med-segmove-increase-bank dxx-rebirth-0.58.1-d2x/editor/data/segsize.pad000066400000000000000000000036171217717237500211210ustar00rootroot00000000000000Segment Scaling Mode ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³Increase³Increase³Increase³ ³ Lock ³Length ³Width ³Height ³ ³ ³Default ³Default ³Default ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 7 ³Increase³Increase³ ³ ³ Home ³Length ³Height ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Perturb³ ³Decrease³ 5 ³Increase³ Curside³ ³Width ³ ³Width ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 1 ³Decrease³Decrease³ ³ ³ End ³Length ³Height ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Next ³ ³ 0 ³ . ³ Edge ³ ³ Select Next ³ Next ³ ³ ³ Mode ³ Vertex ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad6} med-segsize-increase-width {Ctrl}{Pad8} med-segsize-increase-length {Ctrl}{Pad9} med-segsize-increase-height {Ctrl}{Pad4} med-segsize-decrease-width {Ctrl}{Pad2} med-segsize-decrease-length {Ctrl}{Pad3} med-segsize-decrease-height {Ctrl}{Shift}{Pad6} med-segsize-increase-width-big {Ctrl}{Shift}{Pad8} med-segsize-increase-length-big {Ctrl}{Shift}{Pad9} med-segsize-increase-height-big {Ctrl}{Shift}{Pad4} med-segsize-decrease-width-big {Ctrl}{Shift}{Pad2} med-segsize-decrease-length-big {Ctrl}{Shift}{Pad3} med-segsize-decrease-height-big {Ctrl}{Pad0} med-segsize-toggle-mode {Ctrl}{Pad.} med-light-select-next-vertex {Ctrl}{PadEnter} med-light-select-next-edge {Ctrl}{Pad+} med-segsize-perturb-curside {Ctrl}{Shift}{Pad+} med-segsize-perturb-curside-big {Ctrl}{Pad/} med-segsize-increase-length-default {Ctrl}{Pad*} med-segsize-increase-width-default {Ctrl}{Pad-} med-segsize-increase-height-default {Ctrl}{Shift}{Pad/} med-segsize-decrease-length-default {Ctrl}{Shift}{Pad*} med-segsize-decrease-width-default {Ctrl}{Shift}{Pad-} med-segsize-decrease-height-default dxx-rebirth-0.58.1-d2x/editor/data/test.pad000066400000000000000000000016031217717237500204200ustar00rootroot00000000000000Temporary Test Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Num ³ / ³ * ³ - ³ ³ Lock ³ ³ ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ 7 ³ 8 ³ 9 ³ ³ ³ Home ³  ³ PgUp ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ + ³ ³ 4 ³ 5 ³ 6 ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Test ³ Test ³ Test ³ ³ ³Function³Function³Function³ ³ ³ 1 ³ 2 ³ 3 ³ ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Enter ³ ³ 0 ³ . ³ ³ ³ Ins ³ Del ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad1} med-test-1 {Ctrl}{Pad2} med-test-2 {Ctrl}{Pad3} med-test-3 dxx-rebirth-0.58.1-d2x/editor/data/texture.pad000066400000000000000000000030661217717237500211460ustar00rootroot00000000000000Texture Mapping Functions ÚÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ¿ ³ Remap ³ Flip ³ Flip ³ Remap ³ ³ Crsd to³ in X ³ in Y ³ Tmap2 ³ ³ Current³ ³ ³ to Curr³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Stretch³ Slide ³ Stretch³ ³ ³ Less ³ Up ³ More ³ Set ³ ³ ³ ³ ³ Default³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ in ³ ³ Slide ³ Set ³ Slide ³Selected³ ³ Left ³ Default³ Right ³ List ³ ³ ³ ³ ³ ³ ÃÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ ³ Rotate ³ Slide ³ Rotate ³ ³ ³ Left ³ Down ³ Right ³ ³ ³ ³ ³ ³ Select ³ ÃÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄ´ Active ³ ³ Rotate ³ Next ³ Edge ³ ³ 90 degrees ³ Edge ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÙ {Ctrl}{Pad/} med-tass-flip-x {Ctrl}{Pad*} med-tass-flip-y {Ctrl}{Pad8} med-tass-slide-up {Ctrl}{Pad4} med-tass-slide-left {Ctrl}{Pad5} med-tass-set-default {Ctrl}{Pad6} med-tass-slide-right {Ctrl}{Pad7} med-tass-stretch-down {Ctrl}{Pad9} med-tass-stretch-up {Ctrl}{Pad1} med-tass-rotate-left {Ctrl}{Pad2} med-tass-slide-down {Ctrl}{Pad3} med-tass-rotate-right {Ctrl}{PadEnter} med-tass-select-active-edge {Ctrl}{Pad0} med-tass-rotate-90-degrees {Ctrl}{Pad.} med-light-select-next-edge {Ctrl}{Shift}{Pad8} med-tass-slide-up-big {Ctrl}{Shift}{Pad4} med-tass-slide-left-big {Ctrl}{Shift}{Pad6} med-tass-slide-right-big {Ctrl}{Shift}{Pad1} med-tass-rotate-left-big {Ctrl}{Shift}{Pad2} med-tass-slide-down-big {Ctrl}{Shift}{Pad3} med-tass-rotate-right-big dxx-rebirth-0.58.1-d2x/editor/eglobal.c000066400000000000000000000072631217717237500176230ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Globals for editor. * */ #include #include "inferno.h" #include "segment.h" #include "editor.h" // Global pointer to current vertices, right now always Vertices. Set in create_new_mine. // segment New_segment; // segment which can be added to the mine. // replaced by a macro segment *Cursegp = NULL; // Pointer to current segment in mine. int Curside; // Side index in 0..MAX_SIDES_PER_SEGMENT of active side. int Curedge; // Current edge on current side, in 0..3 int Curvert; // Current vertex on current side, in 0..3 int AttachSide = WFRONT; // Side on segment to attach. segment *Markedsegp = NULL; // Marked segment, used in conjunction with *Cursegp to form joints. int Markedside; // Marked side on Markedsegp. int Draw_all_segments; // Set to 1 means draw_world draws all segments in Segments, else draw only connected segments sbyte Vertex_active[MAX_VERTICES]; // !0 means vertex is in use, 0 means not in use. int N_selected_segs = 0; // Number of segments found at Selected_segs short Selected_segs[MAX_SELECTED_SEGS]; // List of segment numbers currently selected int N_warning_segs = 0; // Number of segments warning-worthy, such as a concave segment short Warning_segs[MAX_WARNING_SEGS]; // List of segment numbers currently selected int N_found_segs = 0; // Number of segments found with last shift-mouse-click short Found_segs[MAX_FOUND_SEGS]; // List of warning-worthy segments int Show_axes_flag = 0; // 0 = don't show, !0 = do show coordinate axes in *Cursegp orientation sbyte Been_visited[MAX_SEGMENTS]; // List of segments visited in a recursive search, if element n set, segment n done been visited // Variables global to this editor.c and the k?????.c files. uint Update_flags = UF_ALL; //force total redraw int Funky_chase_mode = 0; vms_angvec Seg_orientation = {0,0,0}; vms_vector Seg_scale = {F1_0*20,F1_0*20,F1_0*20}; int mine_changed = 0; int ModeFlag; editor_view *current_view; int SegSizeMode = 1; // Mode = 0/1 = not/is legal to move bound vertices, //the view for the different windows. editor_view LargeView = {0,1, NULL, i2f(100),IDENTITY_MATRIX,f1_0}; #if ORTHO_VIEWS editor_view TopView = {1,1, NULL, i2f(100),{{f1_0,0,0},{0,0,-f1_0},{0,f1_0,0}},f1_0}; editor_view FrontView = {2,1, NULL, i2f(100),{{f1_0,0,0},{0,f1_0,0},{0,0,f1_0}},f1_0}; editor_view RightView = {3,1, NULL, i2f(100),{{0,0,f1_0},{0,f1_0,0},{f1_0,0,0}},f1_0}; #endif editor_view *Views[ORTHO_VIEWS ? 4 : 1] = {&LargeView, #if ORTHO_VIEWS &TopView,&FrontView,&RightView #endif }; int N_views = (sizeof(Views) / sizeof(*Views)); int Lock_view_to_cursegp = 1; // !0 means whenever cursegp changes, view it int Num_tilings = 1; // Number of tilings per wall short Cur_object_index = -1; // The current object type and id short Cur_object_type = 4; // OBJ_PLAYER short Cur_object_id = 0; // !0 if a degenerate segment has been found. int Degenerate_segment_found=0; dxx-rebirth-0.58.1-d2x/editor/elight.c000066400000000000000000000214601217717237500174650ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Editor lighting functions. * */ #include #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "seguvs.h" #include "wall.h" #include "textures.h" #include "fix.h" #include "dxxerror.h" #include "kdefs.h" #include "gameseg.h" #include "texmap.h" // ----------------------------------------------------------------------------- // Return light intensity at an instance of a vertex on a side in a segment. fix get_light_intensity(segment *segp, int sidenum, int vert) { Assert(sidenum <= MAX_SIDES_PER_SEGMENT); Assert(vert <= 3); return segp->sides[sidenum].uvls[vert].l; } // ----------------------------------------------------------------------------- // Set light intensity at a vertex, saturating in .5 to 15.5 void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity) { Assert(sidenum <= MAX_SIDES_PER_SEGMENT); Assert(vert <= 3); if (intensity < MIN_LIGHTING_VALUE) intensity = MIN_LIGHTING_VALUE; if (intensity > MAX_LIGHTING_VALUE) intensity = MAX_LIGHTING_VALUE; segp->sides[sidenum].uvls[vert].l = intensity; Update_flags |= UF_WORLD_CHANGED; } // ----------------------------------------------------------------------------- // Add light intensity to a vertex, saturating in .5 to 15.5 void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity) { // fix new_intensity; set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity); } // ----------------------------------------------------------------------------- // Recursively apply light to segments. // If current side is a wall, apply light there. // If not a wall, apply light to child through that wall. // Notes: // It is possible to enter a segment twice by taking different paths. It is easy // to prevent this by maintaining a list of visited segments, but it is important // to reach segments with the greatest light intensity. This can be done by doing // a breadth-first-search, or by storing the applied intensity with a visited segment, // and if the current intensity is brighter, then apply the difference between it and // the previous intensity. // Note that it is also possible to visit the original light-casting segment, for example // going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not // desired, but not entirely invalid. 2 reflects some light back to 0. void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth) { int wid_result; if (intensity == 0) return; wid_result = WALL_IS_DOORWAY(segp, sidenum); if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) { int v; for (v=0; v<4; v++) // add light to this wall add_light_intensity(segp, sidenum, v, intensity); return; // we return because there is a wall here, and light does not shine through walls } // No wall here, so apply light recursively if (depth < 3) { int s; for (s=0; schildren[sidenum]], s, intensity/3, depth+1); } } // ----------------------------------------------------------------------------- // Top level recursive function for applying light. // Calls apply_light_intensity. // Uses light value on segp:sidenum (tmap_num2 defines light value) and applies // the associated intensity to segp. It calls apply_light_intensity to apply intensity/3 // to all neighbors. apply_light_intensity recursively calls itself to apply light to // subsequent neighbors (and forming loops, see above). void propagate_light_intensity(segment *segp, int sidenum) { int v,s; fix intensity; short texmap; intensity = 0; texmap = segp->sides[sidenum].tmap_num; intensity += TmapInfo[texmap].lighting; texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff; intensity += TmapInfo[texmap].lighting; if (intensity > 0) { for (v=0; v<4; v++) add_light_intensity(segp, sidenum, v, intensity); // Now, for all sides which are not the same as sidenum (the side casting the light), // add a light value to them (if they have no children, ie, they have a wall there). for (s=0; s= 4) Curvert = 0; Update_flags |= UF_WORLD_CHANGED; return 1; } // ----------------------------------------------------------------------------- int LightSelectNextEdge(void) { Curedge++; if (Curedge >= 4) Curedge = 0; Update_flags |= UF_WORLD_CHANGED; return 1; } // ----------------------------------------------------------------------------- // Copy intensity from current vertex to all other vertices on side. int LightCopyIntensity(void) { int v,intensity; intensity = get_light_intensity(Cursegp, Curside, Curvert); for (v=0; v<4; v++) if (v != Curvert) set_light_intensity(Cursegp, Curside, v, intensity); return 1; } // ----------------------------------------------------------------------------- // Copy intensity from current vertex to all other vertices on side. int LightCopyIntensitySegment(void) { int s,v,intensity; intensity = get_light_intensity(Cursegp, Curside, Curvert); for (s=0; s #include #include #include #include #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "objpage.h" #include "fix.h" #include "dxxerror.h" #include "kdefs.h" #include "object.h" #include "polyobj.h" #include "game.h" #include "ai.h" #include "bm.h" #include "3d.h" // For g3_point_to_vec #include "fvi.h" #include "powerup.h" #include "fuelcen.h" #include "hostage.h" #include "medrobot.h" #include "player.h" #include "gameseg.h" #include "cntrlcen.h" #define OBJ_SCALE (F1_0/2) #define OBJ_DEL_SIZE (F1_0/2) #define ROTATION_UNIT (4096/4) //segment *Cur_object_seg = -1; void show_objects_in_segment(segment *sp) { short objid; objid = sp->objects; while (objid != -1) { objid = Objects[objid].next; } } //returns the number of the first object in a segment, skipping the player int get_first_object(segment *seg) { int id; id = seg->objects; if (id == (ConsoleObject-Objects)) id = Objects[id].next; return id; } //returns the number of the next object in a segment, skipping the player int get_next_object(segment *seg,int id) { if (id==-1 || (id=Objects[id].next)==-1) return get_first_object(seg); if (id == (ConsoleObject-Objects)) return get_next_object(seg,id); return id; } //@@// ------------------------------------------------------------------------------------------------------ //@@// this should be called whenever the current segment may have changed //@@// If Cur_object_seg != Cursegp, then update various variables. //@@// this used to be called update_due_to_new_segment() //@@void ObjectUpdateCurrent(void) //@@{ //@@ if (Cur_object_seg != Cursegp) { //@@ Cur_object_seg = Cursegp; //@@ Cur_object_index = get_first_object(Cur_object_seg); //@@ Update_flags |= UF_WORLD_CHANGED; //@@ } //@@ //@@} // ------------------------------------------------------------------------------------ int place_object(segment *segp, vms_vector *object_pos, short object_type, short object_id) { short objnum=0; object *obj; vms_matrix seg_matrix; med_extract_matrix_from_segment(segp,&seg_matrix); switch (object_type) { case OBJ_HOSTAGE: objnum = obj_create(OBJ_HOSTAGE, -1, segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE, CT_NONE,MT_NONE,RT_HOSTAGE); if ( objnum < 0 ) return 0; obj = &Objects[objnum]; // Fill in obj->id and other hostage info // hostage_init_info( objnum ); //don't need to anymore obj->control_type = CT_POWERUP; obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[object_id]; obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time; obj->rtype.vclip_info.framenum = 0; break; case OBJ_ROBOT: objnum = obj_create(OBJ_ROBOT, object_id, segp - Segments, object_pos, &seg_matrix, Polygon_models[Robot_info[object_id].model_num].rad, CT_AI, MT_PHYSICS, RT_POLYOBJ); if ( objnum < 0 ) return 0; obj = &Objects[objnum]; //Set polygon-object-specific data obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; obj->rtype.pobj_info.subobj_flags = 0; //set Physics info obj->mtype.phys_info.mass = Robot_info[obj->id].mass; obj->mtype.phys_info.drag = Robot_info[obj->id].drag; obj->mtype.phys_info.flags |= (PF_LEVELLING); obj->shields = Robot_info[obj->id].strength; { int hide_segment; if (Markedsegp) hide_segment = Markedsegp-Segments; else hide_segment = -1; // robots which lunge forward to attack cannot have behavior type still. if (Robot_info[obj->id].attack_type) init_ai_object(obj-Objects, AIB_NORMAL, hide_segment); else init_ai_object(obj-Objects, AIB_STILL, hide_segment); } break; case OBJ_POWERUP: objnum = obj_create(OBJ_POWERUP, object_id, segp - Segments, object_pos, &seg_matrix, Powerup_info[object_id].size, CT_POWERUP, MT_NONE, RT_POWERUP); if ( objnum < 0 ) return 0; obj = &Objects[objnum]; //set powerup-specific data obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num; obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames; obj->rtype.vclip_info.framenum = 0; if (obj->id == POW_VULCAN_WEAPON) obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT; else obj->ctype.powerup_info.count = 1; break; case OBJ_CNTRLCEN: { objnum = obj_create(OBJ_CNTRLCEN, object_id, segp - Segments, object_pos, &seg_matrix, Polygon_models[object_id].rad, CT_CNTRLCEN, MT_NONE, RT_POLYOBJ); if ( objnum < 0 ) return 0; obj = &Objects[objnum]; //Set polygon-object-specific data obj->shields = 0; // stored in Reactor_strength or calculated obj->rtype.pobj_info.model_num = Reactors[object_id].model_num; obj->rtype.pobj_info.subobj_flags = 0; break; } case OBJ_PLAYER: { objnum = obj_create(OBJ_PLAYER, object_id, segp - Segments, object_pos, &seg_matrix, Polygon_models[Player_ship->model_num].rad, CT_NONE, MT_PHYSICS, RT_POLYOBJ); if ( objnum < 0 ) return 0; obj = &Objects[objnum]; //Set polygon-object-specific data obj->rtype.pobj_info.model_num = Player_ship->model_num; obj->rtype.pobj_info.subobj_flags = 0; //for (i=0;irtype.pobj_info.anim_angles[i]); //set Physics info vm_vec_zero(&obj->mtype.phys_info.velocity); obj->mtype.phys_info.mass = Player_ship->mass; obj->mtype.phys_info.drag = Player_ship->drag; obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE; obj->shields = i2f(100); break; } default: break; } Cur_object_index = objnum; //Cur_object_seg = Cursegp; show_objects_in_segment(Cursegp); Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ // Count number of player objects, return value. int compute_num_players(void) { int i, count = 0; for (i=0; i<=Highest_object_index; i++) if (Objects[i].type == OBJ_PLAYER) count++; return count; } int ObjectMakeCoop(void) { Assert(Cur_object_index != -1); Assert(Cur_object_index < MAX_OBJECTS); // Assert(Objects[Cur_object_index.type == OBJ_PLAYER); if (Objects[Cur_object_index].type == OBJ_PLAYER ) { Objects[Cur_object_index].type = OBJ_COOP; editor_status("You just made a player object COOPERATIVE"); } else editor_status("This is not a player object"); return 1; } // ------------------------------------------------------------------------------------------------------ // Place current object at center of current segment. int ObjectPlaceObject(void) { int old_cur_object_index; int rval; vms_vector cur_object_loc; #ifdef SHAREWARE if (Cur_object_type == OBJ_PLAYER) { int num_players = compute_num_players(); Assert(num_players <= MAX_PLAYERS); if (num_players == MAX_PLAYERS) { editor_status("Can't place player object. Already %i players.", MAX_PLAYERS); return -1; } } #endif #ifndef SHAREWARE if (Cur_object_type == OBJ_PLAYER) { int num_players = compute_num_players(); Assert(num_players <= MAX_MULTI_PLAYERS); if (num_players > MAX_PLAYERS) editor_status("You just placed a cooperative player object"); if (num_players == MAX_MULTI_PLAYERS) { editor_status_fmt("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS); return -1; } } #endif //update_due_to_new_segment(); compute_segment_center(&cur_object_loc, Cursegp); old_cur_object_index = Cur_object_index; rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id); if (old_cur_object_index != Cur_object_index) Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1; return rval; } // ------------------------------------------------------------------------------------------------------ // Place current object at center of current segment. int ObjectPlaceObjectTmap(void) { int rval, old_cur_object_index; vms_vector cur_object_loc; //update_due_to_new_segment(); compute_segment_center(&cur_object_loc, Cursegp); old_cur_object_index = Cur_object_index; rval = place_object(Cursegp, &cur_object_loc, Cur_object_type, Cur_object_id); if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ)) Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture; else editor_status("Unable to apply current texture map to this object."); return rval; } // ------------------------------------------------------------------------------------------------------ int ObjectSelectNextinSegment(void) { int id; segment *objsegp; //update_due_to_new_segment(); //Assert(Cur_object_seg == Cursegp); if (Cur_object_index == -1) { objsegp = Cursegp; Cur_object_index = objsegp->objects; } else { objsegp = Cursegp; if (Objects[Cur_object_index].segnum != Cursegp-Segments) Cur_object_index = objsegp->objects; } //Debug: make sure current object is in current segment for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next); Assert(id == Cur_object_index); //should have found object // Select the next object, wrapping back to start if we are at the end of the linked list for this segment. if (id != -1) Cur_object_index = get_next_object(objsegp,Cur_object_index); Update_flags |= UF_WORLD_CHANGED; return 1; } //Moves to next object in the mine, skipping the player int ObjectSelectNextInMine() { int i; for (i=0;i= MAX_OBJECTS ) Cur_object_index= 0; if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) { Cursegp = &Segments[Objects[Cur_object_index ].segnum]; med_create_new_segment_from_cursegp(); //Cur_object_seg = Cursegp; return 1; } } Cur_object_index = -1; Update_flags |= UF_WORLD_CHANGED; return 0; } //Moves to next object in the mine, skipping the player int ObjectSelectPrevInMine() { int i; for (i=0;ipos, segnum, 0, __FILE__, __LINE__); if (result.centermask == 0) { int fate; fvi_info hit_info; fvi_query fq; // See if the radius pokes through any wall. fq.p0 = &obj->pos; fq.startseg = obj->segnum; fq.p1 = newpos; fq.rad = obj->size; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = 0; fate = find_vector_intersection(&fq,&hit_info); if (fate != HIT_WALL) { if ( segnum != obj->segnum ) obj_relink( obj-Objects, segnum); obj->pos = *newpos; return 0; } } } return 1; } // Return 0 if object is in expected segment, else return 1 int verify_object_seg(object *objp, vms_vector *newpos) { segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__); if (result.facemask == 0) return 0; else return move_object_within_mine(objp, newpos); } // ------------------------------------------------------------------------------------------------------ int ObjectMoveForward(void) { object *obj; vms_vector fvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec); vm_vec_normalize(&fvec); vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMoveBack(void) { object *obj; vms_vector fvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec); vm_vec_normalize(&fvec); vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMoveLeft(void) { object *obj; vms_vector rvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_right_vector_from_segment(&Segments[obj->segnum], &rvec); vm_vec_normalize(&rvec); vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMoveRight(void) { object *obj; vms_vector rvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_right_vector_from_segment(&Segments[obj->segnum], &rvec); vm_vec_normalize(&rvec); vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectSetDefault(void) { //update_due_to_new_segment(); if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]); Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMoveUp(void) { object *obj; vms_vector uvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_up_vector_from_segment(&Segments[obj->segnum], &uvec); vm_vec_normalize(&uvec); vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMoveDown(void) { object *obj; vms_vector uvec; vms_vector newpos; if (Cur_object_index == -1) { editor_status("No current object, cannot move."); return 1; } obj = &Objects[Cur_object_index]; extract_up_vector_from_segment(&Segments[obj->segnum], &uvec); vm_vec_normalize(&uvec); vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE)); if (!verify_object_seg(obj, &newpos)) obj->pos = newpos; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMakeSmaller(void) { fix cur_size; //update_due_to_new_segment(); cur_size = Objects[Cur_object_index].size; cur_size -= OBJ_DEL_SIZE; if (cur_size < OBJ_DEL_SIZE) cur_size = OBJ_DEL_SIZE; Objects[Cur_object_index].size = cur_size; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int ObjectMakeLarger(void) { fix cur_size; //update_due_to_new_segment(); cur_size = Objects[Cur_object_index].size; cur_size += OBJ_DEL_SIZE; Objects[Cur_object_index].size = cur_size; Update_flags |= UF_WORLD_CHANGED; return 1; } // ------------------------------------------------------------------------------------------------------ int rotate_object(short objnum, int p, int b, int h) { object *obj = &Objects[objnum]; vms_angvec ang; vms_matrix rotmat,tempm; // vm_extract_angles_matrix( &ang,&obj->orient); // ang.p += p; // ang.b += b; // ang.h += h; ang.p = p; ang.b = b; ang.h = h; vm_angles_2_matrix(&rotmat, &ang); vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat); obj->orient = tempm; // vm_angles_2_matrix(&obj->orient, &ang); Update_flags |= UF_WORLD_CHANGED; return 1; } void reset_object(short objnum) { object *obj = &Objects[objnum]; med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient); } int ObjectResetObject() { reset_object(Cur_object_index); Update_flags |= UF_WORLD_CHANGED; return 1; } int ObjectFlipObject() { vms_matrix *m=&Objects[Cur_object_index].orient; vm_vec_negate(&m->uvec); vm_vec_negate(&m->rvec); Update_flags |= UF_WORLD_CHANGED; return 1; } int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);} int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);} int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);} int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);} int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);} int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);} int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);} int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);} int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);} int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);} int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));} int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));} // ----------------------------------------------------------------------------------------------------- // Move object around based on clicks in 2d screen. // Slide an object parallel to the 2d screen, to a point on a vector. // The vector is defined by a point on the 2d screen and the eye. // V = vector from eye to 2d screen point. // E = eye // F = forward vector from eye // O = 3-space location of object // D = depth of object given forward vector F // = (OE dot norm(F)) // Must solve intersection of: // E + tV ( equation of vector from eye through point on 2d screen) // Fs + D ( equation of plane parallel to 2d screen, at depth D) // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0 // // FxEx + FyEy + FzEz - D // t = - ---------------------- // VxFx + VyFy + VzFz void move_object_to_position(int objnum, vms_vector *newpos) { object *objp = &Objects[objnum]; segmasks result = get_seg_masks(newpos, objp->segnum, objp->size, __FILE__, __LINE__); if (result.facemask == 0) { objp->pos = *newpos; } else { if (verify_object_seg(&Objects[objnum], newpos)) { int fate, count; int viewer_segnum; object temp_viewer_obj; fvi_query fq; fvi_info hit_info; vms_vector last_outside_pos; temp_viewer_obj = *Viewer; viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; // If the viewer is outside the mine, get him in the mine! if (viewer_segnum == -1) { // While outside mine, move towards object count = 0; while (viewer_segnum == -1) { vms_vector temp_vec; last_outside_pos = temp_viewer_obj.pos; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos); temp_viewer_obj.pos = temp_vec; viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer in mine. Aborting"); return; } } count = 0; // While inside mine, move away from object. while (viewer_segnum != -1) { vms_vector temp_vec; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos); temp_viewer_obj.pos = temp_vec; update_object_seg(&temp_viewer_obj); viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer back out of mine. Aborting"); return; } } } fq.p0 = &temp_viewer_obj.pos; fq.startseg = temp_viewer_obj.segnum; fq.p1 = newpos; fq.rad = temp_viewer_obj.size; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = 0; fate = find_vector_intersection(&fq,&hit_info); if (fate == HIT_WALL) { int new_segnum; objp->pos = hit_info.hit_pnt; new_segnum = find_object_seg(objp); Assert(new_segnum != -1); obj_relink(objp-Objects, new_segnum); } else { editor_status("Attempted to move object out of mine. Object not moved."); } } } Update_flags |= UF_WORLD_CHANGED; } void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance) { vms_vector result; vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance); move_object_to_position(Cur_object_index, &result); } void move_object_to_mouse_click_delta(fix delta_distance) { short xcrd,ycrd; vms_vector vec_through_screen; if (Cur_object_index == -1) { editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); return; } xcrd = GameViewBox->b1_drag_x1; ycrd = GameViewBox->b1_drag_y1; med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd); move_object_to_vector(&vec_through_screen, delta_distance); } void move_object_to_mouse_click(void) { move_object_to_mouse_click_delta(0); } int ObjectMoveNearer(void) { vms_vector result; if (Cur_object_index == -1) { editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); return 1; } // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos); vm_vec_normalize(&result); move_object_to_vector(&result, -4*F1_0); return 1; } int ObjectMoveFurther(void) { vms_vector result; if (Cur_object_index == -1) { editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); return 1; } // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos); vm_vec_normalize(&result); move_object_to_vector(&result, 4*F1_0); return 1; } dxx-rebirth-0.58.1-d2x/editor/eswitch.c000066400000000000000000000354121217717237500176610ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Editor switch functions. * */ #include #include #include #include #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "eswitch.h" #include "segment.h" #include "dxxerror.h" #include "gameseg.h" #include "wall.h" #include "medwall.h" #include "screens.h" #include "textures.h" #include "texmerge.h" #include "medrobot.h" #include "timer.h" #include "key.h" #include "ehostage.h" #include "centers.h" #include "piggy.h" //------------------------------------------------------------------------- // Variables for this module... //------------------------------------------------------------------------- #define NUM_TRIGGER_FLAGS 10 static UI_DIALOG *MainWindow = NULL; typedef struct trigger_dialog { UI_GADGET_USERBOX *wallViewBox; UI_GADGET_BUTTON *quitButton; UI_GADGET_CHECKBOX *triggerFlag[NUM_TRIGGER_FLAGS]; int old_trigger_num; } trigger_dialog; //----------------------------------------------------------------- // Adds a trigger to wall, and returns the trigger number. // If there is a trigger already present, it returns the trigger number. (To be replaced) int add_trigger(segment *seg, short side) { int trigger_num = Num_triggers; int wall_num = seg->sides[side].wall_num; Assert(trigger_num < MAX_TRIGGERS); if (trigger_num>=MAX_TRIGGERS) return -1; if (wall_num == -1) { wall_add_to_markedside(WALL_OPEN); wall_num = seg->sides[side].wall_num; Walls[wall_num].trigger = trigger_num; // Set default values first time trigger is added Triggers[trigger_num].flags = 0; Triggers[trigger_num].value = F1_0*5; Triggers[trigger_num].num_links = 0; Triggers[trigger_num].flags &= TRIGGER_ON; Num_triggers++; return trigger_num; } else { if (Walls[wall_num].trigger != -1) return Walls[wall_num].trigger; // Create new trigger. Walls[wall_num].trigger = trigger_num; // Set default values first time trigger is added Triggers[trigger_num].flags = 0; Triggers[trigger_num].value = F1_0*5; Triggers[trigger_num].num_links = 0; Triggers[trigger_num].flags &= TRIGGER_ON; Num_triggers++; return trigger_num; } } //----------------------------------------------------------------- // Adds a specific trigger flag to Markedsegp/Markedside if it is possible. // Automatically adds flag to Connectside if possible unless it is a control trigger. // Returns 1 if trigger flag added. // Returns 0 if trigger flag cannot be added. int trigger_flag_Markedside(short flag, int value) { int trigger_num; //, ctrigger_num; int wall_num; if (!Markedsegp) { editor_status("No Markedside."); return 0; } // If no child on Markedside return if (!IS_CHILD(Markedsegp->children[Markedside])) return 0; // If no wall just return wall_num = Markedsegp->sides[Markedside].wall_num; if (!value && wall_num == -1) return 0; trigger_num = value ? add_trigger(Markedsegp, Markedside) : Walls[wall_num].trigger; if (trigger_num == -1) { editor_status(value ? "Cannot add trigger at Markedside." : "No trigger at Markedside."); return 0; } if (value) Triggers[trigger_num].flags |= flag; else Triggers[trigger_num].flags &= ~flag; return 1; } int bind_matcen_to_trigger() { int wall_num, trigger_num, link_num; int i; if (!Markedsegp) { editor_status("No marked segment."); return 0; } wall_num = Markedsegp->sides[Markedside].wall_num; if (wall_num == -1) { editor_status("No wall at Markedside."); return 0; } trigger_num = Walls[wall_num].trigger; if (trigger_num == -1) { editor_status("No trigger at Markedside."); return 0; } if (!(Curseg2p->special & SEGMENT_IS_ROBOTMAKER)) { editor_status("No Matcen at Cursegp."); return 0; } link_num = Triggers[trigger_num].num_links; for (i=0;isides[Markedside].wall_num; if (wall_num == -1) { editor_status("No wall at Markedside."); return 0; } trigger_num = Walls[wall_num].trigger; if (trigger_num == -1) { editor_status("No trigger at Markedside."); return 0; } if (Cursegp->sides[Curside].wall_num == -1) { editor_status("No wall at Curside."); return 0; } if ((Cursegp==Markedsegp) && (Curside==Markedside)) { editor_status("Cannot bind wall to itself."); return 0; } link_num = Triggers[trigger_num].num_links; for (i=0;i trigger_num) Walls[w].trigger--; } return 1; } editor_status("No trigger to remove"); return 0; } int remove_trigger(segment *seg, short side) { if (seg->sides[side].wall_num == -1) { return 0; } return remove_trigger_num(Walls[seg->sides[side].wall_num].trigger); } int add_trigger_control() { trigger_flag_Markedside(TRIGGER_CONTROL_DOORS, 1); Update_flags = UF_WORLD_CHANGED; return 1; } int trigger_remove() { remove_trigger(Markedsegp, Markedside); Update_flags = UF_WORLD_CHANGED; return 1; } int trigger_turn_all_ON() { int t; for (t=0;ttriggerFlag[0] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Door Control" ); i+=22; t->triggerFlag[1] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Shield damage" ); i+=22; t->triggerFlag[2] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Energy drain" ); i+=22; t->triggerFlag[3] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Exit" ); i+=22; t->triggerFlag[4] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "One-shot" ); i+=22; t->triggerFlag[5] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion ON" ); i+=22; t->triggerFlag[6] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion OFF" ); i+=22; t->triggerFlag[7] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Trigger ON" ); i+=22; t->triggerFlag[8] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Matcen Trigger" ); i+=22; t->triggerFlag[9] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Secret Exit" ); i+=22; t->quitButton = ui_add_gadget_button( MainWindow, 20, i, 48, 40, "Done", NULL ); // The little box the wall will appear in. t->wallViewBox = ui_add_gadget_userbox( MainWindow, 155, 5, 64, 64 ); // A bunch of buttons... i = 80; // ui_add_gadget_button( MainWindow,155,i,140, 26, "Add Door Control", add_trigger_control ); i += 29; ui_add_gadget_button( MainWindow,155,i,140, 26, "Remove Trigger", trigger_remove ); i += 29; ui_add_gadget_button( MainWindow,155,i,140, 26, "Bind Wall", bind_wall_to_trigger ); i += 29; ui_add_gadget_button( MainWindow,155,i,140, 26, "Bind Matcen", bind_matcen_to_trigger ); i += 29; ui_add_gadget_button( MainWindow,155,i,140, 26, "All Triggers ON", trigger_turn_all_ON ); i += 29; t->old_trigger_num = -2; // Set to some dummy value so everything works ok on the first frame. return 1; } void close_trigger_window() { if ( MainWindow!=NULL ) { ui_close_dialog( MainWindow ); MainWindow = NULL; } } int trigger_dialog_handler(UI_DIALOG *dlg, d_event *event, trigger_dialog *t) { int i; short Markedwall, trigger_num; int keypress = 0; int rval = 0; Assert(MainWindow != NULL); if (!Markedsegp) { close_trigger_window(); return 0; } //------------------------------------------------------------ // Call the ui code.. //------------------------------------------------------------ ui_button_any_drawn = 0; if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); //------------------------------------------------------------ // If we change walls, we need to reset the ui code for all // of the checkboxes that control the wall flags. //------------------------------------------------------------ Markedwall = Markedsegp->sides[Markedside].wall_num; if (Markedwall != -1) trigger_num = Walls[Markedwall].trigger; else trigger_num = -1; if (t->old_trigger_num != trigger_num) { if (trigger_num != -1) { trigger *trig = &Triggers[trigger_num]; ui_checkbox_check(t->triggerFlag[0], trig->flags & TRIGGER_CONTROL_DOORS); ui_checkbox_check(t->triggerFlag[1], trig->flags & TRIGGER_SHIELD_DAMAGE); ui_checkbox_check(t->triggerFlag[2], trig->flags & TRIGGER_ENERGY_DRAIN); ui_checkbox_check(t->triggerFlag[3], trig->flags & TRIGGER_EXIT); ui_checkbox_check(t->triggerFlag[4], trig->flags & TRIGGER_ONE_SHOT); ui_checkbox_check(t->triggerFlag[5], trig->flags & TRIGGER_ILLUSION_ON); ui_checkbox_check(t->triggerFlag[6], trig->flags & TRIGGER_ILLUSION_OFF); ui_checkbox_check(t->triggerFlag[7], trig->flags & TRIGGER_ON); ui_checkbox_check(t->triggerFlag[8], trig->flags & TRIGGER_MATCEN); ui_checkbox_check(t->triggerFlag[9], trig->flags & TRIGGER_SECRET_EXIT); } } //------------------------------------------------------------ // If any of the checkboxes that control the wallflags are set, then // update the cooresponding wall flag. //------------------------------------------------------------ if (IS_CHILD(Markedsegp->children[Markedside])) { rval = 1; if (GADGET_PRESSED(t->triggerFlag[0])) trigger_flag_Markedside(TRIGGER_CONTROL_DOORS, t->triggerFlag[0]->flag); else if (GADGET_PRESSED(t->triggerFlag[1])) trigger_flag_Markedside(TRIGGER_SHIELD_DAMAGE, t->triggerFlag[1]->flag); else if (GADGET_PRESSED(t->triggerFlag[2])) trigger_flag_Markedside(TRIGGER_ENERGY_DRAIN, t->triggerFlag[2]->flag); else if (GADGET_PRESSED(t->triggerFlag[3])) trigger_flag_Markedside(TRIGGER_EXIT, t->triggerFlag[3]->flag); else if (GADGET_PRESSED(t->triggerFlag[4])) trigger_flag_Markedside(TRIGGER_ONE_SHOT, t->triggerFlag[4]->flag); else if (GADGET_PRESSED(t->triggerFlag[5])) trigger_flag_Markedside(TRIGGER_ILLUSION_ON, t->triggerFlag[5]->flag); else if (GADGET_PRESSED(t->triggerFlag[6])) trigger_flag_Markedside(TRIGGER_ILLUSION_OFF, t->triggerFlag[6]->flag); else if (GADGET_PRESSED(t->triggerFlag[7])) trigger_flag_Markedside(TRIGGER_ON, t->triggerFlag[7]->flag); else if (GADGET_PRESSED(t->triggerFlag[8])) trigger_flag_Markedside(TRIGGER_MATCEN, t->triggerFlag[8]->flag); else if (GADGET_PRESSED(t->triggerFlag[9])) trigger_flag_Markedside(TRIGGER_SECRET_EXIT, t->triggerFlag[9]->flag); else rval = 0; } else for (i = 0; i < NUM_TRIGGER_FLAGS; i++ ) ui_checkbox_check(t->triggerFlag[i], 0); //------------------------------------------------------------ // Draw the wall in the little 64x64 box //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { gr_set_current_canvas( t->wallViewBox->canvas ); if ((Markedsegp->sides[Markedside].wall_num == -1) || (Walls[Markedsegp->sides[Markedside].wall_num].trigger) == -1) gr_clear_canvas( CBLACK ); else { if (Markedsegp->sides[Markedside].tmap_num2 > 0) { gr_ubitmap(0,0, texmerge_get_cached_bitmap( Markedsegp->sides[Markedside].tmap_num, Markedsegp->sides[Markedside].tmap_num2)); } else { if (Markedsegp->sides[Markedside].tmap_num > 0) { PIGGY_PAGE_IN(Textures[Markedsegp->sides[Markedside].tmap_num]); gr_ubitmap(0,0, &GameBitmaps[Textures[Markedsegp->sides[Markedside].tmap_num].index]); } else gr_clear_canvas( CGREY ); } } } //------------------------------------------------------------ // If anything changes in the ui system, redraw all the text that // identifies this robot. //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { if ( Markedsegp->sides[Markedside].wall_num > -1 ) { ui_dprintf_at( MainWindow, 12, 6, "Trigger: %d ", trigger_num); } else { ui_dprintf_at( MainWindow, 12, 6, "Trigger: none "); } } if (ui_button_any_drawn || (t->old_trigger_num != trigger_num) ) Update_flags |= UF_WORLD_CHANGED; if (event->type == EVENT_WINDOW_CLOSE) { d_free(t); MainWindow = NULL; return 0; } if ( GADGET_PRESSED(t->quitButton) || (keypress==KEY_ESC)) { close_trigger_window(); return 1; } t->old_trigger_num = trigger_num; return rval; } dxx-rebirth-0.58.1-d2x/editor/fixseg.c000066400000000000000000000143421217717237500174770ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions to make faces planar and probably other things. * */ #include #include #include #include #include "key.h" #include "gr.h" #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "gameseg.h" #define SWAP(a,b) {temp = (a); (a) = (b); (b) = temp;} // ----------------------------------------------------------------------------------------------------------------- // Gauss-Jordan elimination solution of a system of linear equations. // a[1..n][1..n] is the input matrix. b[1..n][1..m] is input containing the m right-hand side vectors. // On output, a is replaced by its matrix inverse and b is replaced by the corresponding set of solution vectors. void gaussj(fix **a, int n, fix **b, int m) { int indxc[4], indxr[4], ipiv[4]; int i, icol=0, irow=0, j, k, l, ll; fix big, dum, pivinv, temp; if (n > 4) { Int3(); } for (j=1; j<=n; j++) ipiv[j] = 0; for (i=1; i<=n; i++) { big = 0; for (j=1; j<=n; j++) if (ipiv[j] != 1) for (k=1; k<=n; k++) { if (ipiv[k] == 0) { if (abs(a[j][k]) >= big) { big = abs(a[j][k]); irow = j; icol = k; } } else if (ipiv[k] > 1) { Int3(); } } ++(ipiv[icol]); // We now have the pivot element, so we interchange rows, if needed, to put the pivot // element on the diagonal. The columns are not physically interchanged, only relabeled: // indxc[i], the column of the ith pivot element, is the ith column that is reduced, while // indxr[i] is the row in which that pivot element was originally located. If indxr[i] != // indxc[i] there is an implied column interchange. With this form of bookkeeping, the // solution b's will end up in the correct order, and the inverse matrix will be scrambled // by columns. if (irow != icol) { for (l=1; l<=n; l++) SWAP(a[irow][l], a[icol][l]); for (l=1; l<=m; l++) SWAP(b[irow][l], b[icol][l]); } indxr[i] = irow; indxc[i] = icol; if (a[icol][icol] == 0) { Int3(); } pivinv = fixdiv(F1_0, a[icol][icol]); a[icol][icol] = F1_0; for (l=1; l<=n; l++) a[icol][l] = fixmul(a[icol][l], pivinv); for (l=1; l<=m; l++) b[icol][l] = fixmul(b[icol][l], pivinv); for (ll=1; ll<=n; ll++) if (ll != icol) { dum = a[ll][icol]; a[ll][icol] = 0; for (l=1; l<=n; l++) a[ll][l] -= a[icol][l]*dum; for (l=1; l<=m; l++) b[ll][l] -= b[icol][l]*dum; } } // This is the end of the main loop over columns of the reduction. It only remains to unscramble // the solution in view of the column interchanges. We do this by interchanging pairs of // columns in the reverse order that the permutation was built up. for (l=n; l>=1; l--) { if (indxr[l] != indxc[l]) for (k=1; k<=n; k++) SWAP(a[k][indxr[l]], a[k][indxc[l]]); } } // ----------------------------------------------------------------------------------------------------------------- // Return true if side is planar, else return false. int side_is_planar_p(segment *sp, int side) { const sbyte *vp; vms_vector *v0,*v1,*v2,*v3; vms_vector va,vb; vp = Side_to_verts[side]; v0 = &Vertices[sp->verts[vp[0]]]; v1 = &Vertices[sp->verts[vp[1]]]; v2 = &Vertices[sp->verts[vp[2]]]; v3 = &Vertices[sp->verts[vp[3]]]; vm_vec_normalize(vm_vec_normal(&va,v0,v1,v2)); vm_vec_normalize(vm_vec_normal(&vb,v0,v2,v3)); // If the two vectors are very close to being the same, then generate one quad, else generate two triangles. return (vm_vec_dist(&va,&vb) < F1_0/1000); } // ------------------------------------------------------------------------------------------------- // Return coordinates of a vertex which is vertex v moved so that all sides of which it is a part become planar. void compute_planar_vert(segment *sp, int side, int v, vms_vector *vp) { if ((sp) && (side > -3)) *vp = Vertices[v]; } // ------------------------------------------------------------------------------------------------- // Making Cursegp:Curside planar. // If already planar, return. // for each vertex v on side, not part of another segment // choose the vertex v which can be moved to make all sides of which it is a part planar, minimizing distance moved // if there is no vertex v on side, not part of another segment, give up in disgust // Return value: // 0 curside made planar (or already was) // 1 did not make curside planar int make_curside_planar(void) { int v; const sbyte *vp; vms_vector planar_verts[4]; // store coordinates of up to 4 vertices which will make Curside planar, corresponding to each of 4 vertices on side int present_verts[4]; // set to 1 if vertex is present if (side_is_planar_p(Cursegp, Curside)) return 0; // Look at all vertices in side to find a free one. for (v=0; v<4; v++) present_verts[v] = 0; vp = Side_to_verts[Curside]; for (v=0; v<4; v++) { int v1 = vp[v]; // absolute vertex id if (is_free_vertex(Cursegp->verts[v1])) { compute_planar_vert(Cursegp, Curside, Cursegp->verts[v1], &planar_verts[v]); present_verts[v] = 1; } } // Now, for each v for which present_verts[v] == 1, there is a vector (point) in planar_verts[v]. // See which one is closest to the plane defined by the other three points. // Nah...just use the first one we find. for (v=0; v<4; v++) if (present_verts[v]) { med_set_vertex(vp[v],&planar_verts[v]); validate_segment(Cursegp); // -- should propagate tmaps to segments or something here... return 0; } // We tried, but we failed, to make Curside planer. return 1; } dxx-rebirth-0.58.1-d2x/editor/func.c000066400000000000000000000040501217717237500171400ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * . * */ #include #include #include "func.h" #include "strutil.h" #define MAX_PARAMS 10 static FUNCTION * func_table = NULL; static int func_size = 0; static int initialized = 0; static int func_params[MAX_PARAMS]; int func_howmany() { return func_size; } void func_init( FUNCTION * funtable, int size ) { if (!initialized) { initialized = 1; func_table = funtable; func_size = size; atexit( func_close ); } } void func_close() { if (initialized) { initialized = 0; func_table = NULL; func_size = 0; } } int (*func_get( char * name, int * numparams ))(void) { int i; for (i=0; i #include #include "gr.h" #include "ui.h" #include "inferno.h" #include "segment.h" #include "editor/editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "gamemine.h" #include "gameseg.h" #include "bm.h" // For MAX_TEXTURES. #include "textures.h" #include "hash.h" #include "fuelcen.h" #include "medwall.h" void validate_selected_segments(void); struct { int fileinfo_version; int fileinfo_sizeof; } group_top_fileinfo; // Should be same as first two fields below... struct { int fileinfo_version; int fileinfo_sizeof; int header_offset; // Stuff common to game & editor int header_size; int editor_offset; // Editor specific stuff int editor_size; int vertex_offset; int vertex_howmany; int vertex_sizeof; int segment_offset; int segment_howmany; int segment_sizeof; int texture_offset; int texture_howmany; int texture_sizeof; } group_fileinfo; struct { int num_vertices; int num_segments; } group_header; struct { int current_seg; int newsegment_offset; int newsegment_size; int Groupsegp; int Groupside; } group_editor; group GroupList[MAX_GROUPS+1]; segment *Groupsegp[MAX_GROUPS+1]; int Groupside[MAX_GROUPS+1]; int Group_orientation[MAX_GROUPS+1]; int current_group=-1; int num_groups=0; // -- void swap_negate_columns(vms_matrix *rotmat, int col1, int col2) // -- { // -- fix col1_1,col1_2,col1_3; // -- fix col2_1,col2_2,col2_3; // -- // -- switch (col1) { // -- case 0: // -- col1_1 = rotmat->m1; // -- col1_2 = rotmat->m2; // -- col1_3 = rotmat->m3; // -- break; // -- // -- case 1: // -- col1_1 = rotmat->m4; // -- col1_2 = rotmat->m5; // -- col1_3 = rotmat->m6; // -- break; // -- // -- case 2: // -- col1_1 = rotmat->m7; // -- col1_2 = rotmat->m8; // -- col1_3 = rotmat->m9; // -- break; // -- } // -- // -- switch (col2) { // -- case 0: // -- col2_1 = rotmat->m1; // -- col2_2 = rotmat->m2; // -- col2_3 = rotmat->m3; // -- break; // -- // -- case 1: // -- col2_1 = rotmat->m4; // -- col2_2 = rotmat->m5; // -- col2_3 = rotmat->m6; // -- break; // -- // -- case 2: // -- col2_1 = rotmat->m7; // -- col2_2 = rotmat->m8; // -- col2_3 = rotmat->m9; // -- break; // -- } // -- // -- switch (col2) { // -- case 0: // -- rotmat->m1 = -col1_1; // -- rotmat->m2 = -col1_2; // -- rotmat->m3 = -col1_3; // -- break; // -- // -- case 1: // -- rotmat->m4 = -col1_1; // -- rotmat->m5 = -col1_2; // -- rotmat->m6 = -col1_3; // -- break; // -- // -- case 2: // -- rotmat->m7 = -col1_1; // -- rotmat->m8 = -col1_2; // -- rotmat->m9 = -col1_3; // -- break; // -- } // -- // -- switch (col1) { // -- case 0: // -- rotmat->m1 = -col2_1; // -- rotmat->m2 = -col2_2; // -- rotmat->m3 = -col2_3; // -- break; // -- // -- case 1: // -- rotmat->m4 = -col2_1; // -- rotmat->m5 = -col2_2; // -- rotmat->m6 = -col2_3; // -- break; // -- // -- case 2: // -- rotmat->m7 = -col2_1; // -- rotmat->m8 = -col2_2; // -- rotmat->m9 = -col2_3; // -- break; // -- } // -- // -- } // -- // -- void swap_negate_rows(vms_matrix *rotmat, int row1, int row2) // -- { // -- fix row1_1,row1_2,row1_3; // -- fix row2_1,row2_2,row2_3; // -- // -- switch (row1) { // -- case 0: // -- row1_1 = rotmat->m1; // -- row1_2 = rotmat->m4; // -- row1_3 = rotmat->m7; // -- break; // -- // -- case 1: // -- row1_1 = rotmat->m2; // -- row1_2 = rotmat->m5; // -- row1_3 = rotmat->m8; // -- break; // -- // -- case 2: // -- row1_1 = rotmat->m3; // -- row1_2 = rotmat->m6; // -- row1_3 = rotmat->m9; // -- break; // -- } // -- // -- switch (row2) { // -- case 0: // -- row2_1 = rotmat->m1; // -- row2_2 = rotmat->m4; // -- row2_3 = rotmat->m7; // -- break; // -- // -- case 1: // -- row2_1 = rotmat->m2; // -- row2_2 = rotmat->m5; // -- row2_3 = rotmat->m8; // -- break; // -- // -- case 2: // -- row2_1 = rotmat->m3; // -- row2_2 = rotmat->m6; // -- row2_3 = rotmat->m9; // -- break; // -- } // -- // -- switch (row2) { // -- case 0: // -- rotmat->m1 = -row1_1; // -- rotmat->m4 = -row1_2; // -- rotmat->m7 = -row1_3; // -- break; // -- // -- case 1: // -- rotmat->m2 = -row1_1; // -- rotmat->m5 = -row1_2; // -- rotmat->m8 = -row1_3; // -- break; // -- // -- case 2: // -- rotmat->m3 = -row1_1; // -- rotmat->m6 = -row1_2; // -- rotmat->m9 = -row1_3; // -- break; // -- } // -- // -- switch (row1) { // -- case 0: // -- rotmat->m1 = -row2_1; // -- rotmat->m4 = -row2_2; // -- rotmat->m7 = -row2_3; // -- break; // -- // -- case 1: // -- rotmat->m2 = -row2_1; // -- rotmat->m5 = -row2_2; // -- rotmat->m8 = -row2_3; // -- break; // -- // -- case 2: // -- rotmat->m3 = -row2_1; // -- rotmat->m6 = -row2_2; // -- rotmat->m9 = -row2_3; // -- break; // -- } // -- // -- } // -- // -- // ------------------------------------------------------------------------------------------------ // -- void side_based_matrix(vms_matrix *rotmat,int destside) // -- { // -- vms_angvec rotvec; // -- vms_matrix r1,rtemp; // -- // -- switch (destside) { // -- case WLEFT: // -- // swap_negate_columns(rotmat,1,2); // -- // swap_negate_rows(rotmat,1,2); // -- break; // -- // -- case WTOP: // -- break; // -- // -- case WRIGHT: // -- // swap_negate_columns(rotmat,1,2); // -- // swap_negate_rows(rotmat,1,2); // -- break; // -- // -- case WBOTTOM: // -- break; // -- // -- case WFRONT: // -- break; // -- // -- case WBACK: // -- break; // -- } // -- // -- } // ------------------------------------------------------------------------------------------------ // Rotate a group about a point. // The segments in the group are indicated (by segment number) in group_seglist. There are group_size segments. // The point about which the groups is rotated is the center of first_seg:first_side. // delta_flag: // 0 absolute rotation, destination specified in terms of base_seg:base_side, used in moving or copying a group // 1 relative rotation, destination specified relative to current orientation of first_seg:first_side // Note: The group must exist in the mine, consisting of actual points in the world. If any points in the // segments in the group are shared by segments not in the group, those points will get rotated and the // segments not in the group will have their shapes modified. // Return value: // 0 group rotated // 1 unable to rotate group static void med_create_group_rotation_matrix(vms_matrix *result_mat, int delta_flag, segment *first_seg, int first_side, segment *base_seg, int base_side, const vms_matrix *orient_matrix, int orientation) { vms_matrix rotmat2,rotmat,rotmat3,rotmat4; vms_angvec pbh = {0,0,0}; // Determine whether this rotation is a delta rotation, meaning to just rotate in place, or an absolute rotation, // which means that the destination rotation is specified, not as a delta, but as an absolute if (delta_flag) { // Create rotation matrix describing rotation. med_extract_matrix_from_segment(first_seg, &rotmat4); // get rotation matrix describing current orientation of first seg set_matrix_based_on_side(&rotmat4, first_side); rotmat3 = *orient_matrix; vm_transpose_matrix(&rotmat3); vm_matrix_x_matrix(&rotmat,&rotmat4,&rotmat3); // this is the desired orientation of the new segment vm_transpose_matrix(&rotmat4); vm_matrix_x_matrix(&rotmat2,&rotmat,&rotmat4); // this is the desired orientation of the new segment } else { // Create rotation matrix describing rotation. med_extract_matrix_from_segment(base_seg, &rotmat); // get rotation matrix describing desired orientation set_matrix_based_on_side(&rotmat, base_side); // modify rotation matrix for desired side // If the new segment is to be attached without rotation, then its orientation is the same as the base_segment vm_matrix_x_matrix(&rotmat4,&rotmat,orient_matrix); // this is the desired orientation of the new segment pbh.b = orientation*16384; vm_angles_2_matrix(&rotmat3,&pbh); vm_matrix_x_matrix(&rotmat, &rotmat4, &rotmat3); rotmat4 = rotmat; rotmat = rotmat4; med_extract_matrix_from_segment(first_seg, &rotmat3); // get rotation matrix describing current orientation of first seg // It is curious that the following statement has no analogue in the med_attach_segment_rotated code. // Perhaps it is because segments are always attached at their front side. If the back side is the side // passed to the function, then the matrix is not modified, which might suggest that what you need to do below // is use Side_opposite[first_side]. set_matrix_based_on_side(&rotmat3, Side_opposite[first_side]); // modify rotation matrix for desired side vm_transpose_matrix(&rotmat3); // get the inverse of the current orientation matrix vm_matrix_x_matrix(&rotmat2,&rotmat,&rotmat3); // now rotmat2 takes the current segment to the desired orientation vm_transpose_matrix(&rotmat2); } *result_mat = rotmat2; } // ----------------------------------------------------------------------------------------- // Rotate all vertices and objects in group. void med_rotate_group(vms_matrix *rotmat, short *group_seglist, int group_size, segment *first_seg, int first_side) { int v,s, objnum; sbyte vertex_list[MAX_VERTICES]; vms_vector rotate_center; compute_center_point_on_side(&rotate_center, first_seg, first_side); // Create list of points to rotate. for (v=0; v<=Highest_vertex_index; v++) vertex_list[v] = 0; for (s=0; sverts[v]] = 1; // Rotate center of all objects in group. objnum = sp->objects; while (objnum != -1) { vms_vector tv, tv1; vm_vec_sub(&tv1,&Objects[objnum].pos,&rotate_center); vm_vec_rotate(&tv,&tv1,rotmat); vm_vec_add(&Objects[objnum].pos, &tv, &rotate_center); objnum = Objects[objnum].next; } } // Do the pre-rotation xlate, do the rotation, do the post-rotation xlate for (v=0; v<=Highest_vertex_index; v++) if (vertex_list[v]) { vms_vector tv,tv1; vm_vec_sub(&tv1,&Vertices[v],&rotate_center); vm_vec_rotate(&tv,&tv1,rotmat); vm_vec_add(&Vertices[v],&tv,&rotate_center); } } // ------------------------------------------------------------------------------------------------ void cgl_aux(segment *segp, short *seglistp, int *num_segs, short *ignore_list, int num_ignore_segs) { int i, side; int curseg = segp-Segments; for (i=0; i= MAX_SEGMENTS)) { Int3(); } if (!Been_visited[segp-Segments]) { seglistp[(*num_segs)++] = segp-Segments; Been_visited[segp-Segments] = 1; for (side=0; sidechildren[side])) cgl_aux(&Segments[segp->children[side]], seglistp, num_segs, ignore_list, num_ignore_segs); } } // ------------------------------------------------------------------------------------------------ // Sets Been_visited[n] if n is reachable from segp void create_group_list(segment *segp, short *seglistp, int *num_segs, short *ignore_list, int num_ignore_segs) { for (unsigned i=0; ichildren[sidenum]; if (IS_CHILD(seg)) { for (ss=0; ssverts[v]]) { sp->verts[v] = new_vertex_ids[sp->verts[v]]; } } } // end for (s=0... // Now, copy new_segment_ids into segment_ids for (s=0; schildren[base_side])) { editor_status("Error -- unable to copy group, base_seg:base_side must be free."); return 1; } if (num_groups == MAX_GROUPS) { x = ui_messagebox( -2, -2, 2, "Warning: You have reached the MAXIMUM group number limit. Continue?", "No", "Yes" ); if (x==1) return 0; } if (num_groups < MAX_GROUPS) { num_groups++; new_current_group = num_groups-1; } else new_current_group = 0; Assert(current_group >= 0); // Find groupsegp index for (s=0;sverts[v]] = 1; else { for (v=0; v<=Highest_vertex_index; v++) in_vertex_list[v] = 0; for (s=0; schildren[c])) { if (!in_group(segp->children[c], new_current_group)) { segp->children[c] = -1; validate_segment_side(segp,c); // we have converted a connection to a side so validate the segment } } } copy_uvs_seg_to_seg(&New_segment, Groupsegp[new_current_group]); // Now do the copy // First, xlate all vertices so center of group_seg:group_side is at origin compute_center_point_on_side(&srcv,group_seg,group_side); for (v=0; v<=Highest_vertex_index; v++) if (in_vertex_list[v]) vm_vec_sub2(&Vertices[v],&srcv); // Now, translate all object positions. for (s=0; schildren[base_side])) if (base_seg->children[base_side] != group_seg-Segments) { editor_status("Error -- unable to move group, base_seg:base_side must be free or point to group_seg."); return 1; } // // See if any vertices in base_seg are contained in any vertex in group_list // for (v=0; vverts[v]) { // editor_status("Error -- unable to move group, it shares a vertex with destination segment."); // return 1; // } for (v=0; v<=Highest_vertex_index; v++) { in_vertex_list[v] = 0; out_vertex_list[v] = 0; } // Make a list of all vertices in group. for (s=0; sverts[vv] == v) sp->verts[vv] = new_vertex_id; } } for (s=0;schildren[c])) { csegp = &Segments[segp->children[c]]; if (csegp->group != current_group) { for (d=0; dchildren[d])) { dsegp = &Segments[csegp->children[d]]; if (dsegp->group == current_group) { csegp->children[d] = -1; validate_segment_side(csegp,d); // we have converted a connection to a side so validate the segment } } segp->children[c] = -1; validate_segment_side(segp,c); // we have converted a connection to a side so validate the segment } } } copy_uvs_seg_to_seg(&New_segment, Groupsegp[current_group]); // Now do the move // First, xlate all vertices so center of group_seg:group_side is at origin compute_center_point_on_side(&srcv,group_seg,group_side); for (v=0; v<=Highest_vertex_index; v++) if (in_vertex_list[v]) vm_vec_sub2(&Vertices[v],&srcv); // Now, move all object positions. for (s=0; schildren[(int) Side_opposite[Curside]])) { // -- I don't understand this, MK, 01/25/94: if (Cursegp->children[Curside] != group_seg-Segments) { editor_status("Error -- unable to rotate group, Cursegp:Side_opposite[Curside] cannot be free."); return 1; } current_group_save = current_group; current_group = ROT_GROUP; Groupsegp[ROT_GROUP] = Cursegp; save_selected_segs(&n_selected_segs_save, selected_segs_save); GroupList[ROT_GROUP].num_segments = 0; newseg = Cursegp - Segments; newseg_side = Side_opposite[Curside]; // Create list of segments to rotate. // Sever connection between first seg to rotate and its connection on Side_opposite[Curside]. child_save = Cursegp->children[newseg_side]; // save connection we are about to sever Cursegp->children[newseg_side] = -1; // sever connection create_group_list(Cursegp, GroupList[ROT_GROUP].segments, &GroupList[ROT_GROUP].num_segments, Selected_segs, 0); // create list of segments in group Cursegp->children[newseg_side] = child_save; // restore severed connection GroupList[ROT_GROUP].segments[0] = newseg; baseseg = Segments[newseg].children[newseg_side]; if (!IS_CHILD(baseseg)) { editor_status("Error -- unable to rotate segment, side opposite curside is not attached."); restore_selected_segs(n_selected_segs_save,selected_segs_save); current_group = current_group_save; return 1; } baseseg_side = find_connect_side(&Segments[newseg], &Segments[baseseg]); med_extract_matrix_from_segment(&Segments[newseg],&tm1); tm1 = vmd_identity_matrix; vm_angles_2_matrix(&tm2,pbh); vm_matrix_x_matrix(&orient_matrix,&tm1,&tm2); Segments[baseseg].children[baseseg_side] = -1; Segments[newseg].children[newseg_side] = -1; if (!med_move_group(1, &Segments[baseseg], baseseg_side, &Segments[newseg], newseg_side, &orient_matrix, 0)) { Cursegp = &Segments[newseg]; med_create_new_segment_from_cursegp(); // validate_selected_segments(); med_propagate_tmaps_to_segments(&Segments[baseseg], &Segments[newseg], 1); med_propagate_tmaps_to_back_side(&Segments[newseg], Curside, 1); } restore_selected_segs(n_selected_segs_save,selected_segs_save); current_group = current_group_save; return 1; } // ----------------------------------------------------------------------------- // Attach segment in the new-fangled way, which is by using the CopyGroup code. int RotateSegmentNew(vms_angvec *pbh) { int rval; autosave_mine(mine_filename); rval = rotate_segment_new(pbh); if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; warn_if_concave_segment(Cursegp); return rval; } static char current_tmap_list[MAX_TEXTURES][13]; // ----------------------------------------------------------------------------- // Save mine will: // 1. Write file info, header info, editor info, vertex data, segment data, // and new_segment in that order, marking their file offset. // 2. Go through all the fields and fill in the offset, size, and sizeof // values in the headers. int med_save_group( char *filename, int *vertex_ids, short *segment_ids, int num_vertices, int num_segments) { PHYSFS_file * SaveFile; int header_offset, editor_offset, vertex_offset, segment_offset, texture_offset; char ErrorMessage[100]; int i, j, k; int segnum; segment tseg; vms_vector tvert; int found; SaveFile = PHYSFSX_openWriteBuffered( filename ); if (!SaveFile) { sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename ); ui_messagebox( -2, -2, 1, ErrorMessage, "Ok" ); return 1; } //===================== SAVE FILE INFO ======================== group_fileinfo.fileinfo_version = MINE_VERSION; group_fileinfo.fileinfo_sizeof = sizeof(group_fileinfo); group_fileinfo.header_offset = -1; group_fileinfo.header_size = sizeof(group_header); group_fileinfo.editor_offset = -1; group_fileinfo.editor_size = sizeof(group_editor); group_fileinfo.vertex_offset = -1; group_fileinfo.vertex_howmany = num_vertices; group_fileinfo.vertex_sizeof = sizeof(vms_vector); group_fileinfo.segment_offset = -1; group_fileinfo.segment_howmany = num_segments; group_fileinfo.segment_sizeof = sizeof(segment); group_fileinfo.texture_offset = -1; group_fileinfo.texture_howmany = 0; group_fileinfo.texture_sizeof = 13; // num characters in a name // Write the fileinfo PHYSFS_write( SaveFile, &group_fileinfo, sizeof(group_fileinfo), 1); //===================== SAVE HEADER INFO ======================== group_header.num_vertices = num_vertices; group_header.num_segments = num_segments; // Write the editor info header_offset = PHYSFS_tell(SaveFile); PHYSFS_write( SaveFile, &group_header, sizeof(group_header), 1); //===================== SAVE EDITOR INFO ========================== group_editor.newsegment_offset = -1; // To be written group_editor.newsegment_size = sizeof(segment); // Next 3 vars added 10/07 by JAS if (Groupsegp[current_group]) { segnum = Groupsegp[current_group]-Segments; for (i=0;i -1 ) { if (PHYSFSX_fseek( LoadFile,group_fileinfo.header_offset, SEEK_SET )) Error( "Error seeking to header_offset in group.c" ); if (PHYSFS_read( LoadFile, &group_header, group_fileinfo.header_size,1 )!=1) Error( "Error reading group_header in group.c" ); } //===================== READ EDITOR INFO ========================== // Set default values group_editor.current_seg = 0; group_editor.newsegment_offset = -1; // To be written group_editor.newsegment_size = sizeof(segment); group_editor.Groupsegp = -1; group_editor.Groupside = 0; if (group_fileinfo.editor_offset > -1 ) { if (PHYSFSX_fseek( LoadFile,group_fileinfo.editor_offset, SEEK_SET )) Error( "Error seeking to editor_offset in group.c" ); if (PHYSFS_read( LoadFile, &group_editor, group_fileinfo.editor_size,1 )!=1) Error( "Error reading group_editor in group.c" ); } //===================== READ VERTEX INFO ========================== if ( (group_fileinfo.vertex_offset > -1) && (group_fileinfo.vertex_howmany > 0)) { if (PHYSFSX_fseek( LoadFile,group_fileinfo.vertex_offset, SEEK_SET )) Error( "Error seeking to vertex_offset in group.c" ); for (i=0;i -1) && (group_fileinfo.segment_howmany > 0)) { if (PHYSFSX_fseek( LoadFile,group_fileinfo.segment_offset, SEEK_SET )) Error( "Error seeking to segment_offset in group.c" ); for (i=0;i -1) && (group_fileinfo.texture_howmany > 0)) { if (PHYSFSX_fseek( LoadFile, group_fileinfo.texture_offset, SEEK_SET )) Error( "Error seeking to texture_offset in gamemine.c" ); for (i=0; i< group_fileinfo.texture_howmany; i++ ) { if (PHYSFS_read( LoadFile, &old_tmap_list[i], group_fileinfo.texture_sizeof, 1 )!=1) Error( "Error reading old_tmap_list[i] in gamemine.c" ); } } //=============== GENERATE TEXTURE TRANSLATION TABLE =============== translate = 0; Assert (NumTextures < MAX_TEXTURES); { hashtable ht; hashtable_init( &ht, NumTextures ); // Remove all the file extensions in the textures list for (i=0;igroup == current_group) { Cursegp->group = -1; delete_segment_from_group( Cursegp-Segments, current_group ); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message_fmt("Segment Ungrouped from Group %d.", current_group); return 1; } else return 0; } int GroupSegment( void ) { if (Cursegp->group == -1) { Cursegp->group = current_group; add_segment_to_group( Cursegp-Segments, current_group ); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message_fmt("Segment Added to Group %d.", current_group); return 1; } else return 0; } int Degroup( void ) { int i; // GroupList[current_group].num_segments = 0; // Groupsegp[current_group] = 0; if (num_groups==0) return 0; for (i=0; i num_groups-1) current_group--; if (num_groups == 0) current_group = -1; if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Group UNgrouped."); return 1; } void NextGroup( void ) { if (num_groups > 0) { current_group++; if (current_group >= num_groups ) current_group = 0; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; } else editor_status("No Next Group\n"); } void PrevGroup( void ) { if (num_groups > 0) { current_group--; if (current_group < 0 ) current_group = num_groups-1; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; } else editor_status("No Previous Group\n"); } // Returns: // 0 = successfully selected // 1 = bad group number int select_group( int num ) { if ((num>=0) && (numchildren[Groupside[current_group]]; if (attach_seg != -1) { int i; for (i=0; ichildren[Groupside[current_group]]); return 1; } } med_compress_mine(); if (!med_copy_group(0, Cursegp, Curside, Groupsegp[current_group], Groupside[current_group], &vmd_identity_matrix)) { autosave_mine(mine_filename); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Group copied."); return 0; } else return 1; } // ----------------------------------------------------------------------------- int RotateGroup(void) { if (!Groupsegp[current_group]) { editor_status("Error -- Cannot rotate group, no group segment."); return 1; } Group_orientation[current_group]++; if ((Group_orientation[current_group] <0) || (Group_orientation[current_group] >4)) Group_orientation[current_group]=0; med_compress_mine(); if (!med_move_group(0, Cursegp, Curside, Groupsegp[current_group], Groupside[current_group], &vmd_identity_matrix, Group_orientation[current_group])) { Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Group rotated."); return 0; } else return 1; } // ----------------------------------------------------------------------------- // Creates a group from all segments connected to marked segment. int SubtractFromGroup(void) { int x, s, original_group; short *gp; int cur_num_segs; if (!Markedsegp) { editor_status("Error -- Cannot create group, no marked segment."); return 1; } med_compress_mine(); autosave_mine(mine_filename); if (num_groups == MAX_GROUPS) { x = ui_messagebox( -2, -2, 2, "Warning: You are about to wipe out a group.", "ARGH! NO!", "No problemo." ); if (x==1) return 0; } if (current_group == -1) { editor_status("Error -- No current group. Cannot subtract."); return 1; } original_group = current_group; current_group = (current_group + 1) % MAX_GROUPS; // Create a list of segments to copy. GroupList[current_group].num_segments = 0; create_group_list(Markedsegp, GroupList[current_group].segments, &GroupList[current_group].num_segments, Selected_segs, N_selected_segs); // Now, scan the two groups, forming a group which consists of only those segments common to the two groups. gp = GroupList[current_group].segments; cur_num_segs = GroupList[current_group].num_segments; for (s=0; s num_groups-1) current_group--; if (num_groups==0) current_group = -1; strcpy(undo_status[Autosave_count], "Delete Group UNDONE."); if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Group deleted."); // warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly return 1; } int MarkGroupSegment( void ) { if ((Cursegp->group != -1) && (Cursegp->group == current_group)) { autosave_mine(mine_filename); Groupsegp[current_group] = Cursegp; Groupside[current_group] = Curside; editor_status("Group Segment Marked."); Update_flags |= UF_ED_STATE_CHANGED; strcpy(undo_status[Autosave_count], "Mark Group Segment UNDONE."); mine_changed = 1; return 1; } else return 0; } dxx-rebirth-0.58.1-d2x/editor/info.c000066400000000000000000000255041217717237500171470ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Print debugging info in ui. * */ #include #include #include #ifdef DO_MEMINFO #include #endif #include "inferno.h" #include "window.h" #include "segment.h" #include "gr.h" #include "ui.h" #include "editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "textures.h" #include "object.h" #include "ai.h" #include "texpage.h" // Textue selection paging stuff #include "objpage.h" // Object selection paging stuff #include "wall.h" #include "switch.h" int init_info; #ifdef DO_MEMINFO struct meminfo { int LargestBlockAvail; int MaxUnlockedPage; int LargestLockablePage; int LinAddrSpace; int NumFreePagesAvail; int NumPhysicalPagesFree; int TotalPhysicalPages; int FreeLinAddrSpace; int SizeOfPageFile; int Reserved[3]; } MemInfo; #define DPMI_INT 0x31 void read_mem_info() { union REGS regs; struct SREGS sregs; regs.x.eax = 0x00000500; memset( &sregs, 0, sizeof(sregs) ); sregs.es = FP_SEG( &MemInfo ); regs.x.edi = FP_OFF( &MemInfo ); int386x( DPMI_INT, ®s, ®s, &sregs ); } #endif char * get_object_type(int num, char *name) { switch (num) { case OBJ_NONE: strcpy(name, "OBJ_NONE "); break; case OBJ_WALL: strcpy(name, "OBJ_WALL "); break; case OBJ_FIREBALL: strcpy(name, "OBJ_FIREBALL"); break; case OBJ_ROBOT: strcpy(name, "OBJ_ROBOT "); break; case OBJ_HOSTAGE: strcpy(name, "OBJ_HOSTAGE "); break; case OBJ_PLAYER: strcpy(name, "OBJ_PLAYER "); break; case OBJ_WEAPON: strcpy(name, "OBJ_WEAPON "); break; case OBJ_CAMERA: strcpy(name, "OBJ_CAMERA "); break; case OBJ_POWERUP: strcpy(name, "OBJ_POWERUP "); break; default: strcpy(name, " (unknown) "); break; } return name; } char * get_control_type(int num, char *name) { switch (num) { case CT_NONE: strcpy(name, "CT_NONE "); break; case CT_AI: strcpy(name, "CT_AI "); break; case CT_EXPLOSION: strcpy(name, "CT_EXPLOSION "); break; //case CT_MULTIPLAYER: strcpy(name, "CT_MULTIPLAYER"); break; case CT_FLYING: strcpy(name, "CT_FLYING "); break; case CT_SLEW: strcpy(name, "CT_SLEW "); break; case CT_FLYTHROUGH: strcpy(name, "CT_FLYTHROUGH "); break; //case CT_DEMO: strcpy(name, "CT_DEMO "); break; //case CT_ROBOT_FLYTHROUGH: strcpy(name, "CT_FLYTHROUGH "); break; case CT_WEAPON: strcpy(name, "CT_WEAPON "); break; default: strcpy(name, " (unknown) "); break; } return name; } char * get_movement_type(int num, char *name) { switch (num) { case MT_NONE: strcpy(name, "MT_NONE "); break; case MT_PHYSICS: strcpy(name, "MT_PHYSICS "); break; //case MT_MULTIPLAYER: strcpy(name, "MT_MULTIPLAYER"); break; default: strcpy(name, " (unknown) "); break; } return name; } char * get_ai_behavior(int num, char *name) { #define AIB_STILL 0x80 #define AIB_NORMAL 0x81 #define AIB_HIDE 0x82 #define AIB_RUN_FROM 0x83 #define AIB_FOLLOW_PATH 0x84 switch (num) { case AIB_STILL: strcpy(name, "STILL "); break; case AIB_NORMAL: strcpy(name, "NORMAL "); break; case AIB_HIDE: strcpy(name, "HIDE "); break; case AIB_RUN_FROM: strcpy(name, "RUN_FROM "); break; case AIB_FOLLOW_PATH: strcpy(name, "FOLLOW_PATH "); break; default: strcpy(name, " (unknown) "); break; } return name; } // --------------------------------------------------------------------------------------------------- void info_display_object_placement(int show_all) { static int old_Cur_object_index; static int old_type; static int old_movement_type; static int old_control_type; static int old_mode; char name[30]; if (init_info | show_all) { old_Cur_object_index = -2; old_type = -2; old_movement_type = -2; old_control_type = -2; old_mode = -2; } if ( ( Cur_object_index != old_Cur_object_index) || ( Objects[Cur_object_index].type != old_type) || ( Objects[Cur_object_index].movement_type != old_movement_type) || ( Objects[Cur_object_index].control_type != old_control_type) || ( Objects[Cur_object_index].ctype.ai_info.behavior != old_mode) ) { gr_uprintf( 0, 0, "Object id: %4d\n", Cur_object_index); gr_uprintf( 0, 16, "Type: %s\n", get_object_type(Objects[Cur_object_index].type , name)); gr_uprintf( 0, 32, "Movmnt: %s\n", get_movement_type(Objects[Cur_object_index].movement_type, name)); gr_uprintf( 0, 48, "Cntrl: %s\n", get_control_type(Objects[Cur_object_index].control_type, name)); gr_uprintf( 0, 64, "Mode: %s\n", get_ai_behavior(Objects[Cur_object_index].ctype.ai_info.behavior, name)); old_Cur_object_index = Cur_object_index; old_type = Objects[Cur_object_index].type; old_movement_type = Objects[Cur_object_index].movement_type; old_mode = Objects[Cur_object_index].control_type; old_mode = Objects[Cur_object_index].ctype.ai_info.behavior; } } // --------------------------------------------------------------------------------------------------- void info_display_segsize(int show_all) { static int old_SegSizeMode; char name[30]; if (init_info | show_all) { old_SegSizeMode = -2; } if (old_SegSizeMode != SegSizeMode ) { switch (SegSizeMode) { case SEGSIZEMODE_FREE: strcpy(name, "free "); break; case SEGSIZEMODE_ALL: strcpy(name, "all "); break; case SEGSIZEMODE_CURSIDE: strcpy(name, "curside"); break; case SEGSIZEMODE_EDGE: strcpy(name, "edge "); break; case SEGSIZEMODE_VERTEX: strcpy(name, "vertex "); break; default: Error("Illegal value for SegSizeMode in info.c/info_display_segsize\n"); } gr_uprintf( 0, 0, "Mode: %s\n", name); old_SegSizeMode = SegSizeMode; } } extern int num_objects; // --------------------------------------------------------------------------------------------------- void info_display_default(int show_all) { static int old_Num_segments = -1; static int old_Num_vertices = -1; static int old_Num_objects = -1; static int old_Cursegp_num = -1; static int old_Curside = -1; static int old_Cursegp_num_for_verts = -1; static int old_CurrentTexture = -1; static int old_Num_walls = -1; static int old_Num_triggers = -1; if (init_info | show_all) { init_info = 0; old_Num_segments = -1; old_Num_vertices = -1; old_Num_objects = -1; old_Cursegp_num = -1; old_Cursegp_num_for_verts = -1; old_Curside = -1; old_CurrentTexture = -1; old_Num_walls = -1; old_Num_triggers = -1; } gr_set_fontcolor(CBLACK,CWHITE); //--------------- Number of segments ---------------- if ( old_Num_segments != Num_segments ) { gr_uprintf( 0, 0, "Segments: %4d/%4d", Num_segments, MAX_SEGMENTS ); old_Num_segments = Num_segments; } //---------------- Number of vertics ----------------- if ( old_Num_vertices != Num_vertices ) { gr_uprintf( 0, 16, "Vertices: %4d/%4d", Num_vertices, MAX_VERTICES ); old_Num_vertices = Num_vertices; } //---------------- Number of objects ----------------- if ( old_Num_objects != num_objects ) { gr_uprintf( 0, 32, "Objs: %3d/%3d", num_objects, MAX_OBJECTS ); old_Num_objects = num_objects; } //--------------- Current_segment_number ------------- //--------------- Current_side_number ------------- if (( old_Cursegp_num != Cursegp-Segments ) || ( old_Curside != Curside )) { gr_uprintf( 0, 48, "Cursegp/side: %3ld/%1d", Cursegp-Segments, Curside); gr_uprintf( 0, 128, " tmap1,2,o: %3d/%3dx%1d", Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2 & 0x3FFF, (Cursegp->sides[Curside].tmap_num2 >> 14) & 3); old_Cursegp_num = Cursegp-Segments; old_Curside = Curside; } //--------------- Current_vertex_numbers ------------- if ( old_Cursegp_num_for_verts != Cursegp-Segments ) { gr_uprintf( 0, 64, "{%3d,%3d,%3d,%3d,", Cursegp->verts[0],Cursegp->verts[1], Cursegp->verts[2],Cursegp->verts[3] ); gr_uprintf( 0, 80," %3d,%3d,%3d,%3d}", Cursegp->verts[4],Cursegp->verts[5], Cursegp->verts[6],Cursegp->verts[7] ); old_Cursegp_num_for_verts = Cursegp-Segments; } //--------------- Num walls/links/triggers ------------------------- if ( old_Num_walls != Num_walls ) { // gr_uprintf( 0, 96, "Walls/Links %d/%d", Num_walls, Num_links ); gr_uprintf( 0, 96, "Walls %3d", Num_walls ); old_Num_walls = Num_walls; } //--------------- Num triggers ---------------------- if ( old_Num_triggers != Num_triggers ) { gr_uprintf( 0, 112, "Num_triggers %2d", Num_triggers ); old_Num_triggers = Num_triggers; } //--------------- Current texture number ------------- if ( old_CurrentTexture != CurrentTexture ) { gr_uprintf( 0, 144, "Tex/Light: %3d %5.2f", CurrentTexture, f2fl(TmapInfo[CurrentTexture].lighting)); old_CurrentTexture = CurrentTexture; } } // ------------------------------------------------------------------------------------ void clear_pad_display(void) { gr_clear_canvas(CWHITE); gr_set_fontcolor( CBLACK, CWHITE ); } // ------------------------------------------------------------------------------------ int info_display_all(window *wind, d_event *event, void *userdata) { static int old_padnum = -1; int padnum,show_all = 1; // always redraw grs_canvas *save_canvas = grd_curcanv; switch (event->type) { case EVENT_WINDOW_DRAW: userdata++; //kill warning gr_set_current_canvas(window_get_canvas(wind)); padnum = ui_pad_get_current(); Assert(padnum <= MAX_PAD_ID); if (padnum != old_padnum) { clear_pad_display(); old_padnum = padnum; //show_all = 1; } switch (padnum) { case OBJECT_PAD_ID: // Object placement info_display_object_placement(show_all); break; case SEGSIZE_PAD_ID: // Segment sizing info_display_segsize(show_all); break; default: info_display_default(show_all); break; } grd_curcanv = save_canvas; return 1; case EVENT_WINDOW_CLOSE: Pad_info = NULL; break; default: break; } return 0; } // ------------------------------------------------------------------------------------ window *info_window_create(void) { window *wind; wind = window_create(Canv_editor, PAD_X + 250, PAD_Y + 8, 180, 160, info_display_all, NULL); if (wind) window_set_modal(wind, 0); return wind; } dxx-rebirth-0.58.1-d2x/editor/kbuild.c000066400000000000000000000144631217717237500174700ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for building parts of mines. * */ #include #include "inferno.h" #include "editor/editor.h" #include "editor/esegment.h" #include "gameseg.h" #include "gamesave.h" // ---------- Create a bridge segment between current segment/side and marked segment/side ---------- int CreateBridge() { if (!med_form_bridge_segment(Cursegp,Curside,Markedsegp,Markedside)) { Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Bridge segment formed."); strcpy(undo_status[Autosave_count], "Bridge segment UNDONE."); warn_if_concave_segments(); } return 1; } // ---------- Form a joint between current segment:side and marked segment:side, modifying marked segment ---------- int FormJoint() { if (!Markedsegp) diagnostic_message("Marked segment not set -- unable to form joint."); else { if (!med_form_joint(Cursegp,Curside,Markedsegp,Markedside)) { Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Joint formed."); strcpy(undo_status[Autosave_count], "Joint undone."); warn_if_concave_segments(); } } return 1; } // ---------- Create a bridge segment between current segment:side adjacent segment:side ---------- int CreateAdjacentJoint() { int adj_side; segment *adj_sp; if (med_find_adjacent_segment_side(Cursegp, Curside, &adj_sp, &adj_side)) { if (Cursegp->children[Curside] != adj_sp-Segments) { med_form_joint(Cursegp,Curside,adj_sp,adj_side); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Joint segment formed."); strcpy(undo_status[Autosave_count], "Joint segment undone."); warn_if_concave_segments(); } else editor_status("Attempted to form joint through connected side -- joint segment not formed (you bozo)."); } else editor_status("Could not find adjacent segment -- joint segment not formed."); return 1; } // ---------- Create a bridge segment between current segment:side adjacent segment:side ---------- int CreateSloppyAdjacentJoint() { int adj_side; segment *adj_sp; save_level("SLOPPY.LVL"); if (med_find_closest_threshold_segment_side(Cursegp, Curside, &adj_sp, &adj_side, 20*F1_0)) { if (Cursegp->children[Curside] != adj_sp-Segments) { if (!med_form_joint(Cursegp,Curside,adj_sp,adj_side)) { Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Sloppy Joint segment formed."); strcpy(undo_status[Autosave_count], "Sloppy Joint segment undone."); warn_if_concave_segments(); } else editor_status("Couldn't form sloppy joint.\n"); } else editor_status("Attempted to form sloppy joint through connected side -- joint segment not formed (you bozo)."); } else editor_status("Could not find close threshold segment -- joint segment not formed."); return 1; } // -------------- Create all sloppy joints within CurrentGroup ------------------ int CreateSloppyAdjacentJointsGroup() { int adj_side; segment *adj_sp; int num_segs = GroupList[current_group].num_segments; short *segs = GroupList[current_group].segments; segment *segp; int done_been_a_change = 0; int segind, sidenum; for (segind=0; segindchildren[sidenum])) if (med_find_closest_threshold_segment_side(segp, sidenum, &adj_sp, &adj_side, 5*F1_0)) { if (adj_sp->group == segp->group) { if (segp->children[sidenum] != adj_sp-Segments) if (!med_form_joint(segp, sidenum, adj_sp,adj_side)) done_been_a_change = 1; } } } if (done_been_a_change) { Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Sloppy Joint segment formed."); strcpy(undo_status[Autosave_count], "Sloppy Joint segment undone."); warn_if_concave_segments(); } return 1; } // ---------- Create a bridge segment between current segment and all adjacent segment:side ---------- int CreateAdjacentJointsSegment() { int adj_side,s; segment *adj_sp; med_combine_duplicate_vertices(Vertex_active); for (s=0; schildren[s] != adj_sp-Segments) { med_form_joint(Cursegp,s,adj_sp,adj_side); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; autosave_mine(mine_filename); diagnostic_message("Adjacent Joint segment formed."); strcpy(undo_status[Autosave_count], "Adjacent Joint segment UNDONE."); warn_if_concave_segments(); } } return 1; } // ---------- Create a bridge segment between all segment:side and all adjacent segment:side ---------- int CreateAdjacentJointsAll() { int adj_side,seg,s; segment *adj_sp; med_combine_duplicate_vertices(Vertex_active); for (seg=0; seg<=Highest_segment_index; seg++) for (s=0; s #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "kdefs.h" static fix r1scale, r4scale; static int curve; int InitCurve() { curve = 0; return 1; } int GenerateCurve() { if ( (Markedsegp != 0) && !IS_CHILD(Markedsegp->children[Markedside])) { r1scale = r4scale = F1_0*20; autosave_mine( mine_filename ); diagnostic_message("Curve Generated."); Update_flags |= UF_WORLD_CHANGED; curve = generate_curve(r1scale, r4scale); mine_changed = 1; if (curve == 1) { strcpy(undo_status[Autosave_count], "Curve Generation UNDONE.\n"); } if (curve == 0) diagnostic_message("Cannot generate curve -- check Current segment."); } else diagnostic_message("Cannot generate curve -- check Marked segment."); warn_if_concave_segments(); return 1; } int DecreaseR4() { if (curve) { Update_flags |= UF_WORLD_CHANGED; delete_curve(); r4scale -= F1_0; generate_curve(r1scale, r4scale); diagnostic_message("R4 vector decreased."); mine_changed = 1; warn_if_concave_segments(); } return 1; } int IncreaseR4() { if (curve) { Update_flags |= UF_WORLD_CHANGED; delete_curve(); r4scale += F1_0; generate_curve(r1scale, r4scale); diagnostic_message("R4 vector increased."); mine_changed = 1; warn_if_concave_segments(); } return 1; } int DecreaseR1() { if (curve) { Update_flags |= UF_WORLD_CHANGED; delete_curve(); r1scale -= F1_0; generate_curve(r1scale, r4scale); diagnostic_message("R1 vector decreased."); mine_changed = 1; warn_if_concave_segments(); } return 1; } int IncreaseR1() { if (curve) { Update_flags |= UF_WORLD_CHANGED; delete_curve(); r1scale += F1_0; generate_curve(r1scale, r4scale); diagnostic_message("R1 vector increased."); mine_changed = 1; warn_if_concave_segments(); } return 1; } int DeleteCurve() { // fix_bogus_uvs_all(); set_average_light_on_curside(); if (curve) { Update_flags |= UF_WORLD_CHANGED; delete_curve(); curve = 0; mine_changed = 1; diagnostic_message("Curve Deleted."); warn_if_concave_segments(); } return 1; } int SetCurve() { if (curve) curve = 0; //autosave_mine( mine_filename ); //strcpy(undo_status[Autosave_count], "Curve Generation UNDONE.\n"); return 1; } dxx-rebirth-0.58.1-d2x/editor/kfuncs.c000066400000000000000000000434241217717237500175060ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * . * */ #include #include "inferno.h" #include "func.h" #include "editor/kdefs.h" #include "segment.h" #include "editor/editor.h" #include "dxxerror.h" #include "slew.h" #include "gamesave.h" #include "editor/eobject.h" #include "editor/medwall.h" // Test function prototypes (replace Test1, 2 and 3 with whatever function you wish to test.) extern void test_create_path(); extern void test_create_all_paths(); extern void test_create_path_many(); extern void create_all_paths(); extern void test_create_all_anchors(); // extern void make_curside_bottom_side(); extern void move_object_to_mouse_click(); extern void test_create_n_segment_path(); extern void set_all_modes_to_hover(void); extern void check_for_overlapping_segments(void); extern void init_replacements(); extern void do_replacements(void); extern void do_replacements_all(void); int Test1() { init_replacements(); return 0; } int Test2() { do_replacements(); return 0; } //extern fix fcd_test(void); //extern void test_shortpos(void); int Test3() { Int3(); // Are you sure you want to do this? // This will replace all textures in your replacement list // in all mines. // If you don't want to do this, set eip to the return statement // and continue. do_replacements_all(); return 0; } FUNCTION med_functions[] = { // Test functions { "med-test-1", 0, Test1 }, { "med-test-2", 0, Test2 }, { "med-test-3", 0, Test3 }, // In khelp.c { "med-help", 0, DoHelp }, // In kcurve.c { "med-curve-init", 0, InitCurve }, { "med-curve-generate", 0, GenerateCurve }, { "med-curve-decrease-r4", 0, DecreaseR4 }, { "med-curve-increase-r4", 0, IncreaseR4 }, { "med-curve-decrease-r1", 0, DecreaseR1 }, { "med-curve-increase-r1", 0, IncreaseR1 }, { "med-curve-delete", 0, DeleteCurve }, { "med-curve-set", 0, SetCurve }, // In kmine.c { "med-mine-save", 0, SaveMine }, //{ "med-mine-load", 0, LoadMine }, { "med-mine-menu", 0, MineMenu }, { "med-mine-create-new", 0, CreateNewMine }, //{ "med-mine-load-old", 0, LoadOldMine }, { "med-situation-save", 0, SaveSituation }, { "med-situation-load", 0, LoadSituation }, { "med-restore-game-state", 0, RestoreGameState }, //{ "load-mine-only", 0, LoadMineOnly }, // In kgame.c { "med-game-save", 0, SaveGameData }, { "med-game-load", 0, LoadGameData }, // In kview.c { "med-view-zoom-out", 0, ZoomOut }, { "med-view-zoom-in", 0, ZoomIn }, { "med-view-move-away", 0, MoveAway }, { "med-view-move-closer", 0, MoveCloser }, { "med-view-toggle-chase", 0, ToggleChaseMode }, // In kbuild.c { "med-build-bridge", 0, CreateBridge }, { "med-build-joint", 0, FormJoint }, { "med-build-adj-joint", 0, CreateAdjacentJoint }, { "med-build-sloppy-adj-joint", 0, CreateSloppyAdjacentJoint }, { "med-build-sloppy-adj-joint-group", 0, CreateSloppyAdjacentJointsGroup }, { "med-build-adj-joints-segment", 0, CreateAdjacentJointsSegment }, { "med-build-adj-joints-all", 0, CreateAdjacentJointsAll }, // In segment.c { "med-segment-bottom", 0, ToggleBottom }, //make_curside_bottom_side }, { "med-segment-show-bottom", 0, ToggleBottom }, // In ksegmove.c { "med-segmove-decrease-heading", 0, DecreaseHeading }, { "med-segmove-increase-heading", 0, IncreaseHeading }, { "med-segmove-decrease-pitch", 0, DecreasePitch }, { "med-segmove-increase-pitch", 0, IncreasePitch }, { "med-segmove-decrease-bank", 0, DecreaseBank }, { "med-segmove-increase-bank", 0, IncreaseBank }, // In ksegsel.c { "med-segsel-next-segment", 0, SelectCurrentSegForward }, { "med-segsel-prev-segment", 0, SelectCurrentSegBackward }, { "med-segsel-next-side", 0, SelectNextSide }, { "med-segsel-prev-side", 0, SelectPrevSide }, { "med-segsel-set-marked", 0, CopySegToMarked }, { "med-segsel-bottom", 0, SelectBottom }, { "med-segsel-front", 0, SelectFront }, { "med-segsel-top", 0, SelectTop }, { "med-segsel-back", 0, SelectBack }, { "med-segsel-left", 0, SelectLeft }, { "med-segsel-right", 0, SelectRight }, // In ksegsize.c { "med-segsize-increase-length", 0, IncreaseSegLength }, { "med-segsize-decrease-length", 0, DecreaseSegLength }, { "med-segsize-decrease-width", 0, DecreaseSegWidth }, { "med-segsize-increase-width", 0, IncreaseSegWidth }, { "med-segsize-increase-height", 0, IncreaseSegHeight }, { "med-segsize-decrease-height", 0, DecreaseSegHeight }, { "med-segsize-increase-length-big", 0, IncreaseSegLengthBig }, { "med-segsize-decrease-length-big", 0, DecreaseSegLengthBig }, { "med-segsize-decrease-width-big", 0, DecreaseSegWidthBig }, { "med-segsize-increase-width-big", 0, IncreaseSegWidthBig }, { "med-segsize-increase-height-big", 0, IncreaseSegHeightBig }, { "med-segsize-decrease-height-big", 0, DecreaseSegHeightBig }, { "med-segsize-toggle-mode", 0, ToggleSegSizeMode }, { "med-segsize-perturb-curside", 0, PerturbCurside }, { "med-segsize-perturb-curside-big", 0, PerturbCursideBig }, { "med-segsize-increase-length-default", 0, IncreaseSegLengthDefault }, { "med-segsize-decrease-length-default", 0, DecreaseSegLengthDefault }, { "med-segsize-increase-width-default", 0, IncreaseSegWidthDefault }, { "med-segsize-decrease-width-default", 0, DecreaseSegWidthDefault }, { "med-segsize-increase-height-default", 0, IncreaseSegHeightDefault }, { "med-segsize-decrease-height-default", 0, DecreaseSegHeightDefault }, // In ktmap.c { "med-tmap-assign", 0, AssignTexture }, { "med-tmap-assign2", 0, AssignTexture2 }, { "med-tmap-clear2", 0, ClearTexture2 }, { "med-tmap-propogate", 0, PropagateTextures }, { "med-tmap-propogate-move", 0, PropagateTexturesMove }, { "med-tmap-propogate-move-uvs", 0, PropagateTexturesMoveUVs }, { "med-tmap-propogate-move-uvs", 0, PropagateTexturesMoveUVs }, { "med-tmap-propogate-uvs", 0, PropagateTexturesUVs }, { "med-tmap-propogate-selected", 0, PropagateTexturesSelected }, // In wall.c { "med-wall-add-blastable", 0, wall_add_blastable }, { "med-wall-add-door", 0, wall_add_door }, { "med-wall-add-closed", 0, wall_add_closed_wall }, { "med-wall-add-external", 0, wall_add_external_wall }, { "med-wall-add-illusion", 0, wall_add_illusion }, { "med-wall-restore-all", 0, wall_restore_all }, { "med-wall-remove", 0, wall_remove }, { "do-wall-dialog", 0, do_wall_dialog }, { "med-link-doors", 0, wall_link_doors }, { "med-unlink-door", 0, wall_unlink_door }, { "check-walls", 0, check_walls }, { "delete-all-walls", 0, delete_all_walls }, // In centers.c { "do-centers-dialog", 0, do_centers_dialog }, // In switch.c //{ "med-trigger-add-damage", 0, trigger_add_damage }, //{ "med-trigger-add-exit", 0, trigger_add_exit }, //{ "med-trigger-control", 0, trigger_control }, //{ "med-trigger-remove", 0, trigger_remove }, //{ "med-bind-wall-to-control", 0, bind_wall_to_control_trigger }, { "do-trigger-dialog", 0, do_trigger_dialog }, //--//// In macro.c //--//{ "med-macro-menu", 0, MacroMenu }, //--//{ "med-macro-play-fast", 0, MacroPlayFast }, //--//{ "med-macro-play-normal", 0, MacroPlayNormal }, //--//{ "med-macro-record-all", 0, MacroRecordAll }, //--//{ "med-macro-record-keys", 0, MacroRecordKeys }, //--//{ "med-macro-save", 0, MacroSave }, //--//{ "med-macro-load", 0, MacroLoad }, // In editor.c { "med-update", 0, medlisp_update_screen }, { "med-segment-add", 0, AttachSegment }, { "med-segment-delete", 0, medlisp_delete_segment }, { "med-segment-scale", 3, medlisp_scale_segment }, { "med-segment-rotate", 3, medlisp_rotate_segment }, { "med-dos-shell", 0, DosShell }, //{ "med-lisp-call", 0, CallLisp }, { "med-editor-exit", 0, ExitEditor }, { "med-segment-exchange", 0, ExchangeMarkandCurseg }, { "med-segment-mark", 0, CopySegToMarked }, { "med-about", 0, ShowAbout }, #ifndef NDEBUG { "med-mark-start", 0, MarkStart }, { "med-mark-end", 0, MarkEnd }, #endif // In group.c { "med-group-load", 0, LoadGroup }, { "med-group-save", 0, SaveGroup }, { "med-move-group", 0, MoveGroup }, { "med-copy-group", 0, CopyGroup }, { "med-rotate-group", 0, RotateGroup }, { "med-segment-add-new", 0, AttachSegmentNew }, { "med-mark-groupseg", 0, MarkGroupSegment }, { "med-next-group", 0, NextGroup }, { "med-prev-group", 0, PrevGroup }, { "med-delete-group", 0, DeleteGroup }, { "med-create-group", 0, CreateGroup }, { "med-ungroup-segment", 0, UngroupSegment }, { "med-group-segment", 0, GroupSegment }, { "med-degroup-group", 0, Degroup }, { "med-subtract-from-group", 0, SubtractFromGroup }, // In autosave.c { "med-autosave-undo", 0, UndoCommand }, { "med-autosave-toggle", 0, ToggleAutosave }, // In texture.c { "med-tass-flip-x", 0, TexFlipX }, { "med-tass-flip-y", 0, TexFlipY }, { "med-tass-slide-up", 0, TexSlideUp }, { "med-tass-slide-left", 0, TexSlideLeft }, { "med-tass-set-default", 0, TexSetDefault }, { "med-tass-slide-right", 0, TexSlideRight }, { "med-tass-rotate-left", 0, TexRotateLeft }, { "med-tass-slide-down", 0, TexSlideDown }, { "med-tass-stretch-down", 0, TexStretchDown }, { "med-tass-stretch-up", 0, TexStretchUp }, { "med-tass-rotate-right", 0, TexRotateRight }, { "med-tass-select-active-edge", 0, TexSelectActiveEdge }, { "med-tass-rotate-90-degrees", 0, TexRotate90Degrees }, { "med-tass-increase-tiling", 0, TexIncreaseTiling }, { "med-tass-decrease-tiling", 0, TexDecreaseTiling }, { "med-tass-slide-up-big", 0, TexSlideUpBig }, { "med-tass-slide-left-big", 0, TexSlideLeftBig }, { "med-tass-slide-right-big", 0, TexSlideRightBig }, { "med-tass-rotate-left-big", 0, TexRotateLeftBig }, { "med-tass-slide-down-big", 0, TexSlideDownBig }, { "med-tass-rotate-right-big", 0, TexRotateRightBig }, // In eobject.c { "med-obj-set-player", 0, SetPlayerPosition }, { "med-obj-place-object", 0, ObjectPlaceObject }, { "med-obj-place-object-tmap", 0, ObjectPlaceObjectTmap }, { "med-obj-move-nearer", 0, ObjectMoveNearer }, { "med-obj-move-further", 0, ObjectMoveFurther }, { "med-obj-delete-object", 0, ObjectDelete }, { "med-obj-move-forward", 0, ObjectMoveForward }, { "med-obj-move-left", 0, ObjectMoveLeft }, { "med-obj-set-default", 0, ObjectSetDefault }, { "med-obj-move-right", 0, ObjectMoveRight }, { "med-obj-move-back", 0, ObjectMoveBack }, { "med-obj-move-down", 0, ObjectMoveDown }, { "med-obj-move-up", 0, ObjectMoveUp }, { "med-obj-select-next-in-segment", 0, ObjectSelectNextinSegment }, { "med-obj-decrease-bank", 0, ObjectDecreaseBank }, { "med-obj-increase-bank", 0, ObjectIncreaseBank }, { "med-obj-decrease-pitch", 0, ObjectDecreasePitch }, { "med-obj-increase-pitch", 0, ObjectIncreasePitch }, { "med-obj-decrease-heading", 0, ObjectDecreaseHeading }, { "med-obj-increase-heading", 0, ObjectIncreaseHeading }, { "med-obj-decrease-bank-big", 0, ObjectDecreaseBankBig }, { "med-obj-increase-bank-big", 0, ObjectIncreaseBankBig }, { "med-obj-decrease-pitch-big", 0, ObjectDecreasePitchBig }, { "med-obj-increase-pitch-big", 0, ObjectIncreasePitchBig }, { "med-obj-decrease-heading-big", 0, ObjectDecreaseHeadingBig }, { "med-obj-increase-heading-big", 0, ObjectIncreaseHeadingBig }, { "med-obj-reset", 0, ObjectResetObject }, { "med-obj-flip", 0, ObjectFlipObject }, { "med-obj-make-coop", 0, ObjectMakeCoop }, //{ "med-obj-place-hostage", 0, ObjectPlaceHostage }, // In objpage.c { "med-obj-select-next-type", 0, objpage_goto_next_object }, // In elight.c { "med-light-select-next-vertex", 0, LightSelectNextVertex }, { "med-light-select-next-edge", 0, LightSelectNextEdge }, { "med-light-copy-intensity-side", 0, LightCopyIntensity }, { "med-light-copy-intensity-segment", 0, LightCopyIntensitySegment }, { "med-light-decrease-light-vertex", 0, LightDecreaseLightVertex }, { "med-light-increase-light-vertex", 0, LightIncreaseLightVertex }, { "med-light-decrease-light-side", 0, LightDecreaseLightSide }, { "med-light-increase-light-side", 0, LightIncreaseLightSide }, { "med-light-decrease-light-segment", 0, LightDecreaseLightSegment }, { "med-light-increase-light-segment", 0, LightIncreaseLightSegment }, { "med-light-set-maximum", 0, LightSetMaximum }, { "med-light-set-default", 0, LightSetDefault }, { "med-light-assign-default-all", 0, LightSetDefaultAll }, { "med-light-ambient-lighting", 0, LightAmbientLighting }, // In seguvs.c { "med-seguvs-fix-bogus-uvs-on-side", 0, fix_bogus_uvs_on_side}, { "med-seguvs-fix-bogus-uvs-all", 0, fix_bogus_uvs_all}, { "med-seguvs-smooth-lighting-all", 0, set_average_light_on_all}, { "med-seguvs-smooth-lighting-all-quick", 0, set_average_light_on_all_quick}, { "med-seguvs-smooth-lighting", 0, set_average_light_on_curside}, // Miscellaneous, please neaten and catagorize me! { "med-increase-draw-depth", 0, IncreaseDrawDepth }, { "med-decrease-draw-depth", 0, DecreaseDrawDepth }, { "med-goto-main-menu", 0, GotoMainMenu }, { "med-goto-game-screen", 0, GotoGameScreen }, { "med-drop-into-debugger", 0, DropIntoDebugger }, // { "med-sync-large-view", 0, SyncLargeView }, { "med-create-default-new-segment", 0, CreateDefaultNewSegment }, { "med-create-default-new-segment-and-attach", 0, CreateDefaultNewSegmentandAttach }, { "med-clear-selected-list", 0, ClearSelectedList }, { "med-clear-found-list", 0, ClearFoundList }, { "med-sort-selected-list", 0, SortSelectedList }, { "med-set-player-from-curseg", 0, SetPlayerFromCursegAndRotate }, { "med-set-player-from-curseg-minus-one", 0, SetPlayerFromCursegMinusOne }, { "med-find-concave-segs", 0, FindConcaveSegs }, { "med-select-next-found-seg", 0, SelectNextFoundSeg }, { "med-select-prev-found-seg", 0, SelectPreviousFoundSeg }, { "med-stop-slew", 0, slew_stop }, //{ "med-reset-orientation", 0, do_reset_orient }, { "med-game-zoom-out", 0, GameZoomOut }, { "med-game-zoom-in", 0, GameZoomIn }, { "med-keypad-goto-prev", 0, med_keypad_goto_prev }, { "med-keypad-goto-next", 0, med_keypad_goto_next }, { "med-keypad-goto", 1, med_keypad_goto }, // John's temporary function page stuff // { "med-set-function-page", 1, medtmp_set_page }, // In fuelcen.c { "med-fuelcen-create", 0, fuelcen_create_from_curseg }, { "med-repaircen-create", 0, repaircen_create_from_curseg }, { "med-controlcen-create", 0, controlcen_create_from_curseg }, { "med-robotmaker-create", 0, robotmaker_create_from_curseg }, { "med-fuelcen-reset-all", 0, fuelcen_reset_all }, { "med-fuelcen-delete", 0, fuelcen_delete_from_curseg }, // In robot.c { "do-robot-dialog", 0, do_robot_dialog }, { "do-object-dialog", 0, do_object_dialog }, // In gamesavec { "rename-level", 0, get_level_name }, // The terminating marker { NULL, 0, NULL } }; void init_med_functions() { func_init(med_functions, (sizeof(med_functions)/sizeof(FUNCTION))-1 ); } dxx-rebirth-0.58.1-d2x/editor/kgame.c000066400000000000000000000100661217717237500172750ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Game Loading editor functions * */ #include #include #include "inferno.h" #include "editor.h" #include "ui.h" #include "game.h" #include "gamesave.h" #include "gameseq.h" char game_filename[PATH_MAX] = "*.RL2"; extern void checkforext( char * f, char *ext ); void checkforgamext( char * f ) { int i; for (i=1; ipos; Perm_player_orient = ConsoleObject->orient; Perm_player_segnum = ConsoleObject->segnum; editor_status("Player initial position set"); return 0; } // Save game // returns 1 if successful // returns 0 if unsuccessful int SaveGameData() { char Message[200]; if (gamestate_not_restored) { sprintf( Message, "Game State has not been restored...\nContinue?\n"); if (ui_messagebox( -2, -2, 2, Message, "NO", "Yes" )==1) return 0; } if (ui_get_filename( game_filename, "*.RL2", "SAVE GAME" )) { int saved_flag; vms_vector save_pos = ConsoleObject->pos; vms_matrix save_orient = ConsoleObject->orient; int save_segnum = ConsoleObject->segnum; checkforgamext(game_filename); if (Perm_player_segnum > Highest_segment_index) Perm_player_segnum = -1; if (Perm_player_segnum!=-1) { if (get_seg_masks(&Perm_player_position, Perm_player_segnum, 0, __FILE__, __LINE__).centermask == 0) { ConsoleObject->pos = Perm_player_position; obj_relink(ConsoleObject-Objects,Perm_player_segnum); ConsoleObject->orient = Perm_player_orient; } else Perm_player_segnum=-1; //position was bogus } saved_flag=save_level(game_filename); if (Perm_player_segnum!=-1) { int found_save_segnum; if (save_segnum > Highest_segment_index) save_segnum = 0; ConsoleObject->pos = save_pos; found_save_segnum = find_point_seg(&save_pos,save_segnum); if (found_save_segnum == -1) { compute_segment_center(&save_pos, &(Segments[save_segnum])); found_save_segnum = save_segnum; } obj_relink(ConsoleObject-Objects,found_save_segnum); ConsoleObject->orient = save_orient; } if (saved_flag) return 0; mine_changed = 0; } return 1; } // returns 1 if successful // returns 0 if unsuccessful int LoadGameData() { if (SafetyCheck()) { if (ui_get_filename( game_filename, "*.RL2", "LOAD GAME" )) { checkforgamext(game_filename); if (load_level(game_filename)) return 0; Current_level_num = 0; //not a real level gamestate_not_restored = 0; Update_flags = UF_WORLD_CHANGED; Perm_player_position = ConsoleObject->pos; Perm_player_orient = ConsoleObject->orient; Perm_player_segnum = ConsoleObject->segnum; } } return 1; } //called whenever a new mine is created, so new mine doesn't get name //of last saved mine as default void ResetFilename() { strcpy(game_filename,"*.LVL"); } dxx-rebirth-0.58.1-d2x/editor/khelp.c000066400000000000000000000134411217717237500173140ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for showing help. * */ #include "inferno.h" #include "editor.h" #include "ui.h" static char MainHelpText[] = "\nMED General Functions\n\n" \ "SPACEBAR Full Redraw\n" \ "BACKSPACE Drop into debugger\n\n" \ "A Attach a segment\n" \ "D Delete current segment\n\n" \ "F Toggle to game\n" \ "G or S Go to game (Toggle screen)\n\n" \ "ALT-C Create new mine\n" \ "ALT-S Save mine\n" \ "ALT-L Load mine\n"\ "ESC Exit editor\n"\ "ALT-Q/CTRL-Q/SHIFT-Q also Exit editor\n"; static char SegmentHelpText[] = "MED Segment Functions\n\n" \ "ALT-B Create Bridge from current to marked segment\n" \ "ALT-E Exchange current and marked segments\n" \ "ALT-J Create Joint between current and marked segments\n" \ "ALT-SHIFT-J Create Joint on current side and adjacent segments\n" \ "ALT-CTRL-J Create Joint on current segment and adjacent segments\n" \ "ALT-CTRL-SHIFT-J Create Joints on all adjacent segments\n" \ "ALT-M Mark current segment and side\n" \ "ALT-N Create default segment for New_segment\n" \ "CTRL-A Toggle - Draw all segments/Draw connected segments\n" \ "CTRL-C Clear selected list\n" \ "CTRL-D Toggle display of coordinate axes\n" \ "CTRL-S Advance to segment through Curside\n" \ "ALT-T Assign Texture to current side\n" \ "CTRL-P Propogate Textures\n" \ "CTRL-SHIFT-P Propogate Textures on Selected segments\n" \ "CTRL-SHIFT-S Advance to segment opposite Curside\n" \ "CTRL-F Select next side\n" \ "CTRL-SHIFT-F Select previous side\n"; static char KeyPadHelpText[] = "MED KeyPad Functions\n\n" \ "SHIFT-KEYPAD FUNCTIONS (Change direction vector of segment)\n" \ "----------------------\n" \ "(7) 8 Decrease Pitch (9)\n" \ " 4 Decrease Heading (5) 6 Increase Heading\n" \ " 1 Decrease Bank 2 Increase Pitch 3 Increase Bank\n\n" \ "CTRL-KEYPAD FUNCTIONS (Change size/shape of segment)\n" \ "---------------------\n" \ "(7) 8 Increase Length 9 Increase Height\n" \ " 4 Decrease Width (5) 6 Increase Width\n" \ "(1) 2 Decrease Length 3 Decrease Height\n"\ "\nIn addition, CTRL-SHIFT-KEYPAD Changes size at x5 rate as above\n"; char ViewHelpText[] = "MED View Changing Functions\n\n" \ "ALT-V Change to orthogonal view (1,2,3)\n" \ "CTRL-V Toggle view to current segment\n" \ "MINUS (-) Zoom in\n" \ "EQUAL (=) Zoom out\n" \ "SHIFT-MINUS Decrease viewer distance\n" \ "SHIFT-EQUAL Increase viewer distance\n" \ "\n* Holding the Ctrl key and moving the mouse will change\n" \ "the viewer's orientation in the main window."; //"CTRL-MINUS Decreases drawing depth\n" //"CTRL-EQUAL Increases drawing depth\n" static char GameHelpText[] = "MED Game Screen Functions\n\n" \ "KEYPAD FUNCTIONS (Moves in game screen)\n" \ "----------------\n" \ "(7) 8 Move Forward (9)\n" \ " 4 Decrease Heading 5 Complete Stop 6 Increase Heading\n" \ " 1 Decrease Bank 2 Move Backward 3 Increase Bank\n\n" \ "[ Decreases Pitch\n" \ "] Increases Pitch\n" \ "C Set Player from Current segment\n" \ "L Toggle Lock Step\n" \ "O Toggle Outline Mode\n" \ "SHIFT-C Set PLayer from Current segment-1\n" \ "SHIFT-L Toggle Lighting effect\n" \ "NUMLOCK Reset orientation\n" \ "PAD DIVIDE (/) Game Zoom out\n" \ "PAD MULTIPLY (*) Game Zoom In\n"; static char CurveHelpText[] = "MED Curve Generation Functions\n\n" \ "ALT-F10 Generate curve\n" \ "F8 Delete curve\n" \ "F11 'Set' curve\n" \ "F9 Decrease r1 vector\n" \ "SHIFT-F9 Increase r1 vector\n" \ "F10 Decrease r4 vector\n" \ "SHIFT-F10 Increase r4 vector\n"; static char MacrosHelpText[] = "MED Macros Functions\n\n" \ "CTRL-INSERT Play fast\n" \ "CTRL-DELETE Play normal\n" \ "CTRL-HOME Record all\n" \ "CTRL-END Record keys\n" \ "CTRL-PAGEUP Save Macro\n" \ "CTRL-PAGEDOWN Load Macro\n"; int DoHelp() { int help_key = 2; int more_key = 2; while (help_key > 1) { help_key = ui_messagebox( -2, -2, 5, MainHelpText, "Ok", "Segment", "Keypad", "View", "More"); if (help_key == 2) ui_messagebox( -2, -2, 1, SegmentHelpText, "Ok" ); if (help_key == 3) ui_messagebox( -2, -2, 1, KeyPadHelpText, "Ok" ); if (help_key == 4) ui_messagebox( -2, -2, 1, ViewHelpText, "Ok" ); if (help_key == 5) { more_key = ui_messagebox( -2, -2, 4, MainHelpText, "Back", "Curve", "Macro", "Game"); if (more_key == 2) ui_messagebox( -2, -2, 1, CurveHelpText, "Ok" ); if (help_key == 3) ui_messagebox( -2, -2, 1, MacrosHelpText, "Ok" ); if (help_key == 4) ui_messagebox( -2, -2, 1, GameHelpText, "Ok" ); } } return 1; } dxx-rebirth-0.58.1-d2x/editor/kmine.c000066400000000000000000000142241217717237500173140ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions to change entire mines. * */ #include #include #include #include "dxxerror.h" #include "strutil.h" #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "ui.h" #include "texpage.h" // For texpage_goto_first #include "segment.h" #include "kdefs.h" #include "info.h" #include "game.h" #include "gameseq.h" #include "object.h" #define MINESAVE_CRIPPLED 0 char mine_filename[PATH_MAX] = "*.MIN"; char sit_filename[PATH_MAX] = "*.SIT"; #define MAX_NAME_LENGTH PATH_MAX // See if filename f contains an extent. If not, add extent ext. void checkforext( char * f, char *ext ) { int i; for (i=1; ipos.x,(unsigned int) ConsoleObject->pos.y,(unsigned int) ConsoleObject->pos.z); // Write player orientation. PHYSFSX_printf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.rvec.x,(unsigned int) ConsoleObject->orient.rvec.y,(unsigned int) ConsoleObject->orient.rvec.z); PHYSFSX_printf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.uvec.x,(unsigned int) ConsoleObject->orient.uvec.y,(unsigned int) ConsoleObject->orient.uvec.z); PHYSFSX_printf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.fvec.x,(unsigned int) ConsoleObject->orient.fvec.y,(unsigned int) ConsoleObject->orient.fvec.z); PHYSFSX_printf(SaveFile, "%i\n", ConsoleObject->segnum); PHYSFS_close( SaveFile); return 1; } // ----------------------------------------------------------------------------- int SaveSituation(void) { if (ui_get_filename( sit_filename, "*.SIT", "Save Situation" )) { set_extension(sit_filename, "MIN"); if (med_save_mine(sit_filename)) { return 0; } set_extension(sit_filename, "SIT"); if (med_save_situation(sit_filename)) return 0; } return 1; } // ----------------------------------------------------------------------------- // Load a situation file which consists of x,y,z, orientation matrix, mine name. int LoadSituation(void) { if (SafetyCheck()) { if (ui_get_filename( sit_filename, "*.sit", "Load Situation" )) { checkforext(sit_filename, "SIT"); if (med_load_situation(sit_filename)) return 0; // set_view_target_from_segment(Cursegp); Update_flags = UF_WORLD_CHANGED; // SetPlayerFromCurseg(); med_compress_mine(); init_info = 1; mine_changed = 0; } } return 1; } dxx-rebirth-0.58.1-d2x/editor/ksegmove.c000066400000000000000000000040231217717237500200250ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for moving segments. * */ //#include //#include //#include //#include #include "inferno.h" #include "editor.h" #include "editor/esegment.h" // -- old -- int SegOrientCommon(fixang *ang, fix val) // -- old -- { // -- old -- *ang += val; // -- old -- med_rotate_segment_ang(Cursegp,&Seg_orientation); // -- old -- Update_flags |= UF_WORLD_CHANGED; // -- old -- mine_changed = 1; // -- old -- warn_if_concave_segment(Cursegp); // -- old -- return 1; // -- old -- } int SegOrientCommon(fixang *ang, fix val) { Seg_orientation.p = 0; Seg_orientation.b = 0; Seg_orientation.h = 0; *ang += val; rotate_segment_new(&Seg_orientation); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; warn_if_concave_segment(Cursegp); return 1; } // ---------- segment orientation control ---------- int DecreaseHeading() { // decrease heading return SegOrientCommon(&Seg_orientation.h,-512); } int IncreaseHeading() { return SegOrientCommon(&Seg_orientation.h,+512); } int DecreasePitch() { return SegOrientCommon(&Seg_orientation.p,-512); } int IncreasePitch() { return SegOrientCommon(&Seg_orientation.p,+512); } int DecreaseBank() { return SegOrientCommon(&Seg_orientation.b,-512); } int IncreaseBank() { return SegOrientCommon(&Seg_orientation.b,+512); } dxx-rebirth-0.58.1-d2x/editor/ksegsel.c000066400000000000000000000122471217717237500176510ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for selecting segments * */ #include #include "inferno.h" #include "editor/editor.h" #include "editor/esegment.h" // --------------------------------------------------------------------------------------- // Select previous segment. // If there is a connection on the side opposite to the current side, then choose that segment. // If there is no connecting segment on the opposite face, try any segment. void get_previous_segment(int curseg_num, int curside,int *newseg_num, int *newside) { int s; *newseg_num = curseg_num; if (IS_CHILD(Segments[curseg_num].children[(int)Side_opposite[curside]])) *newseg_num = Segments[curseg_num].children[(int)Side_opposite[curside]]; else // no segment on opposite face, connect to anything for (s=0; s= MAX_SIDES_PER_SEGMENT) Curside = 0; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectPrevSide() { if (--Curside < 0) Curside = MAX_SIDES_PER_SEGMENT-1; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } // ---------- Copy current segment and side to marked segment and side ---------- int CopySegToMarked() { autosave_mine(mine_filename); strcpy(undo_status[Autosave_count], "Mark Segment UNDONE."); Markedsegp = Cursegp; Markedside = Curside; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } // ---------- select absolute face on segment ---------- int SelectBottom() { Curside = WBOTTOM; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectFront() { Curside = WFRONT; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectTop() { Curside = WTOP; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectBack() { Curside = WBACK; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectLeft() { Curside = WLEFT; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } int SelectRight() { Curside = WRIGHT; Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; return 1; } dxx-rebirth-0.58.1-d2x/editor/ksegsize.c000066400000000000000000000261111217717237500200330ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for sizing segments * */ #include #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "gameseg.h" #define XDIM 0 #define YDIM 1 #define ZDIM 2 #define MAX_MODIFIED_VERTICES 32 int Modified_vertices[MAX_MODIFIED_VERTICES]; int Modified_vertex_index = 0; // ------------------------------------------------------------------------------------------ void validate_modified_segments(void) { int v,w,v0,seg; char modified_segments[MAX_SEGMENTS]; for (v=0; v<=Highest_segment_index; v++) modified_segments[v] = 0; for (v=0; vx += fixmul(vp->x,scale_factor)/2; vertp->y += fixmul(vp->y,scale_factor)/2; vertp->z += fixmul(vp->z,scale_factor)/2; Assert(Modified_vertex_index < MAX_MODIFIED_VERTICES); Modified_vertices[Modified_vertex_index++] = vertex_ind; } // ------------------------------------------------------------------------------------------ void scale_vert(segment *sp, int vertex_ind, vms_vector *vp, fix scale_factor) { switch (SegSizeMode) { case SEGSIZEMODE_FREE: if (is_free_vertex(vertex_ind)) scale_vert_aux(vertex_ind, vp, scale_factor); break; case SEGSIZEMODE_ALL: scale_vert_aux(vertex_ind, vp, scale_factor); break; case SEGSIZEMODE_CURSIDE: { int v; for (v=0; v<4; v++) if (sp->verts[Side_to_verts[Curside][v]] == vertex_ind) scale_vert_aux(vertex_ind, vp, scale_factor); break; } case SEGSIZEMODE_EDGE: { int v; for (v=0; v<2; v++) if (sp->verts[Side_to_verts[Curside][(Curedge+v)%4]] == vertex_ind) scale_vert_aux(vertex_ind, vp, scale_factor); break; } case SEGSIZEMODE_VERTEX: if (sp->verts[Side_to_verts[Curside][Curvert]] == vertex_ind) scale_vert_aux(vertex_ind, vp, scale_factor); break; default: Error("Unsupported SegSizeMode in ksegsize.c/scale_vert = %i\n", SegSizeMode); } } // ------------------------------------------------------------------------------------------ void scale_free_verts(segment *sp, vms_vector *vp, int side, fix scale_factor) { int v; const sbyte *verts; int vertex_ind; verts = Side_to_verts[side]; for (v=0; v<4; v++) { vertex_ind = sp->verts[(int) verts[v]]; if (SegSizeMode || is_free_vertex(vertex_ind)) scale_vert(sp, vertex_ind, vp, scale_factor); } } // ----------------------------------------------------------------------------- // Make segment *sp bigger in dimension dimension by amount amount. void med_scale_segment_new(segment *sp, int dimension, fix amount) { vms_matrix mat; Modified_vertex_index = 0; med_extract_matrix_from_segment(sp, &mat); switch (dimension) { case XDIM: scale_free_verts(sp, &mat.rvec, WLEFT, -amount); scale_free_verts(sp, &mat.rvec, WRIGHT, +amount); break; case YDIM: scale_free_verts(sp, &mat.uvec, WBOTTOM, -amount); scale_free_verts(sp, &mat.uvec, WTOP, +amount); break; case ZDIM: scale_free_verts(sp, &mat.fvec, WFRONT, -amount); scale_free_verts(sp, &mat.fvec, WBACK, +amount); break; } validate_modified_segments(); } // ------------------------------------------------------------------------------------------ // Extract a vector from a segment. The vector goes from the start face to the end face. // The point on each face is the average of the four points forming the face. void extract_vector_from_segment_side(segment *sp, int side, vms_vector *vp, int vla, int vlb, int vra, int vrb) { vms_vector v1, v2; vm_vec_sub(&v1,&Vertices[sp->verts[Side_to_verts[side][vra]]],&Vertices[sp->verts[Side_to_verts[side][vla]]]); vm_vec_sub(&v2,&Vertices[sp->verts[Side_to_verts[side][vrb]]],&Vertices[sp->verts[Side_to_verts[side][vlb]]]); vm_vec_add(vp, &v1, &v2); vm_vec_scale(vp, F1_0/2); } // ------------------------------------------------------------------------------------------ // Extract the right vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the left face of the segment // to the center of the right face of the segment. void med_extract_right_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp) { extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1); } // ------------------------------------------------------------------------------------------ // Extract the up vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the bottom face of the segment // to the center of the top face of the segment. void med_extract_up_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp) { extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3); } // ----------------------------------------------------------------------------- // Increase the size of Cursegp in dimension dimension by amount int segsize_common(int dimension, fix amount) { int i; int propagated[MAX_SIDES_PER_SEGMENT]; vms_vector uvec, rvec, fvec, scalevec; Degenerate_segment_found = 0; med_scale_segment_new(Cursegp, dimension, amount); med_extract_up_vector_from_segment_side(Cursegp, Curside, &uvec); med_extract_right_vector_from_segment_side(Cursegp, Curside, &rvec); extract_forward_vector_from_segment(Cursegp, &fvec); scalevec.x = vm_vec_mag(&rvec); scalevec.y = vm_vec_mag(&uvec); scalevec.z = vm_vec_mag(&fvec); if (Degenerate_segment_found) { Degenerate_segment_found = 0; editor_status("Applying scale would create degenerate segments. Aborting scale."); med_scale_segment_new(Cursegp, dimension, -amount); return 1; } med_create_new_segment(&scalevec); // For all segments to which Cursegp is connected, propagate tmap (uv coordinates) from the connected // segment back to Cursegp. This will meaningfully propagate uv coordinates to all sides which havve // an incident edge. It will also do some sides more than once. And it is probably just not what you want. for (i=0; ichildren[i])) { int s; for (s=0; schildren[i]],Cursegp,1); } // Now, for all sides that were not adjacent to another side, and therefore did not get tmaps // propagated to them, treat as a back side. for (i=0; i SEGSIZEMODE_MAX) SegSizeMode = SEGSIZEMODE_MIN; return 1; } // --------------------------------------------------------------------------- int PerturbCursideCommon(fix amount) { int saveSegSizeMode = SegSizeMode; vms_vector fvec, rvec, uvec; fix fmag, rmag, umag; int v; SegSizeMode = SEGSIZEMODE_CURSIDE; Modified_vertex_index = 0; extract_forward_vector_from_segment(Cursegp, &fvec); extract_right_vector_from_segment(Cursegp, &rvec); extract_up_vector_from_segment(Cursegp, &uvec); fmag = vm_vec_mag(&fvec); rmag = vm_vec_mag(&rvec); umag = vm_vec_mag(&uvec); for (v=0; v<4; v++) { vms_vector perturb_vec; perturb_vec.x = fixmul(rmag, d_rand()*2 - 32767); perturb_vec.y = fixmul(umag, d_rand()*2 - 32767); perturb_vec.z = fixmul(fmag, d_rand()*2 - 32767); scale_vert(Cursegp, Cursegp->verts[Side_to_verts[Curside][v]], &perturb_vec, amount); } // validate_segment(Cursegp); // if (SegSizeMode) { // for (i=0; ichildren[i] != -1) // validate_segment(&Segments[Cursegp->children[i]]); // } validate_modified_segments(); SegSizeMode = saveSegSizeMode; Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; return 1; } // --------------------------------------------------------------------------- int PerturbCurside(void) { PerturbCursideCommon(F1_0/10); return 1; } // --------------------------------------------------------------------------- int PerturbCursideBig(void) { PerturbCursideCommon(F1_0/2); return 1; } dxx-rebirth-0.58.1-d2x/editor/ktmap.c000066400000000000000000000116421217717237500173260ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Texture map key bindings. * */ #include #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "kdefs.h" // Assign CurrentTexture to Curside in *Cursegp int AssignTexture(void) { autosave_mine( mine_filename ); strcpy(undo_status[Autosave_count], "Assign Texture UNDONE."); Cursegp->sides[Curside].tmap_num = CurrentTexture; New_segment.sides[Curside].tmap_num = CurrentTexture; // propagate_light_intensity(Cursegp, Curside, CurrentTexture, 0); Update_flags |= UF_WORLD_CHANGED; return 1; } // Assign CurrentTexture to Curside in *Cursegp int AssignTexture2(void) { int texnum, orient, ctexnum, newtexnum; autosave_mine( mine_filename ); strcpy(undo_status[Autosave_count], "Assign Texture 2 UNDONE."); texnum = Cursegp->sides[Curside].tmap_num2 & 0x3FFF; orient = ((Cursegp->sides[Curside].tmap_num2 & 0xC000) >> 14) & 3; ctexnum = CurrentTexture; if ( ctexnum == texnum ) { orient = (orient+1) & 3; newtexnum = (orient<<14) | texnum; } else { newtexnum = ctexnum; } Cursegp->sides[Curside].tmap_num2 = newtexnum; New_segment.sides[Curside].tmap_num2 = newtexnum; Update_flags |= UF_WORLD_CHANGED; return 1; } int ClearTexture2(void) { autosave_mine( mine_filename ); strcpy(undo_status[Autosave_count], "Clear Texture 2 UNDONE."); Cursegp->sides[Curside].tmap_num2 = 0; New_segment.sides[Curside].tmap_num2 = 0; Update_flags |= UF_WORLD_CHANGED; return 1; } // -------------------------------------------------------------------------------------------------- // Propagate textures from Cursegp through Curside. // If uv_flag !0, then only propagate uv coordinates (if 0, then propagate textures as well) // If move_flag !0, then move forward to new segment after propagation, else don't int propagate_textures_common(int uv_flag, int move_flag) { autosave_mine( mine_filename ); strcpy(undo_status[Autosave_count], "Propogate Textures UNDONE."); if (IS_CHILD(Cursegp->children[Curside])) med_propagate_tmaps_to_segments(Cursegp, &Segments[Cursegp->children[Curside]], uv_flag); if (move_flag) SelectCurrentSegForward(); Update_flags |= UF_WORLD_CHANGED; return 1; } // Propagate texture maps from current segment, through current side int PropagateTextures(void) { return propagate_textures_common(0, 0); } // Propagate texture maps from current segment, through current side int PropagateTexturesUVs(void) { return propagate_textures_common(-1, 0); } // Propagate texture maps from current segment, through current side // And move to that segment. int PropagateTexturesMove(void) { return propagate_textures_common(0, 1); } // Propagate uv coordinate from current segment, through current side // And move to that segment. int PropagateTexturesMoveUVs(void) { return propagate_textures_common(-1, 1); } // ------------------------------------------------------------------------------------- int is_selected_segment(int segnum) { int i; for (i=0; ichildren[side])) { while ((!Been_visited[sp->children[side]]) && is_selected_segment(sp->children[side])) { med_propagate_tmaps_to_segments(sp,&Segments[sp->children[side]],0); pts_aux(&Segments[sp->children[side]]); } } } } // ------------------------------------------------------------------------------------- // Propagate texture maps from current segment recursively exploring all children, to all segments in Selected_list // until a segment not in Selected_list is reached. int PropagateTexturesSelected(void) { autosave_mine( mine_filename ); strcpy(undo_status[Autosave_count], "Propogate Textures Selected UNDONE."); for (unsigned i=0; i<(sizeof(Been_visited)/sizeof(Been_visited[0])); ++i) Been_visited[i] = 0; //clear visited list Been_visited[Cursegp-Segments] = 1; pts_aux(Cursegp); Update_flags |= UF_WORLD_CHANGED; return 1; } dxx-rebirth-0.58.1-d2x/editor/kview.c000066400000000000000000000036571217717237500173460ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions for changing viewer's position * */ #include "inferno.h" #include "editor.h" #include "editor/esegment.h" // ---------- zoom control on current window ---------- int ZoomIn() { if (!current_view) return 0.0; current_view->ev_zoom = fixmul(current_view->ev_zoom,62259); current_view->ev_changed = 1; return 1; } int ZoomOut() { if (!current_view) return 0.0; current_view->ev_zoom = fixmul(current_view->ev_zoom,68985); current_view->ev_changed = 1; return 1; } // ---------- distance-of-viewer control on current window ---------- int MoveCloser() { if (!current_view) return 0.0; current_view->ev_dist = fixmul(current_view->ev_dist,62259); current_view->ev_changed = 1; return 1; } int MoveAway() { if (!current_view) return 0.0; current_view->ev_dist = fixmul(current_view->ev_dist,68985); current_view->ev_changed = 1; return 1; } // ---------- Toggle chase mode. ---------- int ToggleChaseMode() { Funky_chase_mode = !Funky_chase_mode; set_view_target_from_segment(Cursegp); if (Funky_chase_mode == 1) { diagnostic_message("Chase mode ON."); } if (Funky_chase_mode == 0) { diagnostic_message("Chase mode OFF."); } return Funky_chase_mode; } dxx-rebirth-0.58.1-d2x/editor/med.c000066400000000000000000001051071217717237500167570ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Editor loop for Inferno * */ //#define DEMO 1 #define DIAGNOSTIC_MESSAGE_MAX 90 #define EDITOR_STATUS_MESSAGE_DURATION 4 // Shows for 3+..4 seconds #include #include #include #include #include #include "inferno.h" #include "segment.h" #include "gr.h" #include "palette.h" #include "event.h" #include "window.h" #include "messagebox.h" #include "ui.h" #include "editor.h" #include "editor/esegment.h" #include "gamesave.h" #include "gameseg.h" #include "key.h" #include "kconfig.h" #include "mouse.h" #include "dxxerror.h" #include "kfuncs.h" #include "macro.h" #ifdef INCLUDE_XLISP #include "medlisp.h" #endif #include "u_mem.h" #include "physfsx.h" #include "render.h" #include "game.h" #include "gamefont.h" #include "gamepal.h" #include "menu.h" #include "slew.h" #include "kdefs.h" #include "func.h" #include "textures.h" #include "screens.h" #include "texmap.h" #include "object.h" #include "effects.h" #include "wall.h" #include "info.h" #include "ai.h" #include "console.h" #include "texpage.h" // Textue selection paging stuff #include "objpage.h" // Object selection paging stuff #include "medmisc.h" #include "meddraw.h" #include "medsel.h" #include "medrobot.h" #include "medwall.h" #include "eswitch.h" #include "ehostage.h" #include "centers.h" #include "fuelcen.h" #include "gameseq.h" #include "newmenu.h" //#define _MARK_ON 1 //#include //should come after inferno.h to get mark setting //Not included here. #define COMPRESS_INTERVAL 5 // seconds //char *undo_status[128]; int initializing; //these are instances of canvases, pointed to by variables below grs_canvas _canv_editor_game, _canv_editor; //the game on the editor screen, the canvas that the editor writes to //these are pointers to our canvases grs_canvas *Canv_editor; //the editor screen grs_canvas *Canv_editor_game=&_canv_editor_game; //the game on the editor screen window *Pad_info; // Keypad text grs_font *editor_font=NULL; //where the editor is looking vms_vector Ed_view_target=ZERO_VECTOR; int gamestate_not_restored = 0; UI_DIALOG * EditorWindow = NULL; int Large_view_index = -1; UI_GADGET_USERBOX * GameViewBox; UI_GADGET_USERBOX * LargeViewBox; UI_GADGET_USERBOX * GroupViewBox; #if ORTHO_VIEWS UI_GADGET_USERBOX * TopViewBox; UI_GADGET_USERBOX * FrontViewBox; UI_GADGET_USERBOX * RightViewBox; #endif UI_GADGET_ICON * ViewIcon; UI_GADGET_ICON * AllIcon; UI_GADGET_ICON * AxesIcon; UI_GADGET_ICON * ChaseIcon; UI_GADGET_ICON * OutlineIcon; UI_GADGET_ICON * LockIcon; //-NOLIGHTICON- UI_GADGET_ICON * LightIcon; UI_EVENT * DemoBuffer = NULL; //grs_canvas * BigCanvas[2]; //int CurrentBigCanvas = 0; //int BigCanvasFirstTime = 1; int Found_seg_index=0; // Index in Found_segs corresponding to Cursegp void print_status_bar( char message[DIAGNOSTIC_MESSAGE_MAX] ) { int w,h,aw; gr_set_current_canvas( NULL ); gr_set_curfont(editor_font); gr_set_fontcolor( CBLACK, CGREY ); gr_get_string_size( message, &w, &h, &aw ); gr_string( 4, 583, message ); gr_set_fontcolor( CBLACK, CWHITE ); gr_setcolor( CGREY ); gr_rect( 4+w, 583, 799, 599 ); } static char status_line[DIAGNOSTIC_MESSAGE_MAX] = ""; struct tm Editor_status_last_time; void editor_status_fmt( const char *format, ... ) { va_list ap; va_start(ap, format); vsprintf(status_line, format, ap); va_end(ap); Editor_status_last_time = Editor_time_of_day; } void editor_status( const char *text) { strcpy(status_line, text); Editor_status_last_time = Editor_time_of_day; } // int tm_sec; /* seconds after the minute -- [0,61] */ // int tm_min; /* minutes after the hour -- [0,59] */ // int tm_hour; /* hours after midnight -- [0,23] */ // int tm_mday; /* day of the month -- [1,31] */ // int tm_mon; /* months since January -- [0,11] */ // int tm_year; /* years since 1900 */ // int tm_wday; /* days since Sunday -- [0,6] */ // int tm_yday; /* days since January 1 -- [0,365]*/ // int tm_isdst; /* Daylight Savings Time flag */ void clear_editor_status(void) { int cur_time = Editor_time_of_day.tm_hour * 3600 + Editor_time_of_day.tm_min*60 + Editor_time_of_day.tm_sec; int erase_time = Editor_status_last_time.tm_hour * 3600 + Editor_status_last_time.tm_min*60 + Editor_status_last_time.tm_sec + EDITOR_STATUS_MESSAGE_DURATION; if (cur_time > erase_time) { int i; for (i=0; ipos; //@@ Player_init.orient = Player->orient; //@@ Player_init.segnum = Player->segnum; // -- must always save gamesave.sav because the restore-objects code relies on it // -- that code could be made smarter and use the original file, if appropriate. // if (mine_changed) if (gamestate_not_restored == 0) { gamestate_not_restored = 1; save_level("GAMESAVE.LVL"); editor_status("Gamestate saved.\n"); } ai_reset_all_paths(); start_time(); ModeFlag = 3; return 1; } int GotoMainMenu() { ModeFlag = 2; return 1; } #if 0 void ReadLispMacro( FILE * file, char * buffer ) { // char c; // int size=0; // int pcount = 0; // char text[100]; // int i=0; fscanf( file, " { %s } ", buffer ); /* while (1) { c = text[i++]; if (pcount > 0 ) buffer[size++] = c; if ( c == '(' ) pcount++; if ( c == ')' ) break; } buffer[size++] = 0; */ return; } #endif static int (*KeyFunction[2048])(); void medkey_init() { PHYSFS_file * keyfile; char keypress[100]; char line_buffer[200]; int key; int i; //, size; int np; char * LispCommand; MALLOC( LispCommand, char, DIAGNOSTIC_MESSAGE_MAX ); for (i=0; i<2048; i++ ) KeyFunction[i] = NULL; keyfile = PHYSFSX_openReadBuffered( "GLOBAL.KEY" ); if (keyfile) { while (PHYSFSX_fgets(line_buffer, 200, keyfile)) { sscanf(line_buffer, " %s %s ", keypress, LispCommand); //ReadLispMacro( keyfile, LispCommand ); if ( (key=DecodeKeyText( keypress ))!= -1 ) { Assert( key < 2048); KeyFunction[key] = func_get( LispCommand, &np ); } else { Error( "Bad key %s in GLOBAL.KEY!", keypress ); } } PHYSFS_close(keyfile); } d_free( LispCommand ); } static int padnum=0; //@@short camera_objnum; //a camera for viewing. Who knows, might become handy void init_editor_screen(); void gamestate_restore_check(); void init_editor() { void med_show_warning(char *s); // first, make sure we can find the files we need PHYSFSX_addRelToSearchPath("editor/data", 1); // look in source directory first (for work in progress) PHYSFSX_addRelToSearchPath("editor", 1); // then in editor directory PHYSFSX_addRelToSearchPath("editor.zip", 1); // then in a zip file PHYSFSX_addRelToSearchPath("editor.dxa", 1); // or addon pack ui_init(); init_med_functions(); // Must be called before medlisp_init ui_pad_read( 0, "segmove.pad" ); ui_pad_read( 1, "segsize.pad" ); ui_pad_read( 2, "curve.pad" ); ui_pad_read( 3, "texture.pad" ); ui_pad_read( 4, "object.pad" ); ui_pad_read( 5, "objmov.pad" ); ui_pad_read( 6, "group.pad" ); ui_pad_read( 7, "lighting.pad" ); ui_pad_read( 8, "test.pad" ); medkey_init(); game_flush_inputs(); editor_font = gr_init_font( "pc8x16.fnt" ); menubar_init( "MED.MNU" ); Draw_all_segments = 1; // Say draw all segments, not just connected ones if (!Cursegp) Cursegp = &Segments[0]; init_autosave(); // atexit(close_editor); Clear_window = 1; // do full window clear. InitCurve(); restore_effect_bitmap_icons(); if (!set_screen_mode(SCREEN_EDITOR)) { set_screen_mode(SCREEN_MENU); show_menus(); //force back into menu return; } load_palette(Current_level_palette,1,0); //Editor renders into full (320x200) game screen game_init_render_buffers(320, 200); gr_init_sub_canvas( &_canv_editor, &grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT ); Canv_editor = &_canv_editor; gr_set_current_canvas( Canv_editor ); init_editor_screen(); // load the main editor dialog gr_set_current_canvas( NULL ); gr_set_curfont(editor_font); set_warn_func(med_show_warning); // _MARK_("start of editor");//Nuked to compile -KRB //@@ //create a camera for viewing in the editor. copy position from ConsoleObject //@@ camera_objnum = obj_create(OBJ_CAMERA,0,ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0); //@@ Viewer = &Objects[camera_objnum]; //@@ slew_init(Viewer); //camera is slewing Viewer = ConsoleObject; slew_init(ConsoleObject); init_player_object(); Update_flags = UF_ALL; //set the wire-frame window to be the current view current_view = &LargeView; if (faded_in==0) { faded_in = 1; //gr_pal_fade_in( grd_curscreen->pal ); } gr_set_current_canvas( GameViewBox->canvas ); gr_set_curfont(editor_font); //gr_setcolor( CBLACK ); //gr_deaccent_canvas(); //gr_grey_canvas(); gr_set_curfont(editor_font); FNTScaleX = FNTScaleY = 1; // No font scaling! ui_pad_goto(padnum); ModeFlag = 0; gamestate_restore_check(); } int ShowAbout() { ui_messagebox( -2, -2, 1, "INFERNO Mine Editor\n\n" \ "Copyright (c) 1993 Parallax Software Corp.", "OK"); return 0; } void move_player_2_segment(segment *seg,int side); int SetPlayerFromCurseg() { move_player_2_segment(Cursegp,Curside); Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; return 1; } int fuelcen_create_from_curseg() { Curseg2p->special = SEGMENT_IS_FUELCEN; fuelcen_activate(Cursegp, Curseg2p->special); return 1; } int repaircen_create_from_curseg() { Int3(); // -- no longer supported! // Curseg2p->special = SEGMENT_IS_REPAIRCEN; // fuelcen_activate(Cursegp, Curseg2p->special); return 1; } int controlcen_create_from_curseg() { Curseg2p->special = SEGMENT_IS_CONTROLCEN; fuelcen_activate(Cursegp, Curseg2p->special); return 1; } int robotmaker_create_from_curseg() { Curseg2p->special = SEGMENT_IS_ROBOTMAKER; fuelcen_activate(Cursegp, Curseg2p->special); return 1; } int fuelcen_reset_all() { fuelcen_reset(); return 1; } int fuelcen_delete_from_curseg() { fuelcen_delete( Cursegp ); return 1; } //@@//this routine places the viewer in the center of the side opposite to curside, //@@//with the view toward the center of curside //@@int SetPlayerFromCursegMinusOne() //@@{ //@@ vms_vector vp; //@@ //@@// int newseg,newside; //@@// get_previous_segment(SEG_PTR_2_NUM(Cursegp),Curside,&newseg,&newside); //@@// move_player_2_segment(&Segments[newseg],newside); //@@ //@@ med_compute_center_point_on_side(&Player->obj_position,Cursegp,Side_opposite[Curside]); //@@ med_compute_center_point_on_side(&vp,Cursegp,Curside); //@@ vm_vec_sub2(&vp,&Player->position); //@@ vm_vector_2_matrix(&Player->orient,&vp,NULL,NULL); //@@ //@@ Player->seg = SEG_PTR_2_NUM(Cursegp); //@@ //@@ Update_flags |= UF_GAME_VIEW_CHANGED; //@@ return 1; //@@} //this constant determines how much of the window will be occupied by the //viewed side when SetPlayerFromCursegMinusOne() is called. It actually //determine how from from the center of the window the farthest point will be #define SIDE_VIEW_FRAC (f1_0*8/10) //80% void move_player_2_segment_and_rotate(segment *seg,int side) { vms_vector vp; vms_vector upvec; static int edgenum=0; compute_segment_center(&ConsoleObject->pos,seg); compute_center_point_on_side(&vp,seg,side); vm_vec_sub2(&vp,&ConsoleObject->pos); vm_vec_sub(&upvec, &Vertices[Cursegp->verts[Side_to_verts[Curside][edgenum%4]]], &Vertices[Cursegp->verts[Side_to_verts[Curside][(edgenum+3)%4]]]); edgenum++; vm_vector_2_matrix(&ConsoleObject->orient,&vp,&upvec,NULL); // vm_vector_2_matrix(&ConsoleObject->orient,&vp,NULL,NULL); obj_relink( ConsoleObject-Objects, SEG_PTR_2_NUM(seg) ); } int SetPlayerFromCursegAndRotate() { move_player_2_segment_and_rotate(Cursegp,Curside); Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; return 1; } //sets the player facing curseg/curside, normal to face0 of curside, and //far enough away to see all of curside int SetPlayerFromCursegMinusOne() { vms_vector view_vec,view_vec2,side_center; vms_vector corner_v[4]; vms_vector upvec; g3s_point corner_p[4]; int i; fix max,view_dist=f1_0*10; static int edgenum=0; int newseg; view_vec = Cursegp->sides[Curside].normals[0]; vm_vec_negate(&view_vec); compute_center_point_on_side(&side_center,Cursegp,Curside); vm_vec_copy_scale(&view_vec2,&view_vec,view_dist); vm_vec_sub(&ConsoleObject->pos,&side_center,&view_vec2); vm_vec_sub(&upvec, &Vertices[Cursegp->verts[Side_to_verts[Curside][edgenum%4]]], &Vertices[Cursegp->verts[Side_to_verts[Curside][(edgenum+3)%4]]]); edgenum++; vm_vector_2_matrix(&ConsoleObject->orient,&view_vec,&upvec,NULL); gr_set_current_canvas(Canv_editor_game); g3_start_frame(); g3_set_view_matrix(&ConsoleObject->pos,&ConsoleObject->orient,Render_zoom); for (i=max=0;i<4;i++) { corner_v[i] = Vertices[Cursegp->verts[Side_to_verts[Curside][i]]]; g3_rotate_point(&corner_p[i],&corner_v[i]); if (labs(corner_p[i].p3_x) > max) max = labs(corner_p[i].p3_x); if (labs(corner_p[i].p3_y) > max) max = labs(corner_p[i].p3_y); } view_dist = fixmul(view_dist,fixdiv(fixdiv(max,SIDE_VIEW_FRAC),corner_p[0].p3_z)); vm_vec_copy_scale(&view_vec2,&view_vec,view_dist); vm_vec_sub(&ConsoleObject->pos,&side_center,&view_vec2); //obj_relink(ConsoleObject-Objects, SEG_PTR_2_NUM(Cursegp) ); //update_object_seg(ConsoleObject); //might have backed right out of curseg newseg = find_point_seg(&ConsoleObject->pos,SEG_PTR_2_NUM(Cursegp) ); if (newseg != -1) obj_relink(ConsoleObject-Objects,newseg); Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; return 1; } int ToggleLighting(void) { Lighting_on++; if (Lighting_on >= 2) Lighting_on = 0; Update_flags |= UF_GAME_VIEW_CHANGED; switch (Lighting_on) { case 0: diagnostic_message("Lighting off."); break; case 1: diagnostic_message("Static lighting."); break; case 2: diagnostic_message("Ship lighting."); break; case 3: diagnostic_message("Ship and static lighting."); break; } return Lighting_on; } void find_concave_segs(); int FindConcaveSegs() { find_concave_segs(); Update_flags |= UF_ED_STATE_CHANGED; //list may have changed return 1; } int DosShell() { int ok, w, h; grs_bitmap * save_bitmap; ok = 1; // Save the current graphics state. w = grd_curscreen->sc_canvas.cv_bitmap.bm_w; h = grd_curscreen->sc_canvas.cv_bitmap.bm_h; save_bitmap = gr_create_bitmap( w, h ); gr_bm_ubitblt(w, h, 0, 0, 0, 0, &(grd_curscreen->sc_canvas.cv_bitmap), save_bitmap ); // gr_set_mode( SM_ORIGINAL ); fflush(stdout); key_close(); #ifdef __MSDOS__ ok = spawnl(P_WAIT,getenv("COMSPEC"), NULL ); #endif key_init(); gr_set_mode(grd_curscreen->sc_mode); gr_bm_ubitblt(w, h, 0, 0, 0, 0, save_bitmap, &(grd_curscreen->sc_canvas.cv_bitmap)); gr_free_bitmap( save_bitmap ); //gr_pal_setblock( 0, 256, grd_curscreen->pal ); //gr_use_palette_table(); return ok; } int ToggleOutlineMode() { #ifndef NDEBUG int mode; mode=toggle_outline_mode(); if (mode) { //if (keypress != KEY_O) diagnostic_message("[Ctrl-O] Outline Mode ON."); //else // diagnostic_message("Outline Mode ON."); } else { //if (keypress != KEY_O) diagnostic_message("[Ctrl-O] Outline Mode OFF."); //else // diagnostic_message("Outline Mode OFF."); } Update_flags |= UF_GAME_VIEW_CHANGED; return mode; #else return 1; #endif } //@@int do_reset_orient() //@@{ //@@ slew_reset_orient(SlewObj); //@@ //@@ Update_flags |= UF_GAME_VIEW_CHANGED; //@@ //@@ * (ubyte *) 0x417 &= ~0x20; //@@ //@@ return 1; //@@} int GameZoomOut() { Render_zoom = fixmul(Render_zoom,68985); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } int GameZoomIn() { Render_zoom = fixmul(Render_zoom,62259); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } int med_keypad_goto_0() { ui_pad_goto(0); return 0; } int med_keypad_goto_1() { ui_pad_goto(1); return 0; } int med_keypad_goto_2() { ui_pad_goto(2); return 0; } int med_keypad_goto_3() { ui_pad_goto(3); return 0; } int med_keypad_goto_4() { ui_pad_goto(4); return 0; } int med_keypad_goto_5() { ui_pad_goto(5); return 0; } int med_keypad_goto_6() { ui_pad_goto(6); return 0; } int med_keypad_goto_7() { ui_pad_goto(7); return 0; } int med_keypad_goto_8() { ui_pad_goto(8); return 0; } #define PAD_WIDTH 30 #define PAD_WIDTH1 (PAD_WIDTH + 7) int editor_screen_open = 0; int editor_handler(UI_DIALOG *dlg, d_event *event, void *data); //setup the editors windows, canvases, gadgets, etc. void init_editor_screen() { // grs_bitmap * bmp; if (editor_screen_open) return; grd_curscreen->sc_canvas.cv_font = editor_font; //create canvas for game on the editor screen initializing = 1; gr_set_current_canvas(Canv_editor); Canv_editor->cv_font = editor_font; gr_init_sub_canvas(Canv_editor_game,Canv_editor,GAMEVIEW_X,GAMEVIEW_Y,GAMEVIEW_W,GAMEVIEW_H); //Editor renders into full (320x200) game screen init_info = 1; //do other editor screen setup // Since the palette might have changed, find some good colors... CBLACK = gr_find_closest_color( 1, 1, 1 ); CGREY = gr_find_closest_color( 28, 28, 28 ); CWHITE = gr_find_closest_color( 38, 38, 38 ); CBRIGHT = gr_find_closest_color( 60, 60, 60 ); CRED = gr_find_closest_color( 63, 0, 0 ); gr_set_curfont(editor_font); gr_set_fontcolor( CBLACK, CWHITE ); EditorWindow = ui_create_dialog( 0 , 0, ED_SCREEN_W, ED_SCREEN_H, DF_FILLED, editor_handler, NULL ); LargeViewBox = ui_add_gadget_userbox( EditorWindow,LVIEW_X,LVIEW_Y,LVIEW_W,LVIEW_H); #if ORTHO_VIEWS TopViewBox = ui_add_gadget_userbox( EditorWindow,TVIEW_X,TVIEW_Y,TVIEW_W,TVIEW_H); FrontViewBox = ui_add_gadget_userbox( EditorWindow,FVIEW_X,FVIEW_Y,FVIEW_W,FVIEW_H); RightViewBox = ui_add_gadget_userbox( EditorWindow,RVIEW_X,RVIEW_Y,RVIEW_W,RVIEW_H); #endif ui_gadget_calc_keys(EditorWindow); //make tab work for all windows GameViewBox = ui_add_gadget_userbox( EditorWindow, GAMEVIEW_X, GAMEVIEW_Y, GAMEVIEW_W, GAMEVIEW_H ); // GroupViewBox = ui_add_gadget_userbox( EditorWindow,GVIEW_X,GVIEW_Y,GVIEW_W,GVIEW_H); // GameViewBox->when_tab = GameViewBox->when_btab = (UI_GADGET *) LargeViewBox; // LargeViewBox->when_tab = LargeViewBox->when_btab = (UI_GADGET *) GameViewBox; // ui_gadget_calc_keys(EditorWindow); //make tab work for all windows ViewIcon = ui_add_gadget_icon( EditorWindow, "Lock\nview", 455,25+530, 40, 22, KEY_V+KEY_CTRLED, ToggleLockViewToCursegp ); AllIcon = ui_add_gadget_icon( EditorWindow, "Draw\nall", 500,25+530, 40, 22, -1, ToggleDrawAllSegments ); AxesIcon = ui_add_gadget_icon( EditorWindow, "Coord\naxes",545,25+530, 40, 22, KEY_D+KEY_CTRLED, ToggleCoordAxes ); //-NOLIGHTICON- LightIcon = ui_add_gadget_icon( EditorWindow, "Light\ning", 590,25+530, 40, 22, KEY_L+KEY_SHIFTED,ToggleLighting ); ChaseIcon = ui_add_gadget_icon( EditorWindow, "Chase\nmode",635,25+530, 40, 22, -1, ToggleChaseMode ); OutlineIcon = ui_add_gadget_icon( EditorWindow, "Out\nline", 680,25+530, 40, 22, KEY_O+KEY_CTRLED, ToggleOutlineMode ); LockIcon = ui_add_gadget_icon( EditorWindow, "Lock\nstep", 725,25+530, 40, 22, KEY_L+KEY_CTRLED, ToggleLockstep ); meddraw_init_views(LargeViewBox->canvas); //ui_add_gadget_button( EditorWindow, 460, 510, 50, 25, "Quit", ExitEditor ); //ui_add_gadget_button( EditorWindow, 520, 510, 50, 25, "Lisp", CallLisp ); //ui_add_gadget_button( EditorWindow, 580, 510, 50, 25, "Mine", MineMenu ); //ui_add_gadget_button( EditorWindow, 640, 510, 50, 25, "Help", DoHelp ); //ui_add_gadget_button( EditorWindow, 460, 540, 50, 25, "Macro", MacroMenu ); //ui_add_gadget_button( EditorWindow, 520, 540, 50, 25, "About", ShowAbout ); //ui_add_gadget_button( EditorWindow, 640, 540, 50, 25, "Shell", DosShell ); ui_pad_activate( EditorWindow, PAD_X, PAD_Y ); Pad_info = info_window_create(); ui_add_gadget_button( EditorWindow, PAD_X+6, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "<<", med_keypad_goto_prev ); ui_add_gadget_button( EditorWindow, PAD_X+PAD_WIDTH1+6, PAD_Y+(30*5)+22, PAD_WIDTH, 20, ">>", med_keypad_goto_next ); { int i; i = 0; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "SR", med_keypad_goto_0 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "SS", med_keypad_goto_1 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "CF", med_keypad_goto_2 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "TM", med_keypad_goto_3 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "OP", med_keypad_goto_4 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "OR", med_keypad_goto_5 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "GE", med_keypad_goto_6 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "LI", med_keypad_goto_7 ); i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "TT", med_keypad_goto_8 ); } gr_set_curfont(editor_font); menubar_show(); // INIT TEXTURE STUFF texpage_init( EditorWindow ); objpage_init( EditorWindow ); EditorWindow->keyboard_focus_gadget = (UI_GADGET *)LargeViewBox; // BigCanvas[0]->cv_font = grd_curscreen->sc_canvas.cv_font; // BigCanvas[1]->cv_font = grd_curscreen->sc_canvas.cv_font; // BigCanvasFirstTime = 1; Update_flags = UF_ALL; initializing = 0; editor_screen_open = 1; } //shutdown ui on the editor screen void close_editor_screen() { if (!editor_screen_open) return; editor_screen_open = 0; ui_pad_deactivate(); if (Pad_info) window_close(Pad_info); //ui_close_dialog(EditorWindow); // moved into handler, so we can handle the quit request //EditorWindow = NULL; close_all_windows(); // CLOSE TEXTURE STUFF texpage_close(); objpage_close(); menubar_hide(); } void med_show_warning(char *s) { grs_canvas *save_canv=grd_curcanv; //gr_pal_fade_in(grd_curscreen->pal); //in case palette is blacked ui_messagebox(-2,-2,1,s,"OK"); gr_set_current_canvas(save_canv); } // Returns 1 if OK to trash current mine. int SafetyCheck() { int x; if (mine_changed) { x = nm_messagebox( "Warning!", 2, "Cancel", "OK", "You are about to lose work." ); if (x<1) { return 0; } } return 1; } //called at the end of the program void close_editor() { // _MARK_("end of editor");//Nuked to compile -KRB #ifndef __LINUX__ set_warn_func(msgbox_warning); #else clear_warn_func(NULL); #endif close_editor_screen(); //kill our camera object Viewer = ConsoleObject; //reset viewer //@@obj_delete(camera_objnum); padnum = ui_pad_get_current(); close_autosave(); ui_close(); gr_close_font(editor_font); PHYSFSX_removeRelFromSearchPath("editor/data"); PHYSFSX_removeRelFromSearchPath("editor"); PHYSFSX_removeRelFromSearchPath("editor.zip"); PHYSFSX_removeRelFromSearchPath("editor.dxa"); switch (ModeFlag) { case 1: if (Game_wind) window_close(Game_wind); break; case 2: if (Game_wind) window_close(Game_wind); set_screen_mode(SCREEN_MENU); //put up menu screen show_menus(); break; case 3: set_screen_mode(SCREEN_GAME); //put up game screen Game_mode = GM_EDITOR; editor_reset_stuff_on_level(); N_players = 1; break; } return; } //variables for find segments process // --------------------------------------------------------------------------------------------------- // Subtract all elements in Found_segs from selected list. void subtract_found_segments_from_selected_list(void) { int s,f; for (f=0; fpos; Save_position.orient = ConsoleObject->orient; Save_position.segnum = ConsoleObject->segnum; load_level("GAMESAVE.LVL"); // Restore current position if (Save_position.segnum <= Highest_segment_index) { ConsoleObject->pos = Save_position.pos; ConsoleObject->orient = Save_position.orient; obj_relink(ConsoleObject-Objects,Save_position.segnum); } gamestate_not_restored = 0; Update_flags |= UF_WORLD_CHANGED; } else gamestate_not_restored = 1; } } int RestoreGameState() { load_level("GAMESAVE.LVL"); gamestate_not_restored = 0; editor_status("Gamestate restored.\n"); Update_flags |= UF_WORLD_CHANGED; return 0; } extern void check_wall_validity(void); // Handler for the main editor dialog int editor_handler(UI_DIALOG *dlg, d_event *event, void *data) { editor_view *new_cv; int keypress = 0; int rval = 0; if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); else if (event->type == EVENT_WINDOW_CLOSE) { close_editor(); EditorWindow = NULL; return 0; } // Update the windows if (event->type == EVENT_UI_DIALOG_DRAW) { gr_set_curfont(editor_font); // Draw status box gr_set_current_canvas( NULL ); gr_setcolor( CGREY ); gr_rect(STATUS_X,STATUS_Y,STATUS_X+STATUS_W-1,STATUS_Y+STATUS_H-1); //0, 582, 799, 599 ); medlisp_update_screen(); calc_frame_time(); texpage_do(event); objpage_do(event); ui_pad_draw(EditorWindow, PAD_X, PAD_Y); print_status_bar(status_line); TimedAutosave(mine_filename); // shows the time, hence here set_editor_time_of_day(); return 1; } if ((selected_gadget == (UI_GADGET *)GameViewBox && !render_3d_in_big_window) || (selected_gadget == (UI_GADGET *)LargeViewBox && render_3d_in_big_window)) switch (event->type) { case EVENT_MOUSE_BUTTON_UP: case EVENT_MOUSE_BUTTON_DOWN: break; case EVENT_MOUSE_MOVED: if (!keyd_pressed[ KEY_LCTRL ] && !keyd_pressed[ KEY_RCTRL ]) break; case EVENT_JOYSTICK_BUTTON_UP: case EVENT_JOYSTICK_BUTTON_DOWN: case EVENT_JOYSTICK_MOVED: case EVENT_KEY_COMMAND: case EVENT_KEY_RELEASE: case EVENT_IDLE: kconfig_read_controls(event, 1); if (slew_frame(0)) { //do movement and check keys Update_flags |= UF_GAME_VIEW_CHANGED; if (Gameview_lockstep) { Cursegp = &Segments[ConsoleObject->segnum]; med_create_new_segment_from_cursegp(); Update_flags |= UF_ED_STATE_CHANGED; } rval = 1; } break; default: break; } //do non-essential stuff in idle event if (event->type == EVENT_IDLE) { check_wall_validity(); Assert(Num_walls>=0); if (Gameview_lockstep) { static segment *old_cursegp=NULL; static int old_curside=-1; if (old_cursegp!=Cursegp || old_curside!=Curside) { SetPlayerFromCursegMinusOne(); old_cursegp = Cursegp; old_curside = Curside; } } if ( event_get_idle_seconds() > COMPRESS_INTERVAL ) { med_compress_mine(); event_reset_idle_seconds(); } // Commented out because it occupies about 25% of time in twirling the mine. // Removes some Asserts.... // med_check_all_vertices(); clear_editor_status(); // if enough time elapsed, clear editor status message } gr_set_current_canvas( GameViewBox->canvas ); // Remove keys used for slew switch(keypress) { case KEY_PAD9: case KEY_PAD7: case KEY_PADPLUS: case KEY_PADMINUS: case KEY_PAD8: case KEY_PAD2: case KEY_LBRACKET: case KEY_RBRACKET: case KEY_PAD1: case KEY_PAD3: case KEY_PAD6: case KEY_PAD4: keypress = 0; } if ((keypress&0xff)==KEY_LSHIFT) keypress=0; if ((keypress&0xff)==KEY_RSHIFT) keypress=0; if ((keypress&0xff)==KEY_LCTRL) keypress=0; if ((keypress&0xff)==KEY_RCTRL) keypress=0; // if ((keypress&0xff)==KEY_LALT) keypress=0; // if ((keypress&0xff)==KEY_RALT) keypress=0; //=================== DO FUNCTIONS ==================== if ( KeyFunction[ keypress ] != NULL ) { KeyFunction[keypress](); keypress = 0; rval = 1; } switch (keypress) { case 0: case KEY_Z: case KEY_G: case KEY_LALT: case KEY_RALT: case KEY_LCTRL: case KEY_RCTRL: case KEY_LSHIFT: case KEY_RSHIFT: case KEY_LAPOSTRO: break; case KEY_SHIFTED + KEY_L: ToggleLighting(); rval = 1; break; case KEY_F1: render_3d_in_big_window = !render_3d_in_big_window; Update_flags |= UF_ALL; rval = 1; break; default: if (!rval) { char kdesc[100]; GetKeyDescription( kdesc, keypress ); editor_status_fmt("Error: %s isn't bound to anything.", kdesc ); } } //================================================================ if (ModeFlag) { ui_close_dialog(EditorWindow); return 0; } // if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)GameViewBox) current_view=NULL; // if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)GroupViewBox) current_view=NULL; new_cv = current_view; #if ORTHO_VIEWS if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)LargeViewBox) new_cv=&LargeView; if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)TopViewBox) new_cv=&TopView; if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)FrontViewBox) new_cv=&FrontView; if (EditorWindow->keyboard_focus_gadget == (UI_GADGET *)RightViewBox) new_cv=&RightView; #endif if (new_cv != current_view ) { current_view->ev_changed = 1; new_cv->ev_changed = 1; current_view = new_cv; } // DO TEXTURE STUFF if (texpage_do(event)) rval = 1; if (objpage_do(event)) rval = 1; // Process selection of Cursegp using mouse. if (GADGET_PRESSED(LargeViewBox) && !render_3d_in_big_window) { int xcrd,ycrd; xcrd = LargeViewBox->b1_drag_x1; ycrd = LargeViewBox->b1_drag_y1; find_segments(xcrd,ycrd,LargeViewBox->canvas,&LargeView,Cursegp,Big_depth); // Sets globals N_found_segs, Found_segs // If shift is down, then add segment to found list if (keyd_pressed[ KEY_LSHIFT ] || keyd_pressed[ KEY_RSHIFT ]) subtract_found_segments_from_selected_list(); else add_found_segments_to_selected_list(); Found_seg_index = 0; if (N_found_segs > 0) { sort_seg_list(N_found_segs,Found_segs,&ConsoleObject->pos); Cursegp = &Segments[Found_segs[0]]; med_create_new_segment_from_cursegp(); if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); } Update_flags |= UF_ED_STATE_CHANGED | UF_VIEWPOINT_MOVED; } if ((event->type == EVENT_UI_USERBOX_DRAGGED) && (ui_event_get_gadget(event) == (UI_GADGET *)GameViewBox)) { int x, y; x = GameViewBox->b1_drag_x2; y = GameViewBox->b1_drag_y2; gr_set_current_canvas( GameViewBox->canvas ); gr_setcolor( 15 ); gr_rect( x-1, y-1, x+1, y+1 ); } // Set current segment and side by clicking on a polygon in game window. // If ctrl pressed, also assign current texture map to that side. //if (GameViewBox->mouse_onme && (GameViewBox->b1_done_dragging || GameViewBox->b1_clicked)) { if ((GADGET_PRESSED(GameViewBox) && !render_3d_in_big_window) || (GADGET_PRESSED(LargeViewBox) && render_3d_in_big_window)) { int xcrd,ycrd; int seg,side,face,poly,tmap; if (render_3d_in_big_window) { xcrd = LargeViewBox->b1_drag_x1; ycrd = LargeViewBox->b1_drag_y1; } else { xcrd = GameViewBox->b1_drag_x1; ycrd = GameViewBox->b1_drag_y1; } //Int3(); if (find_seg_side_face(xcrd,ycrd,&seg,&side,&face,&poly)) { if (seg<0) { //found an object Cur_object_index = -seg-1; editor_status_fmt("Object %d selected.",Cur_object_index); Update_flags |= UF_ED_STATE_CHANGED; } else { // See if either shift key is down and, if so, assign texture map if (keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) { Cursegp = &Segments[seg]; Curside = side; AssignTexture(); med_create_new_segment_from_cursegp(); editor_status("Texture assigned"); } else if (keyd_pressed[KEY_G]) { tmap = Segments[seg].sides[side].tmap_num; texpage_grab_current(tmap); editor_status( "Texture grabbed." ); } else if (keyd_pressed[ KEY_LAPOSTRO] ) { move_object_to_mouse_click(); } else { Cursegp = &Segments[seg]; Curside = side; med_create_new_segment_from_cursegp(); editor_status("Curseg and curside selected"); } } Update_flags |= UF_ED_STATE_CHANGED; } else editor_status("Click on non-texture ingored"); } // Allow specification of LargeView using mouse if (event->type == EVENT_MOUSE_MOVED && (keyd_pressed[ KEY_LCTRL ] || keyd_pressed[ KEY_RCTRL ])) { int dx, dy, dz; event_mouse_get_delta(event, &dx, &dy, &dz); if ((dx != 0) && (dy != 0)) { vms_matrix MouseRotMat,tempm; GetMouseRotation( dx, dy, &MouseRotMat ); vm_matrix_x_matrix(&tempm,&LargeView.ev_matrix,&MouseRotMat); LargeView.ev_matrix = tempm; LargeView.ev_changed = 1; Large_view_index = -1; // say not one of the orthogonal views rval = 1; } } if (event->type == EVENT_MOUSE_MOVED) { int dx, dy, dz; event_mouse_get_delta(event, &dx, &dy, &dz); if (dz != 0) { current_view->ev_dist += dz*10000; current_view->ev_changed = 1; } } return rval; } #ifndef NDEBUG int MarkStart(void) { char mystr[30]; sprintf(mystr,"mark %i start",Mark_count); // _MARK_(mystr);//Nuked to compile -KRB return 1; } int MarkEnd(void) { char mystr[30]; sprintf(mystr,"mark %i end",Mark_count); Mark_count++; // _MARK_(mystr);//Nuked to compile -KRB return 1; } #endif dxx-rebirth-0.58.1-d2x/editor/meddraw.c000066400000000000000000000601231217717237500176330ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Med drawing functions. * */ #include #include #include #include #include "inferno.h" #include "segment.h" #include "segpoint.h" #include "gameseg.h" #include "gr.h" #include "ui.h" #include "editor/editor.h" #include "editor/esegment.h" #include "wall.h" #include "switch.h" #include "key.h" #include "mouse.h" #include "dxxerror.h" #include "medlisp.h" #include "u_mem.h" #include "render.h" #include "game.h" #include "kdefs.h" #include "func.h" #include "textures.h" #include "screens.h" #include "texmap.h" #include "object.h" #include "fuelcen.h" // Colors used in editor for indicating various kinds of segments. #define SELECT_COLOR BM_XRGB( 63/2 , 41/2 , 0/2) #define FOUND_COLOR BM_XRGB( 0/2 , 30/2 , 45/2) #define WARNING_COLOR BM_XRGB( 63/2 , 0/2 , 0/2) #define AXIS_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) #define PLAINSEG_COLOR BM_XRGB( 45/2 , 45/2 , 45/2) #define MARKEDSEG_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) #define MARKEDSIDE_COLOR BM_XRGB( 0/2 , 63/2 , 63/2) #define CURSEG_COLOR BM_XRGB( 63/2 , 63/2 , 63/2) #define CURSIDE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) #define CUREDGE_COLOR BM_XRGB( 0 , 63/2 , 0 ) #define GROUPSEG_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) #define GROUPSIDE_COLOR BM_XRGB( 63/2 , 0/2 , 45/2) #define GROUP_COLOR BM_XRGB( 0/2 , 45/2 , 0/2) #define ROBOT_COLOR BM_XRGB( 31 , 0 , 0 ) #define PLAYER_COLOR BM_XRGB( 0 , 0 , 31 ) int Search_mode=0; //if true, searching for segments at given x,y int Search_x,Search_y; int Automap_test=0; // Set to 1 to show wireframe in automap mode. void draw_seg_objects(segment *seg) { int objnum; for (objnum=seg->objects;objnum!=-1;objnum=Objects[objnum].next) { object *obj = &Objects[objnum]; g3s_point sphere_point; if ((obj->type==OBJ_PLAYER) && (objnum > 0 )) gr_setcolor(BM_XRGB( 0, 25, 0 )); else gr_setcolor(obj==ConsoleObject?PLAYER_COLOR:ROBOT_COLOR); g3_rotate_point(&sphere_point,&obj->pos); g3_draw_sphere(&sphere_point,obj->size); } } void draw_line(int pnum0,int pnum1) { g3_draw_line(&Segment_points[pnum0],&Segment_points[pnum1]); } // ---------------------------------------------------------------------------- void draw_segment(segment *seg) { int *svp; int nv; g3s_codes cc; if (seg->segnum == -1) //this segment doesn't exitst return; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? int i; for (i=0;i<4;i++) draw_line(svp[i],svp[i+4]); for (i=0;i<3;i++) { draw_line(svp[i] ,svp[i+1]); draw_line(svp[i+4],svp[i+4+1]); } draw_line(svp[0],svp[3]); draw_line(svp[0+4],svp[3+4]); } } //for looking for segment under a mouse click void check_segment(segment *seg) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? int fn; gr_setcolor(0); #ifdef OGL g3_end_frame(); #endif gr_pixel(Search_x,Search_y); //set our search pixel to color zero #ifdef OGL g3_start_frame(); #endif gr_setcolor(1); //and render in color one for (fn=0;fn<6;fn++) { const g3s_point *vert_list[4]; vert_list[0] = &Segment_points[seg->verts[Side_to_verts[fn][0]]]; vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][1]]]; vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; g3_check_and_draw_poly(3,vert_list,NULL,NULL); vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][3]]]; g3_check_and_draw_poly(3,vert_list,NULL,NULL); } if (gr_ugpixel(&grd_curcanv->cv_bitmap,Search_x,Search_y) == 1) { if (N_found_segs < MAX_FOUND_SEGS) Found_segs[N_found_segs++] = SEG_PTR_2_NUM(seg); else Warning("Found too many segs! (limit=%d)",MAX_FOUND_SEGS); } } } // ---------------------------------------------------------------------------- void draw_seg_side(segment *seg,int side) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? int i; for (i=0;i<3;i++) draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][i+1]]); draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][0]]); } } void draw_side_edge(segment *seg,int side,int edge) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) //on screen? draw_line(svp[Side_to_verts[side][edge]],svp[Side_to_verts[side][(edge+1)%4]]); } int Show_triangulations=0; //edge types - lower number types have precedence #define ET_FACING 0 //this edge on a facing face #define ET_NOTFACING 1 //this edge on a non-facing face #define ET_NOTUSED 2 //no face uses this edge #define ET_NOTEXTANT 3 //would exist if side were triangulated #define ET_EMPTY 255 //this entry in array is empty //colors for those types //int edge_colors[] = {BM_RGB(45/2,45/2,45/2), // BM_RGB(45/3,45/3,45/3), //BM_RGB(0,0,45), // // BM_RGB(45/4,45/4,45/4)}; //BM_RGB(0,45,0)}; // int edge_colors[] = { 54, 59, 64 }; typedef struct seg_edge { union { struct {int v0,v1;} __pack__ n; long vv; }v; ushort type; ubyte face_count, backface_count; } seg_edge; #define MAX_EDGES (MAX_VERTICES*4) seg_edge edge_list[MAX_EDGES]; int used_list[MAX_EDGES]; //which entries in edge_list have been used int n_used; int edge_list_size; //set each frame #define HASH(a,b) ((a*5+b) % edge_list_size) //define edge numberings int edges[] = { 0*8+1, // edge 0 0*8+3, // edge 1 0*8+4, // edge 2 1*8+2, // edge 3 1*8+5, // edge 4 2*8+3, // edge 5 2*8+6, // edge 6 3*8+7, // edge 7 4*8+5, // edge 8 4*8+7, // edge 9 5*8+6, // edge 10 6*8+7, // edge 11 0*8+5, // right cross 0*8+7, // top cross 1*8+3, // front cross 2*8+5, // bottom cross 2*8+7, // left cross 4*8+6, // back cross //crosses going the other way 1*8+4, // other right cross 3*8+4, // other top cross 0*8+2, // other front cross 1*8+6, // other bottom cross 3*8+6, // other left cross 5*8+7, // other back cross }; #define N_NORMAL_EDGES 12 //the normal edges of a box #define N_EXTRA_EDGES 12 //ones created by triangulation #define N_EDGES_PER_SEGMENT (N_NORMAL_EDGES+N_EXTRA_EDGES) #define swap(a,b) do {int t; t=(a); (a)=(b); (b)=t;} while (0) //given two vertex numbers on a segment (range 0..7), tell what edge number it is int find_edge_num(int v0,int v1) { int i; int vv; int *edgep = edges; if (v0 > v1) swap(v0,v1); vv = v0*8+v1; // for (i=0;i v1) swap(v0,v1); found = find_edge(v0,v1,&e); if (found == -1) { e->v.n.v0 = v0; e->v.n.v1 = v1; e->type = type; used_list[n_used] = e-edge_list; if (type == ET_FACING) edge_list[used_list[n_used]].face_count++; else if (type == ET_NOTFACING) edge_list[used_list[n_used]].backface_count++; n_used++; } else { if (type < e->type) e->type = type; if (type == ET_FACING) edge_list[found].face_count++; else if (type == ET_NOTFACING) edge_list[found].backface_count++; } } //adds a segment's edges to the edge list void add_edges(segment *seg) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? int i,sn,fn,vn; int flag; ubyte edge_flags[N_EDGES_PER_SEGMENT]; for (i=0;isides[sn]; int num_faces, num_vertices; int vertex_list[6]; create_all_vertex_lists(&num_faces, vertex_list, seg-Segments, sn); if (num_faces == 1) num_vertices = 4; else num_vertices = 3; for (fn=0; fnverts[vertex_list[fn*3]]],&sidep->normals[fn])) flag = ET_NOTFACING; else flag = ET_FACING; v0 = &vertex_list[fn*3]; for (vn=0; vnverts[edges[i]/8],seg->verts[edges[i]&7],edge_flags[i]); } } // ---------------------------------------------------------------------------- void draw_trigger_side(segment *seg,int side) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? // Draw diagonals draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); //g3_draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); } } // ---------------------------------------------------------------------------- void draw_wall_side(segment *seg,int side) { int *svp; int nv; g3s_codes cc; med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices cc=rotate_list(nv,svp); if (! cc.uand) { //all off screen? // Draw diagonals draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); } } #define WALL_BLASTABLE_COLOR BM_XRGB( 31/2 , 0/2 , 0/2) // RED #define WALL_DOOR_COLOR BM_XRGB( 0/2 , 0/2 , 31/2) // DARK BLUE #define WALL_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) // BLUE #define WALL_AUTO_DOOR_COLOR BM_XRGB( 0/2 , 31/2 , 0/2) // DARK GREEN #define WALL_AUTO_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) // GREEN #define WALL_ILLUSION_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) // PURPLE #define TRIGGER_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW #define TRIGGER_DAMAGE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW // ---------------------------------------------------------------------------------------------------------------- // Draws special walls (for now these are just removable walls.) void draw_special_wall( segment *seg, int side ) { gr_setcolor(PLAINSEG_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_BLASTABLE) gr_setcolor(WALL_BLASTABLE_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_DOOR) gr_setcolor(WALL_DOOR_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_ILLUSION) gr_setcolor(GROUPSIDE_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) gr_setcolor(WALL_DOOR_LOCKED_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) gr_setcolor(WALL_AUTO_DOOR_COLOR); if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) gr_setcolor(WALL_AUTO_DOOR_LOCKED_COLOR); if (Walls[seg->sides[side].wall_num].type == WALL_OPEN) gr_setcolor(PLAINSEG_COLOR); draw_wall_side(seg,side); if (Walls[seg->sides[side].wall_num].trigger != -1) { gr_setcolor(TRIGGER_COLOR); draw_trigger_side(seg,side); } gr_setcolor(PLAINSEG_COLOR); } // ---------------------------------------------------------------------------------------------------------------- // Recursively parse mine structure, drawing segments. void draw_mine_sub(int segnum,int depth) { segment *mine_ptr; if (Been_visited[segnum]) return; // If segment already drawn, return. Been_visited[segnum] = 1; // Say that this segment has been drawn. mine_ptr = &Segments[segnum]; // If this segment is active, process it, else skip it. if (mine_ptr->segnum != -1) { int side; if (Search_mode) check_segment(mine_ptr); else add_edges(mine_ptr); //add this segments edges to list if (depth != 0) { for (side=0; sidechildren[side])) { if (mine_ptr->sides[side].wall_num != -1) draw_special_wall(mine_ptr, side); draw_mine_sub(mine_ptr->children[side],depth-1); } } } } } void draw_mine_edges(int automap_flag) { int i,type; seg_edge *e; for (type=ET_NOTUSED;type>=ET_FACING;type--) { gr_setcolor(edge_colors[type]); for (i=0;itype == type) if ((!automap_flag) || (e->face_count == 1)) draw_line(e->v.n.v0,e->v.n.v1); } } } //draws an entire mine void draw_mine(segment *mine_ptr,int depth) { int i; // clear visited list for (i=0; i<=Highest_segment_index; i++) Been_visited[i] = 0; edge_list_size = min(Num_segments*12,MAX_EDGES); //make maybe smaller than max // clear edge list for (i=0; i -1) { gr_setcolor(GROUP_COLOR); for (s=0; sev_matrix.fvec; vm_vec_scale(&viewer_position,-v->ev_dist); vm_vec_add2(&viewer_position,&Ed_view_target); gr_clear_canvas(0); g3_start_frame(); g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); render_start_frame(); gr_setcolor(PLAINSEG_COLOR); // Draw all segments or only connected segments. // We might want to draw all segments if we have broken the mine into pieces. if (Draw_all_segments) draw_mine_all(Segments, Automap_test); else draw_mine(mine_ptr,depth); // Draw the found segments if (!Automap_test) { draw_warning_segments(); draw_group_segments(); draw_found_segments(); draw_selected_segments(); draw_special_segments(); // Highlight group segment and side. if (current_group > -1) if (Groupsegp[current_group]) { gr_setcolor(GROUPSEG_COLOR); draw_segment(Groupsegp[current_group]); gr_setcolor(GROUPSIDE_COLOR); draw_seg_side(Groupsegp[current_group],Groupside[current_group]); } // Highlight marked segment and side. if (Markedsegp) { gr_setcolor(MARKEDSEG_COLOR); draw_segment(Markedsegp); gr_setcolor(MARKEDSIDE_COLOR); draw_seg_side(Markedsegp,Markedside); } // Highlight current segment and current side. gr_setcolor(CURSEG_COLOR); draw_segment(Cursegp); gr_setcolor(CURSIDE_COLOR); draw_seg_side(Cursegp,Curside); gr_setcolor(CUREDGE_COLOR); draw_side_edge(Cursegp,Curside,Curedge); // Draw coordinate axes if we are rendering the large view. if (Show_axes_flag) if (screen_canvas == LargeViewBox->canvas) draw_coordinate_axes(); // Label the window gr_set_fontcolor((v==current_view)?CRED:CWHITE, -1 ); if ( screen_canvas == LargeViewBox->canvas ) { gr_ustring( 5, 5, "USER VIEW" ); switch (Large_view_index) { case 0: gr_ustring( 85, 5, "-- TOP"); break; case 1: gr_ustring( 85, 5, "-- FRONT"); break; case 2: gr_ustring( 85, 5, "-- RIGHT"); break; } } else #if ORTHO_VIEWS else if ( screen_canvas == TopViewBox->canvas ) gr_ustring( 5, 5, "TOP" ); else if ( screen_canvas == FrontViewBox->canvas ) gr_ustring( 5, 5, "FRONT" ); else if ( screen_canvas == RightViewBox->canvas ) gr_ustring( 5, 5, "RIGHT" ); #else Error("Ortho views have been removed, what gives?\n"); #endif } g3_end_frame(); } //find the segments that render at a given screen x,y //parms other than x,y are like draw_world //fills in globals N_found_segs & Found_segs void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth) { vms_vector viewer_position; gr_set_current_canvas(screen_canvas); //g3_set_points(Segment_points,Vertices); viewer_position = v->ev_matrix.fvec; vm_vec_scale(&viewer_position,-v->ev_dist); vm_vec_add(&viewer_position,&viewer_position,&Ed_view_target); g3_start_frame(); g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); render_start_frame(); gr_setcolor(0); #ifdef OGL g3_end_frame(); #endif gr_pixel(x,y); //set our search pixel to color zero #ifdef OGL g3_start_frame(); #endif gr_setcolor(1); Search_mode = -1; N_found_segs = 0; Search_x = x; Search_y = y; if (Draw_all_segments) draw_mine_all(Segments, 0); else draw_mine(mine_ptr,depth); g3_end_frame(); Search_mode = 0; } void meddraw_init_views( grs_canvas * canvas) { // sticking these here so the correct D2 colors are used edge_colors[0] = BM_XRGB(45/2,45/2,45/2); edge_colors[1] = BM_XRGB(45/3,45/3,45/3); //BM_RGB(0,0,45), // edge_colors[2] = BM_XRGB(45/4,45/4,45/4); //BM_RGB(0,45,0)}; // Views[0]->ev_canv = canvas; #if ORTHO_VIEWS Views[1]->ev_canv = TopViewBox->canvas; Views[2]->ev_canv = FrontViewBox->canvas; Views[3]->ev_canv = RightViewBox->canvas; #endif } dxx-rebirth-0.58.1-d2x/editor/medmisc.c000066400000000000000000000324551217717237500176400ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Miscellaneous functions stripped out of med.c * */ #include #include #include #include #include "gr.h" #include "ui.h" #include "3d.h" #include "u_mem.h" #include "dxxerror.h" #include "key.h" #include "mouse.h" #include "func.h" #include "inferno.h" #include "editor/editor.h" #include "editor/esegment.h" #include "segment.h" #include "render.h" #include "screens.h" #include "object.h" #include "texpage.h" // For texpage_goto_first #include "meddraw.h" // For draw_World #include "game.h" //return 2d distance, i.e, sqrt(x*x + y*y) #ifdef __WATCOMC__ long dist_2d(long x,long y); #pragma aux dist_2d parm [eax] [ebx] value [eax] modify [ecx edx] = \ "imul eax" \ "xchg ebx,eax" \ "mov ecx,edx" \ "imul eax" \ "add eax,ebx" \ "adc edx,ecx" \ "call quad_sqrt"; #else #include long dist_2d(long x,long y) { return (long)sqrt((double)x * (double)x + (double)y * (double)y); } #endif // Given mouse movement in dx, dy, returns a 3x3 rotation matrix in RotMat. // Taken from Graphics Gems III, page 51, "The Rolling Ball" void GetMouseRotation( int idx, int idy, vms_matrix * RotMat ) { fix dr, cos_theta, sin_theta, denom, cos_theta1; fix Radius = i2f(100); fix dx,dy; fix dxdr,dydr; idy *= -1; dx = i2f(idx); dy = i2f(idy); dr = dist_2d(dx,dy); denom = dist_2d(Radius,dr); cos_theta = fixdiv(Radius,denom); sin_theta = fixdiv(dr,denom); cos_theta1 = f1_0 - cos_theta; dxdr = fixdiv(dx,dr); dydr = fixdiv(dy,dr); RotMat->rvec.x = cos_theta + fixmul(fixmul(dydr,dydr),cos_theta1); RotMat->uvec.x = - fixmul(fixmul(dxdr,dydr),cos_theta1); RotMat->fvec.x = fixmul(dxdr,sin_theta); RotMat->rvec.y = RotMat->uvec.x; RotMat->uvec.y = cos_theta + fixmul(fixmul(dxdr,dxdr),cos_theta1); RotMat->fvec.y = fixmul(dydr,sin_theta); RotMat->rvec.z = -RotMat->fvec.x; RotMat->uvec.z = -RotMat->fvec.y; RotMat->fvec.z = cos_theta; } int Gameview_lockstep; //if set, view is locked to Curseg int ToggleLockstep() { Gameview_lockstep = !Gameview_lockstep; if (Gameview_lockstep == 0) { //if (keypress != KEY_L) diagnostic_message("[Ctrl-L] - Lock mode OFF"); //else // diagnostic_message("Lock mode OFF"); } if (Gameview_lockstep) { //if (keypress != KEY_L) diagnostic_message("[Ctrl-L] Lock mode ON"); //else // diagnostic_message("Lock mode ON"); Cursegp = &Segments[ConsoleObject->segnum]; med_create_new_segment_from_cursegp(); set_view_target_from_segment(Cursegp); Update_flags = UF_ED_STATE_CHANGED; } return Gameview_lockstep; } int medlisp_delete_segment(void) { if (!med_delete_segment(Cursegp)) { if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); autosave_mine(mine_filename); strcpy(undo_status[Autosave_count], "Delete Segment UNDONE."); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Segment deleted."); warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly } return 1; } int medlisp_scale_segment(void) { vms_matrix rotmat; vms_vector scale; scale.x = fl2f((float) func_get_param(0)); scale.y = fl2f((float) func_get_param(1)); scale.z = fl2f((float) func_get_param(2)); med_create_new_segment(&scale); med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation)); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; return 1; } int medlisp_rotate_segment(void) { vms_matrix rotmat; Seg_orientation.p = func_get_param(0); Seg_orientation.b = func_get_param(1); Seg_orientation.h = func_get_param(2); med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation)); Update_flags |= UF_WORLD_CHANGED | UF_VIEWPOINT_MOVED; mine_changed = 1; return 1; } int ToggleLockViewToCursegp(void) { Lock_view_to_cursegp = !Lock_view_to_cursegp; Update_flags = UF_ED_STATE_CHANGED; if (Lock_view_to_cursegp) { //if (keypress != KEY_V+KEY_CTRLED) diagnostic_message("[ctrl-V] View locked to Cursegp."); //else // diagnostic_message("View locked to Cursegp."); set_view_target_from_segment(Cursegp); } else { //if (keypress != KEY_V+KEY_CTRLED) diagnostic_message("[ctrl-V] View not locked to Cursegp."); //else // diagnostic_message("View not locked to Cursegp."); } return Lock_view_to_cursegp; } int ToggleDrawAllSegments() { Draw_all_segments = !Draw_all_segments; Update_flags = UF_ED_STATE_CHANGED; if (Draw_all_segments == 1) { //if (keypress != KEY_A+KEY_CTRLED) diagnostic_message("[ctrl-A] Draw all segments ON."); //else // diagnostic_message("Draw all segments ON."); } if (Draw_all_segments == 0) { //if (keypress != KEY_A+KEY_CTRLED) diagnostic_message("[ctrl-A] Draw all segments OFF."); //else // diagnostic_message("Draw all segments OFF."); } return Draw_all_segments; } int Big_depth=6; int IncreaseDrawDepth(void) { Big_depth++; Update_flags = UF_ED_STATE_CHANGED; return 1; } int DecreaseDrawDepth(void) { if (Big_depth > 1) { Big_depth--; Update_flags = UF_ED_STATE_CHANGED; } return 1; } int ToggleCoordAxes() { // Toggle display of coordinate axes. Show_axes_flag = !Show_axes_flag; LargeView.ev_changed = 1; if (Show_axes_flag == 1) { //if (keypress != KEY_D+KEY_CTRLED) diagnostic_message("[ctrl-D] Coordinate axes ON."); //else // diagnostic_message("Coordinate axes ON."); } if (Show_axes_flag == 0) { //if (keypress != KEY_D+KEY_CTRLED) diagnostic_message("[ctrl-D] Coordinate axes OFF."); //else // diagnostic_message("Coordinate axes OFF."); } return Show_axes_flag; } int med_keypad_goto_prev() { ui_pad_goto_prev(); return 0; } int med_keypad_goto_next() { ui_pad_goto_next(); return 0; } int med_keypad_goto() { ui_pad_goto(func_get_param(0)); return 0; } int render_3d_in_big_window=0; int medlisp_update_screen() { int vn; #if 1 //def OGL Update_flags = UF_ALL; #endif if (!render_3d_in_big_window) for (vn=0;vnev_changed || (Update_flags & (UF_WORLD_CHANGED|UF_VIEWPOINT_MOVED|UF_ED_STATE_CHANGED))) { draw_world(Views[vn]->ev_canv,Views[vn],Cursegp,Big_depth); Views[vn]->ev_changed = 0; } if (Update_flags & (UF_WORLD_CHANGED|UF_GAME_VIEW_CHANGED|UF_ED_STATE_CHANGED)) { grs_canvas *render_canv,*show_canv; if (render_3d_in_big_window) { render_canv = LargeView.ev_canv; show_canv = LargeView.ev_canv; } else { render_canv = Canv_editor_game; show_canv = Canv_editor_game; } gr_set_current_canvas(render_canv); render_frame(0, 0); Assert(render_canv->cv_bitmap.bm_w == show_canv->cv_bitmap.bm_w && render_canv->cv_bitmap.bm_h == show_canv->cv_bitmap.bm_h); (void)show_canv; } Update_flags=UF_NONE; //clear flags return 1; } void med_point_2_vec(grs_canvas *canv,vms_vector *v,short sx,short sy) { gr_set_current_canvas(canv); g3_start_frame(); g3_set_view_matrix(&Viewer->pos,&Viewer->orient,Render_zoom); g3_point_2_vec(v,sx,sy); g3_end_frame(); } void draw_world_from_game(void) { if (ModeFlag == 2) draw_world(Views[0]->ev_canv,Views[0],Cursegp,Big_depth); } int UndoCommand() { int u; u = undo(); if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); if (u == 0) { if (Autosave_count==9) diagnostic_message(undo_status[0]); else diagnostic_message(undo_status[Autosave_count+1]); } else if (u == 1) diagnostic_message("Can't Undo."); else if (u == 2) diagnostic_message("Can't Undo - Autosave OFF"); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; warn_if_concave_segments(); return 1; } int ToggleAutosave() { Autosave_flag = !Autosave_flag; if (Autosave_flag == 1) diagnostic_message("Autosave ON."); else diagnostic_message("Autosave OFF."); return Autosave_flag; } int AttachSegment() { if (med_attach_segment(Cursegp, &New_segment, Curside, AttachSide)==4) // Used to be WBACK instead of Curside diagnostic_message("Cannot attach segment - already a connection on current side."); else { if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); vm_angvec_make(&Seg_orientation,0,0,0); Curside = WBACK; Update_flags |= UF_WORLD_CHANGED; autosave_mine(mine_filename); strcpy(undo_status[Autosave_count], "Attach Segment UNDONE.\n"); mine_changed = 1; warn_if_concave_segment(Cursegp); } return 1; } int ForceTotalRedraw() { Update_flags = UF_ALL; return 1; } #if ORTHO_VIEWS int SyncLargeView() { // Make large view be same as one of the orthogonal views. Large_view_index = (Large_view_index + 1) % 3; // keep in 0,1,2 for top, front, right switch (Large_view_index) { case 0: LargeView.ev_matrix = TopView.ev_matrix; break; case 1: LargeView.ev_matrix = FrontView.ev_matrix; break; case 2: LargeView.ev_matrix = RightView.ev_matrix; break; } Update_flags |= UF_VIEWPOINT_MOVED; return 1; } #endif int DeleteCurSegment() { // Delete current segment. med_delete_segment(Cursegp); autosave_mine(mine_filename); strcpy(undo_status[Autosave_count], "Delete segment UNDONE."); if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); Update_flags |= UF_WORLD_CHANGED; mine_changed = 1; diagnostic_message("Segment deleted."); warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly return 1; } int CreateDefaultNewSegment() { // Create a default segment for New_segment. vms_vector tempvec; med_create_new_segment(vm_vec_make(&tempvec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); mine_changed = 1; return 1; } int CreateDefaultNewSegmentandAttach() { CreateDefaultNewSegment(); AttachSegment(); return 1; } int ExchangeMarkandCurseg() { // If Markedsegp != Cursegp, and Markedsegp->segnum != -1, exchange Markedsegp and Cursegp if (Markedsegp) if (Markedsegp->segnum != -1) { segment *tempsegp; int tempside; tempsegp = Markedsegp; Markedsegp = Cursegp; Cursegp = tempsegp; tempside = Markedside; Markedside = Curside; Curside = tempside; med_create_new_segment_from_cursegp(); Update_flags |= UF_ED_STATE_CHANGED; mine_changed = 1; } return 1; } int medlisp_add_segment() { AttachSegment(); //segment *ocursegp = Cursegp; // med_attach_segment(Cursegp, &New_segment, Curside, WFRONT); // Used to be WBACK instead of Curside //med_propagate_tmaps_to_segments(ocursegp,Cursegp); // set_view_target_from_segment(Cursegp); //// while (!vm_angvec_make(&Seg_orientation,0,0,0)); // Curside = WBACK; return 1; } int ClearSelectedList(void) { N_selected_segs = 0; Update_flags |= UF_WORLD_CHANGED; diagnostic_message("Selected list cleared."); return 1; } int ClearFoundList(void) { N_found_segs = 0; Update_flags |= UF_WORLD_CHANGED; diagnostic_message("Found list cleared."); return 1; } // --------------------------------------------------------------------------------------------------- // Do chase mode. // View current segment (Cursegp) from the previous segment. void set_chase_matrix(segment *sp) { int v; vms_vector forvec = ZERO_VECTOR, upvec; vms_vector tv = ZERO_VECTOR; segment *psp; // move back two segments, if possible, else move back one, if possible, else use current if (IS_CHILD(sp->children[WFRONT])) { psp = &Segments[sp->children[WFRONT]]; if (IS_CHILD(psp->children[WFRONT])) psp = &Segments[psp->children[WFRONT]]; } else psp = sp; for (v=0; vverts[v]]); vm_vec_scale(&forvec,F1_0/MAX_VERTICES_PER_SEGMENT); for (v=0; vverts[v]]); vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT); Ed_view_target = forvec; vm_vec_sub2(&forvec,&tv); extract_up_vector_from_segment(psp,&upvec); if (!((forvec.x == 0) && (forvec.y == 0) && (forvec.z == 0))) vm_vector_2_matrix(&LargeView.ev_matrix,&forvec,&upvec,NULL); } // --------------------------------------------------------------------------------------------------- void set_view_target_from_segment(segment *sp) { vms_vector tv = ZERO_VECTOR; int v; if (Funky_chase_mode) { //set_chase_matrix(sp); } else { for (v=0; vverts[v]]); vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT); Ed_view_target = tv; } Update_flags |= UF_VIEWPOINT_MOVED; } dxx-rebirth-0.58.1-d2x/editor/medrobot.c000066400000000000000000000573021217717237500200300ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Dialog box to edit robot properties. * */ #include #include #include #include #include "screens.h" #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "timer.h" #include "objpage.h" #include "fix.h" #include "dxxerror.h" #include "kdefs.h" #include "object.h" #include "polyobj.h" #include "game.h" #include "powerup.h" #include "ai.h" #include "hostage.h" #include "eobject.h" #include "medwall.h" #include "eswitch.h" #include "ehostage.h" #include "key.h" #include "centers.h" #include "bm.h" #define NUM_BOXES 6 // Number of boxes, AI modes int GoodyNextID(); int GoodyPrevID(); void robot_close_window(); //------------------------------------------------------------------------- // Variables for this module... //------------------------------------------------------------------------- static UI_DIALOG *MainWindow = NULL; typedef struct robot_dialog { UI_GADGET_USERBOX *robotViewBox; UI_GADGET_USERBOX *containsViewBox; UI_GADGET_BUTTON *quitButton; UI_GADGET_RADIO *initialMode[NUM_BOXES]; int old_object; fix64 time; vms_angvec angles, goody_angles; } robot_dialog; void call_init_ai_object(object *objp, int behavior) { int hide_segment; if (behavior == AIB_STATION) hide_segment = Cursegp-Segments; else { if (Markedsegp != NULL) hide_segment = Markedsegp-Segments; else hide_segment = Cursegp-Segments; } init_ai_object(objp-Objects, behavior, hide_segment); if (behavior == AIB_STATION) { //objp->ctype.ai_info.follow_path_start_seg = Cursegp-Segments; //objp->ctype.ai_info.follow_path_end_seg = Markedsegp-Segments; } } //------------------------------------------------------------------------- // Called when user presses "Next Type" button. This only works for polygon // objects and it just selects the next polygon model for the current object. //------------------------------------------------------------------------- int RobotNextType() { if (Cur_object_index > -1 ) { if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { object * obj = &Objects[Cur_object_index]; obj->id++; if (obj->id >= N_robot_types ) obj->id = 0; //Set polygon-object-specific data obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; obj->rtype.pobj_info.subobj_flags = 0; //set Physics info obj->mtype.phys_info.flags |= (PF_LEVELLING); obj->shields = Robot_info[obj->id].strength; call_init_ai_object(obj, AIB_NORMAL); Cur_object_id = obj->id; } } Update_flags |= UF_WORLD_CHANGED; return 1; } //------------------------------------------------------------------------- // Called when user presses "Prev Type" button. This only works for polygon // objects and it just selects the prev polygon model for the current object. //------------------------------------------------------------------------- int RobotPrevType() { if (Cur_object_index > -1 ) { if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { object * obj = &Objects[Cur_object_index]; if (obj->id == 0 ) obj->id = N_robot_types-1; else obj->id--; //Set polygon-object-specific data obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; obj->rtype.pobj_info.subobj_flags = 0; //set Physics info obj->mtype.phys_info.flags |= (PF_LEVELLING); obj->shields = Robot_info[obj->id].strength; call_init_ai_object(obj, AIB_NORMAL); Cur_object_id = obj->id; } } Update_flags |= UF_WORLD_CHANGED; return 1; } //------------------------------------------------------------------------- // Dummy function for Mike to write. //------------------------------------------------------------------------- int med_set_ai_path() { return 1; } // #define OBJ_NONE 255 //unused object // #define OBJ_WALL 0 //A wall... not really an object, but used for collisions // #define OBJ_FIREBALL 1 //a fireball, part of an explosion // #define OBJ_ROBOT 2 //an evil enemy // #define OBJ_HOSTAGE 3 //a hostage you need to rescue // #define OBJ_PLAYER 4 //the player on the console // #define OBJ_WEAPON 5 //a laser, missile, etc // #define OBJ_CAMERA 6 //a camera to slew around with // #define OBJ_POWERUP 7 //a powerup you can pick up // #define OBJ_DEBRIS 8 //a piece of robot // #define OBJ_CNTRLCEN 9 //the control center // #define OBJ_FLARE 10 //the control center // #define MAX_OBJECT_TYPES 11 #define GOODY_TYPE_MAX MAX_OBJECT_TYPES #define GOODY_X 6 #define GOODY_Y 132 //#define GOODY_ID_MAX_ROBOT 6 //#define GOODY_ID_MAX_POWERUP 9 #define GOODY_COUNT_MAX 4 int Cur_goody_type = OBJ_POWERUP; int Cur_goody_id = 0; int Cur_goody_count = 0; void update_goody_info(void) { if (Cur_object_index > -1 ) { if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { object * obj = &Objects[Cur_object_index]; obj->contains_type = Cur_goody_type; obj->contains_id = Cur_goody_id; obj->contains_count = Cur_goody_count; } } } // #define OBJ_WALL 0 //A wall... not really an object, but used for collisions // #define OBJ_FIREBALL 1 //a fireball, part of an explosion // #define OBJ_ROBOT 2 //an evil enemy // #define OBJ_HOSTAGE 3 //a hostage you need to rescue // #define OBJ_PLAYER 4 //the player on the console // #define OBJ_WEAPON 5 //a laser, missile, etc // #define OBJ_CAMERA 6 //a camera to slew around with // #define OBJ_POWERUP 7 //a powerup you can pick up // #define OBJ_DEBRIS 8 //a piece of robot // #define OBJ_CNTRLCEN 9 //the control center // #define OBJ_FLARE 10 //the control center // #define MAX_OBJECT_TYPES 11 int GoodyNextType() { Cur_goody_type++; while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) { if (Cur_goody_type > GOODY_TYPE_MAX) Cur_goody_type=0; else Cur_goody_type++; } GoodyNextID(); GoodyPrevID(); update_goody_info(); return 1; } int GoodyPrevType() { Cur_goody_type--; while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) { if (Cur_goody_type < 0) Cur_goody_type = GOODY_TYPE_MAX; else Cur_goody_type--; } GoodyNextID(); GoodyPrevID(); update_goody_info(); return 1; } int GoodyNextID() { Cur_goody_id++; if (Cur_goody_type == OBJ_ROBOT) { if (Cur_goody_id >= N_robot_types) Cur_goody_id=0; } else { if (Cur_goody_id >= N_powerup_types) Cur_goody_id=0; } update_goody_info(); return 1; } int GoodyPrevID() { Cur_goody_id--; if (Cur_goody_type == OBJ_ROBOT) { if (Cur_goody_id < 0) Cur_goody_id = N_robot_types-1; } else { if (Cur_goody_id < 0) Cur_goody_id = N_powerup_types-1; } update_goody_info(); return 1; } int GoodyNextCount() { Cur_goody_count++; if (Cur_goody_count > GOODY_COUNT_MAX) Cur_goody_count=0; update_goody_info(); return 1; } int GoodyPrevCount() { Cur_goody_count--; if (Cur_goody_count < 0) Cur_goody_count=GOODY_COUNT_MAX; update_goody_info(); return 1; } int is_legal_type(int the_type) { return (the_type == OBJ_ROBOT) || (the_type == OBJ_CLUTTER); } int is_legal_type_for_this_window(int objnum) { if (objnum == -1) return 1; else return is_legal_type(Objects[objnum].type); } int LocalObjectSelectNextinSegment(void) { int rval, first_obj; rval = ObjectSelectNextinSegment(); first_obj = Cur_object_index; if (Cur_object_index != -1) { while (!is_legal_type_for_this_window(Cur_object_index)) { rval = ObjectSelectNextinSegment(); if (first_obj == Cur_object_index) break; } Cur_goody_type = Objects[Cur_object_index].contains_type; Cur_goody_id = Objects[Cur_object_index].contains_id; if (Objects[Cur_object_index].contains_count < 0) Objects[Cur_object_index].contains_count = 0; Cur_goody_count = Objects[Cur_object_index].contains_count; } if (Cur_object_index != first_obj) set_view_target_from_segment(Cursegp); return rval; } int LocalObjectSelectNextinMine(void) { int rval, first_obj; rval = ObjectSelectNextInMine(); first_obj = Cur_object_index; if (Cur_object_index != -1) { while (!is_legal_type_for_this_window(Cur_object_index)) { ObjectSelectNextInMine(); if (Cur_object_index == first_obj) break; } Cur_goody_type = Objects[Cur_object_index].contains_type; Cur_goody_id = Objects[Cur_object_index].contains_id; if (Objects[Cur_object_index].contains_count < 0) Objects[Cur_object_index].contains_count = 0; Cur_goody_count = Objects[Cur_object_index].contains_count; } if (Cur_object_index != first_obj) set_view_target_from_segment(Cursegp); return rval; } int LocalObjectSelectPrevinMine(void) { int rval, first_obj; rval = ObjectSelectPrevInMine(); first_obj = Cur_object_index; if (Cur_object_index != -1) { while (!is_legal_type_for_this_window(Cur_object_index)) { ObjectSelectPrevInMine(); if (first_obj == Cur_object_index) break; } Cur_goody_type = Objects[Cur_object_index].contains_type; Cur_goody_id = Objects[Cur_object_index].contains_id; if (Objects[Cur_object_index].contains_count < 0) Objects[Cur_object_index].contains_count = 0; Cur_goody_count = Objects[Cur_object_index].contains_count; } if (Cur_object_index != first_obj) set_view_target_from_segment(Cursegp); return rval; } int LocalObjectDelete(void) { int rval; rval = ObjectDelete(); if (Cur_object_index != -1) { Cur_goody_type = Objects[Cur_object_index].contains_type; Cur_goody_id = Objects[Cur_object_index].contains_id; Cur_goody_count = Objects[Cur_object_index].contains_count; } set_view_target_from_segment(Cursegp); return rval; } int LocalObjectPlaceObject(void) { int rval; Cur_goody_count = 0; if (Cur_object_type != OBJ_ROBOT) { Cur_object_type = OBJ_ROBOT; Cur_object_id = 3; // class 1 drone Num_object_subtypes = N_robot_types; } rval = ObjectPlaceObject(); if (rval == -1) return -1; Objects[Cur_object_index].contains_type = Cur_goody_type; Objects[Cur_object_index].contains_id = Cur_goody_id; Objects[Cur_object_index].contains_count = Cur_goody_count; set_view_target_from_segment(Cursegp); return rval; } void close_all_windows(void) { close_trigger_window(); close_wall_window(); close_centers_window(); hostage_close_window(); robot_close_window(); } int robot_dialog_handler(UI_DIALOG *dlg, d_event *event, robot_dialog *r); //------------------------------------------------------------------------- // Called from the editor... does one instance of the robot dialog box //------------------------------------------------------------------------- int do_robot_dialog() { int i; robot_dialog *r; // Only open 1 instance of this window... if ( MainWindow != NULL ) return 0; MALLOC(r, robot_dialog, 1); if (!r) return 0; // Close other windows close_all_windows(); Cur_goody_count = 0; memset(&r->angles, 0, sizeof(vms_angvec)); memset(&r->goody_angles, 0, sizeof(vms_angvec)); // Open a window with a quit button MainWindow = ui_create_dialog( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, DF_DIALOG, (int (*)(UI_DIALOG *, d_event *, void *))robot_dialog_handler, r ); r->quitButton = ui_add_gadget_button( MainWindow, 20, 286, 40, 32, "Done", NULL ); ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y-3, 25, 22, "<<", GoodyPrevType ); ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y-3, 25, 22, ">>", GoodyNextType ); ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+21, 25, 22, "<<", GoodyPrevID ); ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+21, 25, 22, ">>", GoodyNextID ); ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+45, 25, 22, "<<", GoodyPrevCount ); ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+45, 25, 22, ">>", GoodyNextCount ); r->initialMode[0] = ui_add_gadget_radio( MainWindow, 6, 58, 16, 16, 0, "Hover" ); r->initialMode[1] = ui_add_gadget_radio( MainWindow, 76, 58, 16, 16, 0, "Normal" ); r->initialMode[2] = ui_add_gadget_radio( MainWindow, 6, 78, 16, 16, 0, "(hide)" ); r->initialMode[3] = ui_add_gadget_radio( MainWindow, 76, 78, 16, 16, 0, "Avoid" ); r->initialMode[4] = ui_add_gadget_radio( MainWindow, 6, 98, 16, 16, 0, "Follow" ); r->initialMode[5] = ui_add_gadget_radio( MainWindow, 76, 98, 16, 16, 0, "Station" ); // The little box the robots will spin in. r->robotViewBox = ui_add_gadget_userbox( MainWindow,155, 5, 150, 125 ); // The little box the robots will spin in. r->containsViewBox = ui_add_gadget_userbox( MainWindow,10, 202, 100, 80 ); // A bunch of buttons... i = 135; ui_add_gadget_button( MainWindow,190,i,53, 26, "<>", RobotNextType ); i += 29; ui_add_gadget_button( MainWindow,190,i,110, 26, "Next in Seg", LocalObjectSelectNextinSegment ); i += 29; ui_add_gadget_button( MainWindow,190,i,53, 26, "<>Obj", LocalObjectSelectNextinMine ); i += 29; ui_add_gadget_button( MainWindow,190,i,110, 26, "Delete", LocalObjectDelete ); i += 29; ui_add_gadget_button( MainWindow,190,i,110, 26, "Create New", LocalObjectPlaceObject ); i += 29; ui_add_gadget_button( MainWindow,190,i,110, 26, "Set Path", med_set_ai_path ); r->time = timer_query(); r->old_object = -2; // Set to some dummy value so everything works ok on the first frame. if ( Cur_object_index == -1 ) LocalObjectSelectNextinMine(); return 1; } void robot_close_window() { if ( MainWindow!=NULL ) { ui_close_dialog( MainWindow ); MainWindow = NULL; } } #define STRING_LENGTH 8 int robot_dialog_handler(UI_DIALOG *dlg, d_event *event, robot_dialog *r) { int i; fix DeltaTime; fix64 Temp; int first_object_index; int keypress = 0; int rval = 0; if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); Assert(MainWindow != NULL); first_object_index = Cur_object_index; while (!is_legal_type_for_this_window(Cur_object_index)) { LocalObjectSelectNextinMine(); if (first_object_index == Cur_object_index) { break; } } //------------------------------------------------------------ // Call the ui code.. //------------------------------------------------------------ ui_button_any_drawn = 0; //------------------------------------------------------------ // If we change objects, we need to reset the ui code for all // of the radio buttons that control the ai mode. Also makes // the current AI mode button be flagged as pressed down. //------------------------------------------------------------ if (r->old_object != Cur_object_index ) { for ( i=0; i < NUM_BOXES; i++ ) ui_radio_set_value(r->initialMode[i], 0); if ( Cur_object_index > -1 ) { int behavior = Objects[Cur_object_index].ctype.ai_info.behavior; if ( !((behavior >= MIN_BEHAVIOR) && (behavior <= MAX_BEHAVIOR))) { Objects[Cur_object_index].ctype.ai_info.behavior = AIB_NORMAL; behavior = AIB_NORMAL; } ui_radio_set_value(r->initialMode[behavior - MIN_BEHAVIOR], 1); } } //------------------------------------------------------------ // If any of the radio buttons that control the mode are set, then // update the cooresponding AI state. //------------------------------------------------------------ for ( i=0; i < NUM_BOXES; i++ ) { if ( GADGET_PRESSED(r->initialMode[i]) ) if (Objects[Cur_object_index].ctype.ai_info.behavior != MIN_BEHAVIOR+i) { Objects[Cur_object_index].ctype.ai_info.behavior = MIN_BEHAVIOR+i; // Set the ai_state to the cooresponding radio button call_init_ai_object(&Objects[Cur_object_index], MIN_BEHAVIOR+i); rval = 1; } } //------------------------------------------------------------ // Redraw the object in the little 64x64 box //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { // A simple frame time counter for spinning the objects... Temp = timer_query(); DeltaTime = Temp - r->time; r->time = Temp; if (Cur_object_index > -1 ) { object *obj = &Objects[Cur_object_index]; gr_set_current_canvas( r->robotViewBox->canvas ); draw_object_picture(obj->id, &r->angles, obj->type ); r->angles.h += fixmul(0x1000, DeltaTime ); } else { // no object, so just blank out gr_set_current_canvas( r->robotViewBox->canvas ); gr_clear_canvas( CGREY ); // LocalObjectSelectNextInMine(); } } //------------------------------------------------------------ // Redraw the contained object in the other little box //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { if ((Cur_object_index > -1 ) && (Cur_goody_count > 0)) { gr_set_current_canvas( r->containsViewBox->canvas ); if ( Cur_goody_id > -1 ) draw_object_picture(Cur_goody_id, &r->goody_angles, Cur_goody_type); else gr_clear_canvas( CGREY ); r->goody_angles.h += fixmul(0x1000, DeltaTime ); } else { // no object, so just blank out gr_set_current_canvas( r->containsViewBox->canvas ); gr_clear_canvas( CGREY ); // LocalObjectSelectNextInMine(); } } //------------------------------------------------------------ // If anything changes in the ui system, redraw all the text that // identifies this robot. //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { int i; char id_text[STRING_LENGTH+1]; const char *type_text; if (Cur_object_index != -1) { Cur_goody_type = Objects[Cur_object_index].contains_type; Cur_goody_id = Objects[Cur_object_index].contains_id; if (Objects[Cur_object_index].contains_count < 0) Objects[Cur_object_index].contains_count = 0; Cur_goody_count = Objects[Cur_object_index].contains_count; } ui_dprintf_at( MainWindow, GOODY_X, GOODY_Y, " Type:"); ui_dprintf_at( MainWindow, GOODY_X, GOODY_Y+24, " ID:"); ui_dprintf_at( MainWindow, GOODY_X, GOODY_Y+48, "Count:"); for (i=0; i -1 ) { int id = Objects[Cur_object_index].id; char id_text[12]; int i; for (i=0; iold_object != Cur_object_index) ) Update_flags |= UF_WORLD_CHANGED; if (event->type == EVENT_WINDOW_CLOSE) { d_free(r); MainWindow = NULL; return 0; } if ( GADGET_PRESSED(r->quitButton) || (keypress==KEY_ESC)) { robot_close_window(); return 1; } r->old_object = Cur_object_index; return rval; } // -------------------------------------------------------------------------------------------------------------------------- #define NUM_MATT_THINGS 2 #define MATT_LEN 20 static UI_DIALOG *MattWindow = NULL; typedef struct object_dialog { UI_GADGET_INPUTBOX *xtext, *ytext, *ztext; UI_GADGET_RADIO *initialMode[2]; UI_GADGET_BUTTON *quitButton; } object_dialog; void object_close_window() { if ( MattWindow!=NULL ) { ui_close_dialog( MattWindow ); MattWindow = NULL; } } int object_dialog_handler(UI_DIALOG *dlg, d_event *event, object_dialog *o); //------------------------------------------------------------------------- // Called from the editor... does one instance of the object dialog box //------------------------------------------------------------------------- int do_object_dialog() { char Xmessage[MATT_LEN], Ymessage[MATT_LEN], Zmessage[MATT_LEN]; object *obj=&Objects[Cur_object_index]; object_dialog *o; if (obj->type == OBJ_ROBOT) //don't do this for robots return 0; // Only open 1 instance of this window... if ( MattWindow != NULL ) return 0; MALLOC(o, object_dialog, 1); if (!o) return 0; Cur_goody_count = 0; // Open a window with a quit button MattWindow = ui_create_dialog( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, DF_DIALOG, (int (*)(UI_DIALOG *, d_event *, void *))object_dialog_handler, o ); o->quitButton = ui_add_gadget_button( MattWindow, 20, 286, 40, 32, "Done", NULL ); o->quitButton->hotkey = KEY_ENTER; // These are the radio buttons for each mode o->initialMode[0] = ui_add_gadget_radio( MattWindow, 10, 50, 16, 16, 0, "None" ); o->initialMode[1] = ui_add_gadget_radio( MattWindow, 80, 50, 16, 16, 0, "Spinning" ); o->initialMode[obj->movement_type == MT_SPINNING?1:0]->flag = 1; sprintf(Xmessage,"%.2f",f2fl(obj->mtype.spin_rate.x)); sprintf(Ymessage,"%.2f",f2fl(obj->mtype.spin_rate.y)); sprintf(Zmessage,"%.2f",f2fl(obj->mtype.spin_rate.z)); o->xtext = ui_add_gadget_inputbox( MattWindow, 30, 132, MATT_LEN, MATT_LEN, Xmessage ); o->ytext = ui_add_gadget_inputbox( MattWindow, 30, 162, MATT_LEN, MATT_LEN, Ymessage ); o->ztext = ui_add_gadget_inputbox( MattWindow, 30, 192, MATT_LEN, MATT_LEN, Zmessage ); ui_gadget_calc_keys(MattWindow); MattWindow->keyboard_focus_gadget = (UI_GADGET *) o->initialMode[0]; return 1; } int object_dialog_handler(UI_DIALOG *dlg, d_event *event, object_dialog *o) { object *obj=&Objects[Cur_object_index]; int keypress = 0; int rval = 0; if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); Assert(MattWindow != NULL); //------------------------------------------------------------ // Call the ui code.. //------------------------------------------------------------ ui_button_any_drawn = 0; if (event->type == EVENT_WINDOW_CLOSE) { d_free(o); MattWindow = NULL; return 0; } else if (event->type == EVENT_UI_DIALOG_DRAW) { ui_dprintf_at( MattWindow, 10, 132,"&X:" ); ui_dprintf_at( MattWindow, 10, 162,"&Y:" ); ui_dprintf_at( MattWindow, 10, 192,"&Z:" ); } if ( GADGET_PRESSED(o->quitButton) || (keypress==KEY_ESC)) { if (o->initialMode[0]->flag) obj->movement_type = MT_NONE; if (o->initialMode[1]->flag) obj->movement_type = MT_SPINNING; obj->mtype.spin_rate.x = fl2f(atof(o->xtext->text)); obj->mtype.spin_rate.y = fl2f(atof(o->ytext->text)); obj->mtype.spin_rate.z = fl2f(atof(o->ztext->text)); object_close_window(); return 1; } return rval; } void set_all_modes_to_hover(void) { int i; for (i=0; i<=Highest_object_index; i++) if (Objects[i].control_type == CT_AI) Objects[i].ctype.ai_info.behavior = AIB_STILL; } dxx-rebirth-0.58.1-d2x/editor/medsel.c000066400000000000000000000057421217717237500174670ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines stripped from med.c for segment selection * */ #include #include #include #include #include "gr.h" #include "ui.h" #include "key.h" #include "dxxerror.h" #include "u_mem.h" #include "inferno.h" #include "editor.h" #include "editor/esegment.h" #include "segment.h" #include "object.h" typedef struct sort_element { short segnum; fix dist; } sort_element; //compare the distance of two segments. slow, since it computes the //distance each time int segdist_cmp(sort_element *s0,sort_element *s1) { return (s0->dist==s1->dist)?0:((s0->distdist)?-1:1); } //find the distance between a segment and a point fix compute_dist(segment *seg,vms_vector *pos) { vms_vector delta; compute_segment_center(&delta,seg); vm_vec_sub2(&delta,pos); return vm_vec_mag(&delta); } //sort a list of segments, in order of closeness to pos void sort_seg_list(int n_segs,short *segnumlist,vms_vector *pos) { int i; sort_element *sortlist; sortlist = d_calloc(n_segs, sizeof(*sortlist)); for (i=0;ipos); editor_status_fmt("%i element selected list sorted.",N_selected_segs); return 1; } int SelectNextFoundSeg(void) { if (++Found_seg_index >= N_found_segs) Found_seg_index = 0; Cursegp = &Segments[Found_segs[Found_seg_index]]; med_create_new_segment_from_cursegp(); Update_flags |= UF_WORLD_CHANGED; if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); editor_status("Curseg assigned to next found segment."); return 1; } int SelectPreviousFoundSeg(void) { if (Found_seg_index > 0) Found_seg_index--; else Found_seg_index = N_found_segs-1; Cursegp = &Segments[Found_segs[Found_seg_index]]; med_create_new_segment_from_cursegp(); Update_flags |= UF_WORLD_CHANGED; if (Lock_view_to_cursegp) set_view_target_from_segment(Cursegp); editor_status("Curseg assigned to previous found segment."); return 1; } dxx-rebirth-0.58.1-d2x/editor/medwall.c000066400000000000000000001106061217717237500176370ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Created from version 1.11 of main\wall.c * */ #include #include #include #include #include "editor/medwall.h" #include "inferno.h" #include "editor/editor.h" #include "editor/esegment.h" #include "segment.h" #include "dxxerror.h" #include "gameseg.h" #include "textures.h" #include "screens.h" #include "switch.h" #include "editor/eswitch.h" #include "texmerge.h" #include "medrobot.h" #include "timer.h" #include "cntrlcen.h" #include "key.h" #include "ehostage.h" #include "centers.h" #include "piggy.h" int wall_add_door_flag(sbyte flag); int wall_add_to_side(segment *segp, int side, sbyte type); int wall_remove_door_flag(sbyte flag); //------------------------------------------------------------------------- // Variables for this module... //------------------------------------------------------------------------- static UI_DIALOG *MainWindow = NULL; typedef struct wall_dialog { UI_GADGET_USERBOX *wallViewBox; UI_GADGET_BUTTON *quitButton; UI_GADGET_CHECKBOX *doorFlag[4]; UI_GADGET_RADIO *keyFlag[4]; int old_wall_num; fix64 time; int framenum; } wall_dialog; static int Current_door_type=1; typedef struct count_wall { short wallnum; short segnum,sidenum; } count_wall; //--------------------------------------------------------------------- extern void create_removable_wall(segment *sp, int sidenum, int tmap_num); // Add a wall (removable 2 sided) int add_wall(segment *seg, short side) { int Connectside; segment *csegp; if (Num_walls < MAX_WALLS-2) if (IS_CHILD(seg->children[side])) { if (seg->sides[side].wall_num == -1) { seg->sides[side].wall_num = Num_walls; Num_walls++; } csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); if (csegp->sides[Connectside].wall_num == -1) { csegp->sides[Connectside].wall_num = Num_walls; Num_walls++; } create_removable_wall( seg, side, CurrentTexture ); create_removable_wall( csegp, Connectside, CurrentTexture ); return 1; } return 0; } int wall_assign_door(int door_type) { int Connectside; segment *csegp; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("Cannot assign door. No wall at Curside."); return 0; } if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR && Walls[Cursegp->sides[Curside].wall_num].type != WALL_BLASTABLE) { editor_status("Cannot assign door. No door at Curside."); return 0; } Current_door_type = door_type; csegp = &Segments[Cursegp->children[Curside]]; Connectside = find_connect_side(Cursegp, csegp); Walls[Cursegp->sides[Curside].wall_num].clip_num = door_type; Walls[csegp->sides[Connectside].wall_num].clip_num = door_type; if (WallAnims[door_type].flags & WCF_TMAP1) { Cursegp->sides[Curside].tmap_num = WallAnims[door_type].frames[0]; csegp->sides[Connectside].tmap_num = WallAnims[door_type].frames[0]; Cursegp->sides[Curside].tmap_num2 = 0; csegp->sides[Connectside].tmap_num2 = 0; } else { Cursegp->sides[Curside].tmap_num2 = WallAnims[door_type].frames[0]; csegp->sides[Connectside].tmap_num2 = WallAnims[door_type].frames[0]; } Update_flags |= UF_WORLD_CHANGED; return 1; } int wall_add_blastable() { return wall_add_to_side(Cursegp, Curside, WALL_BLASTABLE); } int wall_add_door() { return wall_add_to_side(Cursegp, Curside, WALL_DOOR); } int wall_add_closed_wall() { return wall_add_to_side(Cursegp, Curside, WALL_CLOSED); } int wall_add_external_wall() { if (Cursegp->children[Curside] == -2) { editor_status( "Wall is already external!" ); return 1; } if (IS_CHILD(Cursegp->children[Curside])) { editor_status( "Cannot add external wall here - seg has children" ); return 0; } Cursegp->children[Curside] = -2; return 1; } int wall_add_illusion() { return wall_add_to_side(Cursegp, Curside, WALL_ILLUSION); } int wall_lock_door() { return wall_add_door_flag(WALL_DOOR_LOCKED); } int wall_unlock_door() { return wall_remove_door_flag(WALL_DOOR_LOCKED); } int wall_automate_door() { return wall_add_door_flag(WALL_DOOR_AUTO); } int wall_deautomate_door() { return wall_remove_door_flag(WALL_DOOR_AUTO); } int GotoPrevWall() { int current_wall; if (Cursegp->sides[Curside].wall_num < 0) current_wall = Num_walls; else current_wall = Cursegp->sides[Curside].wall_num; current_wall--; if (current_wall < 0) current_wall = Num_walls-1; if (current_wall >= Num_walls) current_wall = Num_walls-1; if (Walls[current_wall].segnum == -1) { return 0; } if (Walls[current_wall].sidenum == -1) { return 0; } Cursegp = &Segments[Walls[current_wall].segnum]; Curside = Walls[current_wall].sidenum; return 1; } int GotoNextWall() { int current_wall; current_wall = Cursegp->sides[Curside].wall_num; // It's ok to be -1 because it will immediately become 0 current_wall++; if (current_wall >= Num_walls) current_wall = 0; if (current_wall < 0) current_wall = 0; if (Walls[current_wall].segnum == -1) { return 0; } if (Walls[current_wall].sidenum == -1) { return 0; } Cursegp = &Segments[Walls[current_wall].segnum]; Curside = Walls[current_wall].sidenum; return 1; } int PrevWall() { int wall_type; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("Cannot assign new wall. No wall on curside."); return 0; } wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num; if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { do { wall_type--; if (wall_type < 0) wall_type = Num_wall_anims-1; if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num) Error("Cannot find clip for door."); } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE); } else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) { do { wall_type--; if (wall_type < 0) wall_type = Num_wall_anims-1; if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num) Error("Cannot find clip for blastable wall."); } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE)); } wall_assign_door(wall_type); Update_flags |= UF_WORLD_CHANGED; return 1; } int NextWall() { int wall_type; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("Cannot assign new wall. No wall on curside."); return 0; } wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num; if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { do { wall_type++; if (wall_type >= Num_wall_anims) { wall_type = 0; if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1) Error("Cannot find clip for door."); } } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE); } else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) { do { wall_type++; if (wall_type >= Num_wall_anims) { wall_type = 0; if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1) Error("Cannot find clip for blastable wall."); } } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE)); } wall_assign_door(wall_type); Update_flags |= UF_WORLD_CHANGED; return 1; } int wall_dialog_handler(UI_DIALOG *dlg, d_event *event, wall_dialog *wd); //------------------------------------------------------------------------- // Called from the editor... does one instance of the wall dialog box //------------------------------------------------------------------------- int do_wall_dialog() { int i; wall_dialog *wd; // Only open 1 instance of this window... if ( MainWindow != NULL ) return 0; MALLOC(wd, wall_dialog, 1); if (!wd) return 0; wd->framenum = 0; // Close other windows. close_all_windows(); // Open a window with a quit button MainWindow = ui_create_dialog( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, DF_DIALOG, (int (*)(UI_DIALOG *, d_event *, void *))wall_dialog_handler, wd ); wd->quitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL ); // These are the checkboxes for each door flag. i = 80; wd->doorFlag[0] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Locked" ); i += 24; wd->doorFlag[1] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Auto" ); i += 24; wd->doorFlag[2] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion OFF" ); i += 24; wd->keyFlag[0] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "NONE" ); i += 24; wd->keyFlag[1] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Blue" ); i += 24; wd->keyFlag[2] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Red" ); i += 24; wd->keyFlag[3] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Yellow" ); i += 24; // The little box the wall will appear in. wd->wallViewBox = ui_add_gadget_userbox( MainWindow, 155, 5, 64, 64 ); // A bunch of buttons... i = 80; ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Clip", PrevWall ); ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Clip >>", NextWall );i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Blastable", wall_add_blastable ); i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Door", wall_add_door ); i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Illusory", wall_add_illusion); i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Closed Wall", wall_add_closed_wall ); i+=25; // ui_add_gadget_button( MainWindow,155,i,140, 22, "Restore All Walls", wall_restore_all ); i += 25; ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Prev", GotoPrevWall ); ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Next >>", GotoNextWall );i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Remove Wall", wall_remove ); i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Trigger", bind_wall_to_trigger ); i += 25; ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Control", bind_wall_to_control_center ); i+=25; wd->old_wall_num = -2; // Set to some dummy value so everything works ok on the first frame. return 1; } void close_wall_window() { if ( MainWindow!=NULL ) { ui_close_dialog( MainWindow ); MainWindow = NULL; } } int wall_dialog_handler(UI_DIALOG *dlg, d_event *event, wall_dialog *wd) { int i; sbyte type; fix DeltaTime; fix64 Temp; int keypress = 0; int rval = 0; if (event->type == EVENT_KEY_COMMAND) keypress = event_key_get(event); Assert(MainWindow != NULL); //------------------------------------------------------------ // Call the ui code.. //------------------------------------------------------------ ui_button_any_drawn = 0; //------------------------------------------------------------ // If we change walls, we need to reset the ui code for all // of the checkboxes that control the wall flags. //------------------------------------------------------------ if (wd->old_wall_num != Cursegp->sides[Curside].wall_num) { if ( Cursegp->sides[Curside].wall_num != -1) { wall *w = &Walls[Cursegp->sides[Curside].wall_num]; ui_checkbox_check(wd->doorFlag[0], w->flags & WALL_DOOR_LOCKED); ui_checkbox_check(wd->doorFlag[1], w->flags & WALL_DOOR_AUTO); ui_checkbox_check(wd->doorFlag[2], w->flags & WALL_ILLUSION_OFF); ui_radio_set_value(wd->keyFlag[0], w->keys & KEY_NONE); ui_radio_set_value(wd->keyFlag[1], w->keys & KEY_BLUE); ui_radio_set_value(wd->keyFlag[2], w->keys & KEY_RED); ui_radio_set_value(wd->keyFlag[3], w->keys & KEY_GOLD); } } //------------------------------------------------------------ // If any of the checkboxes that control the wallflags are set, then // update the corresponding wall flag. //------------------------------------------------------------ if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { if (GADGET_PRESSED(wd->doorFlag[0])) { if ( wd->doorFlag[0]->flag == 1 ) Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_LOCKED; else Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_LOCKED; rval = 1; } else if (GADGET_PRESSED(wd->doorFlag[1])) { if ( wd->doorFlag[1]->flag == 1 ) Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_AUTO; else Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_AUTO; rval = 1; } //------------------------------------------------------------ // If any of the radio buttons that control the mode are set, then // update the corresponding key. //------------------------------------------------------------ for ( i=0; i < 4; i++ ) { if (GADGET_PRESSED(wd->keyFlag[i])) { Walls[Cursegp->sides[Curside].wall_num].keys = 1<doorFlag[i], 0); for ( i=0; i < 4; i++ ) ui_radio_set_value(wd->keyFlag[i], 0); } if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_ILLUSION) { if (GADGET_PRESSED(wd->doorFlag[2])) { if ( wd->doorFlag[2]->flag == 1 ) Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_ILLUSION_OFF; else Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_ILLUSION_OFF; rval = 1; } } else for ( i=2; i < 3; i++ ) if (wd->doorFlag[i]->flag == 1) { wd->doorFlag[i]->flag = 0; // Tells ui that this button isn't checked wd->doorFlag[i]->status = 1; // Tells ui to redraw button } //------------------------------------------------------------ // Draw the wall in the little 64x64 box //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { // A simple frame time counter for animating the walls... Temp = timer_query(); DeltaTime = Temp - wd->time; gr_set_current_canvas( wd->wallViewBox->canvas ); if (Cursegp->sides[Curside].wall_num != -1) { type = Walls[Cursegp->sides[Curside].wall_num].type; if ((type == WALL_DOOR) || (type == WALL_BLASTABLE)) { if (DeltaTime > ((F1_0*200)/1000)) { wd->framenum++; wd->time = Temp; } if (wd->framenum >= WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].num_frames) wd->framenum=0; PIGGY_PAGE_IN(Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[wd->framenum]]); gr_ubitmap(0,0, &GameBitmaps[Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[wd->framenum]].index]); } else { if (type == WALL_OPEN) gr_clear_canvas( CBLACK ); else { if (Cursegp->sides[Curside].tmap_num2 > 0) gr_ubitmap(0,0, texmerge_get_cached_bitmap( Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2)); else { PIGGY_PAGE_IN(Textures[Cursegp->sides[Curside].tmap_num]); gr_ubitmap(0,0, &GameBitmaps[Textures[Cursegp->sides[Curside].tmap_num].index]); } } } } else gr_clear_canvas( CGREY ); } //------------------------------------------------------------ // If anything changes in the ui system, redraw all the text that // identifies this wall. //------------------------------------------------------------ if (event->type == EVENT_UI_DIALOG_DRAW) { if ( Cursegp->sides[Curside].wall_num > -1 ) { ui_dprintf_at( MainWindow, 12, 6, "Wall: %d ", Cursegp->sides[Curside].wall_num); switch (Walls[Cursegp->sides[Curside].wall_num].type) { case WALL_NORMAL: ui_dprintf_at( MainWindow, 12, 23, " Type: Normal " ); break; case WALL_BLASTABLE: ui_dprintf_at( MainWindow, 12, 23, " Type: Blastable" ); break; case WALL_DOOR: ui_dprintf_at( MainWindow, 12, 23, " Type: Door " ); ui_dprintf_at( MainWindow, 223, 6, "%s", WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].filename); break; case WALL_ILLUSION: ui_dprintf_at( MainWindow, 12, 23, " Type: Illusion " ); break; case WALL_OPEN: ui_dprintf_at( MainWindow, 12, 23, " Type: Open " ); break; case WALL_CLOSED: ui_dprintf_at( MainWindow, 12, 23, " Type: Closed " ); break; default: ui_dprintf_at( MainWindow, 12, 23, " Type: Unknown " ); break; } if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) ui_dprintf_at( MainWindow, 223, 6, " " ); ui_dprintf_at( MainWindow, 12, 40, " Clip: %d ", Walls[Cursegp->sides[Curside].wall_num].clip_num ); ui_dprintf_at( MainWindow, 12, 57, " Trigger: %d ", Walls[Cursegp->sides[Curside].wall_num].trigger ); } else { ui_dprintf_at( MainWindow, 12, 6, "Wall: none "); ui_dprintf_at( MainWindow, 12, 23, " Type: none "); ui_dprintf_at( MainWindow, 12, 40, " Clip: none "); ui_dprintf_at( MainWindow, 12, 57, " Trigger: none "); } } if (ui_button_any_drawn || (wd->old_wall_num != Cursegp->sides[Curside].wall_num) ) Update_flags |= UF_WORLD_CHANGED; if (event->type == EVENT_WINDOW_CLOSE) { d_free(wd); MainWindow = NULL; return 0; } if ( GADGET_PRESSED(wd->quitButton) || (keypress==KEY_ESC) ) { close_wall_window(); return 1; } wd->old_wall_num = Cursegp->sides[Curside].wall_num; return rval; } //--------------------------------------------------------------------- // Restore all walls to original status (closed doors, repaired walls) int wall_restore_all() { int i, j; int wall_num; for (i=0;i wall_num) Segments[seg].sides[side].wall_num--; return 1; } //--------------------------------------------------------------------- // Remove a specific side. int wall_remove_side(segment *seg, short side) { int Connectside; segment *csegp; int lower_wallnum; int w, s, t, l, t1; if (IS_CHILD(seg->children[side]) && IS_CHILD(seg->sides[side].wall_num)) { csegp = &Segments[seg->children[side]]; Connectside = find_connect_side(seg, csegp); remove_trigger(seg, side); remove_trigger(csegp, Connectside); // Remove walls 'wall_num' and connecting side 'wall_num' // from Walls array. lower_wallnum = seg->sides[side].wall_num; if (csegp->sides[Connectside].wall_num < lower_wallnum) lower_wallnum = csegp->sides[Connectside].wall_num; if (Walls[lower_wallnum].linked_wall != -1) Walls[Walls[lower_wallnum].linked_wall].linked_wall = -1; if (Walls[lower_wallnum+1].linked_wall != -1) Walls[Walls[lower_wallnum+1].linked_wall].linked_wall = -1; for (w=lower_wallnum;w lower_wallnum+1) Segments[s].sides[w].wall_num -= 2; // Destroy any links to the deleted wall. for (t=0;tsides[side].wall_num = -1; csegp->sides[Connectside].wall_num = -1; Update_flags |= UF_WORLD_CHANGED; return 1; } editor_status( "Can't remove wall. No wall present."); return 0; } //--------------------------------------------------------------------- // Remove a special wall. int wall_remove() { return wall_remove_side(Cursegp, Curside); } //--------------------------------------------------------------------- // Add a wall to curside int wall_add_to_side(segment *segp, int side, sbyte type) { int connectside; segment *csegp; if (add_wall(segp, side)) { csegp = &Segments[segp->children[side]]; connectside = find_connect_side(segp, csegp); Walls[segp->sides[side].wall_num].segnum = segp-Segments; Walls[csegp->sides[connectside].wall_num].segnum = csegp-Segments; Walls[segp->sides[side].wall_num].sidenum = side; Walls[csegp->sides[connectside].wall_num].sidenum = connectside; Walls[segp->sides[side].wall_num].flags = 0; Walls[csegp->sides[connectside].wall_num].flags = 0; Walls[segp->sides[side].wall_num].type = type; Walls[csegp->sides[connectside].wall_num].type = type; // Walls[segp->sides[side].wall_num].trigger = -1; // Walls[csegp->sides[connectside].wall_num].trigger = -1; Walls[segp->sides[side].wall_num].clip_num = -1; Walls[csegp->sides[connectside].wall_num].clip_num = -1; Walls[segp->sides[side].wall_num].keys = KEY_NONE; Walls[csegp->sides[connectside].wall_num].keys = KEY_NONE; if (type == WALL_BLASTABLE) { Walls[segp->sides[side].wall_num].hps = WALL_HPS; Walls[csegp->sides[connectside].wall_num].hps = WALL_HPS; //Walls[segp->sides[side].wall_num].clip_num = 0; //Walls[csegp->sides[connectside].wall_num].clip_num = 0; } if (type != WALL_DOOR) { segp->sides[side].tmap_num2 = 0; csegp->sides[connectside].tmap_num2 = 0; } if (type == WALL_DOOR) { Walls[segp->sides[side].wall_num].flags |= WALL_DOOR_AUTO; Walls[csegp->sides[connectside].wall_num].flags |= WALL_DOOR_AUTO; Walls[segp->sides[side].wall_num].clip_num = Current_door_type; Walls[csegp->sides[connectside].wall_num].clip_num = Current_door_type; } //Update_flags |= UF_WORLD_CHANGED; //return 1; // return NextWall(); //assign a clip num return wall_assign_door(Current_door_type); } else { editor_status( "Cannot add wall here, no children" ); return 0; } } //--------------------------------------------------------------------- // Add a wall to markedside int wall_add_to_markedside(sbyte type) { int Connectside; segment *csegp; if (add_wall(Markedsegp, Markedside)) { int wall_num, cwall_num; csegp = &Segments[Markedsegp->children[Markedside]]; Connectside = find_connect_side(Markedsegp, csegp); wall_num = Markedsegp->sides[Markedside].wall_num; cwall_num = csegp->sides[Connectside].wall_num; Walls[wall_num].segnum = Markedsegp-Segments; Walls[cwall_num].segnum = csegp-Segments; Walls[wall_num].sidenum = Markedside; Walls[cwall_num].sidenum = Connectside; Walls[wall_num].flags = 0; Walls[cwall_num].flags = 0; Walls[wall_num].type = type; Walls[cwall_num].type = type; Walls[wall_num].trigger = -1; Walls[cwall_num].trigger = -1; Walls[wall_num].clip_num = -1; Walls[cwall_num].clip_num = -1; Walls[wall_num].keys = KEY_NONE; Walls[cwall_num].keys = KEY_NONE; if (type == WALL_BLASTABLE) { Walls[wall_num].hps = WALL_HPS; Walls[cwall_num].hps = WALL_HPS; Walls[wall_num].clip_num = 0; Walls[cwall_num].clip_num = 0; } if (type != WALL_DOOR) { Markedsegp->sides[Markedside].tmap_num2 = 0; csegp->sides[Connectside].tmap_num2 = 0; } Update_flags |= UF_WORLD_CHANGED; return 1; } else { editor_status( "Cannot add wall here, no children" ); return 0; } } int wall_add_door_flag(sbyte flag) { int Connectside; segment *csegp; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("Cannot change flag. No wall at Curside."); return 0; } if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) { editor_status("Cannot change flag. No door at Curside."); return 0; } csegp = &Segments[Cursegp->children[Curside]]; Connectside = find_connect_side(Cursegp, csegp); Walls[Cursegp->sides[Curside].wall_num].flags |= flag; Walls[csegp->sides[Connectside].wall_num].flags |= flag; Update_flags |= UF_ED_STATE_CHANGED; return 1; } int wall_remove_door_flag(sbyte flag) { int Connectside; segment *csegp; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("Cannot change flag. No wall at Curside."); return 0; } if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) { editor_status("Cannot change flag. No door at Curside."); return 0; } csegp = &Segments[Cursegp->children[Curside]]; Connectside = find_connect_side(Cursegp, csegp); Walls[Cursegp->sides[Curside].wall_num].flags &= ~flag; Walls[csegp->sides[Connectside].wall_num].flags &= ~flag; Update_flags |= UF_ED_STATE_CHANGED; return 1; } int bind_wall_to_control_center() { int link_num; int i; if (Cursegp->sides[Curside].wall_num == -1) { editor_status("No wall at Curside."); return 0; } link_num = ControlCenterTriggers.num_links; for (i=0;isides[Curside].wall_num != -1) w1 = &Walls[Cursegp->sides[Curside].wall_num]; if (Markedsegp->sides[Markedside].wall_num != -1) w2 = &Walls[Markedsegp->sides[Markedside].wall_num]; if (!w1 || w1->type != WALL_DOOR) { editor_status("Curseg/curside is not a door"); return 0; } if (!w2 || w2->type != WALL_DOOR) { editor_status("Markedseg/markedside is not a door"); return 0; } if (w1->linked_wall != -1) editor_status("Curseg/curside is already linked"); if (w2->linked_wall != -1) editor_status("Markedseg/markedside is already linked"); w1->linked_wall = w2-Walls; w2->linked_wall = w1-Walls; return 1; } int wall_unlink_door() { wall *w1=NULL; if (Cursegp->sides[Curside].wall_num != -1) w1 = &Walls[Cursegp->sides[Curside].wall_num]; if (!w1 || w1->type != WALL_DOOR) { editor_status("Curseg/curside is not a door"); return 0; } if (w1->linked_wall == -1) editor_status("Curseg/curside is not linked"); Assert(Walls[w1->linked_wall].linked_wall == w1-Walls); Walls[w1->linked_wall].linked_wall = -1; w1->linked_wall = -1; return 1; } #define DIAGNOSTIC_MESSAGE_MAX 150 int check_walls() { int w, seg, side, wall_count, trigger_count; int w1; count_wall CountedWalls[MAX_WALLS]; char Message[DIAGNOSTIC_MESSAGE_MAX]; int matcen_num; wall_count = 0; for (seg=0;seg<=Highest_segment_index;seg++) if (Segments[seg].segnum != -1) { // Check fuelcenters matcen_num = Segment2s[seg].matcen_num; if (matcen_num == 0) if (RobotCenters[0].segnum != seg) { Segment2s[seg].matcen_num = -1; } if (matcen_num > -1) if (RobotCenters[matcen_num].segnum != seg) { RobotCenters[matcen_num].segnum = seg; } for (side=0;side #include #include #include #include "physfsx.h" #include "key.h" #include "gr.h" #include "bm.h" // for MAX_TEXTURES #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "textures.h" #include "object.h" #include "gamemine.h" #include "gamesave.h" #include "gameseg.h" #include "ui.h" // Because texpage.h need UI_DIALOG type #include "texpage.h" // For texpage_goto_first #include "medwall.h" #include "switch.h" #include "fuelcen.h" #define REMOVE_EXT(s) (*(strchr( (s), '.' ))='\0') int CreateDefaultNewSegment(); int save_mine_data(PHYSFS_file * SaveFile); static char current_tmap_list[MAX_TEXTURES][13]; int New_file_format_save = 1; // Converts descent 2 texture numbers back to descent 1 texture numbers. // Only works properly when the full Descent 1 texture set (descent.pig) is available. short convert_to_d1_tmap_num(short tmap_num) { switch (tmap_num) { case 137: return 0; // grey rock001 case 0: return 1; case 1: return 3; // rock021 case 270: return 6; // blue rock002 case 271: return 7; // yellow rock265 case 2: return 8; // rock004 case 138: return 9; // purple (devil:179) case 272: return 10; // red rock006 case 139: return 11; case 140: return 12; //devil:43 case 3: return 13; // rock014 case 4: return 14; // rock019 case 5: return 15; // rock020 case 6: return 16; case 141: return 17; case 129: return 18; case 7: return 19; case 142: return 20; case 143: return 21; case 8: return 22; case 9: return 23; case 10: return 24; case 144: return 25; //devil:35 case 11: return 26; case 12: return 27; case 145: return 28; //devil:43 //range handled by default case, returns 13..21 (- 16) case 163: return 38; //devil:27 case 147: return 39; //31 case 22: return 40; case 266: return 41; case 23: return 42; case 24: return 43; case 136: return 44; //devil:135 case 25: return 45; case 26: return 46; case 27: return 47; case 28: return 48; case 146: return 49; //devil:60 case 131: return 50; //devil:138 case 29: return 51; case 30: return 52; case 31: return 53; case 32: return 54; case 165: return 55; //devil:193 case 33: return 56; case 132: return 57; //devil:119 // range handled by default case, returns 58..88 (+ 24) case 197: return 88; //devil:15 // range handled by default case, returns 89..106 (- 25) case 167: return 132; // range handled by default case, returns 107..114 (- 26) case 148: return 141; //devil:106 case 115: return 142; case 116: return 143; case 117: return 144; case 118: return 145; case 119: return 146; case 149: return 147; case 120: return 148; case 121: return 149; case 122: return 150; case 123: return 151; case 124: return 152; case 125: return 153; // rock263 case 150: return 154; case 126: return 155; // rock269 case 200: return 156; // metl002 case 201: return 157; // metl003 case 186: return 158; //devil:227 case 190: return 159; //devil:246 case 151: return 160; case 152: return 161; //devil:206 case 202: return 162; case 203: return 163; case 204: return 164; case 205: return 165; case 206: return 166; case 153: return 167; case 154: return 168; case 155: return 169; case 156: return 170;//206; case 157: return 171;//227; case 207: return 172; case 208: return 173; case 158: return 174; case 159: return 175; // range handled by default case, returns 209..217 (+ 33) case 160: return 185; // range handled by default case, returns 218..224 (+ 32) case 161: return 193; case 162: return 194;//206; case 166: return 195; case 225: return 196; case 226: return 197; case 193: return 198; case 168: return 199; //devil:204 case 169: return 200; //devil:204 case 227: return 201; case 170: return 202; //devil:227 // range handled by default case, returns 228..234 (+ 25) case 171: return 210; //devil:242 case 172: return 211; //devil:240 // range handled by default case, returns 235..242 (+ 23) case 173: return 220; //devil:240 case 243: return 221; case 244: return 222; case 174: return 223; case 245: return 224; case 246: return 225; case 164: return 226;//247; matching names but not matching textures case 179: return 227; //devil:181 case 196: return 228;//248; matching names but not matching textures case 175: return 229; //devil:66 case 176: return 230; //devil:66 // range handled by default case, returns 249..257 (+ 18) case 177: return 240; //devil:132 case 130: return 241; //devil:131 case 178: return 242; //devil:15 case 180: return 243; //devil:38 case 258: return 244; case 259: return 245; case 181: return 246; // grate metl127 case 260: return 247; case 261: return 248; case 262: return 249; case 340: return 250; // white doorframe metl126 case 412: return 251; // red doorframe metl133 case 410: return 252; // blue doorframe metl134 case 411: return 253; // yellow doorframe metl135 case 263: return 254; // metl136 case 264: return 255; // metl139 case 265: return 256; // metl140 case 182: return 257;//246; brig001 case 183: return 258;//246; brig002 case 184: return 259;//246; brig003 case 185: return 260;//246; brig004 case 273: return 261; // exit01 case 274: return 262; // exit02 case 187: return 263; // ceil001 case 275: return 264; // ceil002 case 276: return 265; // ceil003 case 188: return 266; //devil:291 // range handled by default case, returns 277..291 (+ 10) case 293: return 282; case 189: return 283; case 295: return 284; case 296: return 285; case 298: return 286; // range handled by default case, returns 300..310 (+ 13) case 191: return 298; // devil:374 misc010 // range handled by default case, returns 311..326 (+ 12) case 192: return 315; // bad producer misc044 // range handled by default case, returns 327..337 (+ 11) case 352: return 327; // arw01 case 353: return 328; // misc17 case 354: return 329; // fan01 case 380: return 330; // mntr04 case 379: return 331;//373; matching names but not matching textures case 355: return 332;//344; matching names but not matching textures case 409: return 333; // lava misc11 //devil:404 case 356: return 334; // ctrl04 case 357: return 335; // ctrl01 case 358: return 336; // ctrl02 case 359: return 337; // ctrl03 case 360: return 338; // misc14 case 361: return 339; // producer misc16 case 362: return 340; // misc049 case 364: return 341; // misc060 case 363: return 342; // blown01 case 366: return 343; // misc061 case 365: return 344; case 368: return 345; case 376: return 346; case 370: return 347; case 367: return 348; case 372: return 349; case 369: return 350; case 374: return 351;//429; matching names but not matching textures case 375: return 352;//387; matching names but not matching textures case 371: return 353; case 377: return 354;//425; matching names but not matching textures case 408: return 355; case 378: return 356; // lava02 case 383: return 357;//384; matching names but not matching textures case 384: return 358;//385; matching names but not matching textures case 385: return 359;//386; matching names but not matching textures case 386: return 360; case 387: return 361; case 194: return 362; // mntr04b (devil: -1) case 388: return 363; case 391: return 364; case 392: return 365; case 393: return 366; case 394: return 367; case 395: return 368; case 396: return 369; case 195: return 370; // mntr04d (devil: -1) // range 371..584 handled by default case (wall01 and door frames) default: // ranges: if (tmap_num >= 13 && tmap_num <= 21) return tmap_num + 16; if (tmap_num >= 34 && tmap_num <= 63) return tmap_num + 24; if (tmap_num >= 64 && tmap_num <= 106) return tmap_num + 25; if (tmap_num >= 107 && tmap_num <= 114) return tmap_num + 26; if (tmap_num >= 209 && tmap_num <= 217) return tmap_num - 33; if (tmap_num >= 218 && tmap_num <= 224) return tmap_num - 32; if (tmap_num >= 228 && tmap_num <= 234) return tmap_num - 25; if (tmap_num >= 235 && tmap_num <= 242) return tmap_num - 23; if (tmap_num >= 249 && tmap_num <= 257) return tmap_num - 18; if (tmap_num >= 277 && tmap_num <= 291) return tmap_num - 10; if (tmap_num >= 300 && tmap_num <= 310) return tmap_num - 13; if (tmap_num >= 311 && tmap_num <= 326) return tmap_num - 12; if (tmap_num >= 327 && tmap_num <= 337) return tmap_num - 11; // matching names but not matching textures // wall01 and door frames: if (tmap_num > 434 && tmap_num < 731) { if (New_file_format_save) return tmap_num - 64; // d1 shareware needs special treatment: if (tmap_num < 478) return tmap_num - 68; if (tmap_num < 490) return tmap_num - 73; if (tmap_num < 537) return tmap_num - 91; if (tmap_num < 557) return tmap_num - 104; if (tmap_num < 573) return tmap_num - 111; if (tmap_num < 603) return tmap_num - 117; if (tmap_num < 635) return tmap_num - 141; if (tmap_num < 731) return tmap_num - 147; } { // handle rare case where orientation != 0 short tmap_num_part = tmap_num & TMAP_NUM_MASK; short orient = tmap_num & ~TMAP_NUM_MASK; if (orient != 0) return orient | convert_to_d1_tmap_num(tmap_num_part); else { Warning("can't convert unknown texture #%d to descent 1.\n", tmap_num_part); return tmap_num; } } } } // ----------------------------------------------------------------------------- // Save mine will: // 1. Write file info, header info, editor info, vertex data, segment data, // and new_segment in that order, marking their file offset. // 2. Go through all the fields and fill in the offset, size, and sizeof // values in the headers. int med_save_mine(char * filename) { PHYSFS_file *SaveFile; char ErrorMessage[256]; SaveFile = PHYSFSX_openWriteBuffered( filename ); if (!SaveFile) { #if 0 //ndef __linux__ char fname[20]; d_splitpath( filename, NULL, NULL, fname, NULL ); sprintf( ErrorMessage, \ "ERROR: Cannot write to '%s'.\nYou probably need to check out a locked\nversion of the file. You should save\nthis under a different filename, and then\ncheck out a locked copy by typing\n\'co -l %s.lvl'\nat the DOS prompt.\n" , filename, fname); #endif sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename ); ui_messagebox( -2, -2, 1, ErrorMessage, "Ok" ); return 1; } save_mine_data(SaveFile); //==================== CLOSE THE FILE ============================= PHYSFS_close(SaveFile); return 0; } // ----------------------------------------------------------------------------- // saves to an already-open file int save_mine_data(PHYSFS_file * SaveFile) { int header_offset, editor_offset, vertex_offset, segment_offset, texture_offset, walls_offset, triggers_offset; //, links_offset; int newseg_verts_offset; int newsegment_offset; int i; med_compress_mine(); warn_if_concave_segments(); for (i=0;i>nbits); if( int_value > 0x7fff ) { short_value = 0x7fff; } else if( int_value < -0x7fff ) { short_value = -0x7fff; } else short_value = (short)int_value; PHYSFS_writeSLE16(SaveFile, short_value); } //version of dump for unsigned values void dump_fix_as_ushort( fix value, int nbits, PHYSFS_file *SaveFile ) { uint int_value=0; ushort short_value; if (value < 0) { Int3(); //hey---show this to Matt value = 0; } else int_value = value >> nbits; if( int_value > 0xffff ) { short_value = 0xffff; } else short_value = int_value; PHYSFS_writeULE16(SaveFile, short_value); } void write_children(segment *seg, ubyte bit_mask, PHYSFS_file *SaveFile) { int bit; for (bit = 0; bit < MAX_SIDES_PER_SEGMENT; bit++) { if (bit_mask & (1 << bit)) PHYSFS_writeSLE16(SaveFile, seg->children[bit]); } } void write_verts(segment *seg, PHYSFS_file *SaveFile) { int i; for (i = 0; i < MAX_VERTICES_PER_SEGMENT; i++) PHYSFS_writeSLE16(SaveFile, seg->verts[i]); } void write_special(segment2 *seg2, ubyte bit_mask, PHYSFS_file *SaveFile) { if (bit_mask & (1 << MAX_SIDES_PER_SEGMENT)) { PHYSFSX_writeU8(SaveFile, seg2->special); PHYSFSX_writeU8(SaveFile, seg2->matcen_num); PHYSFS_writeSLE16(SaveFile, seg2->value); } } // ----------------------------------------------------------------------------- // saves compiled mine data to an already-open file... int save_mine_data_compiled(PHYSFS_file *SaveFile) { short i, segnum, sidenum; ubyte version = COMPILED_MINE_VERSION; ubyte bit_mask = 0; med_compress_mine(); warn_if_concave_segments(); if (Highest_segment_index >= MAX_SEGMENTS) { char message[128]; sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_SEGMENTS); ui_messagebox( -2, -2, 1, message, "Ok" ); } if (Highest_vertex_index >= MAX_VERTICES) { char message[128]; sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_VERTICES); ui_messagebox( -2, -2, 1, message, "Ok" ); } //=============================== Writing part ============================== PHYSFSX_writeU8(SaveFile, version); // 1 byte = compiled version if (New_file_format_save) { PHYSFS_writeSLE16(SaveFile, Num_vertices); // 2 bytes = Num_vertices PHYSFS_writeSLE16(SaveFile, Num_segments); // 2 bytes = Num_segments } else { PHYSFS_writeSLE32(SaveFile, Num_vertices); // 4 bytes = Num_vertices PHYSFS_writeSLE32(SaveFile, Num_segments); // 4 bytes = Num_segments } for (i = 0; i < Num_vertices; i++) PHYSFSX_writeVector(SaveFile, &(Vertices[i])); for (segnum = 0; segnum < Num_segments; segnum++) { segment *seg = &Segments[segnum]; segment2 *seg2 = &Segment2s[segnum]; for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { if (seg->children[sidenum] != -1) bit_mask |= (1 << sidenum); } if ((seg2->special != 0) || (seg2->matcen_num != 0) || (seg2->value != 0)) bit_mask |= (1 << MAX_SIDES_PER_SEGMENT); if (New_file_format_save) PHYSFSX_writeU8(SaveFile, bit_mask); else bit_mask = 0x7F; if (Gamesave_current_version == 5) // d2 SHAREWARE level { write_special(seg2, bit_mask, SaveFile); write_verts(seg, SaveFile); write_children(seg, bit_mask, SaveFile); } else { write_children(seg, bit_mask, SaveFile); write_verts(seg, SaveFile); if (Gamesave_current_version <= 1) // descent 1 level write_special(seg2, bit_mask, SaveFile); } if (Gamesave_current_version <= 5) // descent 1 thru d2 SHAREWARE level dump_fix_as_ushort(seg2->static_light, 4, SaveFile); // Write the walls as a 6 byte array bit_mask = 0; for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { uint wallnum; if (seg->sides[sidenum].wall_num >= 0) { bit_mask |= (1 << sidenum); wallnum = seg->sides[sidenum].wall_num; Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!! (void)wallnum; } } if (New_file_format_save) PHYSFSX_writeU8(SaveFile, bit_mask); else bit_mask = 0x3F; for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { if (bit_mask & (1 << sidenum)) PHYSFSX_writeU8(SaveFile, seg->sides[sidenum].wall_num); } for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { if ((seg->children[sidenum] == -1) || (seg->sides[sidenum].wall_num != -1)) { ushort tmap_num, tmap_num2; tmap_num = seg->sides[sidenum].tmap_num; tmap_num2 = seg->sides[sidenum].tmap_num2; if (Gamesave_current_version <= 3) // convert texture numbers back to d1 { tmap_num = convert_to_d1_tmap_num(tmap_num); if (tmap_num2) tmap_num2 = convert_to_d1_tmap_num(tmap_num2); } if (tmap_num2 != 0 && New_file_format_save) tmap_num |= 0x8000; PHYSFS_writeSLE16(SaveFile, tmap_num); if (tmap_num2 != 0 || !New_file_format_save) PHYSFS_writeSLE16(SaveFile, tmap_num2); for (i = 0; i < 4; i++) { dump_fix_as_short(seg->sides[sidenum].uvls[i].u, 5, SaveFile); dump_fix_as_short(seg->sides[sidenum].uvls[i].v, 5, SaveFile); dump_fix_as_ushort(seg->sides[sidenum].uvls[i].l, 1, SaveFile); } } } } if (Gamesave_current_version > 5) for (i = 0; i < Num_segments; i++) segment2_write(&Segment2s[i], SaveFile); return 0; } dxx-rebirth-0.58.1-d2x/editor/objpage.c000066400000000000000000000254631217717237500176270ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * object selection stuff. * */ #include #include #include "inferno.h" #include "screens.h" // For GAME_SCREEN????? #include "editor.h" // For TMAP_CURBOX?????? #include "gr.h" // For canves, font stuff #include "ui.h" // For UI_GADGET stuff #include "object.h" // For robot_bms #include "dxxerror.h" #include "objpage.h" #include "bm.h" #include "player.h" #include "piggy.h" #include "cntrlcen.h" #define OBJS_PER_PAGE 8 static UI_GADGET_USERBOX * ObjBox[OBJS_PER_PAGE]; static UI_GADGET_USERBOX * ObjCurrent; static int ObjectPage = 0; #include "vecmat.h" #include "3d.h" #include "polyobj.h" #include "texmap.h" #include "hostage.h" #include "powerup.h" vms_angvec objpage_view_orient; fix objpage_view_dist; //this is bad to have the extern, but this snapshot stuff is special extern int polyobj_lighting; //canvas set void draw_object_picture(int id, vms_angvec *orient_angles, int type) { if (id >= Num_object_subtypes) return; switch (type) { case OBJ_HOSTAGE: PIGGY_PAGE_IN(Vclip[Hostage_vclip_num[id]].frames[0]); gr_bitmap(0,0,&GameBitmaps[Vclip[Hostage_vclip_num[id]].frames[0].index]); break; case OBJ_POWERUP: if ( Powerup_info[id].vclip_num > -1 ) { PIGGY_PAGE_IN(Vclip[Powerup_info[id].vclip_num].frames[0]); gr_bitmap(0,0,&GameBitmaps[Vclip[Powerup_info[id].vclip_num].frames[0].index]); } break; case OBJ_PLAYER: draw_model_picture(Player_ship->model_num,orient_angles); // Draw a poly model below break; case OBJ_ROBOT: draw_model_picture(Robot_info[id].model_num,orient_angles); // Draw a poly model below break; case OBJ_CNTRLCEN: draw_model_picture(get_reactor_model_number(id), orient_angles); break; case OBJ_CLUTTER: draw_model_picture(Reactors[id].model_num, orient_angles); break; default: //Int3(); // Invalid type!!! return; } } void redraw_current_object() { grs_canvas * cc; cc = grd_curcanv; gr_set_current_canvas(ObjCurrent->canvas); draw_object_picture(Cur_object_id, &objpage_view_orient, Cur_object_type); gr_set_current_canvas(cc); } void gr_label_box( int i) { gr_clear_canvas(BM_XRGB(0,0,0)); draw_object_picture(i, &objpage_view_orient, Cur_object_type); // char s[20]; // sprintf( s, " %d ", i ); // gr_clear_canvas( BM_XRGB(0,15,0) ); // gr_set_fontcolor( CWHITE, BM_XRGB(0,15,0) ); // ui_string_centered( grd_curcanv->cv_bitmap.bm_w/2, grd_curcanv->cv_bitmap.bm_h/2, Description[i] ); } int objpage_goto_first() { int i; ObjectPage=0; for (i=0; icanvas); if (i+ObjectPage*OBJS_PER_PAGE < Num_object_subtypes ) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else gr_clear_canvas( CGREY ); } return 1; } int objpage_goto_last() { int i; ObjectPage=(Num_object_subtypes)/OBJS_PER_PAGE; for (i=0; icanvas); if (i+ObjectPage*OBJS_PER_PAGE < Num_object_subtypes ) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else { gr_clear_canvas( CGREY ); } } return 1; } static int objpage_goto_prev() { int i; if (ObjectPage > 0) { ObjectPage--; for (i=0; icanvas); if (i+ObjectPage*OBJS_PER_PAGE < Num_object_subtypes) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else { gr_clear_canvas( CGREY ); } } } return 1; } static int objpage_goto_next() { int i; if ((ObjectPage+1)*OBJS_PER_PAGE < Num_object_subtypes) { ObjectPage++; for (i=0; icanvas); if (i+ObjectPage*OBJS_PER_PAGE < Num_object_subtypes) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else { gr_clear_canvas( CGREY ); } } } return 1; } int objpage_grab_current(int n) { int i; if ((n < 0) || (n >= Num_object_subtypes)) return 0; ObjectPage = n / OBJS_PER_PAGE; if (ObjectPage*OBJS_PER_PAGE < Num_object_subtypes) { for (i=0; icanvas); if (i + ObjectPage*OBJS_PER_PAGE < Num_object_subtypes) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else { gr_clear_canvas( CGREY ); } } } Cur_object_id = n; gr_set_current_canvas(ObjCurrent->canvas); //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); gr_label_box(Cur_object_id); //objpage_display_name( Texture[Cur_robot_type]->filename ); return 1; } int objpage_goto_next_object() { // there should be a pop-up menu for this switch (Cur_object_type) { case OBJ_ROBOT: Cur_object_type = OBJ_HOSTAGE; Num_object_subtypes = 1; break; case OBJ_HOSTAGE: Cur_object_type = OBJ_PLAYER; Num_object_subtypes = 1; // can have anarchy/coop, but this is handled automatically break; case OBJ_PLAYER: Cur_object_type = OBJ_POWERUP; Num_object_subtypes = N_powerup_types; break; case OBJ_POWERUP: Cur_object_type = OBJ_CNTRLCEN; Num_object_subtypes = get_num_reactor_models(); break; case OBJ_CNTRLCEN: default: Cur_object_type = OBJ_ROBOT; Num_object_subtypes = N_robot_types; break; } objpage_grab_current(0); return 1; } #define OBJBOX_X (TMAPBOX_X) //location of first one #define OBJBOX_Y (OBJCURBOX_Y - 24 ) #define OBJBOX_W 64 #define OBJBOX_H 64 #define DELTA_ANG 0x800 int objpage_increase_pitch() { objpage_view_orient.p += DELTA_ANG; redraw_current_object(); return 1; } int objpage_decrease_pitch() { objpage_view_orient.p -= DELTA_ANG; redraw_current_object(); return 1; } int objpage_increase_heading() { objpage_view_orient.h += DELTA_ANG; redraw_current_object(); return 1; } int objpage_decrease_heading() { objpage_view_orient.h -= DELTA_ANG; redraw_current_object(); return 1; } int objpage_increase_bank() { objpage_view_orient.b += DELTA_ANG; redraw_current_object(); return 1; } int objpage_decrease_bank() { objpage_view_orient.b -= DELTA_ANG; redraw_current_object(); return 1; } int objpage_increase_z() { objpage_view_dist -= 0x8000; redraw_current_object(); return 1; } int objpage_decrease_z() { objpage_view_dist += 0x8000; redraw_current_object(); return 1; } int objpage_reset_orient() { objpage_view_orient.p = 0; objpage_view_orient.b = 0; objpage_view_orient.h = -0x8000; //objpage_view_dist = DEFAULT_VIEW_DIST; redraw_current_object(); return 1; } // INIT TEXTURE STUFF void objpage_init( UI_DIALOG *dlg ) { int i; //Num_total_object_types = N_polygon_models + N_hostage_types + N_powerup_types; //Assert (N_polygon_models < MAX_POLYGON_MODELS); //Assert (Num_total_object_types < MAX_OBJTYPE ); //Assert (N_hostage_types < MAX_HOSTAGE_TYPES ); //Assert (N_powerup_types < MAX_POWERUP_TYPES ); // Assert (N_robot_types < MAX_ROBOTS); ui_add_gadget_button( dlg, OBJCURBOX_X + 00, OBJCURBOX_Y - 27, 30, 20, "<<", objpage_goto_prev ); ui_add_gadget_button( dlg, OBJCURBOX_X + 32, OBJCURBOX_Y - 27, 30, 20, ">>", objpage_goto_next ); ui_add_gadget_button( dlg, OBJCURBOX_X + 00, OBJCURBOX_Y - 54, 30, 20, "B", objpage_goto_first ); ui_add_gadget_button( dlg, OBJCURBOX_X + 32, OBJCURBOX_Y - 54, 30, 20, "E", objpage_goto_last ); ui_add_gadget_button( dlg, OBJCURBOX_X + 25, OBJCURBOX_Y + 62, 22, 13, "P-", objpage_decrease_pitch ); ui_add_gadget_button( dlg, OBJCURBOX_X + 25, OBJCURBOX_Y + 90, 22, 13, "P+", objpage_increase_pitch ); ui_add_gadget_button( dlg, OBJCURBOX_X + 00, OBJCURBOX_Y + 90, 22, 13, "B-", objpage_decrease_bank ); ui_add_gadget_button( dlg, OBJCURBOX_X + 50, OBJCURBOX_Y + 90, 22, 13, "B+", objpage_increase_bank ); ui_add_gadget_button( dlg, OBJCURBOX_X + 00, OBJCURBOX_Y + 76, 22, 13, "H-", objpage_decrease_heading ); ui_add_gadget_button( dlg, OBJCURBOX_X + 50, OBJCURBOX_Y + 76, 22, 13, "H+", objpage_increase_heading ); ui_add_gadget_button( dlg, OBJCURBOX_X + 00, OBJCURBOX_Y + 62, 22, 13, "Z+", objpage_increase_z ); ui_add_gadget_button( dlg, OBJCURBOX_X + 50, OBJCURBOX_Y + 62, 22, 13, "Z-", objpage_decrease_z ); ui_add_gadget_button( dlg, OBJCURBOX_X + 25, OBJCURBOX_Y + 76, 22, 13, "R", objpage_reset_orient ); for (i=0;itype == EVENT_UI_DIALOG_DRAW) { for (i=0; icanvas); if (i+ObjectPage*OBJS_PER_PAGE < Num_object_subtypes) { //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); } else { gr_clear_canvas( CGREY ); } } // Don't reset robot_type when we return to editor. // Cur_robot_type = ObjectPage*OBJS_PER_PAGE; gr_set_current_canvas(ObjCurrent->canvas); //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); gr_label_box(Cur_object_id); //ObjnameCanvas = gr_create_sub_canvas(&grd_curscreen->sc_canvas, OBJCURBOX_X , OBJCURBOX_Y + OBJBOX_H + 10, 100, 20); //gr_set_current_canvas( ObjnameCanvas ); //gr_set_curfont( ui_small_font ); //gr_set_fontcolor( CBLACK, CWHITE ); //objpage_display_name( Texture[Cur_robot_type]->filename ); return 1; } for (i=0; icanvas); //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); gr_label_box(Cur_object_id); //objpage_display_name( Texture[Cur_robot_type]->filename ); return 1; } } return 0; } dxx-rebirth-0.58.1-d2x/editor/segment.c000066400000000000000000001674731217717237500176720ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Interrogation functions for segment data structure. * */ #include #include #include #include #include "key.h" #include "gr.h" #include "inferno.h" #include "segment.h" #include "editor.h" #include "editor/esegment.h" #include "dxxerror.h" #include "object.h" #include "gameseg.h" #include "render.h" #include "game.h" #include "wall.h" #include "switch.h" #include "fuelcen.h" #include "cntrlcen.h" #include "seguvs.h" #include "gameseq.h" #include "medwall.h" #include "hostage.h" int Do_duplicate_vertex_check = 0; // Gets set to 1 in med_create_duplicate_vertex, means to check for duplicate vertices in compress_mine #define BOTTOM_STUFF 0 // Remap all vertices in polygons in a segment through translation table xlate_verts. #if BOTTOM_STUFF void remap_vertices(segment *segp, int *xlate_verts) { int sidenum, facenum, polynum, v; for (sidenum=0; sidenumsides[sidenum].num_faces; facenum++) for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; for (v=0; vnum_vertices; v++) pp->verts[v] = xlate_verts[pp->verts[v]]; } } // Copy everything from sourceside to destside except sourceside->faces[xx].polys[xx].verts void copy_side_except_vertex_ids(side *destside, side *sourceside) { int facenum, polynum, v; destside->num_faces = sourceside->num_faces; destside->tri_edge = sourceside->tri_edge; destside->wall_num = sourceside->wall_num; for (facenum=0; facenumnum_faces; facenum++) { face *destface = &destside->faces[facenum]; face *sourceface = &sourceside->faces[facenum]; destface->num_polys = sourceface->num_polys; destface->normal = sourceface->normal; for (polynum=0; polynumnum_polys; polynum++) { poly *destpoly = &destface->polys[polynum]; poly *sourcepoly = &sourceface->polys[polynum]; destpoly->num_vertices = sourcepoly->num_vertices; destpoly->face_type = sourcepoly->face_type; destpoly->tmap_num = sourcepoly->tmap_num; destpoly->tmap_num2 = sourcepoly->tmap_num2; for (v=0; vnum_vertices; v++) destpoly->uvls[v] = sourcepoly->uvls[v]; } } } // [side] [index] [cur:next] // To remap the vertices on a side after a forward rotation sbyte xlate_previous[6][4][2] = { { {7, 3}, {3, 2}, {2, 6}, {6, 7} }, // remapping left to left { {5, 4}, {4, 0}, {7, 3}, {6, 7} }, // remapping back to top { {5, 4}, {1, 5}, {0, 1}, {4, 0} }, // remapping right to right { {0, 1}, {1, 5}, {2, 6}, {3, 2} }, // remapping front to bottom { {1, 5}, {5, 4}, {6, 7}, {2, 6} }, // remapping bottom to back { {4, 0}, {0, 1}, {3, 2}, {7, 3} }, // remapping top to front }; void remap_vertices_previous(segment *segp, int sidenum) { int v, w, facenum, polynum; for (facenum=0; facenumsides[sidenum].num_faces; facenum++) { for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; for (v=0; vnum_vertices; v++) { for (w=0; w<4; w++) { if (pp->verts[v] == xlate_previous[sidenum][w][0]) { pp->verts[v] = xlate_previous[sidenum][w][1]; break; } } Assert(w<4); // If w == 4, then didn't find current vertex in list, which means xlate_previous table is bogus } } } } sbyte xlate_previous_right[6][4][2] = { { {5, 6}, {6, 7}, {2, 3}, {1, 2} }, // bottom to left { {6, 7}, {7, 4}, {3, 0}, {2, 3} }, // left to top { {7, 4}, {4, 5}, {0, 1}, {3, 0} }, // top to right { {4, 5}, {5, 6}, {1, 2}, {0, 1} }, // right to bottom { {6, 7}, {5, 6}, {4, 5}, {7, 4} }, // back to back { {3, 2}, {0, 3}, {1, 0}, {2, 1} }, // front to front }; void remap_vertices_previous_right(segment *segp, int sidenum) { int v, w, facenum, polynum; for (facenum=0; facenumsides[sidenum].num_faces; facenum++) { for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; for (v=0; vnum_vertices; v++) { for (w=0; w<4; w++) { if (pp->verts[v] == xlate_previous_right[sidenum][w][0]) { pp->verts[v] = xlate_previous_right[sidenum][w][1]; break; } } Assert(w<4); // If w == 4, then didn't find current vertex in list, which means xlate_previous table is bogus } } } } // ----------------------------------------------------------------------------------- // Takes top to front void med_rotate_segment_forward(segment *segp) { segment seg_copy; int i; seg_copy = *segp; seg_copy.verts[0] = segp->verts[4]; seg_copy.verts[1] = segp->verts[0]; seg_copy.verts[2] = segp->verts[3]; seg_copy.verts[3] = segp->verts[7]; seg_copy.verts[4] = segp->verts[5]; seg_copy.verts[5] = segp->verts[1]; seg_copy.verts[6] = segp->verts[2]; seg_copy.verts[7] = segp->verts[6]; seg_copy.children[WFRONT] = segp->children[WTOP]; seg_copy.children[WTOP] = segp->children[WBACK]; seg_copy.children[WBACK] = segp->children[WBOTTOM]; seg_copy.children[WBOTTOM] = segp->children[WFRONT]; seg_copy.sides[WFRONT] = segp->sides[WTOP]; seg_copy.sides[WTOP] = segp->sides[WBACK]; seg_copy.sides[WBACK] = segp->sides[WBOTTOM]; seg_copy.sides[WBOTTOM] = segp->sides[WFRONT]; for (i=0; i<6; i++) remap_vertices_previous(&seg_copy, i); *segp = seg_copy; } // ----------------------------------------------------------------------------------- // Takes top to right void med_rotate_segment_right(segment *segp) { segment seg_copy; int i; seg_copy = *segp; seg_copy.verts[4] = segp->verts[7]; seg_copy.verts[5] = segp->verts[4]; seg_copy.verts[1] = segp->verts[0]; seg_copy.verts[0] = segp->verts[3]; seg_copy.verts[3] = segp->verts[2]; seg_copy.verts[2] = segp->verts[1]; seg_copy.verts[6] = segp->verts[5]; seg_copy.verts[7] = segp->verts[6]; seg_copy.children[WRIGHT] = segp->children[WTOP]; seg_copy.children[WBOTTOM] = segp->children[WRIGHT]; seg_copy.children[WLEFT] = segp->children[WBOTTOM]; seg_copy.children[WTOP] = segp->children[WLEFT]; seg_copy.sides[WRIGHT] = segp->sides[WTOP]; seg_copy.sides[WBOTTOM] = segp->sides[WRIGHT]; seg_copy.sides[WLEFT] = segp->sides[WBOTTOM]; seg_copy.sides[WTOP] = segp->sides[WLEFT]; for (i=0; i<6; i++) remap_vertices_previous_right(&seg_copy, i); *segp = seg_copy; } void make_curside_bottom_side(void) { switch (Curside) { case WRIGHT: med_rotate_segment_right(Cursegp); break; case WTOP: med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); break; case WLEFT: med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); break; case WBOTTOM: break; case WFRONT: med_rotate_segment_forward(Cursegp); break; case WBACK: med_rotate_segment_forward(Cursegp); med_rotate_segment_forward(Cursegp); med_rotate_segment_forward(Cursegp); break; } Update_flags = UF_WORLD_CHANGED; } #endif int ToggleBottom(void) { Render_only_bottom = !Render_only_bottom; Update_flags = UF_WORLD_CHANGED; return 0; } // --------------------------------------------------------------------------------------------- // ---------- Segment interrogation functions ---------- // ---------------------------------------------------------------------------- // Return a pointer to the list of vertex indices for the current segment in vp and // the number of vertices in *nv. void med_get_vertex_list(segment *s,int *nv,int **vp) { *vp = s->verts; *nv = MAX_VERTICES_PER_SEGMENT; } // ------------------------------------------------------------------------------- // Return number of times vertex vi appears in all segments. // This function can be used to determine whether a vertex is used exactly once in // all segments, in which case it can be freely moved because it is not connected // to any other segment. int med_vertex_count(int vi) { int s,v; segment *sp; int count; count = 0; for (s=0; ssegnum != -1) for (v=0; vverts[v] == vi) count++; } return count; } // ------------------------------------------------------------------------------- int is_free_vertex(int vi) { return med_vertex_count(vi) == 1; } // ------------------------------------------------------------------------------- // Move a free vertex in the segment by adding the vector *vofs to its coordinates. // Error handling: // If the point is not free then: // If the point is not valid (probably valid = in 0..7) then: // If adding *vofs will cause a degenerate segment then: // Note, pi is the point index relative to the segment, not an absolute point index. // For example, 3 is always the front upper left vertex. void med_move_vertex(segment *sp, int pi, vms_vector *vofs) { int abspi; Assert((pi >= 0) && (pi <= 7)); // check valid range of point indices. abspi = sp->verts[pi]; // Make sure vertex abspi is free. If it is free, it appears exactly once in Vertices Assert(med_vertex_count(abspi) == 1); Assert(abspi <= MAX_SEGMENT_VERTICES); // Make sure vertex id is not bogus. vm_vec_add(&Vertices[abspi],&Vertices[abspi],vofs); // Here you need to validate the geometry of the segment, which will be quite tricky. // You need to make sure: // The segment is not concave. // None of the sides are concave. validate_segment(sp); } // ------------------------------------------------------------------------------- // Move a free wall in the segment by adding the vector *vofs to its coordinates. // Wall indices: 0/1/2/3/4/5 = left/top/right/bottom/back/front void med_move_wall(segment *sp,int wi, vms_vector *vofs) { const sbyte *vp; int i; Assert( (wi >= 0) && (wi <= 5) ); vp = Side_to_verts[wi]; for (i=0; i<4; i++) { med_move_vertex(sp,*vp,vofs); vp++; } validate_segment(sp); } // ------------------------------------------------------------------------------- // Return true if one fixed point number is very close to another, else return false. int fnear(fix f1, fix f2) { return (abs(f1 - f2) <= FIX_EPSILON); } // ------------------------------------------------------------------------------- int vnear(vms_vector *vp1, vms_vector *vp2) { return fnear(vp1->x, vp2->x) && fnear(vp1->y, vp2->y) && fnear(vp1->z, vp2->z); } // ------------------------------------------------------------------------------- // Add the vertex *vp to the global list of vertices, return its index. // Search until a matching vertex is found (has nearly the same coordinates) or until Num_vertices // vertices have been looked at without a match. If no match, add a new vertex. int med_add_vertex(vms_vector *vp) { int v,free_index; int count; // number of used vertices found, for loops exits when count == Num_vertices // set_vertex_counts(); Assert(Num_vertices < MAX_SEGMENT_VERTICES); count = 0; free_index = -1; for (v=0; (v < MAX_SEGMENT_VERTICES) && (count < Num_vertices); v++) if (Vertex_active[v]) { count++; if (vnear(vp,&Vertices[v])) { return v; } } else if (free_index == -1) free_index = v; // we want free_index to be the first free slot to add a vertex if (free_index == -1) free_index = Num_vertices; while (Vertex_active[free_index] && (free_index < MAX_VERTICES)) free_index++; Assert(free_index < MAX_VERTICES); Vertices[free_index] = *vp; Vertex_active[free_index] = 1; Num_vertices++; if (free_index > Highest_vertex_index) Highest_vertex_index = free_index; return free_index; } // ------------------------------------------------------------------------------------------ // Returns the index of a free segment. // Scans the Segments array. int get_free_segment_number(void) { int segnum; for (segnum=0; segnum Highest_segment_index) Highest_segment_index = segnum; return segnum; } Assert(0); return 0; } // ------------------------------------------------------------------------------- // Create a new segment, duplicating exactly, including vertex ids and children, the passed segment. int med_create_duplicate_segment(segment *sp) { int segnum; segnum = get_free_segment_number(); Segments[segnum] = *sp; return segnum; } // ------------------------------------------------------------------------------- // Add the vertex *vp to the global list of vertices, return its index. // This is the same as med_add_vertex, except that it does not search for the presence of the vertex. int med_create_duplicate_vertex(vms_vector *vp) { int free_index; Assert(Num_vertices < MAX_SEGMENT_VERTICES); Do_duplicate_vertex_check = 1; free_index = Num_vertices; while (Vertex_active[free_index] && (free_index < MAX_VERTICES)) free_index++; Assert(free_index < MAX_VERTICES); Vertices[free_index] = *vp; Vertex_active[free_index] = 1; Num_vertices++; if (free_index > Highest_vertex_index) Highest_vertex_index = free_index; return free_index; } // ------------------------------------------------------------------------------- // Set the vertex *vp at index vnum in the global list of vertices, return its index (just for compatibility). int med_set_vertex(int vnum,vms_vector *vp) { Assert(vnum < MAX_VERTICES); Vertices[vnum] = *vp; // Just in case this vertex wasn't active, mark it as active. if (!Vertex_active[vnum]) { Vertex_active[vnum] = 1; Num_vertices++; if ((vnum > Highest_vertex_index) && (vnum < NEW_SEGMENT_VERTICES)) { Highest_vertex_index = vnum; } } return vnum; } // ------------------------------------------------------------------------------- void create_removable_wall(segment *sp, int sidenum, int tmap_num) { create_walls_on_side(sp, sidenum); sp->sides[sidenum].tmap_num = tmap_num; assign_default_uvs_to_side(sp, sidenum); assign_light_to_side(sp, sidenum); } #if 0 // --------------------------------------------------------------------------------------------- // Orthogonalize matrix smat, returning result in rmat. // Does not modify smat. // Uses Gram-Schmidt process. // See page 172 of Strang, Gilbert, Linear Algebra and its Applications // Matt -- This routine should be moved to the vector matrix library. // It IS legal for smat == rmat. // We should also have the functions: // mat_a = mat_b * scalar; // we now have mat_a = mat_a * scalar; // mat_a = mat_b + mat_c * scalar; // or maybe not, maybe this is not primitive void make_orthogonal(vms_matrix *rmat,vms_matrix *smat) { vms_matrix tmat; vms_vector tvec1,tvec2; float dot; // Copy source matrix to work area. tmat = *smat; // Normalize the three rows of the matrix tmat. vm_vec_normalize(&tmat.xrow); vm_vec_normalize(&tmat.yrow); vm_vec_normalize(&tmat.zrow); // Now, compute the first vector. // This is very easy -- just copy the (normalized) source vector. rmat->zrow = tmat.zrow; // Now, compute the second vector. // From page 172 of Strang, we use the equation: // b' = b - [transpose(q1) * b] * q1 // where: b = the second row of tmat // q1 = the first row of rmat // b' = the second row of rmat // Compute: transpose(q1) * b dot = vm_vec_dotprod(&rmat->zrow,&tmat.yrow); // Compute: b - dot * q1 rmat->yrow.x = tmat.yrow.x - fixmul(dot,rmat->zrow.x); rmat->yrow.y = tmat.yrow.y - fixmul(dot,rmat->zrow.y); rmat->yrow.z = tmat.yrow.z - fixmul(dot,rmat->zrow.z); // Now, compute the third vector. // From page 173 of Strang, we use the equation: // c' = c - (q1*c)*q1 - (q2*c)*q2 // where: c = the third row of tmat // q1 = the first row of rmat // q2 = the second row of rmat // c' = the third row of rmat // Compute: q1*c dot = vm_vec_dotprod(&rmat->zrow,&tmat.xrow); tvec1.x = fixmul(dot,rmat->zrow.x); tvec1.y = fixmul(dot,rmat->zrow.y); tvec1.z = fixmul(dot,rmat->zrow.z); // Compute: q2*c dot = vm_vec_dotprod(&rmat->yrow,&tmat.xrow); tvec2.x = fixmul(dot,rmat->yrow.x); tvec2.y = fixmul(dot,rmat->yrow.y); tvec2.z = fixmul(dot,rmat->yrow.z); vm_vec_sub(&rmat->xrow,vm_vec_sub(&rmat->xrow,&tmat.xrow,&tvec1),&tvec2); } #endif // ------------------------------------------------------------------------------------------ // Given a segment, extract the rotation matrix which defines it. // Do this by extracting the forward, right, up vectors and then making them orthogonal. // In the process of making the vectors orthogonal, favor them in the order forward, up, right. // This means that the forward vector will remain unchanged. void med_extract_matrix_from_segment(segment *sp,vms_matrix *rotmat) { vms_vector forwardvec,upvec; extract_forward_vector_from_segment(sp,&forwardvec); extract_up_vector_from_segment(sp,&upvec); if (((forwardvec.x == 0) && (forwardvec.y == 0) && (forwardvec.z == 0)) || ((upvec.x == 0) && (upvec.y == 0) && (upvec.z == 0))) { *rotmat = vmd_identity_matrix; return; } vm_vector_2_matrix(rotmat,&forwardvec,&upvec,NULL); #if 0 vms_matrix rm; extract_forward_vector_from_segment(sp,&rm.zrow); extract_right_vector_from_segment(sp,&rm.xrow); extract_up_vector_from_segment(sp,&rm.yrow); vm_vec_normalize(&rm.xrow); vm_vec_normalize(&rm.yrow); vm_vec_normalize(&rm.zrow); make_orthogonal(rotmat,&rm); vm_vec_normalize(&rotmat->xrow); vm_vec_normalize(&rotmat->yrow); vm_vec_normalize(&rotmat->zrow); // *rotmat = rm; // include this line (and remove the call to make_orthogonal) if you don't want the matrix orthogonalized #endif } // ------------------------------------------------------------------------------------------ // Given a rotation matrix *rotmat which describes the orientation of a segment // and a side destside, return the rotation matrix which describes the orientation for the side. void set_matrix_based_on_side(vms_matrix *rotmat,int destside) { vms_angvec rotvec,*tmpvec; vms_matrix r1,rtemp; switch (destside) { case WLEFT: tmpvec=vm_angvec_make(&rotvec,0,0,-16384); vm_angles_2_matrix(&r1,&rotvec); vm_matrix_x_matrix(&rtemp,rotmat,&r1); *rotmat = rtemp; break; case WTOP: tmpvec=vm_angvec_make(&rotvec,-16384,0,0); vm_angles_2_matrix(&r1,&rotvec); vm_matrix_x_matrix(&rtemp,rotmat,&r1); *rotmat = rtemp; break; case WRIGHT: tmpvec=vm_angvec_make(&rotvec,0,0,16384); vm_angles_2_matrix(&r1,&rotvec); vm_matrix_x_matrix(&rtemp,rotmat,&r1); *rotmat = rtemp; break; case WBOTTOM: tmpvec=vm_angvec_make(&rotvec,+16384,-32768,0); // bank was -32768, but I think that was an erroneous compensation vm_angles_2_matrix(&r1,&rotvec); vm_matrix_x_matrix(&rtemp,rotmat,&r1); *rotmat = rtemp; break; case WFRONT: tmpvec=vm_angvec_make(&rotvec,0,0,-32768); vm_angles_2_matrix(&r1,&rotvec); vm_matrix_x_matrix(&rtemp,rotmat,&r1); *rotmat = rtemp; break; case WBACK: break; } (void)tmpvec; } // ------------------------------------------------------------------------------------- void change_vertex_occurrences(int dest, int src) { int g,s,v; // Fix vertices in groups for (g=0;ghole) && (!Vertex_active[vert]); vert--) ; if (vert > hole) { // Ok, hole is the index of a hole, vert is the index of a vertex which follows it. // Copy vert into hole, update pointers to it. Vertices[hole] = Vertices[vert]; change_vertex_occurrences(hole, vert); vert--; } } Highest_vertex_index = Num_vertices-1; } // -------------------------------------------------------------------------------------------------- void compress_segments(void) { int hole,seg; if (Highest_segment_index == Num_segments - 1) return; seg = Highest_segment_index; for (hole=0; hole < seg; hole++) if (Segments[hole].segnum == -1) { // found an unused segment which is a hole if a used segment follows (not necessarily immediately) it. for ( ; (seg>hole) && (Segments[seg].segnum == -1); seg--) ; if (seg > hole) { int f,g,l,s,t,w; segment *sp; int objnum; // Ok, hole is the index of a hole, seg is the index of a segment which follows it. // Copy seg into hole, update pointers to it, update Cursegp, Markedsegp if necessary. Segments[hole] = Segments[seg]; Segments[seg].segnum = -1; if (Cursegp == &Segments[seg]) Cursegp = &Segments[hole]; if (Markedsegp == &Segments[seg]) Markedsegp = &Segments[hole]; // Fix segments in groups for (g=0;gchildren[s])) { segment *csegp; csegp = &Segments[sp->children[s]]; // Find out on what side the segment connection to the former seg is on in *csegp. for (t=0; tchildren[t] == seg) { csegp->children[t] = hole; // It used to be connected to seg, so make it connected to hole } } // end for t } // end if } // end for s //Update object segment pointers for (objnum = sp->objects; objnum != -1; objnum = Objects[objnum].next) { Assert(Objects[objnum].segnum == seg); Objects[objnum].segnum = hole; } seg--; } // end if (seg > hole) } // end if Highest_segment_index = Num_segments-1; med_create_new_segment_from_cursegp(); } // ------------------------------------------------------------------------------- // Combine duplicate vertices. // If two vertices have the same coordinates, within some small tolerance, then assign // the same vertex number to the two vertices, freeing up one of the vertices. void med_combine_duplicate_vertices(sbyte *vlp) { int v,w; for (v=0; vsides[s].tmap_num = sseg->sides[s].tmap_num; dseg->sides[s].tmap_num2 = 0; } } // ------------------------------------------------------------------------------------------ // Attach a segment with a rotated orientation. // Return value: // 0 = successful attach // 1 = No room in Segments[]. // 2 = No room in Vertices[]. // 3 = newside != WFRONT -- for now, the new segment must be attached at its (own) front side // 4 = already a face attached on destseg:destside int med_attach_segment_rotated(segment *destseg, segment *newseg, int destside, int newside,vms_matrix *attmat) { const sbyte *dvp; segment *nsp; segment2 *nsp2; int side,v; vms_matrix rotmat,rotmat1,rotmat2,rotmat3,rotmat4; vms_vector vr,vc,tvs[4],xlate_vec; int segnum; vms_vector forvec,upvec; // Return if already a face attached on this side. if (IS_CHILD(destseg->children[destside])) return 4; segnum = get_free_segment_number(); forvec = attmat->fvec; upvec = attmat->uvec; // We are pretty confident we can add the segment. nsp = &Segments[segnum]; nsp2 = &Segment2s[segnum]; nsp->segnum = segnum; nsp->objects = -1; nsp2->matcen_num = -1; // Copy group value. nsp->group = destseg->group; // Add segment to proper group list. if (nsp->group > -1) add_segment_to_group(nsp-Segments, nsp->group); // Copy the texture map ids. copy_tmap_ids(nsp,newseg); // clear all connections for (side=0; sidechildren[side] = -1; nsp->sides[side].wall_num = -1; } // Form the connection destseg->children[destside] = segnum; // destseg->sides[destside].render_flag = 0; nsp->children[newside] = destseg-Segments; // Copy vertex indices of the four vertices forming the joint dvp = Side_to_verts[destside]; // Set the vertex indices for the four vertices forming the front of the new side for (v=0; v<4; v++) nsp->verts[v] = destseg->verts[(int) dvp[v]]; // The other 4 vertices must be created. // Their coordinates are determined by the 4 welded vertices and the vector from front // to back of the original *newseg. // Do lots of hideous matrix stuff, about 3/4 of which could probably be simplified out. med_extract_matrix_from_segment(destseg,&rotmat); // get orientation matrix for destseg (orthogonal rotation matrix) set_matrix_based_on_side(&rotmat,destside); vm_vector_2_matrix(&rotmat1,&forvec,&upvec,NULL); vm_matrix_x_matrix(&rotmat4,&rotmat,&rotmat1); // this is the desired orientation of the new segment med_extract_matrix_from_segment(newseg,&rotmat3); // this is the current orientation of the new segment vm_transpose_matrix(&rotmat3); // get the inverse of the current orientation matrix vm_matrix_x_matrix(&rotmat2,&rotmat4,&rotmat3); // now rotmat2 takes the current segment to the desired orientation // Warning -- look at this line! vm_transpose_matrix(&rotmat2); // added 12:33 pm, 10/01/93 // Compute and rotate the center point of the attaching face. compute_center_point_on_side(&vc,newseg,newside); vm_vec_rotate(&vr,&vc,&rotmat2); // Now rotate the free vertices in the segment for (v=0; v<4; v++) vm_vec_rotate(&tvs[v],&Vertices[newseg->verts[v+4]],&rotmat2); // Now translate the new segment so that the center point of the attaching faces are the same. compute_center_point_on_side(&vc,destseg,destside); vm_vec_sub(&xlate_vec,&vc,&vr); // Create and add the 4 new vertices. for (v=0; v<4; v++) { vm_vec_add2(&tvs[v],&xlate_vec); nsp->verts[v+4] = med_add_vertex(&tvs[v]); } set_vertex_counts(); // Now all the vertices are in place. Create the faces. validate_segment(nsp); // Say to not render at the joint. // destseg->sides[destside].render_flag = 0; // nsp->sides[newside].render_flag = 0; Cursegp = nsp; return 0; } // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // ------------------------------------------------------------------------------------------ void scale_free_vertices(segment *sp,vms_vector *vp,fix scale_factor,int min_side,int max_side) { int i; const sbyte *verts; verts = Side_to_verts[min_side]; for (i=0; i<4; i++) if (is_free_vertex(sp->verts[(int) verts[i]])) { Vertices[sp->verts[(int) verts[i]]].x = fixmul(vp->x,scale_factor)/2; Vertices[sp->verts[(int) verts[i]]].y = fixmul(vp->y,scale_factor)/2; Vertices[sp->verts[(int) verts[i]]].z = fixmul(vp->z,scale_factor)/2; } verts = Side_to_verts[max_side]; for (i=0; i<4; i++) if (is_free_vertex(sp->verts[(int) verts[i]])) { Vertices[sp->verts[(int) verts[i]]].x = fixmul(vp->x,scale_factor)/2; Vertices[sp->verts[(int) verts[i]]].y = fixmul(vp->y,scale_factor)/2; Vertices[sp->verts[(int) verts[i]]].z = fixmul(vp->z,scale_factor)/2; } } // ------------------------------------------------------------------------------------------ // Attach side newside of newseg to side destside of destseg. // Copies *newseg into global array Segments, increments Num_segments. // Forms a weld between the two segments by making the new segment fit to the old segment. // Updates number of faces per side if necessitated by new vertex coordinates. // Updates Cursegp. // Return value: // 0 = successful attach // 1 = No room in Segments[]. // 2 = No room in Vertices[]. // 3 = newside != WFRONT -- for now, the new segment must be attached at its (own) front side // 4 = already a face attached on side newside int med_attach_segment(segment *destseg, segment *newseg, int destside, int newside) { int rval; segment *ocursegp = Cursegp; vms_angvec tang = {0,0,0}; vms_matrix rotmat; vm_angles_2_matrix(&rotmat,&tang); rval = med_attach_segment_rotated(destseg,newseg,destside,newside,&rotmat); med_propagate_tmaps_to_segments(ocursegp,Cursegp,0); med_propagate_tmaps_to_back_side(Cursegp, Side_opposite[newside],0); copy_uvs_seg_to_seg(&New_segment,Cursegp); return rval; } // ------------------------------------------------------------------------------- // Delete a vertex, sort of. // Decrement the vertex count. If the count goes to 0, then the vertex is free (has been deleted). void delete_vertex(int v) { Assert(v < MAX_VERTICES); // abort if vertex is not in array Vertices Assert(Vertex_active[v] >= 1); // abort if trying to delete a non-existent vertex Vertex_active[v]--; } // ------------------------------------------------------------------------------- // Update Num_vertices. // This routine should be called by anyone who calls delete_vertex. It could be called in delete_vertex, // but then it would be called much more often than necessary, and it is a slow routine. void update_num_vertices(void) { int v; // Now count the number of vertices. Num_vertices = 0; for (v=0; v<=Highest_vertex_index; v++) if (Vertex_active[v]) Num_vertices++; } // ------------------------------------------------------------------------------- // Set Vertex_active to number of occurrences of each vertex. // Set Num_vertices. void set_vertex_counts(void) { int s,v; Num_vertices = 0; for (v=0; v<=Highest_vertex_index; v++) Vertex_active[v] = 0; // Count number of occurrences of each vertex. for (s=0; s<=Highest_segment_index; s++) if (Segments[s].segnum != -1) for (v=0; vverts[v]); update_num_vertices(); } // ------------------------------------------------------------------------------- // Delete segment *sp in Segments array. // Return value: // 0 successfully deleted. // 1 unable to delete. int med_delete_segment(segment *sp) { int s,side,segnum; int objnum; segnum = sp-Segments; // Cannot delete segment if only segment. if (Num_segments == 1) return 1; // Don't try to delete if segment doesn't exist. if (sp->segnum == -1) { return 1; } // Delete its refueling center if it has one fuelcen_delete(sp); delete_vertices_in_segment(sp); Num_segments--; // If deleted segment has walls on any side, wipe out the wall. for (side=0; side < MAX_SIDES_PER_SEGMENT; side++) if (sp->sides[side].wall_num != -1) wall_remove_side(sp, side); // Find out what this segment was connected to and break those connections at the other end. for (side=0; side < MAX_SIDES_PER_SEGMENT; side++) if (IS_CHILD(sp->children[side])) { segment *csp; // the connecting segment int s; csp = &Segments[sp->children[side]]; for (s=0; schildren[s] == segnum) { csp->children[s] = -1; // this is the side of connection, break it validate_segment_side(csp,s); // we have converted a connection to a side so validate the segment med_propagate_tmaps_to_back_side(csp,s,0); } Cursegp = csp; med_create_new_segment_from_cursegp(); copy_uvs_seg_to_seg(&New_segment,Cursegp); } sp->segnum = -1; // Mark segment as inactive. // If deleted segment = marked segment, then say there is no marked segment if (sp == Markedsegp) Markedsegp = 0; // If deleted segment = a Group segment ptr, then wipe it out. for (s=0;sgroup > -1) delete_segment_from_group(sp-Segments, sp->group); // If we deleted something which was not connected to anything, must now select a new current segment. if (Cursegp == sp) for (s=0; sobjects != -1) { for (objnum=sp->objects;objnum!=-1;objnum=Objects[objnum].next) { //if an object is in the seg, delete it //if the object is the player, move to new curseg if (objnum == (ConsoleObject-Objects)) { compute_segment_center(&ConsoleObject->pos,Cursegp); obj_relink(objnum,Cursegp-Segments); } else obj_delete(objnum); } } // Make sure everything deleted ok... Assert( sp->objects==-1 ); // If we are leaving many holes in Segments or Vertices, then compress mine, because it is inefficient to be that way // if ((Highest_segment_index > Num_segments+4) || (Highest_vertex_index > Num_vertices+4*8)) // med_compress_mine(); return 0; } // ------------------------------------------------------------------------------------------ // Copy texture maps from sseg to dseg void copy_tmaps_to_segment(segment *dseg, segment *sseg) { int s; for (s=0; ssides[s].type = sseg->sides[s].type; dseg->sides[s].tmap_num = sseg->sides[s].tmap_num; dseg->sides[s].tmap_num2 = sseg->sides[s].tmap_num2; } } // ------------------------------------------------------------------------------------------ // Rotate the segment *seg by the pitch, bank, heading defined by *rot, destructively // modifying its four free vertices in the global array Vertices. // It is illegal to rotate a segment which has connectivity != 1. // Pitch, bank, heading are about the point which is the average of the four points // forming the side of connection. // Return value: // 0 = successful rotation // 1 = Connectivity makes rotation illegal (connected to 0 or 2+ segments) // 2 = Rotation causes degeneracy, such as self-intersecting segment. // 3 = Unable to rotate because not connected to exactly 1 segment. int med_rotate_segment(segment *seg, vms_matrix *rotmat) { segment *destseg; int newside=0,destside,s; int count; int back_side,side_tmaps[MAX_SIDES_PER_SEGMENT]; // Find side of attachment count = 0; for (s=0; schildren[s])) { count++; newside = s; } // Return if passed in segment is connected to other than 1 segment. if (count != 1) return 3; destseg = &Segments[seg->children[newside]]; destside = 0; while ((destseg->children[destside] != seg-Segments) && (destside < MAX_SIDES_PER_SEGMENT)) destside++; // Before deleting the segment, copy its texture maps to New_segment copy_tmaps_to_segment(&New_segment,seg); if (Curside == WFRONT) Curside = WBACK; med_attach_segment_rotated(destseg,&New_segment,destside,AttachSide,rotmat); // Save tmap_num on each side to restore after call to med_propagate_tmaps_to_segments and _back_side // which will change the tmap nums. for (s=0; ssides[s].tmap_num; back_side = Side_opposite[find_connect_side(destseg, seg)]; med_propagate_tmaps_to_segments(destseg, seg,0); med_propagate_tmaps_to_back_side(seg, back_side,0); for (s=0; ssides[s].tmap_num = side_tmaps[s]; return 0; } // ---------------------------------------------------------------------------------------- int med_rotate_segment_ang(segment *seg, vms_angvec *ang) { vms_matrix rotmat; return med_rotate_segment(seg,vm_angles_2_matrix(&rotmat,ang)); } // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // ---------------------------------------------------------------------------- // Compute the sum of the distances between the four pairs of points. // The connections are: // firstv1 : 0 (firstv1+1)%4 : 1 (firstv1+2)%4 : 2 (firstv1+3)%4 : 3 fix seg_seg_vertex_distsum(segment *seg1, int side1, segment *seg2, int side2, int firstv1) { fix distsum; int secondv; distsum = 0; for (secondv=0; secondv<4; secondv++) { int firstv; firstv = (4-secondv + (3 - firstv1)) % 4; distsum += vm_vec_dist(&Vertices[seg1->verts[Side_to_verts[side1][firstv]]],&Vertices[seg2->verts[Side_to_verts[side2][secondv]]]); } return distsum; } // ---------------------------------------------------------------------------- // Determine how to connect two segments together with the least amount of twisting. // Returns vertex index in 0..3 on first segment. Assumed ordering of vertices // on second segment is 0,1,2,3. // So, if return value is 2, connect 2:0 3:1 0:2 1:3. // Theory: // We select an ordering of vertices for connection. For the first pair of vertices to be connected, // compute the vector. For the three remaining pairs of vertices, compute the vectors from one vertex // to the other. Compute the dot products of these vectors with the original vector. Add them up. // The close we are to 3, the better fit we have. Reason: The largest value for the dot product is // 1.0, and this occurs for a parallel set of vectors. int get_index_of_best_fit(segment *seg1, int side1, segment *seg2, int side2) { int firstv; fix min_distance; int best_index=0; min_distance = F1_0*30000; for (firstv=0; firstv<4; firstv++) { fix t; t = seg_seg_vertex_distsum(seg1, side1, seg2, side2, firstv); if (t <= min_distance) { min_distance = t; best_index = firstv; } } return best_index; } #define MAX_VALIDATIONS 50 // ---------------------------------------------------------------------------- // Remap uv coordinates in all sides in segment *sp which have a vertex in vp[4]. // vp contains absolute vertex indices. void remap_side_uvs(segment *sp,int *vp) { int s,i,v; for (s=0; schildren[side1]) || IS_CHILD(seg2->children[side2])) return 2; // Make sure there is no wall there if ((seg1->sides[side1].wall_num != -1) || (seg2->sides[side2].wall_num != -1)) return 2; // We can form the joint. Find the best orientation of vertices. bfi = get_index_of_best_fit(seg1, side1, seg2, side2); vp1 = Side_to_verts[side1]; vp2 = Side_to_verts[side2]; // Make a copy of the list of vertices in seg2 which will be deleted and set the // associated vertex number, so that all occurrences of the vertices can be replaced. for (v=0; v<4; v++) lost_vertices[v] = seg2->verts[(int) vp2[v]]; // Now, for each vertex in lost_vertices, determine which vertex it maps to. for (v=0; v<4; v++) remap_vertices[3 - ((v + bfi) % 4)] = seg1->verts[(int) vp1[v]]; // Now, in all segments, replace all occurrences of vertices in lost_vertices with remap_vertices // Put the one segment we know are being modified into the validation list. // Note: seg1 does not require a full validation, only a validation of the affected side. Its vertices do not move. nv = 1; validation_list[0] = seg2 - Segments; for (v=0; v<4; v++) for (s=0; s<=Highest_segment_index; s++) if (Segments[s].segnum != -1) for (sv=0; svchildren[side1] = seg2 - Segments; seg2->children[side2] = seg1 - Segments; // validate all segments validate_segment_side(seg1,side1); for (s=0; schildren[side] != -1) // then it is not legal to form the brider. // Return: // 0 bridge segment formed // 1 unable to form bridge because one (or both) of the sides is not open. // Note that no new vertices are created by this process. int med_form_bridge_segment(segment *seg1, int side1, segment *seg2, int side2) { segment *bs; const sbyte *sv; int v,bfi,i; if (IS_CHILD(seg1->children[side1]) || IS_CHILD(seg2->children[side2])) return 1; bs = &Segments[get_free_segment_number()]; bs->segnum = bs-Segments; bs->objects = -1; // Copy vertices from seg2 into last 4 vertices of bridge segment. sv = Side_to_verts[side2]; for (v=0; v<4; v++) bs->verts[(3-v)+4] = seg2->verts[(int) sv[v]]; // Copy vertices from seg1 into first 4 vertices of bridge segment. bfi = get_index_of_best_fit(seg1, side1, seg2, side2); sv = Side_to_verts[side1]; for (v=0; v<4; v++) bs->verts[(v + bfi) % 4] = seg1->verts[(int) sv[v]]; // Form connections to children, first initialize all to unconnected. for (i=0; ichildren[i] = -1; bs->sides[i].wall_num = -1; } // Now form connections between segments. bs->children[AttachSide] = seg1 - Segments; bs->children[(int) Side_opposite[AttachSide]] = seg2 - Segments; seg1->children[side1] = bs-Segments; //seg2 - Segments; seg2->children[side2] = bs-Segments; //seg1 - Segments; // Validate bridge segment, and if degenerate, clean up mess. Degenerate_segment_found = 0; validate_segment(bs); if (Degenerate_segment_found) { seg1->children[side1] = -1; seg2->children[side2] = -1; bs->children[AttachSide] = -1; bs->children[(int) Side_opposite[AttachSide]] = -1; if (med_delete_segment(bs)) { Int3(); } editor_status("Bridge segment would be degenerate, not created.\n"); return 1; } else { validate_segment(seg1); // used to only validate side, but segment does more error checking: ,side1); validate_segment(seg2); // ,side2); med_propagate_tmaps_to_segments(seg1,bs,0); editor_status("Bridge segment formed."); warn_if_concave_segment(bs); return 0; } } // ------------------------------------------------------------------------------- // Create a segment given center, dimensions, rotation matrix. // Note that the created segment will always have planar sides and rectangular cross sections. // It will be created with walls on all sides, ie not connected to anything. void med_create_segment(segment *sp,fix cx, fix cy, fix cz, fix length, fix width, fix height, vms_matrix *mp) { int i,f; vms_vector v0,v1,cv; segment2 *sp2; Num_segments++; sp->segnum = 1; // What to put here? I don't know. sp2 = &Segment2s[sp->segnum]; // Form connections to children, of which it has none. for (i=0; ichildren[i] = -1; // sp->sides[i].render_flag = 0; sp->sides[i].wall_num = -1; } sp->group = -1; sp2->matcen_num = -1; // Create relative-to-center vertices, which are the rotated points on the box defined by length, width, height sp->verts[0] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,+height/2,-length/2),mp)); sp->verts[1] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,-height/2,-length/2),mp)); sp->verts[2] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,-height/2,-length/2),mp)); sp->verts[3] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,+height/2,-length/2),mp)); sp->verts[4] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,+height/2,+length/2),mp)); sp->verts[5] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,-height/2,+length/2),mp)); sp->verts[6] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,-height/2,+length/2),mp)); sp->verts[7] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,+height/2,+length/2),mp)); // Now create the vector which is the center of the segment and add that to all vertices. while (!vm_vec_make(&cv,cx,cy,cz)); // Now, add the center to all vertices, placing the segment in 3 space. for (i=0; iverts[i]],&Vertices[sp->verts[i]],&cv); // Set scale vector. // sp->scale.x = width; // sp->scale.y = height; // sp->scale.z = length; // Add faces to all sides. for (f=0; fobjects = -1; //no objects in this segment // Assume nothing special about this segment sp2->special = 0; sp2->value = 0; sp2->static_light = 0; sp2->matcen_num = -1; copy_tmaps_to_segment(sp, &New_segment); assign_default_uvs_to_segment(sp); } // ---------------------------------------------------------------------------------------------- // Create New_segment using a specified scale factor. void med_create_new_segment(vms_vector *scale) { int s,t; vms_vector v0; segment *sp = &New_segment; segment2 *sp2; fix length,width,height; length = scale->z; width = scale->x; height = scale->y; sp->segnum = 1; // What to put here? I don't know. sp2 = &Segment2s[sp->segnum]; // Create relative-to-center vertices, which are the points on the box defined by length, width, height t = Num_vertices; sp->verts[0] = med_set_vertex(NEW_SEGMENT_VERTICES+0,vm_vec_make(&v0,+width/2,+height/2,-length/2)); sp->verts[1] = med_set_vertex(NEW_SEGMENT_VERTICES+1,vm_vec_make(&v0,+width/2,-height/2,-length/2)); sp->verts[2] = med_set_vertex(NEW_SEGMENT_VERTICES+2,vm_vec_make(&v0,-width/2,-height/2,-length/2)); sp->verts[3] = med_set_vertex(NEW_SEGMENT_VERTICES+3,vm_vec_make(&v0,-width/2,+height/2,-length/2)); sp->verts[4] = med_set_vertex(NEW_SEGMENT_VERTICES+4,vm_vec_make(&v0,+width/2,+height/2,+length/2)); sp->verts[5] = med_set_vertex(NEW_SEGMENT_VERTICES+5,vm_vec_make(&v0,+width/2,-height/2,+length/2)); sp->verts[6] = med_set_vertex(NEW_SEGMENT_VERTICES+6,vm_vec_make(&v0,-width/2,-height/2,+length/2)); sp->verts[7] = med_set_vertex(NEW_SEGMENT_VERTICES+7,vm_vec_make(&v0,-width/2,+height/2,+length/2)); Num_vertices = t; // sp->scale = *scale; // Form connections to children, of which it has none, init faces and tmaps. for (s=0; schildren[s] = -1; // sp->sides[s].render_flag = 0; sp->sides[s].wall_num = -1; create_walls_on_side(sp,s); sp->sides[s].tmap_num = s; // assign some stupid old tmap to this side. sp->sides[s].tmap_num2 = 0; } Seg_orientation.p = 0; Seg_orientation.b = 0; Seg_orientation.h = 0; sp->objects = -1; //no objects in this segment assign_default_uvs_to_segment(sp); // Assume nothing special about this segment sp2->special = 0; sp2->value = 0; sp2->static_light = 0; sp2->matcen_num = -1; } // ------------------------------------------------------------------------------- void med_create_new_segment_from_cursegp(void) { vms_vector scalevec; vms_vector uvec, rvec, fvec; med_extract_up_vector_from_segment_side(Cursegp, Curside, &uvec); med_extract_right_vector_from_segment_side(Cursegp, Curside, &rvec); extract_forward_vector_from_segment(Cursegp, &fvec); scalevec.x = vm_vec_mag(&rvec); scalevec.y = vm_vec_mag(&uvec); scalevec.z = vm_vec_mag(&fvec); med_create_new_segment(&scalevec); } // ------------------------------------------------------------------------------- // Initialize all vertices to inactive status. void init_all_vertices(void) { for (unsigned v=0; vverts[v]; // Now copy the whole struct. *dsp = *ssp; // Now restore the vertex indices. for (v=0; vverts[v] = verts_copy[v]; // Now destructively modify the vertex values for all vertex indices. for (v=0; vverts[v]] = Vertices[ssp->verts[v]]; } // ----------------------------------------------------------------------------- // Create coordinate axes in orientation of specified segment, stores vertices at *vp. void create_coordinate_axes_from_segment(segment *sp,int *vertnums) { vms_matrix rotmat; vms_vector t; med_extract_matrix_from_segment(sp,&rotmat); compute_segment_center(&Vertices[vertnums[0]],sp); t = rotmat.rvec; vm_vec_scale(&t,i2f(32)); vm_vec_add(&Vertices[vertnums[1]],&Vertices[vertnums[0]],&t); t = rotmat.uvec; vm_vec_scale(&t,i2f(32)); vm_vec_add(&Vertices[vertnums[2]],&Vertices[vertnums[0]],&t); t = rotmat.fvec; vm_vec_scale(&t,i2f(32)); vm_vec_add(&Vertices[vertnums[3]],&Vertices[vertnums[0]],&t); } // ----------------------------------------------------------------------------- // Determine if a segment is concave. Returns true if concave int check_seg_concavity(segment *s) { int sn,vn; vms_vector n0,n1; for (sn=0;snverts[Side_to_verts[sn][vn%4]]], &Vertices[s->verts[Side_to_verts[sn][(vn+1)%4]]], &Vertices[s->verts[Side_to_verts[sn][(vn+2)%4]]]); //vm_vec_normalize(&n1); if (vn>0) if (vm_vec_dotprod(&n0,&n1) < f0_5) return 1; n0 = n1; } return 0; } // ----------------------------------------------------------------------------- // Find all concave segments and add to list void find_concave_segs() { int i; segment *s; N_warning_segs = 0; for (s=Segments,i=Highest_segment_index;i>=0;s++,i--) if (s->segnum != -1) if (check_seg_concavity(s)) Warning_segs[N_warning_segs++]=SEG_PTR_2_NUM(s); } // ----------------------------------------------------------------------------- void warn_if_concave_segments(void) { char temp[1]; find_concave_segs(); if (N_warning_segs) { editor_status_fmt("*** WARNING *** %d concave segments in mine! *** WARNING ***",N_warning_segs); sprintf( temp, "%d", N_warning_segs ); } } // ----------------------------------------------------------------------------- // Check segment s, if concave, warn void warn_if_concave_segment(segment *s) { char temp[1]; int result; result = check_seg_concavity(s); if (result) { Warning_segs[N_warning_segs++] = s-Segments; if (N_warning_segs) { editor_status("*** WARNING *** New segment is concave! *** WARNING ***"); sprintf( temp, "%d", N_warning_segs ); } //else // editor_status(""); } //else //editor_status(""); } // ------------------------------------------------------------------------------- // Find segment adjacent to sp:side. // Adjacent means a segment which shares all four vertices. // Return true if segment found and fill in segment in adj_sp and side in adj_side. // Return false if unable to find, in which case adj_sp and adj_side are undefined. int med_find_adjacent_segment_side(segment *sp, int side, segment **adj_sp, int *adj_side) { int seg,s,v,vv; int abs_verts[4]; // Stuff abs_verts[4] array with absolute vertex indices for (v=0; v<4; v++) abs_verts[v] = sp->verts[Side_to_verts[side][v]]; // Scan all segments, looking for a segment which contains the four abs_verts for (seg=0; seg<=Highest_segment_index; seg++) { if (seg != sp-Segments) { for (v=0; v<4; v++) { // do for each vertex in abs_verts for (vv=0; vvchildren[side])) return 0; compute_center_point_on_side(&vsc, sp, side); closest_seg_dist = JOINT_THRESHOLD; // Scan all segments, looking for a segment which contains the four abs_verts for (seg=0; seg<=Highest_segment_index; seg++) if (seg != sp-Segments) for (s=0;ssegnum != -1) for (v=0; vverts[v] <= Highest_vertex_index); } } // ----------------------------------------------------------------------------------------------------- void check_for_overlapping_segment(int segnum) { int i, v; segmasks masks; vms_vector segcenter; compute_segment_center(&segcenter, &Segments[segnum]); for (i=0;i<=Highest_segment_index; i++) { if (i != segnum) { masks = get_seg_masks(&segcenter, i, 0, __FILE__, __LINE__); if (masks.centermask == 0) { continue; } for (v=0; v<8; v++) { vms_vector pdel, presult; vm_vec_sub(&pdel, &Vertices[Segments[segnum].verts[v]], &segcenter); vm_vec_scale_add(&presult, &segcenter, &pdel, (F1_0*15)/16); masks = get_seg_masks(&presult, i, 0, __FILE__, __LINE__); if (masks.centermask == 0) { break; } } } } } // ----------------------------------------------------------------------------------------------------- // Check for overlapping segments. void check_for_overlapping_segments(void) { int i; med_compress_mine(); for (i=0; i<=Highest_segment_index; i++) { check_for_overlapping_segment(i); } } dxx-rebirth-0.58.1-d2x/editor/seguvs.c000066400000000000000000001416351217717237500175340ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * u,v coordinate computation for segment faces * */ #include #include #include #include #include #include "inferno.h" #include "segment.h" #include "editor/editor.h" #include "editor/esegment.h" #include "gameseg.h" #include "fix.h" #include "dxxerror.h" #include "wall.h" #include "editor/kdefs.h" #include "bm.h" // Needed for TmapInfo #include "effects.h" // Needed for effects_bm_num #include "fvi.h" void cast_all_light_in_mine(int quick_flag); //--rotate_uvs-- vms_vector Rightvec; // --------------------------------------------------------------------------------------------- // Returns approximate area of a side fix area_on_side(side *sidep) { fix du,dv,width,height; du = sidep->uvls[1].u - sidep->uvls[0].u; dv = sidep->uvls[1].v - sidep->uvls[0].v; width = fix_sqrt(fixmul(du,du) + fixmul(dv,dv)); du = sidep->uvls[3].u - sidep->uvls[0].u; dv = sidep->uvls[3].v - sidep->uvls[0].v; height = fix_sqrt(fixmul(du,du) + fixmul(dv,dv)); return fixmul(width, height); } // ------------------------------------------------------------------------------------------- // DEBUG function -- callable from debugger. // Returns approximate area of all sides which get mapped (ie, are not a connection). // I wrote this because I was curious how much memory would be required to texture map all // sides individually with custom artwork. For demo1.min on 2/18/94, it would be about 5 meg. int area_on_all_sides(void) { int i,s; int total_area = 0; for (i=0; i<=Highest_segment_index; i++) { segment *segp = &Segments[i]; for (s=0; schildren[s])) total_area += f2i(area_on_side(&segp->sides[s])); } return total_area; } fix average_connectivity(void) { int i,s; int total_sides = 0, total_mapped_sides = 0; for (i=0; i<=Highest_segment_index; i++) { segment *segp = &Segments[i]; for (s=0; schildren[s])) total_mapped_sides++; total_sides++; } } return 6 * fixdiv(total_mapped_sides, total_sides); } #define MAX_LIGHT_SEGS 16 // --------------------------------------------------------------------------------------------- // Scan all polys in all segments, return average light value for vnum. // segs = output array for segments containing vertex, terminated by -1. fix get_average_light_at_vertex(int vnum, short *segs) { int segnum, relvnum, sidenum; fix total_light; int num_occurrences; // #ifndef NDEBUG //Removed this ifdef because the version of Assert that I used to get it to compile doesn't work without this symbol. -KRB short *original_segs; original_segs = segs; // #endif num_occurrences = 0; total_light = 0; for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *segp = &Segments[segnum]; int *vp = segp->verts; for (relvnum=0; relvnumchildren[sidenum])) { side *sidep = &segp->sides[sidenum]; const sbyte *vp = Side_to_verts[sidenum]; int v; for (v=0; v<4; v++) if (*vp++ == relvnum) { total_light += sidep->uvls[v].l; num_occurrences++; } } // end if } // end sidenum } } // end segnum *segs = -1; if (num_occurrences) return total_light/num_occurrences; else return 0; } void set_average_light_at_vertex(int vnum) { int relvnum, sidenum; short Segment_indices[MAX_LIGHT_SEGS]; int segind; fix average_light; average_light = get_average_light_at_vertex(vnum, Segment_indices); if (!average_light) return; segind = 0; while (Segment_indices[segind] != -1) { int segnum = Segment_indices[segind++]; segment *segp = &Segments[segnum]; for (relvnum=0; relvnumverts[relvnum] == vnum) break; if (relvnum < MAX_VERTICES_PER_SEGMENT) { for (sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { if (!IS_CHILD(segp->children[sidenum])) { side *sidep = &segp->sides[sidenum]; const sbyte *vp = Side_to_verts[sidenum]; int v; for (v=0; v<4; v++) if (*vp++ == relvnum) sidep->uvls[v].l = average_light; } // end if } // end sidenum } // end if } // end while Update_flags |= UF_WORLD_CHANGED; } void set_average_light_on_side(segment *segp, int sidenum) { int v; if (!IS_CHILD(segp->children[sidenum])) for (v=0; v<4; v++) { set_average_light_at_vertex(segp->verts[Side_to_verts[sidenum][v]]); } } int set_average_light_on_curside(void) { set_average_light_on_side(Cursegp, Curside); return 0; } // ----------------------------------------------------------------------------------------- void set_average_light_on_all_fast(void) { int s,v,relvnum; fix al; int alc; int seglist[MAX_LIGHT_SEGS]; int *segptr; set_vertex_counts(); // Set total light value for all vertices in array average_light. for (v=0; v<=Highest_vertex_index; v++) { al = 0; alc = 0; if (Vertex_active[v]) { segptr = seglist; for (s=0; s<=Highest_segment_index; s++) { segment *segp = &Segments[s]; for (relvnum=0; relvnumverts[relvnum] == v) break; if (relvnum != MAX_VERTICES_PER_SEGMENT) { int si; *segptr++ = s; // Note this segment in list, so we can process it below. Assert(segptr - seglist < MAX_LIGHT_SEGS); for (si=0; sichildren[si])) { side *sidep = &segp->sides[si]; const sbyte *vp = Side_to_verts[si]; int vv; for (vv=0; vv<4; vv++) if (*vp++ == relvnum) { al += sidep->uvls[vv].l; alc++; } } // if (segp->children[si == -1) { } // for (si=0... } // if (relvnum != ... } // for (s=0; ... *segptr = -1; // Now, divide average_light by number of number of occurrences for each vertex if (alc) al /= alc; else al = 0; segptr = seglist; while (*segptr != -1) { int segnum = *segptr++; segment *segp = &Segments[segnum]; int sidenum; for (relvnum=0; relvnumverts[relvnum] == v) break; Assert(relvnum < MAX_VERTICES_PER_SEGMENT); // IMPOSSIBLE! This segment is in seglist, but vertex v does not occur! for (sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { int wid_result; wid_result = WALL_IS_DOORWAY(segp, sidenum); if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) { side *sidep = &segp->sides[sidenum]; const sbyte *vp = Side_to_verts[sidenum]; int v; for (v=0; v<4; v++) if (*vp++ == relvnum) sidep->uvls[v].l = al; } // end if } // end sidenum } // end while } // if (Vertex_active[v]... } // for (v=0... } extern int Doing_lighting_hack_flag; int set_average_light_on_all(void) { // set_average_light_on_all_fast(); Doing_lighting_hack_flag = 1; cast_all_light_in_mine(0); Doing_lighting_hack_flag = 0; Update_flags |= UF_WORLD_CHANGED; // int seg, side; // for (seg=0; seg<=Highest_segment_index; seg++) // for (side=0; sideu; v0.y = 0; v0.z = uv0->v; v1.x = uv1->u; v1.y = 0; v1.z = uv1->v; return vm_vec_dist(&v0,&v1); } // --------------------------------------------------------------------------------------------- // Given a polygon, compress the uv coordinates so that they are as close to 0 as possible. // Do this by adding a constant u and v to each uv pair. void compress_uv_coordinates(side *sidep) { int v; fix uc, vc; uc = 0; vc = 0; for (v=0; v<4; v++) { uc += sidep->uvls[v].u; vc += sidep->uvls[v].v; } uc /= 4; vc /= 4; uc = uc & 0xffff0000; vc = vc & 0xffff0000; for (v=0; v<4; v++) { sidep->uvls[v].u -= uc; sidep->uvls[v].v -= vc; } } // --------------------------------------------------------------------------------------------- void compress_uv_coordinates_on_side(side *sidep) { compress_uv_coordinates(sidep); } // --------------------------------------------------------------------------------------------- void validate_uv_coordinates_on_side(segment *segp, int sidenum) { // int v; // fix uv_dist,threed_dist; // vms_vector tvec; // fix dist_ratios[MAX_VERTICES_PER_POLY]; side *sidep = &segp->sides[sidenum]; // sbyte *vp = Side_to_verts[sidenum]; // This next hunk doesn't seem to affect anything. @mk, 02/13/94 // for (v=1; v<4; v++) { // uv_dist = compute_uv_dist(&sidep->uvls[v],&sidep->uvls[0]); // threed_dist = vm_vec_mag(vm_vec_sub(&tvec,&Vertices[segp->verts[vp[v]],&Vertices[vp[0]])); // dist_ratios[v-1] = fixdiv(uv_dist,threed_dist); // } compress_uv_coordinates_on_side(sidep); } void compress_uv_coordinates_in_segment(segment *segp) { int side; for (side=0; sidesides[side]); } void compress_uv_coordinates_all(void) { int seg; for (seg=0; seg<=Highest_segment_index; seg++) if (Segments[seg].segnum != -1) compress_uv_coordinates_in_segment(&Segments[seg]); } void check_lighting_side(segment *sp, int sidenum) { int v; side *sidep = &sp->sides[sidenum]; for (v=0; v<4; v++) if ((sidep->uvls[v].l > F1_0*16) || (sidep->uvls[v].l < 0)) Int3(); } void check_lighting_segment(segment *segp) { int side; for (side=0; sidesides[sidenum]; for (v=0; v<4; v++) sidep->uvls[v].l = DEFAULT_LIGHTING; } void assign_default_lighting(segment *segp) { int sidenum; for (sidenum=0; sidenumsides[sidenum]; for (v=0; v<4; v++) sidep->uvls[v] = uvls[v]; } #ifdef __WATCOMC__ fix zhypot(fix a,fix b); #pragma aux zhypot parm [eax] [ebx] value [eax] modify [eax ebx ecx edx] = \ "imul eax" \ "xchg eax,ebx" \ "mov ecx,edx" \ "imul eax" \ "add eax,ebx" \ "adc edx,ecx" \ "call quad_sqrt"; #else fix zhypot(fix a,fix b) { double x = (double)a / 65536; double y = (double)b / 65536; return (long)(sqrt(x * x + y * y) * 65536); } #endif // --------------------------------------------------------------------------------------------- // Assign lighting value to side, a function of the normal vector. void assign_light_to_side(segment *sp, int sidenum) { int v; side *sidep = &sp->sides[sidenum]; for (v=0; v<4; v++) sidep->uvls[v].l = DEFAULT_LIGHTING; } fix Stretch_scale_x = F1_0; fix Stretch_scale_y = F1_0; // --------------------------------------------------------------------------------------------- // Given u,v coordinates at two vertices, assign u,v coordinates to other two vertices on a side. // (Actually, assign them to the coordinates in the faces.) // va, vb = face-relative vertex indices corresponding to uva, uvb. Ie, they are always in 0..3 and should be looked up in // Side_to_verts[side] to get the segment relative index. void assign_uvs_to_side(segment *segp, int sidenum, uvl *uva, uvl *uvb, int va, int vb) { int vlo,vhi,v0,v1,v2,v3; vms_vector fvec,rvec,tvec; vms_matrix rotmat; uvl uvls[4],ruvmag,fuvmag,uvlo,uvhi; fix fmag,mag01; sbyte *vp; Assert( (va<4) && (vb<4) ); Assert((abs(va - vb) == 1) || (abs(va - vb) == 3)); // make sure the verticies specify an edge vp = (sbyte *)&Side_to_verts[sidenum]; // We want vlo precedes vhi, ie vlo < vhi, or vlo = 3, vhi = 0 if (va == ((vb + 1) % 4)) { // va = vb + 1 vlo = vb; vhi = va; uvlo = *uvb; uvhi = *uva; } else { vlo = va; vhi = vb; uvlo = *uva; uvhi = *uvb; } Assert(((vlo+1) % 4) == vhi); // If we are on an edge, then uvhi is one more than uvlo (mod 4) uvls[vlo] = uvlo; uvls[vhi] = uvhi; // Now we have vlo precedes vhi, compute vertices ((vhi+1) % 4) and ((vhi+2) % 4) // Assign u,v scale to a unit length right vector. fmag = zhypot(uvhi.v - uvlo.v,uvhi.u - uvlo.u); if (fmag < 64) { // this is a fix, so 64 = 1/1024 ruvmag.u = F1_0*256; ruvmag.v = F1_0*256; fuvmag.u = F1_0*256; fuvmag.v = F1_0*256; } else { ruvmag.u = uvhi.v - uvlo.v; ruvmag.v = uvlo.u - uvhi.u; fuvmag.u = uvhi.u - uvlo.u; fuvmag.v = uvhi.v - uvlo.v; } v0 = segp->verts[vp[vlo]]; v1 = segp->verts[vp[vhi]]; v2 = segp->verts[vp[(vhi+1)%4]]; v3 = segp->verts[vp[(vhi+2)%4]]; // Compute right vector by computing orientation matrix from: // forward vector = vlo:vhi // right vector = vlo:(vhi+2) % 4 vm_vec_sub(&fvec,&Vertices[v1],&Vertices[v0]); vm_vec_sub(&rvec,&Vertices[v3],&Vertices[v0]); if (((fvec.x == 0) && (fvec.y == 0) && (fvec.z == 0)) || ((rvec.x == 0) && (rvec.y == 0) && (rvec.z == 0))) { rotmat = vmd_identity_matrix; } else vm_vector_2_matrix(&rotmat,&fvec,0,&rvec); rvec = rotmat.rvec; vm_vec_negate(&rvec); fvec = rotmat.fvec; mag01 = vm_vec_dist(&Vertices[v1],&Vertices[v0]); if ((va == 0) || (va == 2)) mag01 = fixmul(mag01, Stretch_scale_x); else mag01 = fixmul(mag01, Stretch_scale_y); if (mag01 < F1_0/1024 ) editor_status_fmt("U, V bogosity in segment #%hu, probably on side #%i. CLEAN UP YOUR MESS!", (unsigned short)(segp-Segments), sidenum); else { vm_vec_sub(&tvec,&Vertices[v2],&Vertices[v1]); uvls[(vhi+1)%4].u = uvhi.u + fixdiv(fixmul(ruvmag.u,vm_vec_dotprod(&rvec,&tvec)),mag01) + fixdiv(fixmul(fuvmag.u,vm_vec_dotprod(&fvec,&tvec)),mag01); uvls[(vhi+1)%4].v = uvhi.v + fixdiv(fixmul(ruvmag.v,vm_vec_dotprod(&rvec,&tvec)),mag01) + fixdiv(fixmul(fuvmag.v,vm_vec_dotprod(&fvec,&tvec)),mag01); vm_vec_sub(&tvec,&Vertices[v3],&Vertices[v0]); uvls[(vhi+2)%4].u = uvlo.u + fixdiv(fixmul(ruvmag.u,vm_vec_dotprod(&rvec,&tvec)),mag01) + fixdiv(fixmul(fuvmag.u,vm_vec_dotprod(&fvec,&tvec)),mag01); uvls[(vhi+2)%4].v = uvlo.v + fixdiv(fixmul(ruvmag.v,vm_vec_dotprod(&rvec,&tvec)),mag01) + fixdiv(fixmul(fuvmag.v,vm_vec_dotprod(&fvec,&tvec)),mag01); uvls[(vhi+1)%4].l = uvhi.l; uvls[(vhi+2)%4].l = uvlo.l; copy_uvs_from_side_to_faces(segp, sidenum, uvls); } } int Vmag = VMAG; // ----------------------------------------------------------------------------------------------------------- // Assign default uvs to side. // This means: // v0 = 0,0 // v1 = k,0 where k is 3d size dependent // v2, v3 assigned by assign_uvs_to_side void assign_default_uvs_to_side(segment *segp,int side) { uvl uv0,uv1; const sbyte *vp; uv0.u = 0; uv0.v = 0; vp = Side_to_verts[side]; uv1.u = 0; uv1.v = Num_tilings * fixmul(Vmag, vm_vec_dist(&Vertices[segp->verts[vp[1]]],&Vertices[segp->verts[vp[0]]])); assign_uvs_to_side(segp, side, &uv0, &uv1, 0, 1); } // ----------------------------------------------------------------------------------------------------------- // Assign default uvs to side. // This means: // v0 = 0,0 // v1 = k,0 where k is 3d size dependent // v2, v3 assigned by assign_uvs_to_side void stretch_uvs_from_curedge(segment *segp, int side) { uvl uv0,uv1; int v0, v1; v0 = Curedge; v1 = (v0 + 1) % 4; uv0.u = segp->sides[side].uvls[v0].u; uv0.v = segp->sides[side].uvls[v0].v; uv1.u = segp->sides[side].uvls[v1].u; uv1.v = segp->sides[side].uvls[v1].v; assign_uvs_to_side(segp, side, &uv0, &uv1, v0, v1); } // -------------------------------------------------------------------------------------------------------------- // Assign default uvs to a segment. void assign_default_uvs_to_segment(segment *segp) { int s; for (s=0; ssides[base_common_side].num_faces; f++) { // -- mk021394 -- face *fp = &base_seg->sides[base_common_side].faces[f]; // -- mk021394 -- for (p=0; pnum_polys; p++) { // -- mk021394 -- poly *pp = &fp->polys[p]; // -- mk021394 -- for (v=0; vnum_vertices; v++) // -- mk021394 -- if (pp->verts[v] == v1) { // -- mk021394 -- *ff = f; // -- mk021394 -- *vv = v; // -- mk021394 -- *pi = p; // -- mk021394 -- return; // -- mk021394 -- } // -- mk021394 -- } // -- mk021394 -- } // -- mk021394 -- // -- mk021394 -- Assert(0); // Error -- Couldn't find face:vertex which matched vertex v1 on base_seg:base_common_side // -- mk021394 -- } // -- mk021394 -- // -------------------------------------------------------------------------------------------------------------- // -- mk021394 -- // Find the vertex index in base_seg:base_common_side which is segment relative vertex v1 // -- mk021394 -- // This very specific routine is subsidiary to med_assign_uvs_to_side. // -- mk021394 -- void get_side_vert(segment *base_seg,int base_common_side,int v1,int *vv) // -- mk021394 -- { // -- mk021394 -- int p,f,v; // -- mk021394 -- // -- mk021394 -- Assert((base_seg->sides[base_common_side].tri_edge == 0) || (base_seg->sides[base_common_side].tri_edge == 1)); // -- mk021394 -- Assert(base_seg->sides[base_common_side].num_faces <= 2); // -- mk021394 -- // -- mk021394 -- for (f=0; fsides[base_common_side].num_faces; f++) { // -- mk021394 -- face *fp = &base_seg->sides[base_common_side].faces[f]; // -- mk021394 -- for (p=0; pnum_polys; p++) { // -- mk021394 -- poly *pp = &fp->polys[p]; // -- mk021394 -- for (v=0; vnum_vertices; v++) // -- mk021394 -- if (pp->verts[v] == v1) { // -- mk021394 -- if (pp->num_vertices == 4) { // -- mk021394 -- *vv = v; // -- mk021394 -- return; // -- mk021394 -- } // -- mk021394 -- // -- mk021394 -- if (base_seg->sides[base_common_side].tri_edge == 0) { // triangulated 012, 023, so if f==0, *vv = v, if f==1, *vv = v if v=0, else v+1 // -- mk021394 -- if ((f == 1) && (v > 0)) // -- mk021394 -- v++; // -- mk021394 -- *vv = v; // -- mk021394 -- return; // -- mk021394 -- } else { // triangulated 013, 123 // -- mk021394 -- if (f == 0) { // -- mk021394 -- if (v == 2) // -- mk021394 -- v++; // -- mk021394 -- } else // -- mk021394 -- v++; // -- mk021394 -- *vv = v; // -- mk021394 -- return; // -- mk021394 -- } // -- mk021394 -- } // -- mk021394 -- } // -- mk021394 -- } // -- mk021394 -- // -- mk021394 -- Assert(0); // Error -- Couldn't find face:vertex which matched vertex v1 on base_seg:base_common_side // -- mk021394 -- } //--rotate_uvs-- // -------------------------------------------------------------------------------------------------------------- //--rotate_uvs-- // Rotate uvl coordinates uva, uvb about their center point by heading //--rotate_uvs-- void rotate_uvs(uvl *uva, uvl *uvb, vms_vector *rvec) //--rotate_uvs-- { //--rotate_uvs-- uvl uvc, uva1, uvb1; //--rotate_uvs-- //--rotate_uvs-- uvc.u = (uva->u + uvb->u)/2; //--rotate_uvs-- uvc.v = (uva->v + uvb->v)/2; //--rotate_uvs-- //--rotate_uvs-- uva1.u = fixmul(uva->u - uvc.u, rvec->x) - fixmul(uva->v - uvc.v, rvec->z); //--rotate_uvs-- uva1.v = fixmul(uva->u - uvc.u, rvec->z) + fixmul(uva->v - uvc.v, rvec->x); //--rotate_uvs-- //--rotate_uvs-- uva->u = uva1.u + uvc.u; //--rotate_uvs-- uva->v = uva1.v + uvc.v; //--rotate_uvs-- //--rotate_uvs-- uvb1.u = fixmul(uvb->u - uvc.u, rvec->x) - fixmul(uvb->v - uvc.v, rvec->z); //--rotate_uvs-- uvb1.v = fixmul(uvb->u - uvc.u, rvec->z) + fixmul(uvb->v - uvc.v, rvec->x); //--rotate_uvs-- //--rotate_uvs-- uvb->u = uvb1.u + uvc.u; //--rotate_uvs-- uvb->v = uvb1.v + uvc.v; //--rotate_uvs-- } // -------------------------------------------------------------------------------------------------------------- void med_assign_uvs_to_side(segment *con_seg, int con_common_side, segment *base_seg, int base_common_side, int abs_id1, int abs_id2) { uvl uv1,uv2; int v,bv1,bv2, vv1, vv2; int cv1=0, cv2=0; bv1 = -1; bv2 = -1; // Find which vertices in segment match abs_id1, abs_id2 for (v=0; vverts[v] == abs_id1) bv1 = v; if (base_seg->verts[v] == abs_id2) bv2 = v; if (con_seg->verts[v] == abs_id1) cv1 = v; if (con_seg->verts[v] == abs_id2) cv2 = v; } // Now, bv1, bv2 are segment relative vertices in base segment which are the same as absolute vertices abs_id1, abs_id2 // cv1, cv2 are segment relative vertices in conn segment which are the same as absolute vertices abs_id1, abs_id2 Assert((bv1 != -1) && (bv2 != -1) && (cv1 != -1) && (cv2 != -1)); // Now, scan 4 vertices in base side and 4 vertices in connected side. // Set uv1, uv2 to uv coordinates from base side which correspond to vertices bv1, bv2. // Set vv1, vv2 to relative vertex ids (in 0..3) in connecting side which correspond to cv1, cv2 vv1 = -1; vv2 = -1; for (v=0; v<4; v++) { if (bv1 == Side_to_verts[base_common_side][v]) uv1 = base_seg->sides[base_common_side].uvls[v]; if (bv2 == Side_to_verts[base_common_side][v]) uv2 = base_seg->sides[base_common_side].uvls[v]; if (cv1 == Side_to_verts[con_common_side][v]) vv1 = v; if (cv2 == Side_to_verts[con_common_side][v]) vv2 = v; } Assert((uv1.u != uv2.u) || (uv1.v != uv2.v)); Assert( (vv1 != -1) && (vv2 != -1) ); assign_uvs_to_side(con_seg, con_common_side, &uv1, &uv2, vv1, vv2); } // ----------------------------------------------------------------------------- // Given a base and a connecting segment, a side on each of those segments and two global vertex ids, // determine which side in each of the segments shares those two vertices. // This is used to propagate a texture map id to a connecting segment in an expected and desired way. // Since we can attach any side of a segment to any side of another segment, and do so in each case in // four different rotations (for a total of 6*6*4 = 144 ways), not having this nifty function will cause // great confusion. void get_side_ids(segment *base_seg, segment *con_seg, int base_side, int con_side, int abs_id1, int abs_id2, int *base_common_side, int *con_common_side) { const sbyte *base_vp,*con_vp; int v0,side; *base_common_side = -1; // Find side in base segment which contains the two global vertex ids. for (side=0; sideverts[(int) base_vp[v0]] == abs_id1) && (base_seg->verts[(int) base_vp[(v0+1) % 4]] == abs_id2)) || ((base_seg->verts[(int) base_vp[v0]] == abs_id2) && (base_seg->verts[(int)base_vp[ (v0+1) % 4]] == abs_id1))) { Assert(*base_common_side == -1); // This means two different sides shared the same edge with base_side == impossible! *base_common_side = side; } } } // Note: For connecting segment, process vertices in reversed order. *con_common_side = -1; // Find side in connecting segment which contains the two global vertex ids. for (side=0; sideverts[(int) con_vp[(v0 + 1) % 4]] == abs_id1) && (con_seg->verts[(int) con_vp[v0]] == abs_id2)) || ((con_seg->verts[(int) con_vp[(v0 + 1) % 4]] == abs_id2) && (con_seg->verts[(int) con_vp[v0]] == abs_id1))) { Assert(*con_common_side == -1); // This means two different sides shared the same edge with con_side == impossible! *con_common_side = side; } } } Assert((*base_common_side != -1) && (*con_common_side != -1)); } // ----------------------------------------------------------------------------- // Propagate texture map u,v coordinates from base_seg:base_side to con_seg:con_side. // The two vertices abs_id1 and abs_id2 are the only two vertices common to the two sides. // If uv_only_flag is 1, then don't assign texture map ids, only update the uv coordinates // If uv_only_flag is -1, then ONLY assign texture map ids, don't update the uv coordinates void propagate_tmaps_to_segment_side(segment *base_seg, int base_side, segment *con_seg, int con_side, int abs_id1, int abs_id2, int uv_only_flag) { int base_common_side,con_common_side; int tmap_num; Assert ((uv_only_flag == -1) || (uv_only_flag == 0) || (uv_only_flag == 1)); // Set base_common_side = side in base_seg which contains edge abs_id1:abs_id2 // Set con_common_side = side in con_seg which contains edge abs_id1:abs_id2 if (base_seg != con_seg) get_side_ids(base_seg, con_seg, base_side, con_side, abs_id1, abs_id2, &base_common_side, &con_common_side); else { base_common_side = base_side; con_common_side = con_side; } // Now, all faces in con_seg which are on side con_common_side get their tmap_num set to whatever tmap is assigned // to whatever face I find which is on side base_common_side. // First, find tmap_num for base_common_side. If it doesn't exist (ie, there is a connection there), look at the segment // that is connected through it. if (!IS_CHILD(con_seg->children[con_common_side])) { if (!IS_CHILD(base_seg->children[base_common_side])) { // There is at least one face here, so get the tmap_num from there. tmap_num = base_seg->sides[base_common_side].tmap_num; // Now assign all faces in the connecting segment on side con_common_side to tmap_num. if ((uv_only_flag == -1) || (uv_only_flag == 0)) con_seg->sides[con_common_side].tmap_num = tmap_num; if (uv_only_flag != -1) med_assign_uvs_to_side(con_seg, con_common_side, base_seg, base_common_side, abs_id1, abs_id2); } else { // There are no faces here, there is a connection, trace through the connection. int cside; cside = find_connect_side(base_seg, &Segments[base_seg->children[base_common_side]]); propagate_tmaps_to_segment_side(&Segments[base_seg->children[base_common_side]], cside, con_seg, con_side, abs_id1, abs_id2, uv_only_flag); } } } sbyte Edge_between_sides[MAX_SIDES_PER_SEGMENT][MAX_SIDES_PER_SEGMENT][2] = { // left top right bottom back front { {-1,-1}, { 3, 7}, {-1,-1}, { 2, 6}, { 6, 7}, { 2, 3} }, // left { { 3, 7}, {-1,-1}, { 0, 4}, {-1,-1}, { 4, 7}, { 0, 3} }, // top { {-1,-1}, { 0, 4}, {-1,-1}, { 1, 5}, { 4, 5}, { 0, 1} }, // right { { 2, 6}, {-1,-1}, { 1, 5}, {-1,-1}, { 5, 6}, { 1, 2} }, // bottom { { 6, 7}, { 4, 7}, { 4, 5}, { 5, 6}, {-1,-1}, {-1,-1} }, // back { { 2, 3}, { 0, 3}, { 0, 1}, { 1, 2}, {-1,-1}, {-1,-1} }}; // front // ----------------------------------------------------------------------------- // Propagate texture map u,v coordinates to base_seg:back_side from base_seg:some-other-side // There is no easy way to figure out which side is adjacent to another side along some edge, so we do a bit of searching. void med_propagate_tmaps_to_back_side(segment *base_seg, int back_side, int uv_only_flag) { int v1=0,v2=0; int s,ss,tmap_num,back_side_tmap; if (IS_CHILD(base_seg->children[back_side])) return; // connection, so no sides here. // Scan all sides, look for an occupied side which is not back_side or Side_opposite[back_side] for (s=0; sverts[v1], base_seg->verts[v2], uv_only_flag); // Assign an unused tmap id to the back side. // Note that this can get undone by the caller if this was not part of a new attach, but a rotation or a scale (which // both do attaches). // First see if tmap on back side is anywhere else. if (!uv_only_flag) { back_side_tmap = base_seg->sides[back_side].tmap_num; for (s=0; ssides[s].tmap_num == back_side_tmap) { for (tmap_num=0; tmap_num < MAX_SIDES_PER_SEGMENT; tmap_num++) { for (ss=0; sssides[ss].tmap_num == New_segment.sides[tmap_num].tmap_num) goto found2; // current texture map (tmap_num) is used on current (ss) side, so try next one // Current texture map (tmap_num) has not been used, assign to all faces on back_side. base_seg->sides[back_side].tmap_num = New_segment.sides[tmap_num].tmap_num; goto done1; found2: ; } } } done1: ; } } int fix_bogus_uvs_on_side(void) { med_propagate_tmaps_to_back_side(Cursegp, Curside, 1); return 0; } void fix_bogus_uvs_on_side1(segment *sp, int sidenum, int uvonly_flag) { side *sidep = &sp->sides[sidenum]; if ((sidep->uvls[0].u == 0) && (sidep->uvls[1].u == 0) && (sidep->uvls[2].u == 0)) { med_propagate_tmaps_to_back_side(sp, sidenum, uvonly_flag); } } void fix_bogus_uvs_seg(segment *segp) { int s; for (s=0; schildren[s])) fix_bogus_uvs_on_side1(segp, s, 1); } } int fix_bogus_uvs_all(void) { int seg; for (seg=0; seg<=Highest_segment_index; seg++) if (Segments[seg].segnum != -1) fix_bogus_uvs_seg(&Segments[seg]); return 0; } // ----------------------------------------------------------------------------- // Propagate texture map u,v coordinates to base_seg:back_side from base_seg:some-other-side // There is no easy way to figure out which side is adjacent to another side along some edge, so we do a bit of searching. void med_propagate_tmaps_to_any_side(segment *base_seg, int back_side, int tmap_num, int uv_only_flag) { int v1=0,v2=0; int s; // Scan all sides, look for an occupied side which is not back_side or Side_opposite[back_side] for (s=0; sverts[v1], base_seg->verts[v2], uv_only_flag); base_seg->sides[back_side].tmap_num = tmap_num; } // ----------------------------------------------------------------------------- // Segment base_seg is connected through side base_side to segment con_seg on con_side. // For all walls in con_seg, find the wall in base_seg which shares an edge. Copy tmap_num // from that side in base_seg to the wall in con_seg. If the wall in base_seg is not present // (ie, there is another segment connected through it), follow the connection through that // segment to get the wall in the connected segment which shares the edge, and get tmap_num from there. void propagate_tmaps_to_segment_sides(segment *base_seg, int base_side, segment *con_seg, int con_side, int uv_only_flag) { const sbyte *base_vp; int abs_id1,abs_id2; int v; base_vp = Side_to_verts[base_side]; // Do for each edge on connecting face. for (v=0; v<4; v++) { abs_id1 = base_seg->verts[(int) base_vp[v]]; abs_id2 = base_seg->verts[(int) base_vp[(v+1) % 4]]; propagate_tmaps_to_segment_side(base_seg, base_side, con_seg, con_side, abs_id1, abs_id2, uv_only_flag); } } // ----------------------------------------------------------------------------- // Propagate texture maps in base_seg to con_seg. // For each wall in con_seg, find the wall in base_seg which shared an edge. Copy tmap_num from that // wall in base_seg to the wall in con_seg. If the wall in base_seg is not present, then look at the // segment connected through base_seg through the wall. The wall with a common edge is the new wall // of interest. Continue searching in this way until a wall of interest is present. void med_propagate_tmaps_to_segments(segment *base_seg,segment *con_seg, int uv_only_flag) { int s; for (s=0; schildren[s] == con_seg-Segments) propagate_tmaps_to_segment_sides(base_seg, s, con_seg, find_connect_side(base_seg, con_seg), uv_only_flag); s2s2(con_seg)->static_light = s2s2(base_seg)->static_light; validate_uv_coordinates(con_seg); } // ------------------------------------------------------------------------------- // Copy texture map uvs from srcseg to destseg. // If two segments have different face structure (eg, destseg has two faces on side 3, srcseg has only 1) // then assign uvs according to side vertex id, not face vertex id. void copy_uvs_seg_to_seg(segment *destseg,segment *srcseg) { int s; for (s=0; ssides[s].tmap_num = srcseg->sides[s].tmap_num; destseg->sides[s].tmap_num2 = srcseg->sides[s].tmap_num2; } s2s2(destseg)->static_light = s2s2(srcseg)->static_light; } // _________________________________________________________________________________________________________________________ // Maximum distance between a segment containing light to a segment to receive light. #define LIGHT_DISTANCE_THRESHOLD (F1_0*80) fix Magical_light_constant = (F1_0*16); // int Seg0, Seg1; //int Bugseg = 27; typedef struct { sbyte flag, hit_type; vms_vector vector; } hash_info; #define FVI_HASH_SIZE 8 #define FVI_HASH_AND_MASK (FVI_HASH_SIZE - 1) // Note: This should be malloced. // Also, the vector should not be 12 bytes, you should only care about some smaller portion of it. hash_info fvi_cache[FVI_HASH_SIZE]; int Hash_hits=0, Hash_retries=0, Hash_calcs=0; // ----------------------------------------------------------------------------------------- // Set light from a light source. // Light incident on a surface is defined by the light incident at its points. // Light at a point = K * (V . N) / d // where: // K = some magical constant to make everything look good // V = normalized vector from light source to point // N = surface normal at point // d = distance from light source to point // (Note that the above equation can be simplified to K * (VV . N) / d^2 where VV = non-normalized V) // Light intensity emitted from a light source is defined to be cast from four points. // These four points are 1/64 of the way from the corners of the light source to the center // of its segment. By assuming light is cast from these points, rather than from on the // light surface itself, light will be properly cast on the light surface. Otherwise, the // vector V would be the null vector. // If quick_light set, then don't use find_vector_intersection void cast_light_from_side(segment *segp, int light_side, fix light_intensity, int quick_light) { vms_vector segment_center; int segnum,sidenum,vertnum, lightnum; compute_segment_center(&segment_center, segp); // Do for four lights, one just inside each corner of side containing light. for (lightnum=0; lightnum<4; lightnum++) { int light_vertex_num, i; vms_vector vector_to_center; vms_vector light_location; // fix inverse_segment_magnitude; light_vertex_num = segp->verts[Side_to_verts[light_side][lightnum]]; light_location = Vertices[light_vertex_num]; // New way, 5/8/95: Move towards center irrespective of size of segment. vm_vec_sub(&vector_to_center, &segment_center, &light_location); vm_vec_normalize_quick(&vector_to_center); vm_vec_add2(&light_location, &vector_to_center); // -- Old way, before 5/8/95 -- // -- This way was kind of dumb. In larger segments, you move LESS towards the center. // -- Old way, before 5/8/95 -- // Main problem, though, is vertices don't illuminate themselves well in oblong segments because the dot product is small. // -- Old way, before 5/8/95 -- vm_vec_sub(&vector_to_center, &segment_center, &light_location); // -- Old way, before 5/8/95 -- inverse_segment_magnitude = fixdiv(F1_0/5, vm_vec_mag(&vector_to_center)); // -- Old way, before 5/8/95 -- vm_vec_scale_add(&light_location, &light_location, &vector_to_center, inverse_segment_magnitude); for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *rsegp = &Segments[segnum]; vms_vector r_segment_center; fix dist_to_rseg; for (i=0; isides[sidenum]; vms_vector *side_normalp = &rsidep->normals[0]; // kinda stupid? always use vector 0. for (vertnum=0; vertnum<4; vertnum++) { fix distance_to_point, light_at_point, light_dot; vms_vector vert_location, vector_to_light; int abs_vertnum; abs_vertnum = rsegp->verts[Side_to_verts[sidenum][vertnum]]; vert_location = Vertices[abs_vertnum]; distance_to_point = vm_vec_dist_quick(&vert_location, &light_location); vm_vec_sub(&vector_to_light, &light_location, &vert_location); vm_vec_normalize(&vector_to_light); // Hack: In oblong segments, it's possible to get a very small dot product // but the light source is very nearby (eg, illuminating light itself!). light_dot = vm_vec_dot(&vector_to_light, side_normalp); if (distance_to_point < F1_0) if (light_dot > 0) light_dot = (light_dot + F1_0)/2; if (light_dot > 0) { light_at_point = fixdiv(fixmul(light_dot, light_dot), distance_to_point); light_at_point = fixmul(light_at_point, Magical_light_constant); if (light_at_point >= 0) { fvi_info hit_data; int hit_type; vms_vector vert_location_1, r_vector_to_center; fix inverse_segment_magnitude; vm_vec_sub(&r_vector_to_center, &r_segment_center, &vert_location); inverse_segment_magnitude = fixdiv(F1_0/3, vm_vec_mag(&r_vector_to_center)); vm_vec_scale_add(&vert_location_1, &vert_location, &r_vector_to_center, inverse_segment_magnitude); vert_location = vert_location_1; //if ((segp-Segments == 199) && (rsegp-Segments==199)) // Int3(); // Seg0 = segp-Segments; // Seg1 = rsegp-Segments; if (!quick_light) { int hash_value = Side_to_verts[sidenum][vertnum]; hash_info *hashp = &fvi_cache[hash_value]; while (1) { if (hashp->flag) { if ((hashp->vector.x == vector_to_light.x) && (hashp->vector.y == vector_to_light.y) && (hashp->vector.z == vector_to_light.z)) { hit_type = hashp->hit_type; Hash_hits++; break; } else { Int3(); // How is this possible? Should be no hits! Hash_retries++; hash_value = (hash_value+1) & FVI_HASH_AND_MASK; hashp = &fvi_cache[hash_value]; } } else { fvi_query fq; Hash_calcs++; hashp->vector = vector_to_light; hashp->flag = 1; fq.p0 = &light_location; fq.startseg = segp-Segments; fq.p1 = &vert_location; fq.rad = 0; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = 0; hit_type = find_vector_intersection(&fq,&hit_data); hashp->hit_type = hit_type; break; } } } else hit_type = HIT_NONE; switch (hit_type) { case HIT_NONE: light_at_point = fixmul(light_at_point, light_intensity); rsidep->uvls[vertnum].l += light_at_point; if (rsidep->uvls[vertnum].l > F1_0) rsidep->uvls[vertnum].l = F1_0; break; case HIT_WALL: break; case HIT_OBJECT: Int3(); // Hit object, should be ignoring objects! break; case HIT_BAD_P0: Int3(); // Ugh, this thing again, what happened, what does it mean? break; } } // end if (light_at_point... } // end if (light_dot >... } // end for (vertnum=0... } // end if (rsegp... } // end for (sidenum=0... } // end if (dist_to_rseg... } // end for (segnum=0... } // end for (lightnum=0... } // ------------------------------------------------------------------------------------------ // Zero all lighting values. void calim_zero_light_values(void) { int segnum, sidenum, vertnum; for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *segp = &Segments[segnum]; for (sidenum=0; sidenumsides[sidenum]; for (vertnum=0; vertnum<4; vertnum++) sidep->uvls[vertnum].l = F1_0/64; // Put a tiny bit of light here. } Segment2s[segnum].static_light = F1_0 / 64; } } // ------------------------------------------------------------------------------------------ // Used in setting average light value in a segment, cast light from a side to the center // of all segments. void cast_light_from_side_to_center(segment *segp, int light_side, fix light_intensity, int quick_light) { vms_vector segment_center; int segnum, lightnum; compute_segment_center(&segment_center, segp); // Do for four lights, one just inside each corner of side containing light. for (lightnum=0; lightnum<4; lightnum++) { int light_vertex_num; vms_vector vector_to_center; vms_vector light_location; light_vertex_num = segp->verts[Side_to_verts[light_side][lightnum]]; light_location = Vertices[light_vertex_num]; vm_vec_sub(&vector_to_center, &segment_center, &light_location); vm_vec_scale_add(&light_location, &light_location, &vector_to_center, F1_0/64); for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *rsegp = &Segments[segnum]; vms_vector r_segment_center; fix dist_to_rseg; //if ((segp == &Segments[Bugseg]) && (rsegp == &Segments[Bugseg])) // Int3(); compute_segment_center(&r_segment_center, rsegp); dist_to_rseg = vm_vec_dist_quick(&r_segment_center, &segment_center); if (dist_to_rseg <= LIGHT_DISTANCE_THRESHOLD) { fix light_at_point; if (dist_to_rseg > F1_0) light_at_point = fixdiv(Magical_light_constant, dist_to_rseg); else light_at_point = Magical_light_constant; if (light_at_point >= 0) { int hit_type; if (!quick_light) { fvi_query fq; fvi_info hit_data; fq.p0 = &light_location; fq.startseg = segp-Segments; fq.p1 = &r_segment_center; fq.rad = 0; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = 0; hit_type = find_vector_intersection(&fq,&hit_data); } else hit_type = HIT_NONE; switch (hit_type) { case HIT_NONE: light_at_point = fixmul(light_at_point, light_intensity); if (light_at_point >= F1_0) light_at_point = F1_0-1; s2s2(rsegp)->static_light += light_at_point; if (s2s2(segp)->static_light < 0) // if it went negative, saturate s2s2(segp)->static_light = 0; break; case HIT_WALL: break; case HIT_OBJECT: Int3(); // Hit object, should be ignoring objects! break; case HIT_BAD_P0: Int3(); // Ugh, this thing again, what happened, what does it mean? break; } } // end if (light_at_point... } // end if (dist_to_rseg... } // end for (segnum=0... } // end for (lightnum=0... } // ------------------------------------------------------------------------------------------ // Process all lights. void calim_process_all_lights(int quick_light) { int segnum, sidenum; for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *segp = &Segments[segnum]; for (sidenum=0; sidenumchildren[sidenum])) { if (WALL_IS_DOORWAY(segp, sidenum) != WID_NO_WALL) { side *sidep = &segp->sides[sidenum]; fix light_intensity; light_intensity = TmapInfo[sidep->tmap_num].lighting + TmapInfo[sidep->tmap_num2 & 0x3fff].lighting; // if (segp->sides[sidenum].wall_num != -1) { // int wall_num, bitmap_num, effect_num; // wall_num = segp->sides[sidenum].wall_num; // effect_num = Walls[wall_num].type; // bitmap_num = effects_bm_num[effect_num]; // // light_intensity += TmapInfo[bitmap_num].lighting; // } if (light_intensity) { light_intensity /= 4; // casting light from four spots, so divide by 4. cast_light_from_side(segp, sidenum, light_intensity, quick_light); cast_light_from_side_to_center(segp, sidenum, light_intensity, quick_light); } } } } } // ------------------------------------------------------------------------------------------ // Apply static light in mine. // First, zero all light values. // Then, for all light sources, cast their light. void cast_all_light_in_mine(int quick_flag) { validate_segment_all(); calim_zero_light_values(); calim_process_all_lights(quick_flag); } // int Fvit_num = 1000; // // fix find_vector_intersection_test(void) // { // int i; // fvi_info hit_data; // int p0_seg, p1_seg, this_objnum, ignore_obj, check_obj_flag; // fix rad; // int start_time = timer_get_milliseconds();; // vms_vector p0,p1; // // ignore_obj = 1; // check_obj_flag = 0; // this_objnum = -1; // rad = F1_0/4; // // for (i=0; ix - v2->x) < Normal_nearness) if (abs(v1->y - v2->y) < Normal_nearness) if (abs(v1->z - v2->z) < Normal_nearness) return 1; return 0; } int Total_normals=0; int Diff_normals=0; void print_normals(void) { int i,j,s,n,nn; // vms_vector *normal; int num_normals=0; Total_normals = 0; Diff_normals = 0; for (i=0; i<=Highest_segment_index; i++) for (s=0; s<6; s++) { if (Segments[i].sides[s].type == SIDE_IS_QUAD) nn=1; else nn=2; for (n=0; n #include #include #include #include "inferno.h" #include "gameseg.h" #include "screens.h" // For GAME_SCREEN????? #include "editor.h" // For TMAP_CURBOX?????? #include "gr.h" // For canves, font stuff #include "ui.h" // For UI_GADGET stuff #include "textures.h" // For NumTextures #include "dxxerror.h" #include "key.h" #include "gamesave.h" #include "mission.h" #include "texpage.h" #include "piggy.h" #define TMAPS_PER_PAGE 12 static UI_GADGET_USERBOX * TmapBox[TMAPS_PER_PAGE]; static UI_GADGET_USERBOX * TmapCurrent; int CurrentTexture = 0; // Used globally int TextureLights = 275; int TextureEffects = 308; int TextureMetals = 202; static int TexturePage = 0; static grs_canvas * TmapnameCanvas; static char tmap_filename[13]; static void texpage_print_name( char name[13] ) { int w,h,aw; int i; for (i=strlen(name);i<12;i++) name[i]=' '; name[i]=0; gr_set_current_canvas( TmapnameCanvas ); gr_get_string_size( name, &w, &h, &aw ); gr_string( 0, 0, name ); } static void texpage_display_name( char *format, ... ) { va_list ap; va_start(ap, format); vsprintf(tmap_filename, format, ap); va_end(ap); texpage_print_name(tmap_filename); } //Redraw the list of textures, based on TexturePage void texpage_redraw() { int i; for (i = 0; i < TMAPS_PER_PAGE; i++) { gr_set_current_canvas(TmapBox[i]->canvas); if (i + TexturePage*TMAPS_PER_PAGE < NumTextures) { PIGGY_PAGE_IN(Textures[i + TexturePage*TMAPS_PER_PAGE]); gr_ubitmap(0, 0, &GameBitmaps[Textures[i + TexturePage*TMAPS_PER_PAGE].index]); } else gr_clear_canvas( CGREY ); } } //shows the current texture, updating the window and printing the name, base //on CurrentTexture void texpage_show_current() { gr_set_current_canvas(TmapCurrent->canvas); PIGGY_PAGE_IN(Textures[CurrentTexture]); gr_ubitmap(0,0, &GameBitmaps[Textures[CurrentTexture].index]); texpage_display_name( TmapInfo[CurrentTexture].filename ); } int texpage_goto_first() { TexturePage=0; texpage_redraw(); return 1; } int texpage_goto_metals() { TexturePage=TextureMetals/TMAPS_PER_PAGE; texpage_redraw(); return 1; } // Goto lights (paste ons) int texpage_goto_lights() { TexturePage=TextureLights/TMAPS_PER_PAGE; texpage_redraw(); return 1; } int texpage_goto_effects() { TexturePage=TextureEffects/TMAPS_PER_PAGE; texpage_redraw(); return 1; } static int texpage_goto_prev() { if (TexturePage > 0) { TexturePage--; texpage_redraw(); } return 1; } static int texpage_goto_next() { if ((TexturePage + 1)*TMAPS_PER_PAGE < NumTextures) { TexturePage++; texpage_redraw(); } return 1; } //NOTE: this code takes the texture map number, not this index in the //list of available textures. There are different if there are holes in //the list int texpage_grab_current(int n) { if ((n < 0) || (n >= NumTextures)) return 0; CurrentTexture = n; TexturePage = CurrentTexture / TMAPS_PER_PAGE; if (TexturePage*TMAPS_PER_PAGE < NumTextures) texpage_redraw(); texpage_show_current(); return 1; } // INIT TEXTURE STUFF void texpage_init( UI_DIALOG * dlg ) { int i; ui_add_gadget_button( dlg, TMAPCURBOX_X + 00, TMAPCURBOX_Y - 24, 30, 20, "<<", texpage_goto_prev ); ui_add_gadget_button( dlg, TMAPCURBOX_X + 32, TMAPCURBOX_Y - 24, 30, 20, ">>", texpage_goto_next ); ui_add_gadget_button( dlg, TMAPCURBOX_X + 00, TMAPCURBOX_Y - 48, 15, 20, "T", texpage_goto_first ); ui_add_gadget_button( dlg, TMAPCURBOX_X + 17, TMAPCURBOX_Y - 48, 15, 20, "M", texpage_goto_metals ); ui_add_gadget_button( dlg, TMAPCURBOX_X + 34, TMAPCURBOX_Y - 48, 15, 20, "L", texpage_goto_lights ); ui_add_gadget_button( dlg, TMAPCURBOX_X + 51, TMAPCURBOX_Y - 48, 15, 20, "E", texpage_goto_effects ); for (i=0;isc_canvas, TMAPCURBOX_X , TMAPCURBOX_Y + TMAPBOX_H + 10, 100, 20); } void texpage_close() { gr_free_sub_canvas(TmapnameCanvas); } // DO TEXTURE STUFF #define MAX_REPLACEMENTS 32 typedef struct replacement { int new, old; } replacement; replacement Replacement_list[MAX_REPLACEMENTS]; int Num_replacements=0; int texpage_do(d_event *event) { int i; if (event->type == EVENT_UI_DIALOG_DRAW) { gr_set_current_canvas( TmapnameCanvas ); gr_set_curfont( ui_small_font ); gr_set_fontcolor( CBLACK, CWHITE ); texpage_redraw(); gr_set_curfont(editor_font); // Don't reset the current tmap every time we go back to the editor. // CurrentTexture = TexturePage*TMAPS_PER_PAGE; texpage_show_current(); return 1; } for (i=0; i= 0); Assert(new_tmap_num >= 0); for (segnum=0; segnum <= Highest_segment_index; segnum++) { segment *segp=&Segments[segnum]; for (sidenum=0; sidenumsides[sidenum]; if (sidep->tmap_num == old_tmap_num) { sidep->tmap_num = new_tmap_num; } if ((sidep->tmap_num2 != 0) && ((sidep->tmap_num2 & 0x3fff) == old_tmap_num)) { if (new_tmap_num == 0) { Int3(); // Error. You have tried to replace a tmap_num2 with // the 0th tmap_num2 which is ILLEGAL! } else { sidep->tmap_num2 = new_tmap_num | (sidep->tmap_num2 & 0xc000); } } } } } } void do_replacements_all(void) { int i; for (i = 0; i < Last_level; i++) { load_level(Level_names[i]); do_replacements(); save_level(Level_names[i]); } for (i = 0; i < -Last_secret_level; i++) { load_level(Secret_level_names[i]); do_replacements(); save_level(Secret_level_names[i]); } } dxx-rebirth-0.58.1-d2x/editor/texture.c000066400000000000000000000221441217717237500177110ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Texture map assignment. * */ #include #include #include #include #include #include "inferno.h" #include "segment.h" #include "seguvs.h" #include "editor.h" #include "editor/esegment.h" #include "fix.h" #include "dxxerror.h" #include "kdefs.h" void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum); void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter); // ----------------------------------------------------------- int TexFlipX() { uvl uvcenter; fix rotmat[4]; compute_uv_side_center(&uvcenter, Cursegp, Curside); // Create a rotation matrix rotmat[0] = -0xffff; rotmat[1] = 0; rotmat[2] = 0; rotmat[3] = 0xffff; rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); Update_flags |= UF_WORLD_CHANGED; return 1; } // ----------------------------------------------------------- int TexFlipY() { uvl uvcenter; fix rotmat[4]; compute_uv_side_center(&uvcenter, Cursegp, Curside); // Create a rotation matrix rotmat[0] = 0xffff; rotmat[1] = 0; rotmat[2] = 0; rotmat[3] = -0xffff; rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); Update_flags |= UF_WORLD_CHANGED; return 1; } // ----------------------------------------------------------- int DoTexSlideLeft(int value) { side *sidep; uvl duvl03; fix dist; const sbyte *vp; int v; vp = Side_to_verts[Curside]; sidep = &Cursegp->sides[Curside]; dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]); dist *= value; if (dist < F1_0/(64*value)) dist = F1_0/(64*value); duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist); duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist); for (v=0; v<4; v++) { sidep->uvls[v].u -= duvl03.u; sidep->uvls[v].v -= duvl03.v; } Update_flags |= UF_WORLD_CHANGED; return 1; } int TexSlideLeft() { return DoTexSlideLeft(3); } int TexSlideLeftBig() { return DoTexSlideLeft(1); } // ----------------------------------------------------------- int DoTexSlideUp(int value) { side *sidep; uvl duvl03; fix dist; const sbyte *vp; int v; vp = Side_to_verts[Curside]; sidep = &Cursegp->sides[Curside]; dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]); dist *= value; if (dist < F1_0/(64*value)) dist = F1_0/(64*value); duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist); duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist); for (v=0; v<4; v++) { sidep->uvls[v].u -= duvl03.u; sidep->uvls[v].v -= duvl03.v; } Update_flags |= UF_WORLD_CHANGED; return 1; } int TexSlideUp() { return DoTexSlideUp(3); } int TexSlideUpBig() { return DoTexSlideUp(1); } // ----------------------------------------------------------- int DoTexSlideDown(int value) { side *sidep; uvl duvl03; fix dist; const sbyte *vp; int v; vp = Side_to_verts[Curside]; sidep = &Cursegp->sides[Curside]; dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]); dist *= value; if (dist < F1_0/(64*value)) dist = F1_0/(64*value); duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist); duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist); for (v=0; v<4; v++) { sidep->uvls[v].u += duvl03.u; sidep->uvls[v].v += duvl03.v; } Update_flags |= UF_WORLD_CHANGED; return 1; } int TexSlideDown() { return DoTexSlideDown(3); } int TexSlideDownBig() { return DoTexSlideDown(1); } // ----------------------------------------------------------- // Compute the center of the side in u,v coordinates. void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum) { int v; side *sidep = &segp->sides[sidenum]; uvcenter->u = 0; uvcenter->v = 0; for (v=0; v<4; v++) { uvcenter->u += sidep->uvls[v].u; uvcenter->v += sidep->uvls[v].v; } uvcenter->u /= 4; uvcenter->v /= 4; } // ----------------------------------------------------------- // rotate point *uv by matrix rotmat, return *uvrot void rotate_uv_point(uvl *uvrot, fix *rotmat, uvl *uv, uvl *uvcenter) { uvrot->u = fixmul(uv->u - uvcenter->u,rotmat[0]) + fixmul(uv->v - uvcenter->v,rotmat[1]) + uvcenter->u; uvrot->v = fixmul(uv->u - uvcenter->u,rotmat[2]) + fixmul(uv->v - uvcenter->v,rotmat[3]) + uvcenter->v; } // ----------------------------------------------------------- // Compute the center of the side in u,v coordinates. void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter) { int v; side *sidep = &segp->sides[sidenum]; uvl tuv; for (v=0; v<4; v++) { rotate_uv_point(&tuv, rotmat, &sidep->uvls[v], uvcenter); sidep->uvls[v] = tuv; } } // ----------------------------------------------------------- // ang is in 0..ffff = 0..359.999 degrees // rotmat is filled in with 4 fixes void create_2d_rotation_matrix(fix *rotmat, fix ang) { fix sinang, cosang; fix_sincos(ang, &sinang, &cosang); rotmat[0] = cosang; rotmat[1] = sinang; rotmat[2] = -sinang; rotmat[3] = cosang; } // ----------------------------------------------------------- int DoTexRotateLeft(int value) { uvl uvcenter; fix rotmat[4]; compute_uv_side_center(&uvcenter, Cursegp, Curside); // Create a rotation matrix create_2d_rotation_matrix(rotmat, -F1_0/value); rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); Update_flags |= UF_WORLD_CHANGED; return 1; } int TexRotateLeft() { return DoTexRotateLeft(192); } int TexRotateLeftBig() { return DoTexRotateLeft(64); } // ----------------------------------------------------------- int DoTexSlideRight(int value) { side *sidep; uvl duvl03; fix dist; const sbyte *vp; int v; vp = Side_to_verts[Curside]; sidep = &Cursegp->sides[Curside]; dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]); dist *= value; if (dist < F1_0/(64*value)) dist = F1_0/(64*value); duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist); duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist); for (v=0; v<4; v++) { sidep->uvls[v].u += duvl03.u; sidep->uvls[v].v += duvl03.v; } Update_flags |= UF_WORLD_CHANGED; return 1; } int TexSlideRight() { return DoTexSlideRight(3); } int TexSlideRightBig() { return DoTexSlideRight(1); } // ----------------------------------------------------------- int DoTexRotateRight(int value) { uvl uvcenter; fix rotmat[4]; compute_uv_side_center(&uvcenter, Cursegp, Curside); // Create a rotation matrix create_2d_rotation_matrix(rotmat, F1_0/value); rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); Update_flags |= UF_WORLD_CHANGED; return 1; } int TexRotateRight() { return DoTexRotateRight(192); } int TexRotateRightBig() { return DoTexRotateRight(64); } // ----------------------------------------------------------- int TexSelectActiveEdge() { return 1; } // ----------------------------------------------------------- int TexRotate90Degrees() { uvl uvcenter; fix rotmat[4]; compute_uv_side_center(&uvcenter, Cursegp, Curside); // Create a rotation matrix create_2d_rotation_matrix(rotmat, F1_0/4); rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); Update_flags |= UF_WORLD_CHANGED; return 1; } // ----------------------------------------------------------- int TexSetDefault() { Num_tilings = 1; Stretch_scale_x = F1_0; Stretch_scale_y = F1_0; assign_default_uvs_to_side(Cursegp,Curside); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } // ----------------------------------------------------------- int TexIncreaseTiling() { Num_tilings++; assign_default_uvs_to_side(Cursegp, Curside); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } // ----------------------------------------------------------- int TexDecreaseTiling() { if (--Num_tilings < 1) Num_tilings = 1; assign_default_uvs_to_side(Cursegp, Curside); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } // direction = -1 or 1 depending on direction int TexStretchCommon(int direction) { fix *sptr; if ((Curedge == 0) || (Curedge == 2)) sptr = &Stretch_scale_x; else sptr = &Stretch_scale_y; *sptr += direction*F1_0/64; if (*sptr < F1_0/16) *sptr = F1_0/16; if (*sptr > 2*F1_0) *sptr = 2*F1_0; stretch_uvs_from_curedge(Cursegp, Curside); editor_status_fmt("Stretch scale = %7.4f, use Set Default to return to 1.0", f2fl(*sptr)); Update_flags |= UF_GAME_VIEW_CHANGED; return 1; } int TexStretchDown(void) { return TexStretchCommon(-1); } int TexStretchUp(void) { return TexStretchCommon(1); } dxx-rebirth-0.58.1-d2x/iff/000077500000000000000000000000001217717237500153205ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/iff/archive/000077500000000000000000000000001217717237500167415ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/iff/archive/iff15bpp.c000066400000000000000000000043601217717237500205240ustar00rootroot00000000000000#include #include #include #include "iff.h" #define INDEX_TO_15BPP(i) ((WORD)((((palptr[(i)].r/2)&31)<<10)+(((palptr[(i)].g/2)&31)<<5)+((palptr[(i)].b/2 )&31))) extern int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header); int x,y,pl,bc; int bytes_per_row,color; int mask,first_bit_value; FILE *ifile; struct bitmap_header iff_bitmap_header; // Parse ilbm style data at my_bh->raw_data. BITMAP15 * IFF_To_15BPP(char * ifilename) { struct bitmap_header * my_bh; int Process_width,Process_height; unsigned char *p; struct pal_entry *palptr; int newptr = 0; int i; BITMAP15 * new; my_bh = &iff_bitmap_header; palptr=my_bh->palette; p=my_bh->raw_data; Process_width = 32767; // say to process full width of bitmap Process_height = 32767; // say to process full height of bitmap if ((ifile = fopen(ifilename,"rb")) == NULL) { printf("Unable to open bitmap file %s.\n", ifilename); exit(1); } parse_iff(ifile,&iff_bitmap_header); if (Process_width > iff_bitmap_header.w) Process_width = iff_bitmap_header.w; if (Process_height > iff_bitmap_header.h) Process_height = iff_bitmap_header.h; //printf( "%d, %d\n", Process_width, Process_height ); new = (BITMAP15 *)malloc( sizeof(BITMAP15)+ (Process_width * Process_height * 2 )); if (new==NULL) exit(1); new->Width = Process_width; new->Height = Process_height; //printf("Process_width = %i, Process_height = %i\n",Process_width,Process_height); first_bit_value = 1 << (my_bh->nplanes-1); bytes_per_row = 2*((my_bh->w+15)/16); for (y=0; yraw_data[y*bytes_per_row*my_bh->nplanes]; switch (my_bh->type) { case PBM_TYPE: for (x=0; xw; x++) { new->Data[newptr++] = INDEX_TO_15BPP(my_bh->raw_data[y*my_bh->w+x]); } break; case ILBM_TYPE: for (x=0; xnplanes; pl++) { color /= 2; if ( p[pl*bytes_per_row+x] & mask) color += first_bit_value; } new->Data[newptr++] = INDEX_TO_15BPP(color); bc--; if (!bc) goto line_done; } } line_done: ; break; } } free( my_bh->raw_data ); return new; } ÿdxx-rebirth-0.58.1-d2x/iff/archive/iff8bpp.c000066400000000000000000000044451217717237500204520ustar00rootroot00000000000000#include #include #include #include "iff.h" extern int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header); int x,y,pl,bc; int bytes_per_row,color; int mask,first_bit_value; FILE *ifile; struct bitmap_header iff_bitmap_header; // Parse ilbm style data at my_bh->raw_data. BITMAP8 * IFF_To_8BPP(char * ifilename) { struct bitmap_header * my_bh; int Process_width,Process_height; unsigned char *p; struct pal_entry *palptr; int newptr = 0; int i; BITMAP8 * new; my_bh = &iff_bitmap_header; palptr=my_bh->palette; p=my_bh->raw_data; Process_width = 32767; // say to process full width of bitmap Process_height = 32767; // say to process full height of bitmap if ((ifile = fopen(ifilename,"rb")) == NULL) { printf("Unable to open bitmap file %s.\n", ifilename); exit(1); } parse_iff(ifile,&iff_bitmap_header); if (Process_width > iff_bitmap_header.w) Process_width = iff_bitmap_header.w; if (Process_height > iff_bitmap_header.h) Process_height = iff_bitmap_header.h; printf( "%d, %d\n", Process_width, Process_height ); new = (BITMAP8 *)malloc( sizeof(BITMAP8)+ (Process_width * Process_height ) ); if (new==NULL) exit(1); new->Width = Process_width; new->Height = Process_height; for (i=0;i<256;i++) { new->Palette[3*i] = my_bh->palette[i].r; new->Palette[3*i+1] = my_bh->palette[i].g; new->Palette[3*i+2] = my_bh->palette[i].b; } printf("Process_width = %i, Process_height = %i\n",Process_width,Process_height); first_bit_value = 1 << (my_bh->nplanes-1); bytes_per_row = 2*((my_bh->w+15)/16); for (y=0; yraw_data[y*bytes_per_row*my_bh->nplanes]; switch (my_bh->type) { case PBM_TYPE: for (x=0; xw; x++) { new->Data[newptr++] = my_bh->raw_data[y*my_bh->w+x]; } break; case ILBM_TYPE: for (x=0; xnplanes; pl++) { color /= 2; if ( p[pl*bytes_per_row+x] & mask) color += first_bit_value; } new->Data[newptr++] = color; bc--; if (!bc) goto line_done; } } line_done: ; break; } } free( my_bh->raw_data ); fclose(ifile); return new; } ÿdxx-rebirth-0.58.1-d2x/iff/archive/iffmike.c000066400000000000000000000247271217717237500205330ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include #include #include "iff.h" #define MIN(a,b) ((a> 8; c1 = n & 0xff; put_byte(c0,f); return put_byte(c1,f); } int put_long(long n,FILE *f) { int n0,n1; n0 = (int) ((n & 0xffff0000l) >> 16); n1 = (int) (n & 0xffff); put_word(n0,f); return put_word(n1,f); } long get_long(FILE *f) { unsigned char c0,c1,c2,c3; c3=getc(f); c2=getc(f); c1=getc(f); c0=getc(f); //printf("get_long %x %x %x %x\n",c3,c2,c1,c0); // if (c0==0xff) return(EOF); return(((long)c3<<24) + ((long)c2<<16) + ((long)c1<<8) + c0); } void parse_bmhd(FILE *ifile,long len,struct bitmap_header *bitmap_header) { len++; /* so no "parm not used" warning */ // debug("parsing bmhd len=%ld\n",len); bitmap_header->w = get_word(ifile); bitmap_header->h = get_word(ifile); bitmap_header->x = get_word(ifile); bitmap_header->y = get_word(ifile); bitmap_header->nplanes = get_byte(ifile); bitmap_header->masking = get_byte(ifile); bitmap_header->compression = get_byte(ifile); get_byte(ifile); /* skip pad */ bitmap_header->transparentcolor = get_word(ifile); bitmap_header->xaspect = get_byte(ifile); bitmap_header->yaspect = get_byte(ifile); bitmap_header->pagewidth = get_word(ifile); bitmap_header->pageheight = get_word(ifile); // debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y); // debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor); } // the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data int parse_body_pbm(FILE *ifile,long len,struct bitmap_header *bitmap_header) { unsigned char huge *p=bitmap_header->raw_data; int width=bitmap_header->w; long cnt,old_cnt; char n; int nn,wid_cnt; char ignore; if (bitmap_header->compression == cmpNone) { /* no compression */ int x,y; for (y=bitmap_header->h;y;y--) { for (x=bitmap_header->w;x;x--) *p++=getc(ifile); if (bitmap_header->w & 1) ignore = getc(ifile); } } else if (bitmap_header->compression == cmpByteRun1) for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) { unsigned char c; if (old_cnt-cnt > 2048) { // printf("."); old_cnt=cnt; } if (wid_cnt <= 0) wid_cnt = width; n=getc(ifile); if (n >= 0) { // copy next n+1 bytes from source, they are not compressed nn = (int) n+1; cnt -= nn+1; wid_cnt -= nn; if (wid_cnt==-1) --nn; while (nn--) *p++=getc(ifile); if (wid_cnt==-1) ignore = getc(ifile); /* extra char */ } else if (n>=-127) { // next -n + 1 bytes are following byte cnt -= 2; c=getc(ifile); nn = (int) -n+1; wid_cnt -= nn; if (wid_cnt==-1) --nn; while (nn--) *p++=c; } } if (len & 1) ignore = getc(ifile); if (ignore) ignore++; // haha, suppress the evil warning message return IFF_NO_ERROR; } // the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data int parse_body_ilbm(FILE *ifile,long len,struct bitmap_header *bitmap_header) { unsigned char huge *p=bitmap_header->raw_data; int width=bitmap_header->w; long cnt,old_cnt; char n; int nn,wid_cnt; char ignore; if (bitmap_header->compression == cmpNone) { /* no compression */ int x,y; for (y=bitmap_header->h;y;y--) { for (x=bitmap_header->w;x;x--) *p++=getc(ifile); if (bitmap_header->w & 1) ignore = getc(ifile); } } else if (bitmap_header->compression == cmpByteRun1) for (old_cnt=cnt=len,wid_cnt=width;cnt>0;) { unsigned char c; if (old_cnt-cnt > 2048) { // printf("."); old_cnt=cnt; } if (wid_cnt <= 0) wid_cnt = width; n=getc(ifile); if (n >= 0) { // copy next n+1 bytes from source, they are not compressed nn = (int) n+1; cnt -= nn+1; wid_cnt -= nn; if (wid_cnt==-1) --nn; while (nn--) *p++=getc(ifile); if (wid_cnt==-1) ignore = getc(ifile); /* extra char */ } else if (n>=-127) { // next -n + 1 bytes are following byte cnt -= 2; c=getc(ifile); nn = (int) -n+1; wid_cnt -= nn; if (wid_cnt==-1) --nn; while (nn--) *p++=c; } } if (len & 1) ignore = getc(ifile); if (ignore) ignore++; // haha, suppress the evil warning message return IFF_NO_ERROR; } void skip_chunk(FILE *ifile,long len) { len = len+1 & ~1; fseek(ifile,len,SEEK_CUR); } // Pass pointer to opened file, and to empty bitmap header. int parse_iff(FILE *ifile,struct bitmap_header *bitmap_header) { long sig,form_len,len,form_type; char ignore; sig=get_sig(ifile); // printsig(sig); if (sig==form_sig) { form_len = get_long(ifile); form_len++; /* get rid of never used message */ form_type = get_sig(ifile); // printf(" %ld ",form_len); // printsig(form_type); // printf("\n"); if ((form_type == pbm_sig) || (form_type == ilbm_sig)) { if (form_type == pbm_sig) bitmap_header->type = PBM_TYPE; else bitmap_header->type = ILBM_TYPE; while ((sig=get_sig(ifile)) != EOF) { len=get_long(ifile); // printf(" "); // printsig(sig); // printf(" %ld\n",len); switch (sig) { case bmhd_sig: parse_bmhd(ifile,len,bitmap_header); if (! (bitmap_header->raw_data = farmalloc((long) bitmap_header->w * bitmap_header->h))) return IFF_NO_MEM; break; case cmap_sig: { int ncolors=(int) (len/3),cnum; unsigned char r,g,b; for (cnum=0;cnum>= 2; bitmap_header->palette[cnum].r = r; g >>= 2; bitmap_header->palette[cnum].g = g; b >>= 2; bitmap_header->palette[cnum].b = b; } if (len & 1) ignore = getc(ifile); break; } case body_sig: { int r; switch (form_type) { case pbm_sig: if (!(r=parse_body_pbm(ifile,len,bitmap_header))) return r; break; case ilbm_sig: if (!(r=parse_body_ilbm(ifile,len,bitmap_header))) return r; break; } break; } default: skip_chunk(ifile,len); break; } } } else return IFF_UNKNOWN_FORM; } else {printf("Not an IFF file\n"); return IFF_NOT_IFF;} if (ignore) ignore++; return IFF_NO_ERROR; /* ok! */ } #define BMHD_SIZE 20 int write_bmhd(FILE *ofile,struct bitmap_header *bitmap_header) { put_sig(bmhd_sig,ofile); put_long((long) BMHD_SIZE,ofile); put_word(bitmap_header->w,ofile); put_word(bitmap_header->h,ofile); put_word(bitmap_header->x,ofile); put_word(bitmap_header->y,ofile); put_byte(bitmap_header->nplanes,ofile); put_byte(bitmap_header->masking,ofile); put_byte(bitmap_header->compression,ofile); put_byte(0,ofile); /* pad */ put_word(bitmap_header->transparentcolor,ofile); put_byte(bitmap_header->xaspect,ofile); put_byte(bitmap_header->yaspect,ofile); put_word(bitmap_header->pagewidth,ofile); put_word(bitmap_header->pageheight,ofile); return 1; } int write_huge(unsigned char huge *huge_ptr,long len,FILE *f) { unsigned char temp_buffer[256],*t; //printf("write_huge %ld\n",len); while (len) { int n,wsize = (int) MIN(len,256); //printf("len,wsize=%ld,%d\n",len,wsize); for (t=temp_buffer,n=wsize;n--;) *t++ = *huge_ptr++; fwrite(temp_buffer,wsize,1,f); len -= wsize; } return 1; } int write_pal(FILE *ofile,struct bitmap_header *bitmap_header) { int i; int n_colors = 1<nplanes; put_sig(cmap_sig,ofile); // put_long(sizeof(struct pal_entry) * n_colors,ofile); put_long(3 * n_colors,ofile); //printf("new write pal %d %d\n",3,n_colors); for (i=0; i<256; i++) { unsigned char r,g,b; r = bitmap_header->palette[i].r * 4; g = bitmap_header->palette[i].g * 4; b = bitmap_header->palette[i].b * 4; fputc(r,ofile); fputc(g,ofile); fputc(b,ofile); } //printf("write pal %d %d\n",sizeof(struct pal_entry),n_colors); // fwrite(bitmap_header->palette,sizeof(struct pal_entry),n_colors,ofile); return 1; } #define EVEN(a) ((a+1)&0xfffffffel) int write_body(FILE *ofile,struct bitmap_header *bitmap_header) { int w=bitmap_header->w,h=bitmap_header->h; int y,odd=w&1; long len = EVEN(w) * h; unsigned char huge *p=bitmap_header->raw_data; put_sig(body_sig,ofile); put_long(len,ofile); for (y=bitmap_header->h;y--;) { write_huge(p,bitmap_header->w,ofile); if (odd) putc(0,ofile); p+=bitmap_header->w; } return 1; } int write_pbm(FILE *ofile,struct bitmap_header *bitmap_header) /* writes a pbm iff file */ { long raw_size = EVEN(bitmap_header->w) * bitmap_header->h; long pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(struct pal_entry)*(1<nplanes)+8; //printf("write_pbm\n"); put_sig(form_sig,ofile); put_long(pbm_size+8,ofile); put_sig(pbm_sig,ofile); write_bmhd(ofile,bitmap_header); write_pal(ofile,bitmap_header); write_body(ofile,bitmap_header); return 1; } dxx-rebirth-0.58.1-d2x/iff/archive/ifftest.c000066400000000000000000000046711217717237500205610ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include #include #include "iff.h" #include "vga.h" #include "palette.h" #include "mem.h" //#define ANIM_TEST 1 //if defined, read in anim brush rle_span(ubyte *dest,ubyte *src,int len); ubyte test_span[] = {0,1,2,3,4,4,5,6,7,8,8,8,8,8,9,10,11,11}; ubyte new_span[256]; extern void gr_pal_setblock( int start, int number, unsigned char * pal ); main(int argc,char **argv) { int ret; grs_bitmap my_bitmap; ubyte my_palette[256*3]; grs_bitmap *bm_list[100]; int n_bitmaps; char key; #if 0 { int new_len,i; new_len=rle_span(new_span,test_span,sizeof(test_span)); printf("old span (%d): ",sizeof(test_span)); for (i=0;i",iff_errormsg(ret)); if (ret == IFF_NO_ERROR) { int i; vga_init(); gr_init(); vga_set_mode(SM_320x200C); for (i=0;i2) { ret = iff_write_bitmap(argv[2],bm_list[i],&my_palette); printf("ret = %d\n",ret); } //gr_pal_setblock(0,256,&my_palette); gr_palette_load(&my_palette); //gr_pal_fade_in(grd_curscreen->pal); //in case palette is blacked gr_ubitmap(0,0,bm_list[i]); key = getch(); if (key=='-') {if (i) i--;} else i++; } gr_close(); for (i=0;ibm_data); #ifdef ANIM_TEST free(bm_list[i]); #endif } } } dxx-rebirth-0.58.1-d2x/iff/archive/ifftestv.c000066400000000000000000000025121217717237500207370ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include #include "iff.h" draw_ubitmap(int x,int y,grs_bitmap *bm) { int xx,yy; short *data15 = (short *) bm->bm_data; printf("x,y=%d,%d w,h=%d,%d\n",x,y,bm->bm_w,bm->bm_h); for (yy=0;yybm_h;yy++) for (xx=0;xxbm_w;xx++) gr_vesa_pixel15(x+xx,y+yy,data15[yy*bm->bm_w+xx]); } main(int argc,char **argv) { int ret; grs_bitmap my_bitmap; ubyte my_palette[256*3]; ret = iff_read_bitmap(argv[1],&my_bitmap,BM_RGB15,&my_palette); printf("ret = %d\n",ret); if (ret == IFF_NO_ERROR) { gr_vesa_setmode(0x110); draw_ubitmap(0,0,&my_bitmap); getch(); } } dxx-rebirth-0.58.1-d2x/iff/iff.c000066400000000000000000000600331217717237500162320ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines for reading and writing IFF files * */ #define COMPRESS 1 //do the RLE or not? (for debugging mostly) #define WRITE_TINY 0 //should we write a TINY chunk? #define MIN_COMPRESS_WIDTH 65 //don't compress if less than this wide #include #include #include #include "u_mem.h" #include "iff.h" #include "dxxerror.h" #include "makesig.h" #include "physfsx.h" //Internal constants and structures for this library //Type values for bitmaps #define TYPE_PBM 0 #define TYPE_ILBM 1 //Compression types #define cmpNone 0 #define cmpByteRun1 1 //Masking types #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 //Palette entry structure typedef struct pal_entry { sbyte r,g,b; } pal_entry; //structure of the header in the file typedef struct iff_bitmap_header { short w,h; //width and height of this bitmap short x,y; //generally unused short type; //see types above short transparentcolor; //which color is transparent (if any) short pagewidth,pageheight; //width & height of source screen sbyte nplanes; //number of planes (8 for 256 color image) sbyte masking,compression; //see constants above sbyte xaspect,yaspect; //aspect ratio (usually 5/6) pal_entry palette[256]; //the palette for this bitmap ubyte *raw_data; //ptr to array of data short row_size; //offset to next row } iff_bitmap_header; ubyte iff_transparent_color; ubyte iff_has_transparency; // 0=no transparency, 1=iff_transparent_color is valid #define form_sig MAKE_SIG('F','O','R','M') #define ilbm_sig MAKE_SIG('I','L','B','M') #define body_sig MAKE_SIG('B','O','D','Y') #define pbm_sig MAKE_SIG('P','B','M',' ') #define bmhd_sig MAKE_SIG('B','M','H','D') #define anhd_sig MAKE_SIG('A','N','H','D') #define cmap_sig MAKE_SIG('C','M','A','P') #define tiny_sig MAKE_SIG('T','I','N','Y') #define anim_sig MAKE_SIG('A','N','I','M') #define dlta_sig MAKE_SIG('D','L','T','A') int get_sig(PHYSFS_file *f) { int s; PHYSFS_readSBE32(f, &s); return s; } #define put_sig(sig, f) PHYSFS_writeSBE32(f, sig) int parse_bmhd(PHYSFS_file *ifile,long len,iff_bitmap_header *bmheader) { len++; /* so no "parm not used" warning */ // debug("parsing bmhd len=%ld\n",len); PHYSFS_readSBE16(ifile, &bmheader->w); PHYSFS_readSBE16(ifile, &bmheader->h); PHYSFS_readSBE16(ifile, &bmheader->x); PHYSFS_readSBE16(ifile, &bmheader->y); bmheader->nplanes = PHYSFSX_readByte(ifile); bmheader->masking = PHYSFSX_readByte(ifile); bmheader->compression = PHYSFSX_readByte(ifile); PHYSFSX_readByte(ifile); /* skip pad */ PHYSFS_readSBE16(ifile, &bmheader->transparentcolor); bmheader->xaspect = PHYSFSX_readByte(ifile); bmheader->yaspect = PHYSFSX_readByte(ifile); PHYSFS_readSBE16(ifile, &bmheader->pagewidth); PHYSFS_readSBE16(ifile, &bmheader->pageheight); iff_transparent_color = bmheader->transparentcolor; iff_has_transparency = 0; if (bmheader->masking == mskHasTransparentColor) iff_has_transparency = 1; else if (bmheader->masking != mskNone && bmheader->masking != mskHasMask) return IFF_UNKNOWN_MASK; // debug("w,h=%d,%d x,y=%d,%d\n",w,h,x,y); // debug("nplanes=%d, masking=%d ,compression=%d, transcolor=%d\n",nplanes,masking,compression,transparentcolor); return IFF_NO_ERROR; } // the buffer pointed to by raw_data is stuffed with a pointer to decompressed pixel data int parse_body(PHYSFS_file *ifile,long len,iff_bitmap_header *bmheader) { unsigned char *p=bmheader->raw_data; int width,depth; signed char n; int nn,wid_cnt,end_cnt,plane; unsigned char *data_end; int end_pos; #ifndef NDEBUG int row_count=0; #endif width=0; depth=0; end_pos = PHYSFS_tell(ifile) + len; if (len&1) end_pos++; if (bmheader->type == TYPE_PBM) { width=bmheader->w; depth=1; } else if (bmheader->type == TYPE_ILBM) { width = (bmheader->w+7)/8; depth=bmheader->nplanes; } end_cnt = (width&1)?-1:0; data_end = p + width*bmheader->h*depth; if (bmheader->compression == cmpNone) { /* no compression */ int y; for (y=bmheader->h;y;y--) { PHYSFS_read(ifile, p, width, depth); p += bmheader->w; if (bmheader->masking == mskHasMask) PHYSFSX_fseek(ifile, width, SEEK_CUR); //skip mask! if (bmheader->w & 1) PHYSFSX_fgetc(ifile); } //cnt = len - bmheader->h * ((bmheader->w+1)&~1); } else if (bmheader->compression == cmpByteRun1) for (wid_cnt=width,plane=0; PHYSFS_tell(ifile) < end_pos && pmasking == mskHasMask && plane==depth+1) || (bmheader->masking != mskHasMask && plane==depth)) plane=0; } Assert(wid_cnt > end_cnt); n=PHYSFSX_fgetc(ifile); if (n >= 0) { // copy next n+1 bytes from source, they are not compressed nn = (int) n+1; wid_cnt -= nn; if (wid_cnt==-1) {--nn; Assert(width&1);} if (plane==depth) //masking row PHYSFSX_fseek(ifile, nn, SEEK_CUR); else { PHYSFS_read(ifile, p, nn, 1); p += nn; } if (wid_cnt==-1) PHYSFSX_fseek(ifile, 1, SEEK_CUR); } else if (n>=-127) { // next -n + 1 bytes are following byte c=PHYSFSX_fgetc(ifile); nn = (int) -n+1; wid_cnt -= nn; if (wid_cnt==-1) {--nn; Assert(width&1);} if (plane!=depth) //not masking row {memset(p,c,nn); p+=nn;} } #ifndef NDEBUG if ((p-bmheader->raw_data) % width == 0) row_count++; Assert((p-bmheader->raw_data) - (width*row_count) < width); #endif } if (p!=data_end) //if we don't have the whole bitmap... return IFF_CORRUPT; //...the give an error //Pretend we read the whole chuck, because if we didn't, it's because //we didn't read the last mask like or the last rle record for padding //or whatever and it's not important, because we check to make sure //we got the while bitmap, and that's what really counts. return IFF_NO_ERROR; } //modify passed bitmap int parse_delta(PHYSFS_file *ifile,long len,iff_bitmap_header *bmheader) { unsigned char *p=bmheader->raw_data; int y; long chunk_end = PHYSFS_tell(ifile) + len; PHYSFSX_fseek(ifile, 4, SEEK_CUR); //longword, seems to be equal to 4. Don't know what it is for (y=0;yh;y++) { ubyte n_items; int cnt = bmheader->w; ubyte code; n_items = PHYSFSX_readByte(ifile); while (n_items--) { code = PHYSFSX_readByte(ifile); if (code==0) { //repeat ubyte rep,val; rep = PHYSFSX_readByte(ifile); val = PHYSFSX_readByte(ifile); cnt -= rep; if (cnt==-1) rep--; while (rep--) *p++ = val; } else if (code > 0x80) { //skip cnt -= (code-0x80); p += (code-0x80); if (cnt==-1) p--; } else { //literal cnt -= code; if (cnt==-1) code--; while (code--) *p++ = PHYSFSX_readByte(ifile); if (cnt==-1) PHYSFSX_readByte(ifile); } } if (cnt == -1) { if (!bmheader->w&1) return IFF_CORRUPT; } else if (cnt) return IFF_CORRUPT; } if (PHYSFS_tell(ifile) == chunk_end-1) //pad PHYSFSX_fseek(ifile, 1, SEEK_CUR); if (PHYSFS_tell(ifile) != chunk_end) return IFF_CORRUPT; else return IFF_NO_ERROR; } // the buffer pointed to by raw_data is stuffed with a pointer to bitplane pixel data void skip_chunk(PHYSFS_file *ifile,long len) { int ilen; ilen = (len+1) & ~1; PHYSFSX_fseek(ifile,ilen,SEEK_CUR); } //read an ILBM or PBM file // Pass pointer to opened file, and to empty bitmap_header structure, and form length int iff_parse_ilbm_pbm(PHYSFS_file *ifile,long form_type,iff_bitmap_header *bmheader,int form_len,grs_bitmap *prev_bm) { int sig,len; long start_pos,end_pos; start_pos = PHYSFS_tell(ifile); end_pos = start_pos-4+form_len; if (form_type == pbm_sig) bmheader->type = TYPE_PBM; else bmheader->type = TYPE_ILBM; while ((PHYSFS_tell(ifile) < end_pos) && (sig=get_sig(ifile)) != EOF) { if (PHYSFS_readSBE32(ifile, &len)==EOF) break; switch (sig) { case bmhd_sig: { int ret; int save_w=bmheader->w,save_h=bmheader->h; ret = parse_bmhd(ifile,len,bmheader); if (ret != IFF_NO_ERROR) return ret; if (bmheader->raw_data) { if (save_w != bmheader->w || save_h != bmheader->h) return IFF_BM_MISMATCH; } else { MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h ); if (!bmheader->raw_data) return IFF_NO_MEM; } break; } case anhd_sig: if (!prev_bm) return IFF_CORRUPT; bmheader->w = prev_bm->bm_w; bmheader->h = prev_bm->bm_h; bmheader->type = prev_bm->bm_type; MALLOC( bmheader->raw_data, ubyte, bmheader->w * bmheader->h ); memcpy(bmheader->raw_data, prev_bm->bm_data, bmheader->w * bmheader->h ); skip_chunk(ifile,len); break; case cmap_sig: { int ncolors=(int) (len/3),cnum; unsigned char r,g,b; for (cnum=0;cnumdata[ifile->position++]; // g = ifile->data[ifile->position++]; // b = ifile->data[ifile->position++]; r >>= 2; bmheader->palette[cnum].r = r; g >>= 2; bmheader->palette[cnum].g = g; b >>= 2; bmheader->palette[cnum].b = b; } if (len & 1) PHYSFSX_fgetc(ifile); //if (len & 1 ) ifile->position++; break; } case body_sig: { int r; if ((r=parse_body(ifile,len,bmheader))!=IFF_NO_ERROR) return r; break; } case dlta_sig: { int r; if ((r=parse_delta(ifile,len,bmheader))!=IFF_NO_ERROR) return r; break; } default: skip_chunk(ifile,len); break; } } if (PHYSFS_tell(ifile) != start_pos-4+form_len) return IFF_CORRUPT; return IFF_NO_ERROR; /* ok! */ } //convert an ILBM file to a PBM file int convert_ilbm_to_pbm(iff_bitmap_header *bmheader) { int x,y,p; sbyte *new_data, *destptr, *rowptr; int bytes_per_row,byteofs; ubyte checkmask,newbyte,setbit; MALLOC(new_data, sbyte, bmheader->w * bmheader->h); if (new_data == NULL) return IFF_NO_MEM; destptr = new_data; bytes_per_row = 2*((bmheader->w+15)/16); for (y=0;yh;y++) { rowptr = (signed char *) &bmheader->raw_data[y * bytes_per_row * bmheader->nplanes]; for (x=0,checkmask=0x80;xw;x++) { byteofs = x >> 3; for (p=newbyte=0,setbit=1;pnplanes;p++) { if (rowptr[bytes_per_row * p + byteofs] & checkmask) newbyte |= setbit; setbit <<= 1; } *destptr++ = newbyte; if ((checkmask >>= 1) == 0) checkmask=0x80; } } d_free(bmheader->raw_data); bmheader->raw_data = (unsigned char *) new_data; bmheader->type = TYPE_PBM; return IFF_NO_ERROR; } #define INDEX_TO_15BPP(i) ((short)((((palptr[(i)].r/2)&31)<<10)+(((palptr[(i)].g/2)&31)<<5)+((palptr[(i)].b/2 )&31))) int convert_rgb15(grs_bitmap *bm,iff_bitmap_header *bmheader) { ushort *new_data; int x,y; int newptr = 0; pal_entry *palptr; palptr = bmheader->palette; // if ((new_data = d_malloc(bm->bm_w * bm->bm_h * 2)) == NULL) // {ret=IFF_NO_MEM; goto done;} MALLOC(new_data, ushort, bm->bm_w * bm->bm_h * 2); if (new_data == NULL) return IFF_NO_MEM; for (y=0; ybm_h; y++) { for (x=0; xw; x++) new_data[newptr++] = INDEX_TO_15BPP(bmheader->raw_data[y*bmheader->w+x]); } d_free(bm->bm_data); //get rid of old-style data bm->bm_data = (ubyte *) new_data; //..and point to new data bm->bm_rowsize *= 2; //two bytes per row return IFF_NO_ERROR; } //copy an iff header structure to a grs_bitmap structure void copy_iff_to_grs(grs_bitmap *bm,iff_bitmap_header *bmheader) { bm->bm_x = bm->bm_y = 0; bm->bm_w = bmheader->w; bm->bm_h = bmheader->h; bm->bm_type = bmheader->type; bm->bm_rowsize = bmheader->w; bm->bm_data = bmheader->raw_data; bm->bm_flags = bm->bm_handle = 0; } //if bm->bm_data is set, use it (making sure w & h are correct), else //allocate the memory int iff_parse_bitmap(PHYSFS_file *ifile, grs_bitmap *bm, int bitmap_type, sbyte *palette, grs_bitmap *prev_bm) { int ret; //return code iff_bitmap_header bmheader; int sig,form_len; long form_type; bmheader.raw_data = bm->bm_data; if (bmheader.raw_data) { bmheader.w = bm->bm_w; bmheader.h = bm->bm_h; } sig=get_sig(ifile); if (sig != form_sig) { return IFF_NOT_IFF; } PHYSFS_readSBE32(ifile, &form_len); form_type = get_sig(ifile); if (form_type == anim_sig) ret = IFF_FORM_ANIM; else if ((form_type == pbm_sig) || (form_type == ilbm_sig)) ret = iff_parse_ilbm_pbm(ifile,form_type,&bmheader,form_len,prev_bm); else ret = IFF_UNKNOWN_FORM; if (ret != IFF_NO_ERROR) { //got an error parsing if (bmheader.raw_data) d_free(bmheader.raw_data); return ret; } //If IFF file is ILBM, convert to PPB if (bmheader.type == TYPE_ILBM) { ret = convert_ilbm_to_pbm(&bmheader); if (ret != IFF_NO_ERROR) return ret; } //Copy data from iff_bitmap_header structure into grs_bitmap structure copy_iff_to_grs(bm,&bmheader); if (palette) memcpy(palette,&bmheader.palette,sizeof(bmheader.palette)); //Now do post-process if required if (bitmap_type == BM_RGB15) { ret = convert_rgb15(bm,&bmheader); if (ret != IFF_NO_ERROR) return ret; } return ret; } //returns error codes - see IFF.H. see GR.H for bitmap_type int iff_read_bitmap(char *ifilename,grs_bitmap *bm,int bitmap_type,ubyte *palette) { int ret; //return code PHYSFS_file *ifile; ifile = PHYSFSX_openReadBuffered(ifilename); if (ifile == NULL) return IFF_NO_FILE; bm->bm_data = NULL; ret = iff_parse_bitmap(ifile,bm,bitmap_type,(signed char *) palette,NULL); PHYSFS_close(ifile); return ret; } //like iff_read_bitmap(), but reads into a bitmap that already exists, //without allocating memory for the bitmap. int iff_read_into_bitmap(char *ifilename, grs_bitmap *bm, sbyte *palette) { int ret; //return code PHYSFS_file *ifile; ifile = PHYSFSX_openReadBuffered(ifilename); if (ifile == NULL) return IFF_NO_FILE; ret = iff_parse_bitmap(ifile,bm,bm->bm_type,palette,NULL); PHYSFS_close(ifile); return ret; } #define BMHD_SIZE 20 int write_bmhd(PHYSFS_file *ofile,iff_bitmap_header *bitmap_header) { put_sig(bmhd_sig,ofile); PHYSFS_writeSBE32(ofile, BMHD_SIZE); PHYSFS_writeSBE16(ofile, bitmap_header->w); PHYSFS_writeSBE16(ofile, bitmap_header->h); PHYSFS_writeSBE16(ofile, bitmap_header->x); PHYSFS_writeSBE16(ofile, bitmap_header->y); PHYSFSX_writeU8(ofile, bitmap_header->nplanes); PHYSFSX_writeU8(ofile, bitmap_header->masking); PHYSFSX_writeU8(ofile, bitmap_header->compression); PHYSFSX_writeU8(ofile, 0); /* pad */ PHYSFS_writeSBE16(ofile, bitmap_header->transparentcolor); PHYSFSX_writeU8(ofile, bitmap_header->xaspect); PHYSFSX_writeU8(ofile, bitmap_header->yaspect); PHYSFS_writeSBE16(ofile, bitmap_header->pagewidth); PHYSFS_writeSBE16(ofile, bitmap_header->pageheight); return IFF_NO_ERROR; } int write_pal(PHYSFS_file *ofile,iff_bitmap_header *bitmap_header) { int i; int n_colors = 1<nplanes; put_sig(cmap_sig,ofile); // PHYSFS_writeSBE32(sizeof(pal_entry) * n_colors,ofile); PHYSFS_writeSBE32(ofile, 3 * n_colors); for (i=0; i<256; i++) { unsigned char r,g,b; r = bitmap_header->palette[i].r * 4 + (bitmap_header->palette[i].r?3:0); g = bitmap_header->palette[i].g * 4 + (bitmap_header->palette[i].g?3:0); b = bitmap_header->palette[i].b * 4 + (bitmap_header->palette[i].b?3:0); PHYSFSX_writeU8(ofile, r); PHYSFSX_writeU8(ofile, g); PHYSFSX_writeU8(ofile, b); } return IFF_NO_ERROR; } int rle_span(ubyte *dest,ubyte *src,int len) { int n,lit_cnt,rep_cnt; ubyte last,*cnt_ptr,*dptr; cnt_ptr=0; dptr = dest; last=src[0]; lit_cnt=1; for (n=1;n 2 || lit_cnt < 2) { if (lit_cnt > 1) {*cnt_ptr = lit_cnt-2; --dptr;} //save old lit count *dptr++ = -(rep_cnt-1); *dptr++ = last; last = src[n]; lit_cnt = (n 1) *cnt_ptr = lit_cnt-1; return dptr-dest; } #define EVEN(a) ((a+1)&0xfffffffel) //returns length of chunk int write_body(PHYSFS_file *ofile,iff_bitmap_header *bitmap_header,int compression_on) { int w=bitmap_header->w,h=bitmap_header->h; int y,odd=w&1; long len = EVEN(w) * h,newlen,total_len=0; ubyte *p=bitmap_header->raw_data,*new_span; long save_pos; put_sig(body_sig,ofile); save_pos = PHYSFS_tell(ofile); PHYSFS_writeSBE32(ofile, len); //if (! (new_span = d_malloc(bitmap_header->w+(bitmap_header->w/128+2)*2))) return IFF_NO_MEM; MALLOC( new_span, ubyte, bitmap_header->w + (bitmap_header->w/128+2)*2); if (new_span == NULL) return IFF_NO_MEM; for (y=bitmap_header->h;y--;) { if (compression_on) { total_len += newlen = rle_span(new_span,p,bitmap_header->w+odd); PHYSFS_write(ofile,new_span,newlen,1); } else PHYSFS_write(ofile,p,bitmap_header->w+odd,1); p+=bitmap_header->row_size; //bitmap_header->w; } if (compression_on) { //write actual data length Assert(PHYSFSX_fseek(ofile,save_pos,SEEK_SET)==0); (void)save_pos; PHYSFS_writeSBE32(ofile, total_len); Assert(PHYSFSX_fseek(ofile,total_len,SEEK_CUR)==0); if (total_len&1) PHYSFSX_writeU8(ofile, 0); //pad to even } d_free(new_span); return ((compression_on) ? (EVEN(total_len)+8) : (len+8)); } #if WRITE_TINY //write a small representation of a bitmap. returns size int write_tiny(PHYSFS_file *ofile,iff_bitmap_header *bitmap_header,int compression_on) { int skip; int new_w,new_h; int len,total_len=0,newlen; int x,y,xofs,odd; ubyte *p = bitmap_header->raw_data; ubyte tspan[80],new_span[80*2]; long save_pos; skip = max((bitmap_header->w+79)/80,(bitmap_header->h+63)/64); new_w = bitmap_header->w / skip; new_h = bitmap_header->h / skip; odd = new_w & 1; len = new_w * new_h + 4; put_sig(tiny_sig,ofile); save_pos = PHYSFS_tell(ofile); PHYSFS_writeSBE32(ofile, EVEN(len)); PHYSFS_writeSBE16(ofile, new_w); PHYSFS_writeSBE16(ofile, new_h); for (y=0;yrow_size; //bitmap_header->w; } if (compression_on) { Assert(PHYSFSX_fseek(ofile,save_pos,SEEK_SET)==0); (void)save_pos; PHYSFS_writeSBE32(ofile, 4+total_len); Assert(PHYSFSX_fseek(ofile,4+total_len,SEEK_CUR)==0); if (total_len&1) PHYSFSX_writeU8(ofile, 0); //pad to even } return ((compression_on) ? (EVEN(total_len)+8+4) : (len+8)); } #endif int write_pbm(PHYSFS_file *ofile,iff_bitmap_header *bitmap_header,int compression_on) /* writes a pbm iff file */ { int ret; long raw_size = EVEN(bitmap_header->w) * bitmap_header->h; long body_size,tiny_size,pbm_size = 4 + BMHD_SIZE + 8 + EVEN(raw_size) + sizeof(pal_entry)*(1<nplanes)+8; long save_pos; put_sig(form_sig,ofile); save_pos = PHYSFS_tell(ofile); PHYSFS_writeSBE32(ofile, pbm_size+8); put_sig(pbm_sig,ofile); ret = write_bmhd(ofile,bitmap_header); if (ret != IFF_NO_ERROR) return ret; ret = write_pal(ofile,bitmap_header); if (ret != IFF_NO_ERROR) return ret; #if WRITE_TINY tiny_size = write_tiny(ofile,bitmap_header,compression_on); #else tiny_size = 0; #endif body_size = write_body(ofile,bitmap_header,compression_on); pbm_size = 4 + BMHD_SIZE + body_size + tiny_size + sizeof(pal_entry)*(1<nplanes)+8; Assert(PHYSFSX_fseek(ofile,save_pos,SEEK_SET)==0); (void)save_pos; PHYSFS_writeSBE32(ofile, pbm_size+8); Assert(PHYSFSX_fseek(ofile,pbm_size+8,SEEK_CUR)==0); return ret; } //writes an IFF file from a grs_bitmap structure. writes palette if not null //returns error codes - see IFF.H. int iff_write_bitmap(char *ofilename,grs_bitmap *bm,ubyte *palette) { PHYSFS_file *ofile; iff_bitmap_header bmheader; int ret; int compression_on; if (bm->bm_type == BM_RGB15) return IFF_BAD_BM_TYPE; #if COMPRESS compression_on = (bm->bm_w>=MIN_COMPRESS_WIDTH); #else compression_on = 0; #endif //fill in values in bmheader bmheader.x = bmheader.y = 0; bmheader.w = bm->bm_w; bmheader.h = bm->bm_h; bmheader.type = TYPE_PBM; bmheader.transparentcolor = iff_transparent_color; bmheader.pagewidth = bm->bm_w; //I don't think it matters what I write bmheader.pageheight = bm->bm_h; bmheader.nplanes = 8; bmheader.masking = mskNone; if (iff_has_transparency) { bmheader.masking |= mskHasTransparentColor; } bmheader.compression = (compression_on?cmpByteRun1:cmpNone); bmheader.xaspect = bmheader.yaspect = 1; //I don't think it matters what I write bmheader.raw_data = bm->bm_data; bmheader.row_size = bm->bm_rowsize; if (palette) memcpy(&bmheader.palette,palette,256*3); //open file and write if ((ofile = PHYSFS_openWrite(ofilename)) == NULL) return IFF_NO_FILE; ret = write_pbm(ofile,&bmheader,compression_on); PHYSFS_close(ofile); return ret; } //read in many brushes. fills in array of pointers, and n_bitmaps. //returns iff error codes int iff_read_animbrush(char *ifilename,grs_bitmap **bm_list,int max_bitmaps,int *n_bitmaps,ubyte *palette) { int ret = IFF_NO_ERROR; //return code PHYSFS_file *ifile; int sig,form_len; long form_type; *n_bitmaps=0; ifile = PHYSFSX_openReadBuffered(ifilename); if (ifile == NULL) return IFF_NO_FILE; sig=get_sig(ifile); PHYSFS_readSBE32(ifile, &form_len); if (sig != form_sig) { ret = IFF_NOT_IFF; goto done; } form_type = get_sig(ifile); if ((form_type == pbm_sig) || (form_type == ilbm_sig)) ret = IFF_FORM_BITMAP; else if (form_type == anim_sig) { int anim_end = PHYSFS_tell(ifile) + form_len - 4; while (PHYSFS_tell(ifile) < anim_end && *n_bitmaps < max_bitmaps) { grs_bitmap *prev_bm; prev_bm = *n_bitmaps>0?bm_list[*n_bitmaps-1]:NULL; MALLOC(bm_list[*n_bitmaps] , grs_bitmap, 1 ); bm_list[*n_bitmaps]->bm_data = NULL; ret = iff_parse_bitmap(ifile,bm_list[*n_bitmaps],form_type,*n_bitmaps>0?NULL:(signed char *)palette,prev_bm); if (ret != IFF_NO_ERROR) goto done; (*n_bitmaps)++; } if (PHYSFS_tell(ifile) < anim_end) //ran out of room ret = IFF_TOO_MANY_BMS; } else ret = IFF_UNKNOWN_FORM; done: PHYSFS_close(ifile); return ret; } //text for error messges static const char error_messages[] = { "No error.\0" "Not enough mem for loading or processing bitmap.\0" "IFF file has unknown FORM type.\0" "Not an IFF file.\0" "Cannot open file.\0" "Tried to save invalid type, like BM_RGB15.\0" "Bad data in file.\0" "ANIM file cannot be loaded with normal bitmap loader.\0" "Normal bitmap file cannot be loaded with anim loader.\0" "Array not big enough on anim brush read.\0" "Unknown mask type in bitmap header.\0" "Error reading file.\0" }; //function to return pointer to error message const char *iff_errormsg(int error_number) { const char *p = error_messages; while (error_number--) { if (!p) return NULL; p += strlen(p)+1; } return p; } dxx-rebirth-0.58.1-d2x/include/000077500000000000000000000000001217717237500161775ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/include/3d.h000066400000000000000000000172021217717237500166600ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header file for 3d library * except for functions implemented in interp.c * */ #ifndef _3D_H #define _3D_H #include "fix.h" #include "vecmat.h" //the vector/matrix library #include "gr.h" extern int g3d_interp_outline; //if on, polygon models outlined in white extern vms_vector Matrix_scale; //how the matrix is currently scaled extern short highest_texture_num; //Structure for storing u,v,light values. This structure doesn't have a //prefix because it was defined somewhere else before it was moved here typedef struct g3s_uvl { fix u,v,l; } g3s_uvl; //Structure for storing light color. Also uses l of g3s-uvl to add/compute mono (white) light typedef struct g3s_lrgb { fix r,g,b; } g3s_lrgb; //Stucture to store clipping codes in a word typedef struct g3s_codes { ubyte uor,uand; //or is low byte, and is high byte } g3s_codes; //flags for point structure #define PF_PROJECTED 1 //has been projected, so sx,sy valid #define PF_OVERFLOW 2 //can't project #define PF_TEMP_POINT 4 //created during clip #define PF_UVS 8 //has uv values set #define PF_LS 16 //has lighting values set //clipping codes flags #define CC_OFF_LEFT 1 #define CC_OFF_RIGHT 2 #define CC_OFF_BOT 4 #define CC_OFF_TOP 8 #define CC_BEHIND 0x80 //Used to store rotated points for mines. Has frame count to indictate //if rotated, and flag to indicate if projected. typedef struct g3s_point { vms_vector p3_vec; //x,y,z of rotated point fix p3_u,p3_v,p3_l; //u,v,l coords fix p3_sx,p3_sy; //screen x&y ubyte p3_codes; //clipping codes ubyte p3_flags; //projected? short p3_pad; //keep structure longword aligned } g3s_point; //macros to reference x,y,z elements of a 3d point #define p3_x p3_vec.x #define p3_y p3_vec.y #define p3_z p3_vec.z //An object, such as a robot typedef struct g3s_object { vms_vector o3_pos; //location of this object vms_angvec o3_orient; //orientation of this object int o3_nverts; //number of points in the object int o3_nfaces; //number of faces in the object //this will be filled in later } g3s_object; //Functions in library //Frame setup functions: //start the frame void g3_start_frame(void); //set view from x,y,z & p,b,h, zoom. Must call one of g3_set_view_*() void g3_set_view_angles(const vms_vector *view_pos,const vms_angvec *view_orient,fix zoom); //set view from x,y,z, viewer matrix, and zoom. Must call one of g3_set_view_*() void g3_set_view_matrix(const vms_vector *view_pos,const vms_matrix *view_matrix,fix zoom); //end the frame void g3_end_frame(void); //draw a horizon void g3_draw_horizon(int sky_color,int ground_color); //Instancing //instance at specified point with specified orientation void g3_start_instance_matrix(const vms_vector *pos,const vms_matrix *orient); //instance at specified point with specified orientation void g3_start_instance_angles(const vms_vector *pos,const vms_angvec *angles); //pops the old context void g3_done_instance(); //Misc utility functions: //get zoom. For a given window size, return the zoom which will achieve //the given FOV along the given axis. fix g3_get_zoom(char axis,fixang fov,short window_width,short window_height); //returns true if a plane is facing the viewer. takes the unrotated surface //normal of the plane, and a point on it. The normal need not be normalized bool g3_check_normal_facing(const vms_vector *v,const vms_vector *norm); //Point definition and rotation functions: //specify the arrays refered to by the 'pointlist' parms in the following //functions. I'm not sure if we will keep this function, but I need //it now. //void g3_set_points(g3s_point *points,vms_vector *vecs); //returns codes_and & codes_or of a list of points numbers g3s_codes g3_check_codes(int nv,g3s_point **pointlist); //rotates a point. returns codes. does not check if already rotated ubyte g3_rotate_point(g3s_point *dest,const vms_vector *src); //projects a point void g3_project_point(g3s_point *point); //calculate the depth of a point - returns the z coord of the rotated point fix g3_calc_point_depth(const vms_vector *pnt); //from a 2d point, compute the vector through that point void g3_point_2_vec(vms_vector *v,short sx,short sy); //code a point. fills in the p3_codes field of the point, and returns the codes ubyte g3_code_point(g3s_point *point); //delta rotation functions vms_vector *g3_rotate_delta_x(vms_vector *dest,fix dx); vms_vector *g3_rotate_delta_y(vms_vector *dest,fix dy); vms_vector *g3_rotate_delta_z(vms_vector *dest,fix dz); vms_vector *g3_rotate_delta_vec(vms_vector *dest,const vms_vector *src); ubyte g3_add_delta_vec(g3s_point *dest,const g3s_point *src,const vms_vector *deltav); //Drawing functions: //draw a flat-shaded face. //returns 1 if off screen, 0 if drew bool g3_draw_poly(int nv,const g3s_point **pointlist); //draw a texture-mapped face. //returns 1 if off screen, 0 if drew bool g3_draw_tmap(int nv,const g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb,grs_bitmap *bm); //draw a sortof sphere - i.e., the 2d radius is proportional to the 3d //radius, but not to the distance from the eye int g3_draw_sphere(g3s_point *pnt,fix rad); //@@//return ligting value for a point //@@fix g3_compute_lighting_value(g3s_point *rotated_point,fix normval); //like g3_draw_poly(), but checks to see if facing. If surface normal is //NULL, this routine must compute it, which will be slow. It is better to //pre-compute the normal, and pass it to this function. When the normal //is passed, this function works like g3_check_normal_facing() plus //g3_draw_poly(). //returns -1 if not facing, 1 if off screen, 0 if drew bool g3_check_and_draw_poly(int nv,const g3s_point **pointlist,vms_vector *norm,vms_vector *pnt); bool g3_check_and_draw_tmap(int nv,const g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb, grs_bitmap *bm,vms_vector *norm,vms_vector *pnt); //draws a line. takes two points. bool g3_draw_line(const g3s_point *p0,const g3s_point *p1); //draw a polygon that is always facing you //returns 1 if off screen, 0 if drew bool g3_draw_rod_flat(g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width); //draw a bitmap object that is always facing you //returns 1 if off screen, 0 if drew bool g3_draw_rod_tmap(grs_bitmap *bitmap,g3s_point *bot_point,fix bot_width,g3s_point *top_point,fix top_width,g3s_lrgb light); //draws a bitmap with the specified 3d width & height //returns 1 if off screen, 0 if drew bool g3_draw_bitmap(vms_vector *pos,fix width,fix height,grs_bitmap *bm); //specifies 2d drawing routines to use instead of defaults. Passing //NULL for either or both restores defaults typedef void (*tmap_drawer_type)(grs_bitmap *bm,int nv,g3s_point **vertlist); typedef void (*flat_drawer_type)(int nv,int *vertlist); typedef int (*line_drawer_type)(fix x0,fix y0,fix x1,fix y1); void g3_set_special_render(tmap_drawer_type tmap_drawer,flat_drawer_type flat_drawer,line_drawer_type line_drawer); #endif dxx-rebirth-0.58.1-d2x/include/args.h000066400000000000000000000046151217717237500173120ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Prototypes for accessing arguments. * */ #ifndef _ARGS_H #define _ARGS_H extern int Num_args; extern char *Args[]; extern void InitArgs(int argc, char **argv); extern void args_exit(); // Struct that keeps all variables used by FindArg // Prefixes are: // Sys - System Options // Ctl - Control Options // Snd - Sound Options // Gfx - Graphics Options // Ogl - OpenGL Options // Mpl - Multiplayer Options // Edi - Editor Options // Dbg - Debugging/Undocumented Options typedef struct Arg { int SysShowCmdHelp; int SysUseNiceFPS; int SysMaxFPS; char *SysHogDir; int SysNoHogDir; int SysUsePlayersDir; int SysLowMem; char *SysPilot; int SysWindow; int SysNoBorders; int SysAutoDemo; int SysNoMovies; int CtlNoCursor; int CtlNoMouse; int CtlNoJoystick; int CtlNoStickyKeys; int SndNoSound; int SndNoMusic; int SndDisableSdlMixer; int SndDigiSampleRate; int GfxMovieHires; int GfxHiresGFXAvailable; int GfxHiresFNTAvailable; #ifdef OGL int OglFixedFont; #endif const char *MplUdpHostAddr; int MplUdpHostPort; int MplUdpMyPort; #ifdef USE_TRACKER const char *MplTrackerAddr; int MplTrackerPort; #endif char *EdiAutoLoad; int EdiSaveHoardData; int EdiMacData; // also used for some read routines in non-editor build int DbgVerbose; int DbgSafelog; int DbgNoRun; int DbgRenderStats; char *DbgAltTex; char *DbgTexMap; int DbgShowMemInfo; int DbgUseDoubleBuffer; int DbgBigPig; int DbgBpp; #ifdef OGL int DbgAltTexMerge; int DbgGlIntensity4Ok; int DbgGlLuminance4Alpha4Ok; int DbgGlRGBA2Ok; int DbgGlReadPixelsOk; int DbgGlGetTexLevelParamOk; #else int DbgSdlHWSurface; int DbgSdlASyncBlit; #endif } Arg; extern struct Arg GameArg; #endif dxx-rebirth-0.58.1-d2x/include/byteswap.h000066400000000000000000000073361217717237500202170ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * code to swap bytes because of big/little endian problems. * contains the macros: * SWAP{INT64,INT,SHORT}(x): returns a swapped version of x * INTEL_{INT64,INT,SHORT}(x): returns x after conversion to/from little endian * GET_INTEL_{INT64,INT,SHORT}(src): gets value from little-endian buffer src * PUT_INTEL_{INT64,INT,SHORT}(dest, src): puts src into little-endian buffer dest * * the GET/PUT macros are safe to use on platforms which segfault on unaligned word access * */ #ifndef _BYTESWAP_H #define _BYTESWAP_H #include // for memcpy #include "pstypes.h" #define SWAPSHORT(x) (((ubyte)(x) << 8) | (((ushort)(x)) >> 8)) #define SWAPINT(x) (((x)<<24) | (((uint)(x)) >> 24) | (((x) &0x0000ff00) << 8) | (((x) & 0x00ff0000) >> 8)) #ifndef macintosh #define SWAPINT64(x) ((((x) & 0xff00000000000000LL) >> 56) | (((x) & 0x00ff000000000000LL) >> 40) | (((x) & 0x0000ff0000000000LL) >> 24) | (((x) & 0x000000ff00000000LL) >> 8) | (((x) & 0x00000000ff000000LL) << 8) | (((x) & 0x0000000000ff0000LL) << 24) | (((x) & 0x000000000000ff00LL) << 40) | (((x) & 0x00000000000000ffLL) << 56)) #else #define SWAPINT64(x) ((((x) & 0xff00000000000000LL)/(2^56)) | (((x) & 0x00ff000000000000LL)/(2^40)) | (((x) & 0x0000ff0000000000LL)/(2^24)) | (((x) & 0x000000ff00000000LL)/(2^8)) | (((x) & 0x00000000ff000000LL)*(2^8)) | (((x) & 0x0000000000ff0000LL)*(2^24)) | (((x) & 0x000000000000ff00LL)*(2^40)) | (((x) & 0x00000000000000ffLL)*(2^56))) #endif #ifndef WORDS_BIGENDIAN #define INTEL_INT64(x) x #define INTEL_INT(x) x #define INTEL_SHORT(x) x #else // ! WORDS_BIGENDIAN #define INTEL_INT64(x) SWAPINT64(x) #define INTEL_INT(x) SWAPINT(x) #define INTEL_SHORT(x) SWAPSHORT(x) #endif // ! WORDS_BIGENDIAN #ifndef WORDS_NEED_ALIGNMENT #define GET_INTEL_INT64(s) INTEL_INT64(*(const u_int64_t *)(s)) #define GET_INTEL_INT(s) INTEL_INT(*(const uint *)(s)) #define GET_INTEL_SHORT(s) INTEL_SHORT(*(const ushort *)(s)) #define PUT_INTEL_INT64(d, s) { *(u_int64_t *)(d) = INTEL_INT64((u_int64_t)(s)); } #define PUT_INTEL_INT(d, s) { *(uint *)(d) = INTEL_INT((uint)(s)); } #define PUT_INTEL_SHORT(d, s) { *(ushort *)(d) = INTEL_SHORT((ushort)(s)); } #else // ! WORDS_NEED_ALIGNMENT static inline u_int64_t GET_INTEL_INT64(const void *s) { u_int64_t tmp; memcpy((void *)&tmp, s, 8); return INTEL_INT64(tmp); } static inline uint GET_INTEL_INT(const void *s) { uint tmp; memcpy((void *)&tmp, s, 4); return INTEL_INT(tmp); } static inline ushort GET_INTEL_SHORT(const void *s) { ushort tmp; memcpy((void *)&tmp, s, 2); return INTEL_SHORT(tmp); } #define PUT_INTEL_INT64(d, s) { uint tmp = INTEL_INT64(s); \ memcpy((void *)(d), (void *)&tmp, 8); } #define PUT_INTEL_INT(d, s) { uint tmp = INTEL_INT(s); \ memcpy((void *)(d), (void *)&tmp, 4); } #define PUT_INTEL_SHORT(d, s) { ushort tmp = INTEL_SHORT(s); \ memcpy((void *)(d), (void *)&tmp, 2); } #endif // ! WORDS_NEED_ALIGNMENT #endif // ! _BYTESWAP_H dxx-rebirth-0.58.1-d2x/include/console.h000066400000000000000000000013271217717237500200150ustar00rootroot00000000000000/* Console */ #ifndef _CONSOLE_H_ #define _CONSOLE_H_ #include "pstypes.h" /* Priority levels */ #define CON_CRITICAL -3 #define CON_URGENT -2 #define CON_HUD -1 #define CON_NORMAL 0 #define CON_VERBOSE 1 #define CON_DEBUG 2 #define CON_LINES_ONSCREEN 18 #define CON_SCROLL_OFFSET (CON_LINES_ONSCREEN - 3) #define CON_LINES_MAX 128 #define CON_LINE_LENGTH 2048 #define CON_STATE_OPEN 2 #define CON_STATE_OPENING 1 #define CON_STATE_CLOSING -1 #define CON_STATE_CLOSED -2 typedef struct console_buffer { char line[CON_LINE_LENGTH]; int priority; } __pack__ console_buffer; void con_init(void); void con_printf(int level, const char *fmt, ...); void con_showup(void); #endif /* _CONSOLE_H_ */ dxx-rebirth-0.58.1-d2x/include/dxxerror.h000066400000000000000000000036311217717237500202300ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for error handling/printing/exiting code * */ #ifndef _ERROR_H #define _ERROR_H #include #include #ifdef __GNUC__ #define __noreturn __attribute__ ((noreturn)) #define __attribute_gcc_format(X) __attribute__ ((format X)) #else #define __noreturn #define __attribute_gcc_format(X) #endif void warn_printf(char *s); int error_init(void (*func)(const char *)); //init error system, returns 0=ok void Warning(char *fmt,...); //print out warning message to user void set_warn_func(void (*f)(char *s));//specifies the function to call with warning messages void clear_warn_func(void (*f)(char *s));//say this function no longer valid void Error(const char *fmt,...) __noreturn __attribute_gcc_format((printf, 1, 2)); //exit with error code=1, print message #define Assert assert #ifndef NDEBUG //macros for debugging # if defined(__APPLE__) || defined(macintosh) extern void Debugger(void); // Avoids some name clashes # define Int3 Debugger # else # define Int3() ((void)0) # endif // Macintosh #else //macros for real game //Changed Assert and Int3 because I couldn't get the macros to compile -KRB #define Int3() ((void)0) #endif #endif /* _ERROR_H */ dxx-rebirth-0.58.1-d2x/include/editor/000077500000000000000000000000001217717237500174655ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/include/editor/centers.h000066400000000000000000000017641217717237500213110ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Center header * */ #ifndef _CENTERS_H #define _CENTERS_H #define CENTER_STRING_LENGTH 12 #include "fuelcen.h" extern char Center_names[MAX_CENTER_TYPES][CENTER_STRING_LENGTH]; void close_centers_window(); void do_centers_window(); #endif dxx-rebirth-0.58.1-d2x/include/editor/editor.h000066400000000000000000000564601217717237500211370ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for editor functions, data strcutures, etc. * */ #ifndef _EDITOR_H #define _EDITOR_H #include "vecmat.h" #include "segment.h" #include "inferno.h" #include "gr.h" #include "ui.h" struct window; struct segment; /* * Constants * */ #define ORTHO_VIEWS 0 // set to 1 to enable 3 orthogonal views #define ED_SCREEN_W 800 //width of editor screen #define ED_SCREEN_H 600 //height of editor screen #define MENUBAR_H 16 #define GAMEVIEW_X 1 //where the 320x200 game window goes #define GAMEVIEW_Y 1+MENUBAR_H #define GAMEVIEW_W 320 #define GAMEVIEW_H 200 #define STATUS_X 0 #define STATUS_H 18 #define STATUS_Y (ED_SCREEN_H-STATUS_H) #define STATUS_W ED_SCREEN_W #define LVIEW_X 1 //large view #define LVIEW_Y (GAMEVIEW_Y+GAMEVIEW_H+2) #define LVIEW_W 447 #define LVIEW_H (STATUS_Y-LVIEW_Y-2) #define TMAPBOX_X (LVIEW_X+LVIEW_W+4) //location of first one #define TMAPBOX_Y (LVIEW_Y+2) #define TMAPBOX_W 64 #define TMAPBOX_H 64 #define TMAPCURBOX_X (TMAPBOX_X + 4*(TMAPBOX_W + 3)) #define TMAPCURBOX_Y (TMAPBOX_Y + TMAPBOX_H) #define OBJCURBOX_X (TMAPCURBOX_X) #define OBJCURBOX_Y (TMAPCURBOX_Y + 3*(TMAPBOX_H + 2) -40) #define PAD_X (GAMEVIEW_X + GAMEVIEW_W + 16) #define PAD_Y (GAMEVIEW_Y + 4) #define SMALLVIEW_W 173 //width of small view windows #define SMALLVIEW_H 148 //height of small view windows #define TVIEW_X (LVIEW_X+LVIEW_W+2) //top view #define TVIEW_Y LVIEW_Y #define TVIEW_W SMALLVIEW_W #define TVIEW_H SMALLVIEW_H #define FVIEW_X TVIEW_X //front view #define FVIEW_Y (TVIEW_Y+SMALLVIEW_H+2) #define FVIEW_W SMALLVIEW_W #define FVIEW_H SMALLVIEW_H #define RVIEW_X (TVIEW_X+SMALLVIEW_W+2) //right view #define RVIEW_Y FVIEW_Y #define RVIEW_W SMALLVIEW_W #define RVIEW_H SMALLVIEW_H #define GVIEW_X RVIEW_X //group view #define GVIEW_Y TVIEW_Y #define GVIEW_W SMALLVIEW_W #define GVIEW_H SMALLVIEW_H //there were color constants here, but I moved them to meddraw.c - Matt #define SEGMOVE_PAD_ID 0 #define SEGSIZE_PAD_ID 1 #define CURVE_PAD_ID 2 #define TEXTURE_PAD_ID 3 #define OBJECT_PAD_ID 4 #define OBJMOV_PAD_ID 5 #define GROUP_PAD_ID 6 #define LIGHTING_PAD_ID 7 #define TEST_PAD_ID 8 #define MAX_PAD_ID 8 /* * Strucures * */ #define VF_ANGLES 0 #define VF_MATRIX 1 // Default size of a segment #define DEFAULT_X_SIZE F1_0*20 #define DEFAULT_Y_SIZE F1_0*20 #define DEFAULT_Z_SIZE F1_0*20 // Scale factor from 3d units (integer portion) to uv coordinates (integer portion) #define VMAG (F1_0 / (DEFAULT_X_SIZE/F1_0)) #define UMAG VMAG // unused // Number of segments which can be found (size of Found_segs[]) #define MAX_FOUND_SEGS 200 #define MAX_SELECTED_SEGS (MAX_SEGMENTS) #define MAX_WARNING_SEGS (MAX_SEGMENTS) #define MAX_GROUPS 10 #define ROT_GROUP MAX_GROUPS // Modes for segment sizing #define SEGSIZEMODE_FREE 1 #define SEGSIZEMODE_ALL 2 #define SEGSIZEMODE_CURSIDE 3 #define SEGSIZEMODE_EDGE 4 #define SEGSIZEMODE_VERTEX 5 #define SEGSIZEMODE_MIN SEGSIZEMODE_FREE #define SEGSIZEMODE_MAX SEGSIZEMODE_VERTEX //defines a view for an editor window typedef struct editor_view { short ev_num; //each view has it's own number short ev_changed; //set to true if view changed grs_canvas *ev_canv; //points to this window's canvas fix ev_dist; //the distance from the view point vms_matrix ev_matrix; //the view matrix fix ev_zoom; //zoom for this window } editor_view; /* * Global variables * */ extern editor_view *Views[ORTHO_VIEWS ? 4 : 1]; extern int N_views; extern int Large_view_index; extern UI_GADGET_USERBOX * LargeViewBox; extern int Found_seg_index; // Index in Found_segs corresponding to Cursegp extern int gamestate_not_restored; extern grs_font *editor_font; extern vms_vector Ed_view_target; // what editor is looking at extern struct window *Pad_info; // Keypad text extern int Show_axes_flag; // 0 = don't show, !0 = do show coordinate axes in *Cursegp orientation extern int Autosave_count; // Current counter for which autosave mine we are "on" extern int Autosave_flag; // Whether or not Autosave is on. extern struct tm Editor_time_of_day; extern int SegSizeMode; // Mode = 0/1 = not/is legal to move bound vertices, void init_editor(void); void close_editor(void); // Initialize all vertices to inactive status. extern void init_all_vertices(void); // Returns true if vertex vi is contained in exactly one segment, else returns false. extern int is_free_vertex(int vi); // Set existing vertex vnum to value *vp. extern int med_set_vertex(int vnum,vms_vector *vp); extern void med_combine_duplicate_vertices(sbyte *vlp); // Attach side newside of newseg to side destside of destseg. // Copies *newseg into global array Segments, increments Num_segments. // Forms a weld between the two segments by making the new segment fit to the old segment. // Updates number of faces per side if necessitated by new vertex coordinates. // Return value: // 0 = successful attach // 1 = No room in Segments[]. // 2 = No room in Vertices[]. extern int med_attach_segment(struct segment *destseg, struct segment *newseg, int destside, int newside); // Delete a segment. // Deletes a segment from the global array Segments. // Updates Cursegp to be the segment to which the deleted segment was connected. If there is // more than one connected segment, the new Cursegp will be the segment with the highest index // of connection in the deleted segment (highest index = front) // Return value: // 0 = successful deletion // 1 = unable to delete extern int med_delete_segment(struct segment *sp); // Rotate the segment *seg by the pitch, bank, heading defined by *rot, destructively // modifying its four free vertices in the global array Vertices. // It is illegal to rotate a segment which has MAX_SIDES_PER_SEGMENT != 1. // Pitch, bank, heading are about the point which is the average of the four points // forming the side of connection. // Return value: // 0 = successful rotation // 1 = MAX_SIDES_PER_SEGMENT makes rotation illegal (connected to 0 or 2+ segments) // 2 = Rotation causes degeneracy, such as self-intersecting segment. extern int med_rotate_segment(struct segment *seg, vms_matrix *rotmat); extern int med_rotate_segment_ang(struct segment *seg, vms_angvec *ang); // Scales a segment, destructively modifying vertex coordinates in global Vertices[]. // Uses scale factor in sp->scale. // Modifies only free vertices (those which are not part of a segment other than *sp). // The vector *svp contains the x,y,z scale factors. The x,y,z directions are relative // to the segment. x scales in the dimension of the right vector, y of the up vector, z of the forward vector. // The dimension of the vectors is determined by averaging appropriate sets of 4 of the 8 points. extern void med_scale_segment(struct segment *sp); // Loads mine *name from disk, updating global variables: // Segments, Vertices // Num_segments,Num_vertices // Cursegp = pointer to active segment. Written as an index in med_save_mine, converted to a pointer // at load time. // Returns: // 0 = successfully loaded. // 1 = unable to load. extern int med_load_mine(char *name); // Loads game *name from disk. // This function automatically loads mine with name.MIN extern int med_load_game(char *name); // Loads a previous generation mine. Needs to be updated in code. extern int med_load_pmine(char *name); // Saves mine contained in Segments[] and Vertices[]. // Num_segments = number of segments in mine. // Num_vertices = number of vertices in mine. // Cursegp = current segment. // Saves Num_segments, and index of current segment (which is Cursegp - Segments), which will be converted to a pointer // and written to Cursegp in med_load_mine. // Returns: // 0 = successfully saved. // 1 = unable to save. extern int med_save_mine(char *name); // Loads group *filename from disk. // Adds group to global Segments and Vertices array. // Returns: // 0 = successfully loaded. // 1 = unable to load. extern int med_load_group( char *filename, int *vertex_ids, short *segment_ids, int *num_vertices, int *num_segments); // Saves group *filename from disk. // Saves group defined by vertex_ids and segment_ids to disk. // Returns: // 0 = successfully saved. // 1 = unable to save. extern int med_save_group( char *filename, int *vertex_ids, short *segment_ids, int num_vertices, int num_segments); // Updates the screen... (I put the prototype here for curves.c) extern int medlisp_update_screen(); // Returns 0 if no error, 1 if error, whatever that might be. // Sets globals: // Num_segments // Num_vertices // Cursegp = pointer to only segment. extern int create_new_mine(void); // extern void med_create_segment(segment *sp, vms_vector *scale); extern void old_med_attach_segment(struct segment *sp,int main_side,int branch_side,fix cx, fix cy, fix cz, fix length, fix width, fix height, vms_matrix *mp); // Copy a segment from *ssp to *dsp. Do not simply copy the struct. Use *dsp's vertices, copying in // just the values, not the indices. extern void med_copy_segment(struct segment *dsp,struct segment *ssp); // Create a segment given center, dimensions, rotation matrix. // Note that the created segment will always have planar sides and rectangular cross sections. // It will be created with walls on all sides, ie not connected to anything. void med_create_segment(struct segment *sp,fix cx, fix cy, fix cz, fix length, fix width, fix height, vms_matrix *mp); // Create a default segment. // Useful for when user creates a garbage segment. extern void med_create_default_segment(struct segment *sp); // Create New_segment with sizes found in *scale. extern void med_create_new_segment(vms_vector *scale); // Create New_segment with sizes found in Cursegp. extern void med_create_new_segment_from_cursegp(void); // Update New_segment using scale factors. extern void med_update_new_segment(void); // Replace *sp with New_segment. extern void med_update_segment(struct segment *sp); // Create a new segment and use it to form a bridge between two existing segments. // Specify two segment:side pairs. If either segment:side is not open (ie, segment->children[side] != -1) // then it is not legal to form the brider. // Return: // 0 bridge segment formed // 1 unable to form bridge because one (or both) of the sides is not open. // Note that no new vertices are created by this process. extern int med_form_bridge_segment(struct segment *seg1, int side1, struct segment *seg2, int side2); // Compress mine at Segments and Vertices by squeezing out all holes. // If no holes (ie, an unused segment followed by a used segment), then no action. // If Cursegp or Markedsegp is a segment which gets moved to fill in a hole, then // they are properly updated. extern void med_compress_mine(void); // Extract the forward vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the front face of the segment // to the center of the back face of the segment. extern void med_extract_forward_vector_from_segment(struct segment *sp,vms_vector *vp); // Extract the right vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the left face of the segment // to the center of the right face of the segment. extern void med_extract_right_vector_from_segment(struct segment *sp,vms_vector *vp); // Extract the up vector from segment *sp, return in *vp. // The forward vector is defined to be the vector from the the center of the bottom face of the segment // to the center of the top face of the segment. extern void med_extract_up_vector_from_segment(struct segment *sp,vms_vector *vp); // Compute the center point of a side of a segment. // The center point is defined to be the average of the 4 points defining the side. extern void med_compute_center_point_on_side(vms_vector *vp,struct segment *sp,int side); extern void set_matrix_based_on_side(vms_matrix *rotmat,int destside); // Given a forward vector, compute and return an angvec triple. // [ THIS SHOULD BE MOVED TO THE VECTOR MATRIX LIBRARY ] extern vms_angvec *vm_vec_to_angles(vms_angvec *result, vms_vector *forvec); // Curves stuff. #define ACCURACY 0.1*F1_0 typedef struct vms_equation { union { struct {fix x3, x2, x1, x0, y3, y2, y1, y0, z3, z2, z1, z0;} n; fix xyz[3][4]; }; } vms_equation; extern void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs); // Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t^3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4 extern vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t); extern fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist); extern void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir); extern void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t); // Curve generation routine. // Returns 1 if curve is generated. // Returns 0 if no curve. extern int generate_curve( fix r1scale, fix r4scale ); // Deletes existing curve generated in generate_curve(). extern void delete_curve(); // --- // -- Temporary function, identical to med_rotate_segment, but it takes a vector instead of an angvec // --- extern int med_rotate_segment_vec(segment *seg, vms_vector *vec); extern void med_extract_matrix_from_segment(struct segment *sp,vms_matrix *rotmat); // Assign default u,v coordinates to all sides of a segment. // This routine should only be used for segments which are not connected to anything else, // ie the segment created at mine creation. extern void assign_default_uvs_to_segment(struct segment *segp); extern void assign_default_uvs_to_side(struct segment *segp, int side); extern void assign_default_uvs_to_side(struct segment *segp,int side); // Assign u,v coordinates to con_seg, con_common_side from base_seg, base_common_side // They are connected at the edge defined by the vertices abs_id1, abs_id2. extern void med_assign_uvs_to_side(struct segment *con_seg, int con_common_side, struct segment *base_seg, int base_common_side, int abs_id1, int abs_id2); // Debug -- show a matrix. // type: 1 --> printf // *s = string to display // *mp = matrix to display extern void show_matrix(char *s,vms_matrix *mp,int type); // Create coordinate axes in orientation of specified segment, stores vertices at *vp. extern void create_coordinate_axes_from_segment(struct segment *sp,int *vertnums); // Scale a segment. Then, if it is connected to something, rotate it. extern int med_scale_and_rotate_segment(struct segment *seg, vms_angvec *rot); // Set Vertex_active to number of occurrences of each vertex. // Set Num_vertices. extern void set_vertex_counts(void); // Modify seg2 to share side2 with seg1:side1. This forms a connection between // two segments without creating a new segment. It modifies seg2 by sharing // vertices from seg1. seg1 is not modified. Four vertices from seg2 are // deleted. // If the four vertices forming side2 in seg2 are not free, the joint is not formed. // Return code: // 0 joint formed // 1 unable to form joint because one or more vertices of side2 is not free // 2 unable to form joint because side1 is already used extern int med_form_joint(struct segment *seg1, int side1, struct segment *seg2, int side2); // The current texture... use by saying something=bm_lock_bitmap(CurrentTexture) extern int CurrentTexture; extern void compute_segment_center(vms_vector *vp,struct segment *sp); extern void med_propagate_tmaps_to_segments(struct segment *base_seg,struct segment *con_seg, int uv_only_flag); extern void med_propagate_tmaps_to_back_side(struct segment *base_seg, int back_side, int uv_only_flag); extern void med_propagate_tmaps_to_any_side(struct segment *base_seg, int back_side, int tmap_num, int uv_only_flag); // Find segment adjacent to sp:side. // Adjacent means a segment which shares all four vertices. // Return true if segment found and fill in segment in adj_sp and side in adj_side. // Return false if unable to find, in which case adj_sp and adj_side are undefined. extern int med_find_adjacent_segment_side(struct segment *sp, int side, struct segment **adj_sp, int *adj_side); // Finds the closest segment and side to sp:side. extern int med_find_closest_threshold_segment_side(struct segment *sp, int side, struct segment **adj_sp, int *adj_side, fix threshold); // Given two segments, return the side index in the connecting segment which connects to the base segment extern int find_connect_side(struct segment *base_seg, struct segment *con_seg); // Select previous segment. // If there is a connection on the side opposite to the current side, then choose that segment. // If there is no connecting segment on the opposite face, try any segment. extern void get_previous_segment(int curseg_num, int curside,int *newseg_num, int *newside); // Select next segment. // If there is a connection on the current side, then choose that segment. // If there is no connecting segment on the current side, try any segment. extern void get_next_segment(int curseg_num, int curside, int *newseg_num, int *newside); // Copy texture maps in newseg to nsp. extern void copy_uvs_seg_to_seg(struct segment *nsp,struct segment *newseg); // Return true if segment is concave. extern int check_seg_concavity(struct segment *s); // Return N_found_segs = number of concave segments in mine. // Segment ids stored at Found_segs extern void find_concave_segs(void); // High level call. Check for concave segments, print warning message (using editor_status) // if any concave segments. // Calls find_concave_segs, therefore N_found_segs gets set, and Found_segs filled in. extern void warn_if_concave_segments(void); // Warn if segment s is concave. extern void warn_if_concave_segment(struct segment *s); // Add a vertex to the vertex list. extern int med_add_vertex(vms_vector *vp); // Add a vertex to the vertex list which may be identical to another vertex (in terms of coordinates). // Don't scan list, looking for presence of a vertex with same coords, add this one. extern int med_create_duplicate_vertex(vms_vector *vp); // Create a new segment, duplicating exactly, including vertex ids and children, the passed segment. extern int med_create_duplicate_segment(struct segment *sp); // Returns the index of a free segment. // Scans the Segments array. extern int get_free_segment_number(void); // Diagnostic message. #define diagnostic_message editor_status #define diagnostic_message_fmt editor_status_fmt // Status Icon. extern void print_status_icon( char icon[1], int position ); extern void clear_status_icon( char icon[1], int position ); // Editor status message. extern void editor_status_fmt(const char *format, ... ); // Variables in editor.c that the k*.c files need #define UF_NONE 0x000 //nothing has changed #define UF_WORLD_CHANGED 0x001 //something added or deleted #define UF_VIEWPOINT_MOVED 0x002 //what we're watching has moved #define UF_GAME_VIEW_CHANGED 0x004 //the game window changed #define UF_ED_STATE_CHANGED 0x008 //something like curside,curseg changed #define UF_ALL 0xffffffff //all flags extern uint Update_flags; extern int Funky_chase_mode; extern vms_angvec Seg_orientation; extern vms_vector Seg_scale; extern int mine_changed; extern int ModeFlag; extern editor_view *current_view; //the view for the different windows extern editor_view LargeView; extern editor_view TopView; extern editor_view FrontView; extern editor_view RightView; extern void set_view_target_from_segment(struct segment *sp); extern int SafetyCheck(); void editor_status( const char *text); extern int MacroNumEvents; extern int MacroStatus; //extern int Highest_vertex_index; // Highest index in Vertices and Vertex_active, an efficiency hack //extern int Highest_segment_index; // Highest index in Segments, an efficiency hack extern int Lock_view_to_cursegp; // !0 means whenever cursegp changes, view it // eglobal.c extern int Num_tilings; // number of tilings/wall extern int Degenerate_segment_found; extern sbyte Been_visited[MAX_SEGMENTS]; // List of segments visited in a recursive search, if element n set, segment n done been visited // Initializes autosave system. // Sets global Autosave_count to 0. extern void init_autosave(void); // Closes autosave system. // Deletes all autosaved files. extern void close_autosave(void); // Saves current mine to name.miX where name = suffix of mine name and X = Autosave_count. // For example, if name = "cookie.min", and Autosave_count = 3, then writes "cookie.mi3". // Increments Autosave_count, wrapping from 9 to 0. // (If there is no current mine name, assume "temp.min") // Call med_save_mine to save the mine. extern void autosave_mine(char *name); // Timed autosave extern void TimedAutosave(char *name); extern void set_editor_time_of_day(); // Undo function extern int undo(void); extern char mine_filename[PATH_MAX]; extern char undo_status[10][100]; // group.c int AttachSegmentNewAng(vms_angvec *pbh); int RotateSegmentNew(vms_angvec *pbh); int rotate_segment_new(vms_angvec *pbh); //get & free vertices int alloc_vert(); void free_vert(int vert_num); // The current object type and id declared in eglobal.c extern short Cur_object_type; extern short Cur_object_id; // From med.c extern int DisplayCurrentRobotType(void); extern short Cur_object_index; extern int render_3d_in_big_window; extern void move_object_to_mouse_click(void); //these are instances of canvases, pointed to by variables below extern grs_canvas _canv_editor_game; //the game on the editor screen //these are pointers to our canvases extern grs_canvas *Canv_editor; //the editor screen extern grs_canvas *Canv_editor_game; //the game on the editor screen extern struct window *Pad_info; // Keypad text //where the editor is looking extern vms_vector Ed_view_target; extern int gamestate_not_restored; extern UI_DIALOG * EditorWindow; extern int Large_view_index; extern UI_GADGET_USERBOX * GameViewBox; extern UI_GADGET_USERBOX * LargeViewBox; extern UI_GADGET_USERBOX * GroupViewBox; extern void med_point_2_vec(grs_canvas *canv,vms_vector *v,short sx,short sy); //shutdown ui on the editor screen void close_editor_screen(void); // from ksegsize.c extern void med_extract_up_vector_from_segment_side(struct segment *sp, int sidenum, vms_vector *vp); extern void med_extract_right_vector_from_segment_side(struct segment *sp, int sidenum, vms_vector *vp); extern void med_extract_forward_vector_from_segment_side(struct segment *sp, int sidenum, vms_vector *vp); // In medmisc.c extern void draw_world_from_game(void); // In medrobot.c extern void close_all_windows(void); // In seguvs.c // Amount to stretch a texture map by. // The two different ones are for the two dimensions of a texture map. extern fix Stretch_scale_x, Stretch_scale_y; #endif dxx-rebirth-0.58.1-d2x/include/editor/ehostage.h000066400000000000000000000015161217717237500214400ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * . * */ #ifndef _EHOSTAGE_H #define _EHOSTAGE_H static inline void hostage_close_window() {} #endif dxx-rebirth-0.58.1-d2x/include/editor/eobject.h000066400000000000000000000021251217717237500212510ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for eobject.c * */ #ifndef _EOBJECT_H #define _EOBJECT_H int ObjectSelectNextInMine(void); int ObjectSelectPrevInMine(void); int ObjectDecreaseBankBig(); int ObjectIncreaseBankBig(); int ObjectDecreasePitchBig(); int ObjectIncreasePitchBig(); int ObjectDecreaseHeadingBig(); int ObjectIncreaseHeadingBig(); int ObjectFlipObject(); #endif dxx-rebirth-0.58.1-d2x/include/editor/esegment.h000066400000000000000000000072551217717237500214560ustar00rootroot00000000000000#pragma once #include "segment.h" extern segment *Cursegp; // Pointer to current segment in the mine, the one to which things happen. #define Curseg2p s2s2(Cursegp) // Pointer to segment2 for Cursegp // -- extern segment New_segment; // The segment which can be added to the mine. #define New_segment (Segments[MAX_SEGMENTS-1]) extern int Curside; // Side index in 0..MAX_SIDES_PER_SEGMENT of active side. extern int Curedge; // Current edge on current side, in 0..3 extern int Curvert; // Current vertex on current side, in 0..3 extern int AttachSide; // Side on segment to attach extern int Draw_all_segments; // Set to 1 means draw_world draws all segments in Segments, else draw only connected segments extern segment *Markedsegp; // Marked segment, used in conjunction with *Cursegp to form joints. extern int Markedside; // Marked side on Markedsegp. extern sbyte Vertex_active[MAX_VERTICES]; // !0 means vertex is in use, 0 means not in use. // The extra group in the following arrays is used for group rotation. extern group GroupList[MAX_GROUPS+1]; extern segment *Groupsegp[MAX_GROUPS+1]; extern int Groupside[MAX_GROUPS+1]; extern int current_group; extern int num_groups; extern int Current_group; extern short Found_segs[]; // List of segment numbers "found" under cursor click extern int N_found_segs; // Number of segments found at Found_segs extern int N_selected_segs; // Number of segments found at Selected_segs extern short Selected_segs[]; // List of segment numbers currently selected extern int N_warning_segs; // Number of segments warning-worthy, such as a concave segment extern short Warning_segs[]; // List of warning-worthy segments extern int Groupside[MAX_GROUPS+1]; extern int current_group; extern int num_groups; extern int Current_group; // Returns true if vertex vi is contained in exactly one segment, else returns false. extern int is_free_vertex(int vi); // Set existing vertex vnum to value *vp. extern int med_set_vertex(int vnum,vms_vector *vp); extern void med_combine_duplicate_vertices(sbyte *vlp); // Attach side newside of newseg to side destside of destseg. // Copies *newseg into global array Segments, increments Num_segments. // Forms a weld between the two segments by making the new segment fit to the old segment. // Updates number of faces per side if necessitated by new vertex coordinates. // Return value: // 0 = successful attach // 1 = No room in Segments[]. // 2 = No room in Vertices[]. extern int med_attach_segment(segment *destseg, segment *newseg, int destside, int newside); // Delete a segment. // Deletes a segment from the global array Segments. // Updates Cursegp to be the segment to which the deleted segment was connected. If there is // more than one connected segment, the new Cursegp will be the segment with the highest index // of connection in the deleted segment (highest index = front) // Return value: // 0 = successful deletion // 1 = unable to delete extern int med_delete_segment(segment *sp); // Rotate the segment *seg by the pitch, bank, heading defined by *rot, destructively // modifying its four free vertices in the global array Vertices. // It is illegal to rotate a segment which has MAX_SIDES_PER_SEGMENT != 1. // Pitch, bank, heading are about the point which is the average of the four points // forming the side of connection. // Return value: // 0 = successful rotation // 1 = MAX_SIDES_PER_SEGMENT makes rotation illegal (connected to 0 or 2+ segments) // 2 = Rotation causes degeneracy, such as self-intersecting segment. extern int med_rotate_segment(segment *seg, vms_matrix *rotmat); extern int med_rotate_segment_ang(segment *seg, vms_angvec *ang); dxx-rebirth-0.58.1-d2x/include/editor/eswitch.h000066400000000000000000000020771217717237500213120ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Headers for switch adding functions * */ #ifndef _ESWITCH_H #define _ESWITCH_H #include "inferno.h" #include "segment.h" #include "switch.h" extern int bind_wall_to_trigger(); extern int trigger_remove(); extern int remove_trigger(segment *seg, short side); extern void close_trigger_window(); extern void do_trigger_window(); #endif dxx-rebirth-0.58.1-d2x/include/editor/info.h000066400000000000000000000015711217717237500205750ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for info.c * */ #ifndef _INFO_H #define _INFO_H struct window; struct window *info_window_create(void); extern int init_info; #endif dxx-rebirth-0.58.1-d2x/include/editor/kdefs.h000066400000000000000000000200751217717237500207360ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ // In khelp.c int DoHelp(); // In kcurve.c int InitCurve(); int GenerateCurve(); int DecreaseR4(); int IncreaseR4(); int DecreaseR1(); int IncreaseR1(); int DeleteCurve(); int SetCurve(); // In kmine.c int SaveMine(); int LoadMine(); int MineMenu(); int CreateNewMine(); int LoadOldMine(); int SaveSituation(); int LoadSituation(); // In kgame.c int SetPlayerPosition(void); int SaveGameData(); int LoadGameData(); int LoadMineOnly(); void ResetFilename(); // In group.c int LoadGroup(); int SaveGroup(); int PrevGroup(); int NextGroup(); int CreateGroup(); int SubtractFromGroup(); int DeleteGroup(); int MarkGroupSegment(); int MoveGroup(void); int CopyGroup(void); int AttachSegmentNew(); int UngroupSegment(); int GroupSegment(); int Degroup(); int RotateGroup(); // In segment.c int ToggleBottom(); void make_curside_bottom_side(); int select_segment_by_number(); int select_segment_with_powerup(); // In editor.c int UndoCommand(); // In kview.c int ZoomOut(); int ZoomIn(); int MoveAway(); int MoveCloser(); int ToggleChaseMode(); // In kbuild.c int CreateBridge(); int FormJoint(); int CreateAdjacentJoint(); int CreateAdjacentJointsSegment(); int CreateAdjacentJointsAll(); int CreateSloppyAdjacentJoint(); int CreateSloppyAdjacentJointsGroup(); // In ksegmove.c int DecreaseHeading(); int IncreaseHeading(); int DecreasePitch(); int IncreasePitch(); int DecreaseBank(); int IncreaseBank(); // In ksegsel.c int SelectCurrentSegForward(); int SelectCurrentSegBackward(); int SelectNextSide(); int SelectPrevSide(); int CopySegToMarked(); int SelectBottom(); int SelectFront(); int SelectTop(); int SelectBack(); int SelectLeft(); int SelectRight(); // In ksegsize.c int IncreaseSegLength(); int DecreaseSegLength(); int DecreaseSegWidth(); int IncreaseSegWidth(); int IncreaseSegHeight(); int DecreaseSegHeight(); int ToggleSegSizeMode(); int PerturbCurside(); int PerturbCursideBig(); int IncreaseSegLengthBig(); int DecreaseSegLengthBig(); int DecreaseSegWidthBig(); int IncreaseSegWidthBig(); int IncreaseSegHeightBig(); int DecreaseSegHeightBig(); int IncreaseSegLengthDefault(); int DecreaseSegLengthDefault(); int IncreaseSegWidthDefault(); int DecreaseSegWidthDefault(); int IncreaseSegHeightDefault(); int DecreaseSegHeightDefault(); // In ktmap.c int AssignTexture(); int AssignTexture2(); int ClearTexture2(); int PropagateTextures(); int PropagateTexturesMove(); int PropagateTexturesMoveUVs(); int PropagateTexturesUVs(); int PropagateTexturesSelected(); //--//// In macro.c //--//int MacroMenu(); //--//int MacroPlayFast(); //--//int MacroPlayNormal(); //--//int MacroRecordAll(); //--//int MacroRecordKeys(); //--//int MacroSave(); //--//int MacroLoad(); // In editor.c int medlisp_update_screen(); int medlisp_delete_segment(void); int medlisp_scale_segment(void); int medlisp_rotate_segment(void); int medlisp_add_segment(); int AttachSegment(); int DeleteSegment(); int DosShell(); int CallLisp(); int ExitEditor(); int ShowAbout(); int ExchangeMarkandCurseg(); int CopySegtoMarked(); int med_keypad_goto_prev(); int med_keypad_goto_next(); int med_keypad_goto(); int med_increase_tilings(); int med_decrease_tilings(); int ToggleAutosave(); int MarkStart(); int MarkEnd(); // Texture.c int TexFlipX(); int TexFlipY(); int TexSlideUp(); int TexSlideLeft(); int TexSetDefault(); int TexSetDefaultSelected(); int TexSlideRight(); int TexRotateLeft(); int TexSlideDown(); int TexRotateRight(); int TexSelectActiveEdge(); int TexRotate90Degrees(); int TexIncreaseTiling(); int TexDecreaseTiling(); int TexSlideUpBig(); int TexSlideLeftBig(); int TexSlideRightBig(); int TexRotateLeftBig(); int TexSlideDownBig(); int TexRotateRightBig(); int TexStretchDown(); int TexStretchUp(); int TexChangeAll(); int TexChangeAll2(); // object.c int ObjectPlaceObject(); int ObjectMakeCoop(); int ObjectPlaceObjectTmap(); int ObjectDelete(); int ObjectMoveForward(); int ObjectMoveLeft(); int ObjectSetDefault(); int ObjectMoveRight(); int ObjectMoveBack(); int ObjectMoveDown(); int ObjectMoveUp(); int ObjectMoveNearer(); int ObjectMoveFurther(); int ObjectSelectNextinSegment(); int ObjectSelectNextType(); int ObjectDecreaseBank(); int ObjectIncreaseBank(); int ObjectDecreasePitch(); int ObjectIncreasePitch(); int ObjectDecreaseHeading(); int ObjectIncreaseHeading(); int ObjectResetObject(); // elight.c int LightSelectNextVertex(); int LightSelectNextEdge(); int LightCopyIntensity(); int LightCopyIntensitySegment(); int LightDecreaseLightVertex(); int LightIncreaseLightVertex(); int LightDecreaseLightSide(); int LightIncreaseLightSide(); int LightDecreaseLightSegment(); int LightIncreaseLightSegment(); int LightSetMaximum(); int LightSetDefault(); int LightSetDefaultAll(); int LightAmbientLighting(); // seguvs.c int fix_bogus_uvs_on_side(); int fix_bogus_uvs_all(); int set_average_light_on_curside(void); int set_average_light_on_all(void); int set_average_light_on_all_quick(void); // Miscellaneous, please put in correct file if you have time int IncreaseDrawDepth(); int DecreaseDrawDepth(); int GotoMainMenu(); int GotoGameScreen(); int DropIntoDebugger(); int CreateDefaultNewSegment(); int CreateDefaultNewSegmentandAttach(); int ClearSelectedList(); int ClearFoundList(); int SortSelectedList(); int SetPlayerFromCurseg(); int SetPlayerFromCursegAndRotate(); int SetPlayerFromCursegMinusOne(); int FindConcaveSegs(); int SelectNextFoundSeg(); int SelectPreviousFoundSeg(void); int do_reset_orient(); int GameZoomOut(); int GameZoomIn(); // John's temp page stuff int medtmp_set_page(); // In objpage.c int objpage_goto_next_object(); // In medsel.c extern int SortSelectedList(void); extern int SelectNextFoundSeg(void); extern int SelectPreviousFoundSeg(void); // In wall.c extern int wall_add_blastable(void); extern int wall_add_door(void); extern int wall_add_closed_wall(void); extern int wall_add_external_wall(void); extern int wall_lock_door(void); extern int wall_unlock_door(void); extern int wall_automate_door(void); extern int wall_deautomate_door(void); extern int wall_add_illusion(void); extern int wall_remove(void); extern int wall_restore_all(void); extern int wall_assign_door_1(void); extern int wall_assign_door_2(void); extern int wall_assign_door_3(void); extern int wall_assign_door_4(void); extern int wall_assign_door_5(void); extern int wall_assign_door_6(void); extern int wall_assign_door_7(void); extern int wall_assign_door_8(void); extern int do_wall_dialog(void); extern int do_trigger_dialog(void); extern int check_walls(void); extern int delete_all_walls(void); extern int delete_all_controlcen_triggers(void); // In centers.c extern int do_centers_dialog(void); // In switch.c //extern int trigger_add_damage(void); //extern int trigger_add_blank(void); //extern int trigger_add_exit(void); //extern int trigger_add_repair(void); //extern int trigger_control(void); //extern int trigger_remove(void); //extern int trigger_add_if_control_center_dead(void); extern int bind_wall_to_control_trigger(void); // In med.c extern int fuelcen_create_from_curseg(); extern int repaircen_create_from_curseg(); extern int controlcen_create_from_curseg(); extern int robotmaker_create_from_curseg(); extern int fuelcen_reset_all(); extern int RestoreGameState(); extern int fuelcen_delete_from_curseg(); extern int goal_blue_create_from_curseg(); extern int goal_red_create_from_curseg(); // In editor\robot.c extern int do_robot_dialog(); extern int do_object_dialog(); // In editor\hostage.c extern int do_hostage_dialog(); dxx-rebirth-0.58.1-d2x/include/editor/kfuncs.h000066400000000000000000000015161217717237500211320ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for kfuncs.c * */ #ifndef _KFUNCS_H #define _KFUNCS_H void init_med_functions(void); #endif dxx-rebirth-0.58.1-d2x/include/editor/macro.h000066400000000000000000000015121217717237500207360ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for macro.c * */ #ifndef _MACRO_H #define _MACRO_H void macro_free_buffer(void); #endif dxx-rebirth-0.58.1-d2x/include/editor/meddraw.h000066400000000000000000000023671217717237500212710ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Defnts for med drawing stuff * */ #ifndef _MEDDRAW_H #define _MEDDRAW_H void meddraw_init_views( grs_canvas * canvas); void draw_world(grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth); void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth); // segp = pointer to segments array, probably always Segments. // automap_flag = 1 if this render is for the automap, else 0 (for editor) extern void draw_mine_all(segment *segp, int automap_flag); #endif dxx-rebirth-0.58.1-d2x/include/editor/medlisp.h000066400000000000000000000020301217717237500212660ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifndef _MEDLISP_H #define _MEDLISP_H int medlisp_init(); void medlisp_go(); void medlisp_do_string( char * s, int length, int show_results ); void medlisp_close(); int medlisp_attach_function( char * LispFuncName, double (* Cfunction)(void), int NumArgs ); extern double medlisp_args[]; #endif dxx-rebirth-0.58.1-d2x/include/editor/medmisc.h000066400000000000000000000024631217717237500212640ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Defn'tns for medmisc.c * */ #ifndef _MEDMISC_H #define _MEDMISC_H void GetMouseRotation( int idx, int idy, vms_matrix * RotMat ); extern int Gameview_lockstep; //In medmisc.c int ToggleLockstep(); int medlisp_delete_segment(void); int medlisp_scale_segment(void); int medlisp_rotate_segment(void); int ToggleLockViewToCursegp(void); int ToggleDrawAllSegments(); int IncreaseDrawDepth(void); int DecreaseDrawDepth(void); int ToggleCoordAxes(); extern int Big_depth; void set_chase_matrix(segment *sp); void set_view_target_from_segment(segment *sp); #endif dxx-rebirth-0.58.1-d2x/include/editor/medrobot.h000066400000000000000000000016711217717237500214560ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for robot.c * */ #ifndef _MED_ROBOT_H #define _MED_ROBOT_H extern void robot_close_window(); extern void do_robot_window(); extern void object_close_window(); extern void do_object_window(); #endif dxx-rebirth-0.58.1-d2x/include/editor/medsel.h000066400000000000000000000016271217717237500211150ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * rountines stipped from med.c for segment selection * */ #ifndef _MEDSEL_H #define _MEDSEL_H extern void sort_seg_list(int n_segs,short *segnumlist,vms_vector *pos); #endif dxx-rebirth-0.58.1-d2x/include/editor/medwall.h000066400000000000000000000034441217717237500212700ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Created from version 1.6 of main\wall.h * */ #ifndef _MEDWALL_H #define _MEDWALL_H #include "wall.h" #include "inferno.h" #include "segment.h" extern int wall_add_removable(); // Restores all the walls to original status extern int wall_restore_all(); // Reset a wall. extern void wall_reset(segment *seg, short side); // Adds a removable wall (medwall.c) extern int wall_add_removable(); // Adds a door (medwall.c) extern int wall_add_door(); // Adds an illusory wall (medwall.c) extern int wall_add_illusion(); // Removes a removable wall (medwall.c) extern int wall_remove_blastable(); // Adds a wall. (visually) extern int wall_add_to_curside(); extern int wall_add_to_markedside(sbyte type); // Removes a wall. (visually) extern int wall_remove(); // Removes a specific side. int wall_remove_side(segment *seg, short side); extern int bind_wall_to_control_center(); extern void close_wall_window(); extern void do_wall_window(); extern int wall_link_doors(); extern int wall_unlink_door(); extern void copy_group_walls(int old_group, int new_group); #endif dxx-rebirth-0.58.1-d2x/include/editor/objpage.h000066400000000000000000000021041217717237500212420ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * object selection stuff. * */ #ifndef _OBJPAGE_H #define _OBJPAGE_H #include "ui.h" struct d_event; int objpage_grab_current(int n); int objpage_goto_first(); void objpage_init( UI_DIALOG *dlg ); void objpage_close(); int objpage_do(struct d_event *event); extern void draw_object_picture(int id, vms_angvec *orient_angles, int type); #endif dxx-rebirth-0.58.1-d2x/include/editor/seguvs.h000066400000000000000000000017311217717237500211540ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for seguvs.c * */ #ifndef _SEGUVS_H #define _SEGUVS_H extern void assign_light_to_side(segment *sp, int sidenum); extern void assign_default_lighting_all(void); extern void stretch_uvs_from_curedge(segment *segp, int side); #endif dxx-rebirth-0.58.1-d2x/include/editor/texpage.h000066400000000000000000000021071217717237500212730ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Definitions for texpage.c * */ #ifndef _TEXPAGE_H #define _TEXPAGE_H #include "ui.h" struct d_event; extern int TextureLights; extern int TextureEffects; extern int TextureMetals; int texpage_grab_current(int n); int texpage_goto_first(); void texpage_init( UI_DIALOG * dlg ); void texpage_close(); int texpage_do(struct d_event *event); #endif dxx-rebirth-0.58.1-d2x/include/fix.h000066400000000000000000000000611217717237500171330ustar00rootroot00000000000000/* fix.h points to maths.h */ #include "maths.h" dxx-rebirth-0.58.1-d2x/include/func.h000066400000000000000000000022421217717237500173030ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifndef _FUNC_H #define _FUNC_H typedef struct { char * name; int nparams; int (*cfunction)(void); } FUNCTION; void func_init( FUNCTION * funtable, int size ); void func_close(); int (*func_get( char * name, int * numparams ))(void); int func_howmany(); int (*func_nget( int func_number, int * numparams, char **name ))(void); void func_set_param( int n, int value ); int func_get_param( int n ); int func_get_index( char * name ); #endif dxx-rebirth-0.58.1-d2x/include/gr.h000066400000000000000000000352031217717237500167630ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Definitions for graphics lib. * */ #ifndef _GR_H #define _GR_H #include "pstypes.h" #include "fix.h" // some defines for transparency and blending #define TRANSPARENCY_COLOR 255 // palette entry of transparency color -- 255 on the PC #define GR_FADE_LEVELS 34 #define GR_FADE_OFF GR_FADE_LEVELS // yes, max means OFF - don't screw that up #define GR_BLEND_NORMAL 0 // normal blending #define GR_BLEND_ADDITIVE_A 1 // additive alpha blending #define GR_BLEND_ADDITIVE_C 2 // additive color blending #define GWIDTH grd_curcanv->cv_bitmap.bm_w #define GHEIGHT grd_curcanv->cv_bitmap.bm_h #define SWIDTH (grd_curscreen->sc_w) #define SHEIGHT (grd_curscreen->sc_h) #define HIRESMODE (SWIDTH >= 640 && SHEIGHT >= 480 && GameArg.GfxHiresGFXAvailable) #define MAX_BMP_SIZE(width, height) (4 + ((width) + 2) * (height)) #define SCRNS_DIR "screenshots/" typedef struct _grs_point { fix x,y; } grs_point; //these are control characters that have special meaning in the font code #define CC_COLOR 1 //next char is new foreground color #define CC_LSPACING 2 //next char specifies line spacing #define CC_UNDERLINE 3 //next char is underlined //now have string versions of these control characters (can concat inside a string) #define CC_COLOR_S "\x1" //next char is new foreground color #define CC_LSPACING_S "\x2" //next char specifies line spacing #define CC_UNDERLINE_S "\x3" //next char is underlined #define BM_LINEAR 0 #define BM_MODEX 1 #define BM_SVGA 2 #define BM_RGB15 3 //5 bits each r,g,b stored at 16 bits #define BM_SVGA15 4 #ifdef OGL #define BM_OGL 5 #endif /* def OGL */ #define SM(w,h) ((((u_int32_t)w)<<16)+(((u_int32_t)h)&0xFFFF)) #define SM_W(m) (m>>16) #define SM_H(m) (m&0xFFFF) #define SM_ORIGINAL 0 #define BM_FLAG_TRANSPARENT 1 #define BM_FLAG_SUPER_TRANSPARENT 2 #define BM_FLAG_NO_LIGHTING 4 #define BM_FLAG_RLE 8 // A run-length encoded bitmap. #define BM_FLAG_PAGED_OUT 16 // This bitmap's data is paged out. #define BM_FLAG_RLE_BIG 32 // for bitmaps that RLE to > 255 per row (i.e. cockpits) typedef struct _grs_bitmap { short bm_x,bm_y; // Offset from parent's origin short bm_w,bm_h; // width,height sbyte bm_type; // 0=Linear, 1=ModeX, 2=SVGA sbyte bm_flags; // bit 0 on means it has transparency. // bit 1 on means it has supertransparency // bit 2 on means it doesn't get passed through lighting. short bm_rowsize; // unsigned char offset to next row unsigned char * bm_data; // ptr to pixel data... // Linear = *parent+(rowsize*y+x) // ModeX = *parent+(rowsize*y+x/4) // SVGA = *parent+(rowsize*y+x) unsigned short bm_handle; //for application. initialized to 0 ubyte avg_color; // Average color of all pixels in texture map. fix avg_color_rgb[3]; // same as above but real rgb value to be used to textured objects that should emit light sbyte unused; // to 4-byte align. struct _grs_bitmap *bm_parent; #ifdef OGL struct _ogl_texture *gltexture; #endif /* def OGL */ } grs_bitmap; //font structure typedef struct _grs_font { short ft_w; // Width in pixels short ft_h; // Height in pixels short ft_flags; // Proportional? short ft_baseline; // ubyte ft_minchar; // First char defined by this font ubyte ft_maxchar; // Last char defined by this font short ft_bytewidth; // Width in unsigned chars ubyte * ft_data; // Ptr to raw data. ubyte ** ft_chars; // Ptrs to data for each char (required for prop font) short * ft_widths; // Array of widths (required for prop font) ubyte * ft_kerndata; // Array of kerning triplet data #ifdef OGL // These fields do not participate in disk i/o! grs_bitmap *ft_bitmaps; grs_bitmap ft_parent_bitmap; #endif /* def OGL */ } __pack__ grs_font; #define GRS_FONT_SIZE 28 // how much space it takes up on disk typedef struct _grs_canvas { grs_bitmap cv_bitmap; // the bitmap for this canvas short cv_color; // current color int cv_fade_level; // transparency level ubyte cv_blend_func; // blending function to use short cv_drawmode; // fill,XOR,etc. grs_font * cv_font; // the currently selected font short cv_font_fg_color; // current font foreground color (-1==Invisible) short cv_font_bg_color; // current font background color (-1==Invisible) } grs_canvas; typedef struct _grs_screen { // This is a video screen grs_canvas sc_canvas; // Represents the entire screen int sc_mode; // Video mode number short sc_w, sc_h; // Actual Width and Height fix sc_aspect; //aspect ratio (w/h) for this screen } grs_screen; //========================================================================= // System functions: // setup and set mode. this creates a grs_screen structure and sets // grd_curscreen to point to it. grs_curcanv points to this screen's // canvas. Saves the current VGA state and screen mode. int gr_init(int mode); int gr_list_modes( u_int32_t gsmodes[] ); int gr_check_mode(u_int32_t mode); int gr_set_mode(u_int32_t mode); void gr_set_attributes(void); extern void gr_pal_setblock( int start, int number, unsigned char * pal ); extern void gr_pal_getblock( int start, int number, unsigned char * pal ); //shut down the 2d. Restore the screen mode. void gr_close(void); //========================================================================= // Canvas functions: // Makes a new canvas. allocates memory for the canvas and its bitmap, // including the raw pixel buffer. grs_canvas *gr_create_canvas(int w, int h); // Creates a canvas that is part of another canvas. this can be used to make // a window on the screen. the canvas structure is malloc'd; the address of // the raw pixel data is inherited from the parent canvas. grs_canvas *gr_create_sub_canvas(grs_canvas *canv,int x,int y,int w, int h); // Initialize the specified canvas. the raw pixel data buffer is passed as // a parameter. no memory allocation is performed. void gr_init_canvas(grs_canvas *canv,unsigned char *pixdata,int pixtype, int w,int h); // Initialize the specified sub canvas. no memory allocation is performed. void gr_init_sub_canvas(grs_canvas *,grs_canvas *src,int x,int y,int w, int h); // Free up the canvas and its pixel data. void gr_free_canvas(grs_canvas *canv); // Free up the canvas. do not free the pixel data, which belongs to the // parent canvas. void gr_free_sub_canvas(grs_canvas *canv); // Clear the current canvas to the specified color void gr_clear_canvas(int color); //========================================================================= // Bitmap functions: // these are the two workhorses, the others just use these extern void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ); extern void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h ); extern void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline); // Allocate a bitmap and its pixel data buffer. grs_bitmap *gr_create_bitmap(int w,int h); // Allocated a bitmap and makes its data be raw_data that is already somewhere. grs_bitmap *gr_create_bitmap_raw(int w, int h, unsigned char * raw_data ); // Creates a bitmap which is part of another bitmap grs_bitmap *gr_create_sub_bitmap(grs_bitmap *bm,int x,int y,int w, int h); // Free the bitmap and its pixel data void gr_free_bitmap(grs_bitmap *bm); // Free the bitmap's data void gr_free_bitmap_data (grs_bitmap *bm); void gr_init_bitmap_data (grs_bitmap *bm); // Free the bitmap, but not the pixel data buffer void gr_free_sub_bitmap(grs_bitmap *bm); void gr_bm_pixel( grs_bitmap * bm, int x, int y, unsigned char color ); void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); void gr_bm_ubitblt( int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); void gr_set_bitmap_flags(grs_bitmap *pbm, int flags); void gr_set_transparent(grs_bitmap *pbm, int bTransparent); void gr_set_super_transparent(grs_bitmap *pbm, int bTransparent); void gr_set_bitmap_data(grs_bitmap *bm, unsigned char *data); //========================================================================= // Color functions: // When this function is called, the guns are set to gr_palette, and // the palette stays the same until gr_close is called void gr_use_palette_table(char * filename ); void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size); //========================================================================= // Drawing functions: // Sets the color in the current canvas. void gr_setcolor(int color); // Sets transparency and blending function void gr_settransblend(int fade_level, ubyte blend_func); // Draws a point into the current canvas in the current color and drawmode. void gr_pixel(int x,int y); void gr_upixel(int x,int y); // Gets a pixel; unsigned char gr_gpixel( grs_bitmap * bitmap, int x, int y ); unsigned char gr_ugpixel( grs_bitmap * bitmap, int x, int y ); // Draws a line into the current canvas in the current color and drawmode. int gr_line(fix x0,fix y0,fix x1,fix y1); int gr_uline(fix x0,fix y0,fix x1,fix y1); // Draw the bitmap into the current canvas at the specified location. void gr_bitmap(int x,int y,grs_bitmap *bm); void gr_ubitmap(int x,int y,grs_bitmap *bm); void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst); void show_fullscr(grs_bitmap *bm); // Find transparent area in bitmap void gr_bitblt_find_transparent_area(grs_bitmap *bm, int *minx, int *miny, int *maxx, int *maxy); // bitmap function with transparency void gr_bitmapm( int x, int y, grs_bitmap *bm ); void gr_ubitmapm( int x, int y, grs_bitmap *bm ); // Draw a rectangle into the current canvas. void gr_rect(int left,int top,int right,int bot); void gr_urect(int left,int top,int right,int bot); // Draw a filled circle int gr_disk(fix x,fix y,fix r); // Draw an outline circle int gr_circle(fix x,fix y,fix r); int gr_ucircle(fix x,fix y,fix r); // Draw an unfilled rectangle into the current canvas void gr_box(int left,int top,int right,int bot); void gr_ubox(int left,int top,int right,int bot); void gr_scanline( int x1, int x2, int y ); void gr_uscanline( int x1, int x2, int y ); // Reads in a font file... current font set to this one. grs_font * gr_init_font( const char * fontfile ); void gr_close_font( grs_font * font ); //remap a font, re-reading its data & palette void gr_remap_font( grs_font *font, char * fontname, char *font_data ); //remap (by re-reading) all the color fonts void gr_remap_color_fonts(); void gr_remap_mono_fonts(); // Writes a string using current font. Returns the next column after last char. void gr_set_curfont( grs_font * ); void gr_set_fontcolor( int fg_color, int bg_color ); int gr_string(int x, int y, const char *s ); int gr_ustring(int x, int y, const char *s ); int gr_printf( int x, int y, const char * format, ... ); int gr_uprintf( int x, int y, const char * format, ... ); void gr_get_string_size(const char *s, int *string_width, int *string_height, int *average_width ); // From scale.c void scale_bitmap(grs_bitmap *bp, grs_point *vertbuf, int orientation ); //=========================================================================== // Global variables extern grs_canvas *grd_curcanv; //active canvas extern grs_screen *grd_curscreen; //active screen extern void gr_set_current_canvas( grs_canvas *canv ); //flags for fonts #define FT_COLOR 1 #define FT_PROPORTIONAL 2 #define FT_KERNED 4 extern ubyte gr_palette[256*3]; extern ubyte gr_fade_table[256*GR_FADE_LEVELS]; extern ubyte gr_inverse_table[32*32*32]; extern ushort gr_palette_selector; extern ushort gr_inverse_table_selector; extern ushort gr_fade_table_selector; // Remaps a bitmap into the current palette. If transparent_color is // between 0 and 255 then all occurances of that color are mapped to // whatever color the 2d uses for transparency. This is normally used // right after a call to iff_read_bitmap like this: // iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal); // if (iff_error != IFF_NO_ERROR) Error("Can't load IFF file <%s>, error=%d",filename,iff_error); // if ( iff_has_transparency ) // gr_remap_bitmap( new, newpal, iff_transparent_color ); // else // gr_remap_bitmap( new, newpal, -1 ); extern void gr_remap_bitmap( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ); // Same as above, but searches using gr_find_closest_color which uses // 18-bit accurracy instead of 15bit when translating colors. extern void gr_remap_bitmap_good( grs_bitmap * bmp, ubyte * palette, int transparent_color, int super_transparent_color ); extern void build_colormap_good( ubyte * palette, ubyte * colormap, int * freq ); extern void gr_palette_step_up( int r, int g, int b ); extern void gr_bitmap_check_transparency( grs_bitmap * bmp ); #define BM_RGB(r,g,b) ( (((r)&31)<<10) | (((g)&31)<<5) | ((b)&31) ) #define BM_XRGB(r,g,b) gr_find_closest_color( (r)*2,(g)*2,(b)*2 ) // Given: r,g,b, each in range of 0-63, return the color index that // best matches the input. int gr_find_closest_color( int r, int g, int b ); int gr_find_closest_color_15bpp( int rgb ); extern void gr_flip(void); extern void gr_set_draw_buffer(int buf); /* * must return 0 if windowed, 1 if fullscreen */ int gr_check_fullscreen(void); /* * returns state after toggling (ie, same as if you had called * check_fullscreen immediatly after) */ int gr_toggle_fullscreen(void); void ogl_do_palfx(void); void ogl_init_pixel_buffers(int w, int h); void ogl_close_pixel_buffers(void); #endif /* def _GR_H */ dxx-rebirth-0.58.1-d2x/include/grdef.h000066400000000000000000000043631217717237500174450ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Internal definitions for graphics lib. * */ void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline); void gr_init_sub_bitmap (grs_bitmap *bm, grs_bitmap *bmParent, int x, int y, int w, int h ); void gr_init_bitmap( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline, unsigned char * data ); extern void gr_set_buffer(int w, int h, int r, int (*buffer_func)()); extern void gr_pal_setblock( int start, int n, unsigned char * palette ); extern void gr_pal_getblock( int start, int n, unsigned char * palette ); extern void gr_pal_setone( int index, unsigned char red, unsigned char green, unsigned char blue ); void gr_linear_movsb( ubyte * source, ubyte * dest, int nbytes); void gr_linear_movsw( ubyte * source, ubyte * dest, int nbytes); void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes); extern unsigned int gr_var_color; extern unsigned int gr_var_bwidth; extern unsigned char * gr_var_bitmap; void gr_linear_line( int x0, int y0, int x1, int y1); extern unsigned int Table8to32[256]; #ifdef __MSDOS__ extern unsigned char * gr_video_memory; #endif #define MINX 0 #define MINY 0 #define MAXX (GWIDTH-1) #define MAXY (GHEIGHT-1) #define TYPE grd_curcanv->cv_bitmap.bm_type #define DATA grd_curcanv->cv_bitmap.bm_data #define XOFFSET grd_curcanv->cv_bitmap.bm_x #define YOFFSET grd_curcanv->cv_bitmap.bm_y #define ROWSIZE grd_curcanv->cv_bitmap.bm_rowsize #define COLOR grd_curcanv->cv_color void order( int *x1, int *x2 ); dxx-rebirth-0.58.1-d2x/include/hash.h000066400000000000000000000021301217717237500172670ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifndef _HASH_H #define _HASH_H typedef struct hashtable { int bitsize; int and_mask; int size; int nitems; char **key; int *value; } hashtable; int hashtable_init( hashtable *ht, int size ); void hashtable_free( hashtable *ht ); int hashtable_search( hashtable *ht, char *key ); void hashtable_insert( hashtable *ht, char *key, int value ); #endif dxx-rebirth-0.58.1-d2x/include/hmp.h000066400000000000000000000036761217717237500171500ustar00rootroot00000000000000#ifndef __HMP_H #define __HMP_H #ifdef _WIN32 #include #include #endif #include "physfsx.h" #define HMP_TRACKS 32 #ifdef _WIN32 #define MIDI_VOLUME_SCALE 128 #define HMP_BUFFERS 4 #define HMP_BUFSIZE 1024 #define HMP_INVALID_FILE -1 #define HMP_OUT_OF_MEM -2 #define HMP_MM_ERR -3 #define HMP_EOF 1 #define MIDI_CONTROL_CHANGE 0xB #define MIDI_PROGRAM_CHANGE 0xC #define MIDI_BANK_SELECT_MSB 0x00 #define MIDI_BANK_SELECT_LSB 0x20 #define MIDI_VOLUME 0x07 #define MIDI_PANPOT 0x0A #define MIDI_REVERB 0x5B #define MIDI_CHORUS 0x5D #define MIDI_ALL_SOUNDS_OFF 0x78 #define MIDI_RESET_ALL_CONTROLLERS 0x79 #define MIDI_ALL_NOTES_OFF 0x7B #define HMP_LOOP_START 0x6E #define HMP_LOOP_END 0x6F #endif #ifdef _WIN32 typedef struct event { unsigned int delta; unsigned char msg[3]; unsigned char *data; unsigned int datalen; } event; #endif typedef struct hmp_track { unsigned char *data; unsigned char *loop; unsigned int len; unsigned char *cur; unsigned int left; unsigned int cur_time; unsigned int loop_start; int loop_set; } hmp_track; typedef struct hmp_file { PHYSFS_sint64 filesize; int num_trks; hmp_track trks[HMP_TRACKS]; unsigned int cur_time; unsigned int loop_start; unsigned int loop_end; int looping; int tempo; #ifdef _WIN32 MIDIHDR *evbuf; HMIDISTRM hmidi; UINT devid; #endif unsigned char *pending; unsigned int pending_size; unsigned int pending_event; int stop; int bufs_in_mm; int bLoop; unsigned int midi_division; } hmp_file; hmp_file *hmp_open(const char *filename); void hmp_close(hmp_file *hmp); void hmp2mid(char *hmp_name, unsigned char **midbuf, unsigned int *midlen); #ifdef _WIN32 void hmp_setvolume(hmp_file *hmp, int volume); int hmp_play(hmp_file *hmp, int bLoop); void hmp_pause(hmp_file *hmp); void hmp_resume(hmp_file *hmp); void hmp_reset(); #endif #endif dxx-rebirth-0.58.1-d2x/include/iff.h000066400000000000000000000063351217717237500171230ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for IFF routines * */ #ifndef _IFF_H #define _IFF_H #include "pstypes.h" #include "gr.h" //Prototypes for IFF library functions int iff_read_bitmap(char *ifilename,grs_bitmap *bm,int bitmap_type,ubyte *palette); //reads an IFF file into a grs_bitmap structure. fills in palette if not null //returns error codes - see IFF.H. see GR.H for bitmap_type //MEM DETAILS: This routines assumes that you already have the grs_bitmap //structure allocated, but that you don't have the data for this bitmap //allocated. In other words, do this: // grs_bitmap * MyPicture; // MALLOC( MyPicture, grs_bitmap, 1); // iff_read_bitmap( filename, MyPicture, BM_LINEAR, NULL ); // ...do whatever with your bitmap ... // gr_free_bitmap( MyPicture ); // exit(0) //like iff_read_bitmap(), but reads into a bitmap that already exists, //without allocating memory for the bitmap. int iff_read_into_bitmap(char *ifilename,grs_bitmap *bm, sbyte *palette); //read in animator brush (.abm) file //fills in array of pointers, and n_bitmaps. //returns iff error codes. max_bitmaps is size of array. int iff_read_animbrush(char *ifilename,grs_bitmap **bm,int max_bitmaps,int *n_bitmaps,ubyte *palette); // After a read extern ubyte iff_transparent_color; extern ubyte iff_has_transparency; // 0=no transparency, 1=iff_transparent_color is valid int iff_write_bitmap(char *ofilename,grs_bitmap *bm,ubyte *palette); //writes an IFF file from a grs_bitmap structure. writes palette if not null //returns error codes - see IFF.H. //function to return pointer to error message const char *iff_errormsg(int error_number); //Error codes for read & write routines #define IFF_NO_ERROR 0 //everything is fine, have a nice day #define IFF_NO_MEM 1 //not enough mem for loading or processing #define IFF_UNKNOWN_FORM 2 //IFF file, but not a bitmap #define IFF_NOT_IFF 3 //this isn't even an IFF file #define IFF_NO_FILE 4 //cannot find or open file #define IFF_BAD_BM_TYPE 5 //tried to save invalid type, like BM_RGB15 #define IFF_CORRUPT 6 //bad data in file #define IFF_FORM_ANIM 7 //this is an anim, with non-anim load rtn #define IFF_FORM_BITMAP 8 //this is not an anim, with anim load rtn #define IFF_TOO_MANY_BMS 9 //anim read had more bitmaps than room for #define IFF_UNKNOWN_MASK 10 //unknown masking type #define IFF_READ_ERROR 11 //error reading from file #define IFF_BM_MISMATCH 12 //bm being loaded doesn't match bm loaded into #endif dxx-rebirth-0.58.1-d2x/include/ignorecase.h000066400000000000000000000065001217717237500204700ustar00rootroot00000000000000/** \file ignorecase.h */ /** * \mainpage PhysicsFS ignorecase * * This is an extension to PhysicsFS to let you handle files in a * case-insensitive manner, regardless of what sort of filesystem or * archive they reside in. It does this by enumerating directories as * needed and manually locating matching entries. * * Please note that this brings with it some caveats: * - On filesystems that are case-insensitive to start with, such as those * used on Windows or MacOS, you are adding extra overhead. * - On filesystems that are case-sensitive, you might select the wrong dir * or file (which brings security considerations and potential bugs). This * code favours exact case matches, but you will lose access to otherwise * duplicate filenames, or you might go down a wrong directory tree, etc. * In practive, this is rarely a problem, but you need to be aware of it. * - This doesn't do _anything_ with the write directory; you're on your * own for opening the right files for writing. You can sort of get around * this by adding your write directory to the search path, but then the * interpolated directory tree can screw you up even more. * * This code should be considered an aid for legacy code. New development * shouldn't do dumbass things that require this aid in the first place. :) * * Usage: Set up PhysicsFS as you normally would, then use * PHYSFSEXT_locateCorrectCase() to get a "correct" pathname to pass to * functions like PHYSFS_openRead(), etc. * * License: this code is public domain. I make no warranty that it is useful, * correct, harmless, or environmentally safe. * * This particular file may be used however you like, including copying it * verbatim into a closed-source project, exploiting it commercially, and * removing any trace of my name from the source (although I hope you won't * do that). I welcome enhancements and corrections to this file, but I do * not require you to send me patches if you make changes. This code has * NO WARRANTY. * * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. * Please see LICENSE in the root of the source tree. * * \author Ryan C. Gordon. */ /** * \fn int PHYSFSEXT_locateCorrectCase(char *buf) * \brief Find an existing filename with matching case. * * This function will look for a path/filename that matches the passed in * buffer. Each element of the buffer's path is checked for a * case-insensitive match. The buffer must specify a null-terminated string * in platform-independent notation. * * Please note results may be skewed differently depending on whether symlinks * are enabled or not. * * Each element of the buffer is overwritten with the actual case of an * existing match. If there is no match, the search aborts and reports an * error. Exact matches are favored over case-insensitive matches. * * THIS IS RISKY. Please do not use this function for anything but crappy * legacy code. * * \param buf Buffer with null-terminated string of path/file to locate. * This buffer will be modified by this function. * \return zero if match was found, -1 if the final element (the file itself) * is missing, -2 if one of the parent directories is missing. */ int PHYSFSEXT_locateCorrectCase(char *buf); /* end of ignorecase.h ... */ dxx-rebirth-0.58.1-d2x/include/internal.h000066400000000000000000000050571217717237500201730ustar00rootroot00000000000000/* prototypes for function calls between files within the OpenGL module */ #ifndef _INTERNAL_H_ #define _INTERNAL_H_ #include "ogl_init.h" // interface to OpenGL module /* I assume this ought to be >= MAX_BITMAP_FILES in piggy.h? */ #define OGL_TEXTURE_LIST_SIZE 20000 extern ogl_texture ogl_texture_list[OGL_TEXTURE_LIST_SIZE]; void ogl_init_texture_list_internal(void); void ogl_smash_texture_list_internal(void); void ogl_vivify_texture_list_internal(void); extern int ogl_brightness_ok; extern int ogl_brightness_r, ogl_brightness_g, ogl_brightness_b; extern int ogl_fullscreen; extern int GL_TEXTURE_2D_enabled; #define OGL_ENABLE2(a,f) {if (a ## _enabled!=1) {f;a ## _enabled=1;}} #define OGL_DISABLE2(a,f) {if (a ## _enabled!=0) {f;a ## _enabled=0;}} //#define OGL_ENABLE(a) OGL_ENABLE2(a,glEnable(a)) //#define OGL_DISABLE(a) OGL_DISABLE2(a,glDisable(a)) #define OGL_ENABLE(a) OGL_ENABLE2(GL_ ## a,glEnable(GL_ ## a)) #define OGL_DISABLE(a) OGL_DISABLE2(GL_ ## a,glDisable(GL_ ## a)) //#define OGL_TEXCLAMP() OGL_ENABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);) //#define OGL_TEXREPEAT() OGL_DISABLE2(GL_texclamp,glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);) //#define OGL_SETSTATE(a,s,f) {if (a ## _state!=s) {f;a ## _state=s;}} //#define OGL_TEXENV(p,m) OGL_SETSTATE(p,m,glTexEnvi(GL_TEXTURE_ENV, p,m)); //#define OGL_TEXPARAM(p,m) OGL_SETSTATE(p,m,glTexParameteri(GL_TEXTURE_2D,p,m)) extern int last_width,last_height; #define OGL_VIEWPORT(x,y,w,h){if (w!=last_width || h!=last_height){glViewport(x,grd_curscreen->sc_canvas.cv_bitmap.bm_h-y-h,w,h);last_width=w;last_height=h;}} //platform specific funcs extern void ogl_swap_buffers_internal(void); extern unsigned char *ogl_pal; //whee //#define PAL2Tr(c) ((gr_palette[c*3]+gr_palette_gamma)/63.0) //#define PAL2Tg(c) ((gr_palette[c*3+1]+gr_palette_gamma)/63.0) //#define PAL2Tb(c) ((gr_palette[c*3+2]+gr_palette_gamma)/63.0) //#define PAL2Tr(c) ((gr_palette[c*3])/63.0) //#define PAL2Tg(c) ((gr_palette[c*3+1])/63.0) //#define PAL2Tb(c) ((gr_palette[c*3+2])/63.0) #define CPAL2Tr(c) ((gr_current_pal[c*3])/63.0) #define CPAL2Tg(c) ((gr_current_pal[c*3+1])/63.0) #define CPAL2Tb(c) ((gr_current_pal[c*3+2])/63.0) #define PAL2Tr(c) ((ogl_pal[c*3])/63.0) #define PAL2Tg(c) ((ogl_pal[c*3+1])/63.0) #define PAL2Tb(c) ((ogl_pal[c*3+2])/63.0) //inline GLfloat PAL2Tr(int c); //inline GLfloat PAL2Tg(int c); //inline GLfloat PAL2Tb(int c); #endif // _INTERNAL_H_ dxx-rebirth-0.58.1-d2x/include/interp.h000066400000000000000000000046431217717237500176600ustar00rootroot00000000000000/* * * took out functions declarations from include/3d.h * which are implemented in 3d/interp.c * */ #ifndef _INTERP_H #define _INTERP_H #include "fix.h" #include "gr.h" #include "3d.h" //Object functions: //gives the interpreter an array of points to use void g3_set_interp_points(g3s_point *pointlist); //calls the object interpreter to render an object. The object renderer //is really a seperate pipeline. returns true if drew bool g3_draw_polygon_model(ubyte *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,g3s_lrgb light,fix *glow_values); //init code for bitmap models void g3_init_polygon_model(void *model_ptr); //un-initialize, i.e., convert color entries back to RGB15 static inline void g3_uninit_polygon_model(void *model_ptr) { (void)model_ptr; } //alternate interpreter for morphing object bool g3_draw_morphing_model(ubyte *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,g3s_lrgb light,vms_vector *new_points); //this remaps the 15bpp colors for the models into a new palette. It should //be called whenever the palette changes void g3_remap_interp_colors(void); // check a polymodel for it's color and return it int g3_poly_get_color(ubyte *model_ptr); #ifdef WORDS_BIGENDIAN // routine to convert little to big endian in polygon model data void swap_polygon_model_data(ubyte *data); //routines to convert little to big endian in vectors void vms_vector_swap(vms_vector *v); void vms_angvec_swap(vms_angvec *v); #endif #ifdef WORDS_NEED_ALIGNMENT /* * A chunk struct (as used for alignment) contains all relevant data * concerning a piece of data that may need to be aligned. * To align it, we need to copy it to an aligned position, * and update all pointers to it. * (Those pointers are actually offsets * relative to start of model_data) to it. */ typedef struct chunk { ubyte *old_base; // where the offset sets off from (relative to beginning of model_data) ubyte *new_base; // where the base is in the aligned structure short offset; // how much to add to base to get the address of the offset short correction; // how much the value of the offset must be shifted for alignment } chunk; #define MAX_CHUNKS 100 // increase if insufficent /* * finds what chunks the data points to, adds them to the chunk_list, * and returns the length of the current chunk */ int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no); #endif //def WORDS_NEED_ALIGNMENT #endif //_INTERP_H dxx-rebirth-0.58.1-d2x/include/libmve.h000066400000000000000000000021231217717237500176240ustar00rootroot00000000000000#ifndef _LIBMVE_H #define _LIBMVE_H #define MVE_ERR_EOF 1 typedef struct{ int screenWidth; int screenHeight; int width; int height; int truecolor; } MVE_videoSpec; int MVE_rmPrepMovie(void *stream, int x, int y, int track); int MVE_rmStepMovie(); void MVE_rmHoldMovie(); void MVE_rmEndMovie(); void MVE_getVideoSpec(MVE_videoSpec *vSpec); void MVE_sndInit(int x); typedef unsigned int (*mve_cb_Read)(void *stream, void *buffer, unsigned int count); typedef void *(*mve_cb_Alloc)(unsigned int size); typedef void (*mve_cb_Free)(void *ptr); typedef void (*mve_cb_ShowFrame)(unsigned char *buffer, int dstx, int dsty, int bufw, int bufh, int sw, int sh); typedef void (*mve_cb_SetPalette)(unsigned char *p, unsigned int start, unsigned int count); void MVE_ioCallbacks(mve_cb_Read io_read); void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free); void MVE_sfCallbacks(mve_cb_ShowFrame showframe); void MVE_palCallbacks(mve_cb_SetPalette setpalette); #endif /* _LIBMVE_H */ dxx-rebirth-0.58.1-d2x/include/loadgl.h000066400000000000000000003035371217717237500176250ustar00rootroot00000000000000/* * * dynamic opengl loading - courtesy of Jeff Slutter * * */ #ifndef __LOADGL_H__ #define __LOADGL_H__ #ifdef _WIN32 #include #define OGLFUNCCALL __stdcall #else #define OGLFUNCCALL #endif #include #include "pstypes.h" //gl extensions. #ifndef GL_ARB_multitexture #define GL_ARB_multitexture 1 #define GL_TEXTURE0_ARB 0x84C0 #define GL_TEXTURE1_ARB 0x84C1 #define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 #endif #ifndef GL_SGIS_multitexture #define GL_SGIS_multitexture 1 #define GL_TEXTURE0_SGIS 0x835F #define GL_TEXTURE1_SGIS 0x8360 #define GL_MAX_TEXTURES_SGIS 0x835D #endif #ifndef GL_EXT_paletted_texture #define GL_EXT_paletted_texture 1 #define GL_COLOR_INDEX8_EXT 0x80E5 #define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED #endif #ifndef GL_TEXTURE_INDEX_SIZE_EXT #define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED #endif #ifndef GL_SCISSOR_TEST #define GL_SCISSOR_TEST 0x0C11 #endif #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #ifndef GL_NV_register_combiners #define GL_NV_register_combiners 1 #define GL_REGISTER_COMBINERS_NV 0x8522 #define GL_VARIABLE_A_NV 0x8523 #define GL_VARIABLE_B_NV 0x8524 #define GL_VARIABLE_C_NV 0x8525 #define GL_VARIABLE_D_NV 0x8526 #define GL_VARIABLE_E_NV 0x8527 #define GL_VARIABLE_F_NV 0x8528 #define GL_VARIABLE_G_NV 0x8529 #define GL_CONSTANT_COLOR0_NV 0x852A #define GL_CONSTANT_COLOR1_NV 0x852B #define GL_PRIMARY_COLOR_NV 0x852C #define GL_SECONDARY_COLOR_NV 0x852D #define GL_SPARE0_NV 0x852E #define GL_SPARE1_NV 0x852F #define GL_DISCARD_NV 0x8530 #define GL_E_TIMES_F_NV 0x8531 #define GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532 #define GL_UNSIGNED_IDENTITY_NV 0x8536 #define GL_UNSIGNED_INVERT_NV 0x8537 #define GL_EXPAND_NORMAL_NV 0x8538 #define GL_EXPAND_NEGATE_NV 0x8539 #define GL_HALF_BIAS_NORMAL_NV 0x853A #define GL_HALF_BIAS_NEGATE_NV 0x853B #define GL_SIGNED_IDENTITY_NV 0x853C #define GL_SIGNED_NEGATE_NV 0x853D #define GL_SCALE_BY_TWO_NV 0x853E #define GL_SCALE_BY_FOUR_NV 0x853F #define GL_SCALE_BY_ONE_HALF_NV 0x8540 #define GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541 #define GL_COMBINER_INPUT_NV 0x8542 #define GL_COMBINER_MAPPING_NV 0x8543 #define GL_COMBINER_COMPONENT_USAGE_NV 0x8544 #define GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545 #define GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546 #define GL_COMBINER_MUX_SUM_NV 0x8547 #define GL_COMBINER_SCALE_NV 0x8548 #define GL_COMBINER_BIAS_NV 0x8549 #define GL_COMBINER_AB_OUTPUT_NV 0x854A #define GL_COMBINER_CD_OUTPUT_NV 0x854B #define GL_COMBINER_SUM_OUTPUT_NV 0x854C #define GL_MAX_GENERAL_COMBINERS_NV 0x854D #define GL_NUM_GENERAL_COMBINERS_NV 0x854E #define GL_COLOR_SUM_CLAMP_NV 0x854F #define GL_COMBINER0_NV 0x8550 #define GL_COMBINER1_NV 0x8551 #define GL_COMBINER2_NV 0x8552 #define GL_COMBINER3_NV 0x8553 #define GL_COMBINER4_NV 0x8554 #define GL_COMBINER5_NV 0x8555 #define GL_COMBINER6_NV 0x8556 #define GL_COMBINER7_NV 0x8557 #endif #define GL_SCISSOR_TEST 0x0C11 #ifdef _cplusplus #define OEXTERN extern "C" #else #define OEXTERN extern #define true 1 #define false 0 #endif #ifdef DECLARE_VARS #define DEFVAR #else #define DEFVAR OEXTERN #endif #define glAccum dglAccum #define glAlphaFunc dglAlphaFunc #define glAreTexturesResident dglAreTexturesResident #define glArrayElement dglArrayElement #define glBegin dglBegin #define glBindTexture dglBindTexture #define glBitmap dglBitmap #define glBlendFunc dglBlendFunc #define glCallList dglCallList #define glCallLists dglCallLists #define glClear dglClear #define glClearAccum dglClearAccum #define glClearColor dglClearColor #define glClearDepth dglClearDepth #define glClearIndex dglClearIndex #define glClearStencil dglClearStencil #define glClipPlane dglClipPlane #define glColor3b dglColor3b #define glColor3bv dglColor3bv #define glColor3d dglColor3d #define glColor3dv dglColor3dv #define glColor3f dglColor3f #define glColor3fv dglColor3fv #define glColor3i dglColor3i #define glColor3iv dglColor3iv #define glColor3s dglColor3s #define glColor3sv dglColor3sv #define glColor3ub dglColor3ub #define glColor3ubv dglColor3ubv #define glColor3ui dglColor3ui #define glColor3uiv dglColor3uiv #define glColor3us dglColor3us #define glColor3usv dglColor3usv #define glColor4b dglColor4b #define glColor4bv dglColor4bv #define glColor4d dglColor4d #define glColor4dv dglColor4dv #define glColor4f dglColor4f #define glColor4fv dglColor4fv #define glColor4i dglColor4i #define glColor4iv dglColor4iv #define glColor4s dglColor4s #define glColor4sv dglColor4sv #define glColor4ub dglColor4ub #define glColor4ubv dglColor4ubv #define glColor4ui dglColor4ui #define glColor4uiv dglColor4uiv #define glColor4us dglColor4us #define glColor4usv dglColor4usv #define glColorMask dglColorMask #define glColorMaterial dglColorMaterial #define glColorPointer dglColorPointer #define glCopyPixels dglCopyPixels #define glCopyTexImage1D dglCopyTexImage1D #define glCopyTexImage2D dglCopyTexImage2D #define glCopyTexSubImage1D dglCopyTexSubImage1D #define glCopyTexSubImage2D dglCopyTexSubImage2D #define glCullFace dglCullFace #define glDeleteLists dglDeleteLists #define glDeleteTextures dglDeleteTextures #define glDepthFunc dglDepthFunc #define glDepthMask dglDepthMask #define glDepthRange dglDepthRange #define glDisable dglDisable #define glDisableClientState dglDisableClientState #define glDrawArrays dglDrawArrays #define glDrawBuffer dglDrawBuffer #define glDrawElements dglDrawElements #define glDrawPixels dglDrawPixels #define glEdgeFlag dglEdgeFlag #define glEdgeFlagPointer dglEdgeFlagPointer #define glEdgeFlagv dglEdgeFlagv #define glEnable dglEnable #define glEnableClientState dglEnableClientState #define glEnd dglEnd #define glEndList dglEndList #define glEvalCoord1d dglEvalCoord1d #define glEvalCoord1dv dglEvalCoord1dv #define glEvalCoord1f dglEvalCoord1f #define glEvalCoord1fv dglEvalCoord1fv #define glEvalCoord2d dglEvalCoord2d #define glEvalCoord2dv dglEvalCoord2dv #define glEvalCoord2f dglEvalCoord2f #define glEvalCoord2fv dglEvalCoord2fv #define glEvalMesh1 dglEvalMesh1 #define glEvalMesh2 dglEvalMesh2 #define glEvalPoint1 dglEvalPoint1 #define glEvalPoint2 dglEvalPoint2 #define glFeedbackBuffer dglFeedbackBuffer #define glFinish dglFinish #define glFlush dglFlush #define glFogf dglFogf #define glFogfv dglFogfv #define glFogi dglFogi #define glFogiv dglFogiv #define glFrontFace dglFrontFace #define glFrustum dglFrustum #define glGenLists dglGenLists #define glGenTextures dglGenTextures #define glGetBooleanv dglGetBooleanv #define glGetClipPlane dglGetClipPlane #define glGetDoublev dglGetDoublev #define glGetError dglGetError #define glGetFloatv dglGetFloatv #define glGetIntegerv dglGetIntegerv #define glGetLightfv dglGetLightfv #define glGetLightiv dglGetLightiv #define glGetMapdv dglGetMapdv #define glGetMapfv dglGetMapfv #define glGetMapiv dglGetMapiv #define glGetMaterialfv dglGetMaterialfv #define glGetMaterialiv dglGetMaterialiv #define glGetPixelMapfv dglGetPixelMapfv #define glGetPixelMapuiv dglGetPixelMapuiv #define glGetPixelMapusv dglGetPixelMapusv #define glGetPointerv dglGetPointerv #define glGetPolygonStipple dglGetPolygonStipple #define glGetString dglGetString #define glGetTexEnvfv dglGetTexEnvfv #define glGetTexEnviv dglGetTexEnviv #define glGetTexGendv dglGetTexGendv #define glGetTexGenfv dglGetTexGenfv #define glGetTexGeniv dglGetTexGeniv #define glGetTexImage dglGetTexImage #define glGetTexLevelParameterfv dglGetTexLevelParameterfv #define glGetTexLevelParameteriv dglGetTexLevelParameteriv #define glGetTexParameterfv dglGetTexParameterfv #define glGetTexParameteriv dglGetTexParameteriv #define glHint dglHint #define glIndexMask dglIndexMask #define glIndexPointer dglIndexPointer #define glIndexd dglIndexd #define glIndexdv dglIndexdv #define glIndexf dglIndexf #define glIndexfv dglIndexfv #define glIndexi dglIndexi #define glIndexiv dglIndexiv #define glIndexs dglIndexs #define glIndexsv dglIndexsv #define glIndexub dglIndexub #define glIndexubv dglIndexubv #define glInitNames dglInitNames #define glInterleavedArrays dglInterleavedArrays #define glIsEnabled dglIsEnabled #define glIsList dglIsList #define glIsTexture dglIsTexture #define glLightModelf dglLightModelf #define glLightModelfv dglLightModelfv #define glLightModeli dglLightModeli #define glLightModeliv dglLightModeliv #define glLightf dglLightf #define glLightfv dglLightfv #define glLighti dglLighti #define glLightiv dglLightiv #define glLineStipple dglLineStipple #define glLineWidth dglLineWidth #define glListBase dglListBase #define glLoadIdentity dglLoadIdentity #define glLoadMatrixd dglLoadMatrixd #define glLoadMatrixf dglLoadMatrixf #define glLoadName dglLoadName #define glLogicOp dglLogicOp #define glMap1d dglMap1d #define glMap1f dglMap1f #define glMap2d dglMap2d #define glMap2f dglMap2f #define glMapGrid1d dglMapGrid1d #define glMapGrid1f dglMapGrid1f #define glMapGrid2d dglMapGrid2d #define glMapGrid2f dglMapGrid2f #define glMaterialf dglMaterialf #define glMaterialfv dglMaterialfv #define glMateriali dglMateriali #define glMaterialiv dglMaterialiv #define glMatrixMode dglMatrixMode #define glMultMatrixd dglMultMatrixd #define glMultMatrixf dglMultMatrixf #define glNewList dglNewList #define glNormal3b dglNormal3b #define glNormal3bv dglNormal3bv #define glNormal3d dglNormal3d #define glNormal3dv dglNormal3dv #define glNormal3f dglNormal3f #define glNormal3fv dglNormal3fv #define glNormal3i dglNormal3i #define glNormal3iv dglNormal3iv #define glNormal3s dglNormal3s #define glNormal3sv dglNormal3sv #define glNormalPointer dglNormalPointer #define glOrtho dglOrtho #define glPassThrough dglPassThrough #define glPixelMapfv dglPixelMapfv #define glPixelMapuiv dglPixelMapuiv #define glPixelMapusv dglPixelMapusv #define glPixelStoref dglPixelStoref #define glPixelStorei dglPixelStorei #define glPixelTransferf dglPixelTransferf #define glPixelTransferi dglPixelTransferi #define glPixelZoom dglPixelZoom #define glPointSize dglPointSize #define glPolygonMode dglPolygonMode #define glPolygonOffset dglPolygonOffset #define glPolygonStipple dglPolygonStipple #define glPopAttrib dglPopAttrib #define glPopClientAttrib dglPopClientAttrib #define glPopMatrix dglPopMatrix #define glPopName dglPopName #define glPrioritizeTextures dglPrioritizeTextures #define glPushAttrib dglPushAttrib #define glPushClientAttrib dglPushClientAttrib #define glPushMatrix dglPushMatrix #define glPushName dglPushName #define glRasterPos2d dglRasterPos2d #define glRasterPos2dv dglRasterPos2dv #define glRasterPos2f dglRasterPos2f #define glRasterPos2fv dglRasterPos2fv #define glRasterPos2i dglRasterPos2i #define glRasterPos2iv dglRasterPos2iv #define glRasterPos2s dglRasterPos2s #define glRasterPos2sv dglRasterPos2sv #define glRasterPos3d dglRasterPos3d #define glRasterPos3dv dglRasterPos3dv #define glRasterPos3f dglRasterPos3f #define glRasterPos3fv dglRasterPos3fv #define glRasterPos3i dglRasterPos3i #define glRasterPos3iv dglRasterPos3iv #define glRasterPos3s dglRasterPos3s #define glRasterPos3sv dglRasterPos3sv #define glRasterPos4d dglRasterPos4d #define glRasterPos4dv dglRasterPos4dv #define glRasterPos4f dglRasterPos4f #define glRasterPos4fv dglRasterPos4fv #define glRasterPos4i dglRasterPos4i #define glRasterPos4iv dglRasterPos4iv #define glRasterPos4s dglRasterPos4s #define glRasterPos4sv dglRasterPos4sv #define glReadBuffer dglReadBuffer #define glReadPixels dglReadPixels #define glRectd dglRectd #define glRectdv dglRectdv #define glRectf dglRectf #define glRectfv dglRectfv #define glRecti dglRecti #define glRectiv dglRectiv #define glRects dglRects #define glRectsv dglRectsv #define glRenderMode dglRenderMode #define glRotated dglRotated #define glRotatef dglRotatef #define glScaled dglScaled #define glScalef dglScalef #define glScissor dglScissor #define glSelectBuffer dglSelectBuffer #define glShadeModel dglShadeModel #define glStencilFunc dglStencilFunc #define glStencilMask dglStencilMask #define glStencilOp dglStencilOp #define glTexCoord1d dglTexCoord1d #define glTexCoord1dv dglTexCoord1dv #define glTexCoord1f dglTexCoord1f #define glTexCoord1fv dglTexCoord1fv #define glTexCoord1i dglTexCoord1i #define glTexCoord1iv dglTexCoord1iv #define glTexCoord1s dglTexCoord1s #define glTexCoord1sv dglTexCoord1sv #define glTexCoord2d dglTexCoord2d #define glTexCoord2dv dglTexCoord2dv #define glTexCoord2f dglTexCoord2f #define glTexCoord2fv dglTexCoord2fv #define glTexCoord2i dglTexCoord2i #define glTexCoord2iv dglTexCoord2iv #define glTexCoord2s dglTexCoord2s #define glTexCoord2sv dglTexCoord2sv #define glTexCoord3d dglTexCoord3d #define glTexCoord3dv dglTexCoord3dv #define glTexCoord3f dglTexCoord3f #define glTexCoord3fv dglTexCoord3fv #define glTexCoord3i dglTexCoord3i #define glTexCoord3iv dglTexCoord3iv #define glTexCoord3s dglTexCoord3s #define glTexCoord3sv dglTexCoord3sv #define glTexCoord4d dglTexCoord4d #define glTexCoord4dv dglTexCoord4dv #define glTexCoord4f dglTexCoord4f #define glTexCoord4fv dglTexCoord4fv #define glTexCoord4i dglTexCoord4i #define glTexCoord4iv dglTexCoord4iv #define glTexCoord4s dglTexCoord4s #define glTexCoord4sv dglTexCoord4sv #define glTexCoordPointer dglTexCoordPointer #define glTexEnvf dglTexEnvf #define glTexEnvfv dglTexEnvfv #define glTexEnvi dglTexEnvi #define glTexEnviv dglTexEnviv #define glTexGend dglTexGend #define glTexGendv dglTexGendv #define glTexGenf dglTexGenf #define glTexGenfv dglTexGenfv #define glTexGeni dglTexGeni #define glTexGeniv dglTexGeniv #define glTexImage1D dglTexImage1D #define glTexImage2D dglTexImage2D #define glTexParameterf dglTexParameterf #define glTexParameterfv dglTexParameterfv #define glTexParameteri dglTexParameteri #define glTexParameteriv dglTexParameteriv #define glTexSubImage1D dglTexSubImage1D #define glTexSubImage2D dglTexSubImage2D #define glTranslated dglTranslated #define glTranslatef dglTranslatef #define glVertex2d dglVertex2d #define glVertex2dv dglVertex2dv #define glVertex2f dglVertex2f #define glVertex2fv dglVertex2fv #define glVertex2i dglVertex2i #define glVertex2iv dglVertex2iv #define glVertex2s dglVertex2s #define glVertex2sv dglVertex2sv #define glVertex3d dglVertex3d #define glVertex3dv dglVertex3dv #define glVertex3f dglVertex3f #define glVertex3fv dglVertex3fv #define glVertex3i dglVertex3i #define glVertex3iv dglVertex3iv #define glVertex3s dglVertex3s #define glVertex3sv dglVertex3sv #define glVertex4d dglVertex4d #define glVertex4dv dglVertex4dv #define glVertex4f dglVertex4f #define glVertex4fv dglVertex4fv #define glVertex4i dglVertex4i #define glVertex4iv dglVertex4iv #define glVertex4s dglVertex4s #define glVertex4sv dglVertex4sv #define glVertexPointer dglVertexPointer #define glViewport dglViewport #define glMultiTexCoord2fARB dglMultiTexCoord2fARB #define glActiveTextureARB dglActiveTextureARB #define glMultiTexCoord2fSGIS dglMultiTexCoord2fSGIS #define glSelectTextureSGIS dglSelectTextureSGIS #define glColorTableEXT dglColorTableEXT #define glCombinerParameteriNV dglCombinerParameteriNV #define glCombinerInputNV dglCombinerInputNV #define glCombinerOutputNV dglCombinerOutputNV #define glFinalCombinerInputNV dglFinalCombinerInputNV #ifdef _WIN32 #define wglCopyContext dwglCopyContext #define wglCreateContext dwglCreateContext #define wglCreateLayerContext dwglCreateLayerContext #define wglDeleteContext dwglDeleteContext #define wglGetCurrentContext dwglGetCurrentContext #define wglGetCurrentDC dwglGetCurrentDC #define wglGetProcAddress dwglGetProcAddress #define wglMakeCurrent dwglMakeCurrent #define wglShareLists dwglShareLists #define wglUseFontBitmapsA dwglUseFontBitmapsA #define wglUseFontBitmapsW dwglUseFontBitmapsW #define wglUseFontOutlinesA dwglUseFontOutlinesA #define wglUseFontOutlinesW dwglUseFontOutlinesW #define wglDescribeLayerPlane dwglDescribeLayerPlane #define wglSetLayerPaletteEntries dwglSetLayerPaletteEntries #define wglGetLayerPaletteEntries dwglGetLayerPaletteEntries #define wglRealizeLayerPalette dwglRealizeLayerPalette #define wglSwapLayerBuffers dwglSwapLayerBuffers #if (WINVER >= 0x0500) #define wglSwapMultipleBuffers dwglSwapMultipleBuffers #endif #endif typedef void (OGLFUNCCALL *glAccum_fp)(GLenum op, GLfloat value); typedef void (OGLFUNCCALL *glAlphaFunc_fp)(GLenum func, GLclampf ref); typedef GLboolean (OGLFUNCCALL *glAreTexturesResident_fp)(GLsizei n, const GLuint *textures, GLboolean *residences); typedef void (OGLFUNCCALL *glArrayElement_fp)(GLint i); typedef void (OGLFUNCCALL *glBegin_fp)(GLenum mode); typedef void (OGLFUNCCALL *glBindTexture_fp)(GLenum target, GLuint texture); typedef void (OGLFUNCCALL *glBitmap_fp)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); typedef void (OGLFUNCCALL *glBlendFunc_fp)(GLenum sfactor, GLenum dfactor); typedef void (OGLFUNCCALL *glCallList_fp)(GLuint list); typedef void (OGLFUNCCALL *glCallLists_fp)(GLsizei n, GLenum type, const GLvoid *lists); typedef void (OGLFUNCCALL *glClear_fp)(GLbitfield mask); typedef void (OGLFUNCCALL *glClearAccum_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); typedef void (OGLFUNCCALL *glClearColor_fp)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); typedef void (OGLFUNCCALL *glClearDepth_fp)(GLclampd depth); typedef void (OGLFUNCCALL *glClearIndex_fp)(GLfloat c); typedef void (OGLFUNCCALL *glClearStencil_fp)(GLint s); typedef void (OGLFUNCCALL *glClipPlane_fp)(GLenum plane, const GLdouble *equation); typedef void (OGLFUNCCALL *glColor3b_fp)(GLbyte red, GLbyte green, GLbyte blue); typedef void (OGLFUNCCALL *glColor3bv_fp)(const GLbyte *v); typedef void (OGLFUNCCALL *glColor3d_fp)(GLdouble red, GLdouble green, GLdouble blue); typedef void (OGLFUNCCALL *glColor3dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glColor3f_fp)(GLfloat red, GLfloat green, GLfloat blue); typedef void (OGLFUNCCALL *glColor3fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glColor3i_fp)(GLint red, GLint green, GLint blue); typedef void (OGLFUNCCALL *glColor3iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glColor3s_fp)(GLshort red, GLshort green, GLshort blue); typedef void (OGLFUNCCALL *glColor3sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glColor3ub_fp)(GLubyte red, GLubyte green, GLubyte blue); typedef void (OGLFUNCCALL *glColor3ubv_fp)(const GLubyte *v); typedef void (OGLFUNCCALL *glColor3ui_fp)(GLuint red, GLuint green, GLuint blue); typedef void (OGLFUNCCALL *glColor3uiv_fp)(const GLuint *v); typedef void (OGLFUNCCALL *glColor3us_fp)(GLushort red, GLushort green, GLushort blue); typedef void (OGLFUNCCALL *glColor3usv_fp)(const GLushort *v); typedef void (OGLFUNCCALL *glColor4b_fp)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); typedef void (OGLFUNCCALL *glColor4bv_fp)(const GLbyte *v); typedef void (OGLFUNCCALL *glColor4d_fp)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); typedef void (OGLFUNCCALL *glColor4dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glColor4f_fp)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); typedef void (OGLFUNCCALL *glColor4fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glColor4i_fp)(GLint red, GLint green, GLint blue, GLint alpha); typedef void (OGLFUNCCALL *glColor4iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glColor4s_fp)(GLshort red, GLshort green, GLshort blue, GLshort alpha); typedef void (OGLFUNCCALL *glColor4sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glColor4ub_fp)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); typedef void (OGLFUNCCALL *glColor4ubv_fp)(const GLubyte *v); typedef void (OGLFUNCCALL *glColor4ui_fp)(GLuint red, GLuint green, GLuint blue, GLuint alpha); typedef void (OGLFUNCCALL *glColor4uiv_fp)(const GLuint *v); typedef void (OGLFUNCCALL *glColor4us_fp)(GLushort red, GLushort green, GLushort blue, GLushort alpha); typedef void (OGLFUNCCALL *glColor4usv_fp)(const GLushort *v); typedef void (OGLFUNCCALL *glColorMask_fp)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); typedef void (OGLFUNCCALL *glColorMaterial_fp)(GLenum face, GLenum mode); typedef void (OGLFUNCCALL *glColorPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glCopyPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); typedef void (OGLFUNCCALL *glCopyTexImage1D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); typedef void (OGLFUNCCALL *glCopyTexImage2D_fp)(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); typedef void (OGLFUNCCALL *glCopyTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); typedef void (OGLFUNCCALL *glCopyTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef void (OGLFUNCCALL *glCullFace_fp)(GLenum mode); typedef void (OGLFUNCCALL *glDeleteLists_fp)(GLuint list, GLsizei range); typedef void (OGLFUNCCALL *glDeleteTextures_fp)(GLsizei n, const GLuint *textures); typedef void (OGLFUNCCALL *glDepthFunc_fp)(GLenum func); typedef void (OGLFUNCCALL *glDepthMask_fp)(GLboolean flag); typedef void (OGLFUNCCALL *glDepthRange_fp)(GLclampd zNear, GLclampd zFar); typedef void (OGLFUNCCALL *glDisable_fp)(GLenum cap); typedef void (OGLFUNCCALL *glDisableClientState_fp)(GLenum array); typedef void (OGLFUNCCALL *glDrawArrays_fp)(GLenum mode, GLint first, GLsizei count); typedef void (OGLFUNCCALL *glDrawBuffer_fp)(GLenum mode); typedef void (OGLFUNCCALL *glDrawElements_fp)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); typedef void (OGLFUNCCALL *glDrawPixels_fp)(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); typedef void (OGLFUNCCALL *glEdgeFlag_fp)(GLboolean flag); typedef void (OGLFUNCCALL *glEdgeFlagPointer_fp)(GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glEdgeFlagv_fp)(const GLboolean *flag); typedef void (OGLFUNCCALL *glEnable_fp)(GLenum cap); typedef void (OGLFUNCCALL *glEnableClientState_fp)(GLenum array); typedef void (OGLFUNCCALL *glEnd_fp)(void); typedef void (OGLFUNCCALL *glEndList_fp)(void); typedef void (OGLFUNCCALL *glEvalCoord1d_fp)(GLdouble u); typedef void (OGLFUNCCALL *glEvalCoord1dv_fp)(const GLdouble *u); typedef void (OGLFUNCCALL *glEvalCoord1f_fp)(GLfloat u); typedef void (OGLFUNCCALL *glEvalCoord1fv_fp)(const GLfloat *u); typedef void (OGLFUNCCALL *glEvalCoord2d_fp)(GLdouble u, GLdouble v); typedef void (OGLFUNCCALL *glEvalCoord2dv_fp)(const GLdouble *u); typedef void (OGLFUNCCALL *glEvalCoord2f_fp)(GLfloat u, GLfloat v); typedef void (OGLFUNCCALL *glEvalCoord2fv_fp)(const GLfloat *u); typedef void (OGLFUNCCALL *glEvalMesh1_fp)(GLenum mode, GLint i1, GLint i2); typedef void (OGLFUNCCALL *glEvalMesh2_fp)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); typedef void (OGLFUNCCALL *glEvalPoint1_fp)(GLint i); typedef void (OGLFUNCCALL *glEvalPoint2_fp)(GLint i, GLint j); typedef void (OGLFUNCCALL *glFeedbackBuffer_fp)(GLsizei size, GLenum type, GLfloat *buffer); typedef void (OGLFUNCCALL *glFinish_fp)(void); typedef void (OGLFUNCCALL *glFlush_fp)(void); typedef void (OGLFUNCCALL *glFogf_fp)(GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glFogfv_fp)(GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glFogi_fp)(GLenum pname, GLint param); typedef void (OGLFUNCCALL *glFogiv_fp)(GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glFrontFace_fp)(GLenum mode); typedef void (OGLFUNCCALL *glFrustum_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); typedef GLuint (OGLFUNCCALL *glGenLists_fp)(GLsizei range); typedef void (OGLFUNCCALL *glGenTextures_fp)(GLsizei n, GLuint *textures); typedef void (OGLFUNCCALL *glGetBooleanv_fp)(GLenum pname, GLboolean *params); typedef void (OGLFUNCCALL *glGetClipPlane_fp)(GLenum plane, GLdouble *equation); typedef void (OGLFUNCCALL *glGetDoublev_fp)(GLenum pname, GLdouble *params); typedef GLenum (OGLFUNCCALL *glGetError_fp)(void); typedef void (OGLFUNCCALL *glGetFloatv_fp)(GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetIntegerv_fp)(GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetLightfv_fp)(GLenum light, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetLightiv_fp)(GLenum light, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetMapdv_fp)(GLenum target, GLenum query, GLdouble *v); typedef void (OGLFUNCCALL *glGetMapfv_fp)(GLenum target, GLenum query, GLfloat *v); typedef void (OGLFUNCCALL *glGetMapiv_fp)(GLenum target, GLenum query, GLint *v); typedef void (OGLFUNCCALL *glGetMaterialfv_fp)(GLenum face, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetMaterialiv_fp)(GLenum face, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetPixelMapfv_fp)(GLenum map, GLfloat *values); typedef void (OGLFUNCCALL *glGetPixelMapuiv_fp)(GLenum map, GLuint *values); typedef void (OGLFUNCCALL *glGetPixelMapusv_fp)(GLenum map, GLushort *values); typedef void (OGLFUNCCALL *glGetPointerv_fp)(GLenum pname, GLvoid* *params); typedef void (OGLFUNCCALL *glGetPolygonStipple_fp)(GLubyte *mask); typedef const GLubyte *(OGLFUNCCALL *glGetString_fp)(GLenum name); typedef void (OGLFUNCCALL *glGetTexEnvfv_fp)(GLenum target, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetTexEnviv_fp)(GLenum target, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetTexGendv_fp)(GLenum coord, GLenum pname, GLdouble *params); typedef void (OGLFUNCCALL *glGetTexGenfv_fp)(GLenum coord, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetTexGeniv_fp)(GLenum coord, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetTexImage_fp)(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); typedef void (OGLFUNCCALL *glGetTexLevelParameterfv_fp)(GLenum target, GLint level, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetTexLevelParameteriv_fp)(GLenum target, GLint level, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glGetTexParameterfv_fp)(GLenum target, GLenum pname, GLfloat *params); typedef void (OGLFUNCCALL *glGetTexParameteriv_fp)(GLenum target, GLenum pname, GLint *params); typedef void (OGLFUNCCALL *glHint_fp)(GLenum target, GLenum mode); typedef void (OGLFUNCCALL *glIndexMask_fp)(GLuint mask); typedef void (OGLFUNCCALL *glIndexPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glIndexd_fp)(GLdouble c); typedef void (OGLFUNCCALL *glIndexdv_fp)(const GLdouble *c); typedef void (OGLFUNCCALL *glIndexf_fp)(GLfloat c); typedef void (OGLFUNCCALL *glIndexfv_fp)(const GLfloat *c); typedef void (OGLFUNCCALL *glIndexi_fp)(GLint c); typedef void (OGLFUNCCALL *glIndexiv_fp)(const GLint *c); typedef void (OGLFUNCCALL *glIndexs_fp)(GLshort c); typedef void (OGLFUNCCALL *glIndexsv_fp)(const GLshort *c); typedef void (OGLFUNCCALL *glIndexub_fp)(GLubyte c); typedef void (OGLFUNCCALL *glIndexubv_fp)(const GLubyte *c); typedef void (OGLFUNCCALL *glInitNames_fp)(void); typedef void (OGLFUNCCALL *glInterleavedArrays_fp)(GLenum format, GLsizei stride, const GLvoid *pointer); typedef GLboolean (OGLFUNCCALL *glIsEnabled_fp)(GLenum cap); typedef GLboolean (OGLFUNCCALL *glIsList_fp)(GLuint list); typedef GLboolean (OGLFUNCCALL *glIsTexture_fp)(GLuint texture); typedef void (OGLFUNCCALL *glLightModelf_fp)(GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glLightModelfv_fp)(GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glLightModeli_fp)(GLenum pname, GLint param); typedef void (OGLFUNCCALL *glLightModeliv_fp)(GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glLightf_fp)(GLenum light, GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glLightfv_fp)(GLenum light, GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glLighti_fp)(GLenum light, GLenum pname, GLint param); typedef void (OGLFUNCCALL *glLightiv_fp)(GLenum light, GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glLineStipple_fp)(GLint factor, GLushort pattern); typedef void (OGLFUNCCALL *glLineWidth_fp)(GLfloat width); typedef void (OGLFUNCCALL *glListBase_fp)(GLuint base); typedef void (OGLFUNCCALL *glLoadIdentity_fp)(void); typedef void (OGLFUNCCALL *glLoadMatrixd_fp)(const GLdouble *m); typedef void (OGLFUNCCALL *glLoadMatrixf_fp)(const GLfloat *m); typedef void (OGLFUNCCALL *glLoadName_fp)(GLuint name); typedef void (OGLFUNCCALL *glLogicOp_fp)(GLenum opcode); typedef void (OGLFUNCCALL *glMap1d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); typedef void (OGLFUNCCALL *glMap1f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); typedef void (OGLFUNCCALL *glMap2d_fp)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); typedef void (OGLFUNCCALL *glMap2f_fp)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); typedef void (OGLFUNCCALL *glMapGrid1d_fp)(GLint un, GLdouble u1, GLdouble u2); typedef void (OGLFUNCCALL *glMapGrid1f_fp)(GLint un, GLfloat u1, GLfloat u2); typedef void (OGLFUNCCALL *glMapGrid2d_fp)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); typedef void (OGLFUNCCALL *glMapGrid2f_fp)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); typedef void (OGLFUNCCALL *glMaterialf_fp)(GLenum face, GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glMaterialfv_fp)(GLenum face, GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glMateriali_fp)(GLenum face, GLenum pname, GLint param); typedef void (OGLFUNCCALL *glMaterialiv_fp)(GLenum face, GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glMatrixMode_fp)(GLenum mode); typedef void (OGLFUNCCALL *glMultMatrixd_fp)(const GLdouble *m); typedef void (OGLFUNCCALL *glMultMatrixf_fp)(const GLfloat *m); typedef void (OGLFUNCCALL *glNewList_fp)(GLuint list, GLenum mode); typedef void (OGLFUNCCALL *glNormal3b_fp)(GLbyte nx, GLbyte ny, GLbyte nz); typedef void (OGLFUNCCALL *glNormal3bv_fp)(const GLbyte *v); typedef void (OGLFUNCCALL *glNormal3d_fp)(GLdouble nx, GLdouble ny, GLdouble nz); typedef void (OGLFUNCCALL *glNormal3dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glNormal3f_fp)(GLfloat nx, GLfloat ny, GLfloat nz); typedef void (OGLFUNCCALL *glNormal3fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glNormal3i_fp)(GLint nx, GLint ny, GLint nz); typedef void (OGLFUNCCALL *glNormal3iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glNormal3s_fp)(GLshort nx, GLshort ny, GLshort nz); typedef void (OGLFUNCCALL *glNormal3sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glNormalPointer_fp)(GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glOrtho_fp)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); typedef void (OGLFUNCCALL *glPassThrough_fp)(GLfloat token); typedef void (OGLFUNCCALL *glPixelMapfv_fp)(GLenum map, GLsizei mapsize, const GLfloat *values); typedef void (OGLFUNCCALL *glPixelMapuiv_fp)(GLenum map, GLsizei mapsize, const GLuint *values); typedef void (OGLFUNCCALL *glPixelMapusv_fp)(GLenum map, GLsizei mapsize, const GLushort *values); typedef void (OGLFUNCCALL *glPixelStoref_fp)(GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glPixelStorei_fp)(GLenum pname, GLint param); typedef void (OGLFUNCCALL *glPixelTransferf_fp)(GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glPixelTransferi_fp)(GLenum pname, GLint param); typedef void (OGLFUNCCALL *glPixelZoom_fp)(GLfloat xfactor, GLfloat yfactor); typedef void (OGLFUNCCALL *glPointSize_fp)(GLfloat size); typedef void (OGLFUNCCALL *glPolygonMode_fp)(GLenum face, GLenum mode); typedef void (OGLFUNCCALL *glPolygonOffset_fp)(GLfloat factor, GLfloat units); typedef void (OGLFUNCCALL *glPolygonStipple_fp)(const GLubyte *mask); typedef void (OGLFUNCCALL *glPopAttrib_fp)(void); typedef void (OGLFUNCCALL *glPopClientAttrib_fp)(void); typedef void (OGLFUNCCALL *glPopMatrix_fp)(void); typedef void (OGLFUNCCALL *glPopName_fp)(void); typedef void (OGLFUNCCALL *glPrioritizeTextures_fp)(GLsizei n, const GLuint *textures, const GLclampf *priorities); typedef void (OGLFUNCCALL *glPushAttrib_fp)(GLbitfield mask); typedef void (OGLFUNCCALL *glPushClientAttrib_fp)(GLbitfield mask); typedef void (OGLFUNCCALL *glPushMatrix_fp)(void); typedef void (OGLFUNCCALL *glPushName_fp)(GLuint name); typedef void (OGLFUNCCALL *glRasterPos2d_fp)(GLdouble x, GLdouble y); typedef void (OGLFUNCCALL *glRasterPos2dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glRasterPos2f_fp)(GLfloat x, GLfloat y); typedef void (OGLFUNCCALL *glRasterPos2fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glRasterPos2i_fp)(GLint x, GLint y); typedef void (OGLFUNCCALL *glRasterPos2iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glRasterPos2s_fp)(GLshort x, GLshort y); typedef void (OGLFUNCCALL *glRasterPos2sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glRasterPos3d_fp)(GLdouble x, GLdouble y, GLdouble z); typedef void (OGLFUNCCALL *glRasterPos3dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glRasterPos3f_fp)(GLfloat x, GLfloat y, GLfloat z); typedef void (OGLFUNCCALL *glRasterPos3fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glRasterPos3i_fp)(GLint x, GLint y, GLint z); typedef void (OGLFUNCCALL *glRasterPos3iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glRasterPos3s_fp)(GLshort x, GLshort y, GLshort z); typedef void (OGLFUNCCALL *glRasterPos3sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glRasterPos4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (OGLFUNCCALL *glRasterPos4dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glRasterPos4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (OGLFUNCCALL *glRasterPos4fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glRasterPos4i_fp)(GLint x, GLint y, GLint z, GLint w); typedef void (OGLFUNCCALL *glRasterPos4iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glRasterPos4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); typedef void (OGLFUNCCALL *glRasterPos4sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glReadBuffer_fp)(GLenum mode); typedef void (OGLFUNCCALL *glReadPixels_fp)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); typedef void (OGLFUNCCALL *glRectd_fp)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); typedef void (OGLFUNCCALL *glRectdv_fp)(const GLdouble *v1, const GLdouble *v2); typedef void (OGLFUNCCALL *glRectf_fp)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); typedef void (OGLFUNCCALL *glRectfv_fp)(const GLfloat *v1, const GLfloat *v2); typedef void (OGLFUNCCALL *glRecti_fp)(GLint x1, GLint y1, GLint x2, GLint y2); typedef void (OGLFUNCCALL *glRectiv_fp)(const GLint *v1, const GLint *v2); typedef void (OGLFUNCCALL *glRects_fp)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); typedef void (OGLFUNCCALL *glRectsv_fp)(const GLshort *v1, const GLshort *v2); typedef GLint (OGLFUNCCALL *glRenderMode_fp)(GLenum mode); typedef void (OGLFUNCCALL *glRotated_fp)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); typedef void (OGLFUNCCALL *glRotatef_fp)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); typedef void (OGLFUNCCALL *glScaled_fp)(GLdouble x, GLdouble y, GLdouble z); typedef void (OGLFUNCCALL *glScalef_fp)(GLfloat x, GLfloat y, GLfloat z); typedef void (OGLFUNCCALL *glScissor_fp)(GLint x, GLint y, GLsizei width, GLsizei height); typedef void (OGLFUNCCALL *glSelectBuffer_fp)(GLsizei size, GLuint *buffer); typedef void (OGLFUNCCALL *glShadeModel_fp)(GLenum mode); typedef void (OGLFUNCCALL *glStencilFunc_fp)(GLenum func, GLint ref, GLuint mask); typedef void (OGLFUNCCALL *glStencilMask_fp)(GLuint mask); typedef void (OGLFUNCCALL *glStencilOp_fp)(GLenum fail, GLenum zfail, GLenum zpass); typedef void (OGLFUNCCALL *glTexCoord1d_fp)(GLdouble s); typedef void (OGLFUNCCALL *glTexCoord1dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glTexCoord1f_fp)(GLfloat s); typedef void (OGLFUNCCALL *glTexCoord1fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glTexCoord1i_fp)(GLint s); typedef void (OGLFUNCCALL *glTexCoord1iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glTexCoord1s_fp)(GLshort s); typedef void (OGLFUNCCALL *glTexCoord1sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glTexCoord2d_fp)(GLdouble s, GLdouble t); typedef void (OGLFUNCCALL *glTexCoord2dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glTexCoord2f_fp)(GLfloat s, GLfloat t); typedef void (OGLFUNCCALL *glTexCoord2fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glTexCoord2i_fp)(GLint s, GLint t); typedef void (OGLFUNCCALL *glTexCoord2iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glTexCoord2s_fp)(GLshort s, GLshort t); typedef void (OGLFUNCCALL *glTexCoord2sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glTexCoord3d_fp)(GLdouble s, GLdouble t, GLdouble r); typedef void (OGLFUNCCALL *glTexCoord3dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glTexCoord3f_fp)(GLfloat s, GLfloat t, GLfloat r); typedef void (OGLFUNCCALL *glTexCoord3fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glTexCoord3i_fp)(GLint s, GLint t, GLint r); typedef void (OGLFUNCCALL *glTexCoord3iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glTexCoord3s_fp)(GLshort s, GLshort t, GLshort r); typedef void (OGLFUNCCALL *glTexCoord3sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glTexCoord4d_fp)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); typedef void (OGLFUNCCALL *glTexCoord4dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glTexCoord4f_fp)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); typedef void (OGLFUNCCALL *glTexCoord4fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glTexCoord4i_fp)(GLint s, GLint t, GLint r, GLint q); typedef void (OGLFUNCCALL *glTexCoord4iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glTexCoord4s_fp)(GLshort s, GLshort t, GLshort r, GLshort q); typedef void (OGLFUNCCALL *glTexCoord4sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glTexCoordPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glTexEnvf_fp)(GLenum target, GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glTexEnvfv_fp)(GLenum target, GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glTexEnvi_fp)(GLenum target, GLenum pname, GLint param); typedef void (OGLFUNCCALL *glTexEnviv_fp)(GLenum target, GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glTexGend_fp)(GLenum coord, GLenum pname, GLdouble param); typedef void (OGLFUNCCALL *glTexGendv_fp)(GLenum coord, GLenum pname, const GLdouble *params); typedef void (OGLFUNCCALL *glTexGenf_fp)(GLenum coord, GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glTexGenfv_fp)(GLenum coord, GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glTexGeni_fp)(GLenum coord, GLenum pname, GLint param); typedef void (OGLFUNCCALL *glTexGeniv_fp)(GLenum coord, GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glTexImage1D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (OGLFUNCCALL *glTexImage2D_fp)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); typedef void (OGLFUNCCALL *glTexParameterf_fp)(GLenum target, GLenum pname, GLfloat param); typedef void (OGLFUNCCALL *glTexParameterfv_fp)(GLenum target, GLenum pname, const GLfloat *params); typedef void (OGLFUNCCALL *glTexParameteri_fp)(GLenum target, GLenum pname, GLint param); typedef void (OGLFUNCCALL *glTexParameteriv_fp)(GLenum target, GLenum pname, const GLint *params); typedef void (OGLFUNCCALL *glTexSubImage1D_fp)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); typedef void (OGLFUNCCALL *glTexSubImage2D_fp)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); typedef void (OGLFUNCCALL *glTranslated_fp)(GLdouble x, GLdouble y, GLdouble z); typedef void (OGLFUNCCALL *glTranslatef_fp)(GLfloat x, GLfloat y, GLfloat z); typedef void (OGLFUNCCALL *glVertex2d_fp)(GLdouble x, GLdouble y); typedef void (OGLFUNCCALL *glVertex2dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glVertex2f_fp)(GLfloat x, GLfloat y); typedef void (OGLFUNCCALL *glVertex2fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glVertex2i_fp)(GLint x, GLint y); typedef void (OGLFUNCCALL *glVertex2iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glVertex2s_fp)(GLshort x, GLshort y); typedef void (OGLFUNCCALL *glVertex2sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glVertex3d_fp)(GLdouble x, GLdouble y, GLdouble z); typedef void (OGLFUNCCALL *glVertex3dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glVertex3f_fp)(GLfloat x, GLfloat y, GLfloat z); typedef void (OGLFUNCCALL *glVertex3fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glVertex3i_fp)(GLint x, GLint y, GLint z); typedef void (OGLFUNCCALL *glVertex3iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glVertex3s_fp)(GLshort x, GLshort y, GLshort z); typedef void (OGLFUNCCALL *glVertex3sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glVertex4d_fp)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); typedef void (OGLFUNCCALL *glVertex4dv_fp)(const GLdouble *v); typedef void (OGLFUNCCALL *glVertex4f_fp)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); typedef void (OGLFUNCCALL *glVertex4fv_fp)(const GLfloat *v); typedef void (OGLFUNCCALL *glVertex4i_fp)(GLint x, GLint y, GLint z, GLint w); typedef void (OGLFUNCCALL *glVertex4iv_fp)(const GLint *v); typedef void (OGLFUNCCALL *glVertex4s_fp)(GLshort x, GLshort y, GLshort z, GLshort w); typedef void (OGLFUNCCALL *glVertex4sv_fp)(const GLshort *v); typedef void (OGLFUNCCALL *glVertexPointer_fp)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (OGLFUNCCALL *glViewport_fp)(GLint x, GLint y, GLsizei width, GLsizei height); typedef void (OGLFUNCCALL *glMultiTexCoord2fARB_fp)(GLenum target, GLfloat s, GLfloat t); typedef void (OGLFUNCCALL *glActiveTextureARB_fp)(GLenum target); typedef void (OGLFUNCCALL *glMultiTexCoord2fSGIS_fp)(GLenum target, GLfloat s, GLfloat t); typedef void (OGLFUNCCALL *glSelectTextureSGIS_fp)(GLenum target); typedef void (OGLFUNCCALL *glColorTableEXT_fp)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); typedef void (OGLFUNCCALL *glCombinerParameteriNV_fp)(GLenum, GLint); typedef void (OGLFUNCCALL *glCombinerInputNV_fp)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum); typedef void (OGLFUNCCALL *glCombinerOutputNV_fp)(GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLenum, GLboolean, GLboolean, GLboolean); typedef void (OGLFUNCCALL *glFinalCombinerInputNV_fp)(GLenum, GLenum, GLenum, GLenum); #ifdef _WIN32 typedef BOOL (OGLFUNCCALL *wglCopyContext_fp)(HGLRC, HGLRC, UINT); typedef HGLRC (OGLFUNCCALL *wglCreateContext_fp)(HDC); typedef HGLRC (OGLFUNCCALL *wglCreateLayerContext_fp)(HDC, int); typedef BOOL (OGLFUNCCALL *wglDeleteContext_fp)(HGLRC); typedef HGLRC (OGLFUNCCALL *wglGetCurrentContext_fp)(VOID); typedef HDC (OGLFUNCCALL *wglGetCurrentDC_fp)(VOID); typedef PROC (OGLFUNCCALL *wglGetProcAddress_fp)(LPCSTR); typedef BOOL (OGLFUNCCALL *wglMakeCurrent_fp)(HDC, HGLRC); typedef BOOL (OGLFUNCCALL *wglShareLists_fp)(HGLRC, HGLRC); typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsA_fp)(HDC, DWORD, DWORD, DWORD); typedef BOOL (OGLFUNCCALL *wglUseFontBitmapsW_fp)(HDC, DWORD, DWORD, DWORD); typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesA_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); typedef BOOL (OGLFUNCCALL *wglUseFontOutlinesW_fp)(HDC, DWORD, DWORD, DWORD, FLOAT,FLOAT, int, LPGLYPHMETRICSFLOAT); typedef BOOL (OGLFUNCCALL *wglDescribeLayerPlane_fp)(HDC, int, int, UINT,LPLAYERPLANEDESCRIPTOR); typedef int (OGLFUNCCALL *wglSetLayerPaletteEntries_fp)(HDC, int, int, int,CONST COLORREF *); typedef int (OGLFUNCCALL *wglGetLayerPaletteEntries_fp)(HDC, int, int, int,COLORREF *); typedef BOOL (OGLFUNCCALL *wglRealizeLayerPalette_fp)(HDC, int, BOOL); typedef BOOL (OGLFUNCCALL *wglSwapLayerBuffers_fp)(HDC, UINT); #if (WINVER >= 0x0500) typedef DWORD (OGLFUNCCALL *wglSwapMultipleBuffers_fp)(UINT, CONST WGLSWAP *); #endif #endif DEFVAR glAccum_fp dglAccum; DEFVAR glAlphaFunc_fp dglAlphaFunc; DEFVAR glAreTexturesResident_fp dglAreTexturesResident; DEFVAR glArrayElement_fp dglArrayElement; DEFVAR glBegin_fp dglBegin; DEFVAR glBindTexture_fp dglBindTexture; DEFVAR glBitmap_fp dglBitmap; DEFVAR glBlendFunc_fp dglBlendFunc; DEFVAR glCallList_fp dglCallList; DEFVAR glCallLists_fp dglCallLists; DEFVAR glClear_fp dglClear; DEFVAR glClearAccum_fp dglClearAccum; DEFVAR glClearColor_fp dglClearColor; DEFVAR glClearDepth_fp dglClearDepth; DEFVAR glClearIndex_fp dglClearIndex; DEFVAR glClearStencil_fp dglClearStencil; DEFVAR glClipPlane_fp dglClipPlane; DEFVAR glColor3b_fp dglColor3b; DEFVAR glColor3bv_fp dglColor3bv; DEFVAR glColor3d_fp dglColor3d; DEFVAR glColor3dv_fp dglColor3dv; DEFVAR glColor3f_fp dglColor3f; DEFVAR glColor3fv_fp dglColor3fv; DEFVAR glColor3i_fp dglColor3i; DEFVAR glColor3iv_fp dglColor3iv; DEFVAR glColor3s_fp dglColor3s; DEFVAR glColor3sv_fp dglColor3sv; DEFVAR glColor3ub_fp dglColor3ub; DEFVAR glColor3ubv_fp dglColor3ubv; DEFVAR glColor3ui_fp dglColor3ui; DEFVAR glColor3uiv_fp dglColor3uiv; DEFVAR glColor3us_fp dglColor3us; DEFVAR glColor3usv_fp dglColor3usv; DEFVAR glColor4b_fp dglColor4b; DEFVAR glColor4bv_fp dglColor4bv; DEFVAR glColor4d_fp dglColor4d; DEFVAR glColor4dv_fp dglColor4dv; DEFVAR glColor4f_fp dglColor4f; DEFVAR glColor4fv_fp dglColor4fv; DEFVAR glColor4i_fp dglColor4i; DEFVAR glColor4iv_fp dglColor4iv; DEFVAR glColor4s_fp dglColor4s; DEFVAR glColor4sv_fp dglColor4sv; DEFVAR glColor4ub_fp dglColor4ub; DEFVAR glColor4ubv_fp dglColor4ubv; DEFVAR glColor4ui_fp dglColor4ui; DEFVAR glColor4uiv_fp dglColor4uiv; DEFVAR glColor4us_fp dglColor4us; DEFVAR glColor4usv_fp dglColor4usv; DEFVAR glColorMask_fp dglColorMask; DEFVAR glColorMaterial_fp dglColorMaterial; DEFVAR glColorPointer_fp dglColorPointer; DEFVAR glCopyPixels_fp dglCopyPixels; DEFVAR glCopyTexImage1D_fp dglCopyTexImage1D; DEFVAR glCopyTexImage2D_fp dglCopyTexImage2D; DEFVAR glCopyTexSubImage1D_fp dglCopyTexSubImage1D; DEFVAR glCopyTexSubImage2D_fp dglCopyTexSubImage2D; DEFVAR glCullFace_fp dglCullFace; DEFVAR glDeleteLists_fp dglDeleteLists; DEFVAR glDeleteTextures_fp dglDeleteTextures; DEFVAR glDepthFunc_fp dglDepthFunc; DEFVAR glDepthMask_fp dglDepthMask; DEFVAR glDepthRange_fp dglDepthRange; DEFVAR glDisable_fp dglDisable; DEFVAR glDisableClientState_fp dglDisableClientState; DEFVAR glDrawArrays_fp dglDrawArrays; DEFVAR glDrawBuffer_fp dglDrawBuffer; DEFVAR glDrawElements_fp dglDrawElements; DEFVAR glDrawPixels_fp dglDrawPixels; DEFVAR glEdgeFlag_fp dglEdgeFlag; DEFVAR glEdgeFlagPointer_fp dglEdgeFlagPointer; DEFVAR glEdgeFlagv_fp dglEdgeFlagv; DEFVAR glEnable_fp dglEnable; DEFVAR glEnableClientState_fp dglEnableClientState; DEFVAR glEnd_fp dglEnd; DEFVAR glEndList_fp dglEndList; DEFVAR glEvalCoord1d_fp dglEvalCoord1d; DEFVAR glEvalCoord1dv_fp dglEvalCoord1dv; DEFVAR glEvalCoord1f_fp dglEvalCoord1f; DEFVAR glEvalCoord1fv_fp dglEvalCoord1fv; DEFVAR glEvalCoord2d_fp dglEvalCoord2d; DEFVAR glEvalCoord2dv_fp dglEvalCoord2dv; DEFVAR glEvalCoord2f_fp dglEvalCoord2f; DEFVAR glEvalCoord2fv_fp dglEvalCoord2fv; DEFVAR glEvalMesh1_fp dglEvalMesh1; DEFVAR glEvalMesh2_fp dglEvalMesh2; DEFVAR glEvalPoint1_fp dglEvalPoint1; DEFVAR glEvalPoint2_fp dglEvalPoint2; DEFVAR glFeedbackBuffer_fp dglFeedbackBuffer; DEFVAR glFinish_fp dglFinish; DEFVAR glFlush_fp dglFlush; DEFVAR glFogf_fp dglFogf; DEFVAR glFogfv_fp dglFogfv; DEFVAR glFogi_fp dglFogi; DEFVAR glFogiv_fp dglFogiv; DEFVAR glFrontFace_fp dglFrontFace; DEFVAR glFrustum_fp dglFrustum; DEFVAR glGenLists_fp dglGenLists; DEFVAR glGenTextures_fp dglGenTextures; DEFVAR glGetBooleanv_fp dglGetBooleanv; DEFVAR glGetClipPlane_fp dglGetClipPlane; DEFVAR glGetDoublev_fp dglGetDoublev; DEFVAR glGetError_fp dglGetError; DEFVAR glGetFloatv_fp dglGetFloatv; DEFVAR glGetIntegerv_fp dglGetIntegerv; DEFVAR glGetLightfv_fp dglGetLightfv; DEFVAR glGetLightiv_fp dglGetLightiv; DEFVAR glGetMapdv_fp dglGetMapdv; DEFVAR glGetMapfv_fp dglGetMapfv; DEFVAR glGetMapiv_fp dglGetMapiv; DEFVAR glGetMaterialfv_fp dglGetMaterialfv; DEFVAR glGetMaterialiv_fp dglGetMaterialiv; DEFVAR glGetPixelMapfv_fp dglGetPixelMapfv; DEFVAR glGetPixelMapuiv_fp dglGetPixelMapuiv; DEFVAR glGetPixelMapusv_fp dglGetPixelMapusv; DEFVAR glGetPointerv_fp dglGetPointerv; DEFVAR glGetPolygonStipple_fp dglGetPolygonStipple; DEFVAR glGetString_fp dglGetString; DEFVAR glGetTexEnvfv_fp dglGetTexEnvfv; DEFVAR glGetTexEnviv_fp dglGetTexEnviv; DEFVAR glGetTexGendv_fp dglGetTexGendv; DEFVAR glGetTexGenfv_fp dglGetTexGenfv; DEFVAR glGetTexGeniv_fp dglGetTexGeniv; DEFVAR glGetTexImage_fp dglGetTexImage; DEFVAR glGetTexLevelParameterfv_fp dglGetTexLevelParameterfv; DEFVAR glGetTexLevelParameteriv_fp dglGetTexLevelParameteriv; DEFVAR glGetTexParameterfv_fp dglGetTexParameterfv; DEFVAR glGetTexParameteriv_fp dglGetTexParameteriv; DEFVAR glHint_fp dglHint; DEFVAR glIndexMask_fp dglIndexMask; DEFVAR glIndexPointer_fp dglIndexPointer; DEFVAR glIndexd_fp dglIndexd; DEFVAR glIndexdv_fp dglIndexdv; DEFVAR glIndexf_fp dglIndexf; DEFVAR glIndexfv_fp dglIndexfv; DEFVAR glIndexi_fp dglIndexi; DEFVAR glIndexiv_fp dglIndexiv; DEFVAR glIndexs_fp dglIndexs; DEFVAR glIndexsv_fp dglIndexsv; DEFVAR glIndexub_fp dglIndexub; DEFVAR glIndexubv_fp dglIndexubv; DEFVAR glInitNames_fp dglInitNames; DEFVAR glInterleavedArrays_fp dglInterleavedArrays; DEFVAR glIsEnabled_fp dglIsEnabled; DEFVAR glIsList_fp dglIsList; DEFVAR glIsTexture_fp dglIsTexture; DEFVAR glLightModelf_fp dglLightModelf; DEFVAR glLightModelfv_fp dglLightModelfv; DEFVAR glLightModeli_fp dglLightModeli; DEFVAR glLightModeliv_fp dglLightModeliv; DEFVAR glLightf_fp dglLightf; DEFVAR glLightfv_fp dglLightfv; DEFVAR glLighti_fp dglLighti; DEFVAR glLightiv_fp dglLightiv; DEFVAR glLineStipple_fp dglLineStipple; DEFVAR glLineWidth_fp dglLineWidth; DEFVAR glListBase_fp dglListBase; DEFVAR glLoadIdentity_fp dglLoadIdentity; DEFVAR glLoadMatrixd_fp dglLoadMatrixd; DEFVAR glLoadMatrixf_fp dglLoadMatrixf; DEFVAR glLoadName_fp dglLoadName; DEFVAR glLogicOp_fp dglLogicOp; DEFVAR glMap1d_fp dglMap1d; DEFVAR glMap1f_fp dglMap1f; DEFVAR glMap2d_fp dglMap2d; DEFVAR glMap2f_fp dglMap2f; DEFVAR glMapGrid1d_fp dglMapGrid1d; DEFVAR glMapGrid1f_fp dglMapGrid1f; DEFVAR glMapGrid2d_fp dglMapGrid2d; DEFVAR glMapGrid2f_fp dglMapGrid2f; DEFVAR glMaterialf_fp dglMaterialf; DEFVAR glMaterialfv_fp dglMaterialfv; DEFVAR glMateriali_fp dglMateriali; DEFVAR glMaterialiv_fp dglMaterialiv; DEFVAR glMatrixMode_fp dglMatrixMode; DEFVAR glMultMatrixd_fp dglMultMatrixd; DEFVAR glMultMatrixf_fp dglMultMatrixf; DEFVAR glNewList_fp dglNewList; DEFVAR glNormal3b_fp dglNormal3b; DEFVAR glNormal3bv_fp dglNormal3bv; DEFVAR glNormal3d_fp dglNormal3d; DEFVAR glNormal3dv_fp dglNormal3dv; DEFVAR glNormal3f_fp dglNormal3f; DEFVAR glNormal3fv_fp dglNormal3fv; DEFVAR glNormal3i_fp dglNormal3i; DEFVAR glNormal3iv_fp dglNormal3iv; DEFVAR glNormal3s_fp dglNormal3s; DEFVAR glNormal3sv_fp dglNormal3sv; DEFVAR glNormalPointer_fp dglNormalPointer; DEFVAR glOrtho_fp dglOrtho; DEFVAR glPassThrough_fp dglPassThrough; DEFVAR glPixelMapfv_fp dglPixelMapfv; DEFVAR glPixelMapuiv_fp dglPixelMapuiv; DEFVAR glPixelMapusv_fp dglPixelMapusv; DEFVAR glPixelStoref_fp dglPixelStoref; DEFVAR glPixelStorei_fp dglPixelStorei; DEFVAR glPixelTransferf_fp dglPixelTransferf; DEFVAR glPixelTransferi_fp dglPixelTransferi; DEFVAR glPixelZoom_fp dglPixelZoom; DEFVAR glPointSize_fp dglPointSize; DEFVAR glPolygonMode_fp dglPolygonMode; DEFVAR glPolygonOffset_fp dglPolygonOffset; DEFVAR glPolygonStipple_fp dglPolygonStipple; DEFVAR glPopAttrib_fp dglPopAttrib; DEFVAR glPopClientAttrib_fp dglPopClientAttrib; DEFVAR glPopMatrix_fp dglPopMatrix; DEFVAR glPopName_fp dglPopName; DEFVAR glPrioritizeTextures_fp dglPrioritizeTextures; DEFVAR glPushAttrib_fp dglPushAttrib; DEFVAR glPushClientAttrib_fp dglPushClientAttrib; DEFVAR glPushMatrix_fp dglPushMatrix; DEFVAR glPushName_fp dglPushName; DEFVAR glRasterPos2d_fp dglRasterPos2d; DEFVAR glRasterPos2dv_fp dglRasterPos2dv; DEFVAR glRasterPos2f_fp dglRasterPos2f; DEFVAR glRasterPos2fv_fp dglRasterPos2fv; DEFVAR glRasterPos2i_fp dglRasterPos2i; DEFVAR glRasterPos2iv_fp dglRasterPos2iv; DEFVAR glRasterPos2s_fp dglRasterPos2s; DEFVAR glRasterPos2sv_fp dglRasterPos2sv; DEFVAR glRasterPos3d_fp dglRasterPos3d; DEFVAR glRasterPos3dv_fp dglRasterPos3dv; DEFVAR glRasterPos3f_fp dglRasterPos3f; DEFVAR glRasterPos3fv_fp dglRasterPos3fv; DEFVAR glRasterPos3i_fp dglRasterPos3i; DEFVAR glRasterPos3iv_fp dglRasterPos3iv; DEFVAR glRasterPos3s_fp dglRasterPos3s; DEFVAR glRasterPos3sv_fp dglRasterPos3sv; DEFVAR glRasterPos4d_fp dglRasterPos4d; DEFVAR glRasterPos4dv_fp dglRasterPos4dv; DEFVAR glRasterPos4f_fp dglRasterPos4f; DEFVAR glRasterPos4fv_fp dglRasterPos4fv; DEFVAR glRasterPos4i_fp dglRasterPos4i; DEFVAR glRasterPos4iv_fp dglRasterPos4iv; DEFVAR glRasterPos4s_fp dglRasterPos4s; DEFVAR glRasterPos4sv_fp dglRasterPos4sv; DEFVAR glReadBuffer_fp dglReadBuffer; DEFVAR glReadPixels_fp dglReadPixels; DEFVAR glRectd_fp dglRectd; DEFVAR glRectdv_fp dglRectdv; DEFVAR glRectf_fp dglRectf; DEFVAR glRectfv_fp dglRectfv; DEFVAR glRecti_fp dglRecti; DEFVAR glRectiv_fp dglRectiv; DEFVAR glRects_fp dglRects; DEFVAR glRectsv_fp dglRectsv; DEFVAR glRenderMode_fp dglRenderMode; DEFVAR glRotated_fp dglRotated; DEFVAR glRotatef_fp dglRotatef; DEFVAR glScaled_fp dglScaled; DEFVAR glScalef_fp dglScalef; DEFVAR glScissor_fp dglScissor; DEFVAR glSelectBuffer_fp dglSelectBuffer; DEFVAR glShadeModel_fp dglShadeModel; DEFVAR glStencilFunc_fp dglStencilFunc; DEFVAR glStencilMask_fp dglStencilMask; DEFVAR glStencilOp_fp dglStencilOp; DEFVAR glTexCoord1d_fp dglTexCoord1d; DEFVAR glTexCoord1dv_fp dglTexCoord1dv; DEFVAR glTexCoord1f_fp dglTexCoord1f; DEFVAR glTexCoord1fv_fp dglTexCoord1fv; DEFVAR glTexCoord1i_fp dglTexCoord1i; DEFVAR glTexCoord1iv_fp dglTexCoord1iv; DEFVAR glTexCoord1s_fp dglTexCoord1s; DEFVAR glTexCoord1sv_fp dglTexCoord1sv; DEFVAR glTexCoord2d_fp dglTexCoord2d; DEFVAR glTexCoord2dv_fp dglTexCoord2dv; DEFVAR glTexCoord2f_fp dglTexCoord2f; DEFVAR glTexCoord2fv_fp dglTexCoord2fv; DEFVAR glTexCoord2i_fp dglTexCoord2i; DEFVAR glTexCoord2iv_fp dglTexCoord2iv; DEFVAR glTexCoord2s_fp dglTexCoord2s; DEFVAR glTexCoord2sv_fp dglTexCoord2sv; DEFVAR glTexCoord3d_fp dglTexCoord3d; DEFVAR glTexCoord3dv_fp dglTexCoord3dv; DEFVAR glTexCoord3f_fp dglTexCoord3f; DEFVAR glTexCoord3fv_fp dglTexCoord3fv; DEFVAR glTexCoord3i_fp dglTexCoord3i; DEFVAR glTexCoord3iv_fp dglTexCoord3iv; DEFVAR glTexCoord3s_fp dglTexCoord3s; DEFVAR glTexCoord3sv_fp dglTexCoord3sv; DEFVAR glTexCoord4d_fp dglTexCoord4d; DEFVAR glTexCoord4dv_fp dglTexCoord4dv; DEFVAR glTexCoord4f_fp dglTexCoord4f; DEFVAR glTexCoord4fv_fp dglTexCoord4fv; DEFVAR glTexCoord4i_fp dglTexCoord4i; DEFVAR glTexCoord4iv_fp dglTexCoord4iv; DEFVAR glTexCoord4s_fp dglTexCoord4s; DEFVAR glTexCoord4sv_fp dglTexCoord4sv; DEFVAR glTexCoordPointer_fp dglTexCoordPointer; DEFVAR glTexEnvf_fp dglTexEnvf; DEFVAR glTexEnvfv_fp dglTexEnvfv; DEFVAR glTexEnvi_fp dglTexEnvi; DEFVAR glTexEnviv_fp dglTexEnviv; DEFVAR glTexGend_fp dglTexGend; DEFVAR glTexGendv_fp dglTexGendv; DEFVAR glTexGenf_fp dglTexGenf; DEFVAR glTexGenfv_fp dglTexGenfv; DEFVAR glTexGeni_fp dglTexGeni; DEFVAR glTexGeniv_fp dglTexGeniv; DEFVAR glTexImage1D_fp dglTexImage1D; DEFVAR glTexImage2D_fp dglTexImage2D; DEFVAR glTexParameterf_fp dglTexParameterf; DEFVAR glTexParameterfv_fp dglTexParameterfv; DEFVAR glTexParameteri_fp dglTexParameteri; DEFVAR glTexParameteriv_fp dglTexParameteriv; DEFVAR glTexSubImage1D_fp dglTexSubImage1D; DEFVAR glTexSubImage2D_fp dglTexSubImage2D; DEFVAR glTranslated_fp dglTranslated; DEFVAR glTranslatef_fp dglTranslatef; DEFVAR glVertex2d_fp dglVertex2d; DEFVAR glVertex2dv_fp dglVertex2dv; DEFVAR glVertex2f_fp dglVertex2f; DEFVAR glVertex2fv_fp dglVertex2fv; DEFVAR glVertex2i_fp dglVertex2i; DEFVAR glVertex2iv_fp dglVertex2iv; DEFVAR glVertex2s_fp dglVertex2s; DEFVAR glVertex2sv_fp dglVertex2sv; DEFVAR glVertex3d_fp dglVertex3d; DEFVAR glVertex3dv_fp dglVertex3dv; DEFVAR glVertex3f_fp dglVertex3f; DEFVAR glVertex3fv_fp dglVertex3fv; DEFVAR glVertex3i_fp dglVertex3i; DEFVAR glVertex3iv_fp dglVertex3iv; DEFVAR glVertex3s_fp dglVertex3s; DEFVAR glVertex3sv_fp dglVertex3sv; DEFVAR glVertex4d_fp dglVertex4d; DEFVAR glVertex4dv_fp dglVertex4dv; DEFVAR glVertex4f_fp dglVertex4f; DEFVAR glVertex4fv_fp dglVertex4fv; DEFVAR glVertex4i_fp dglVertex4i; DEFVAR glVertex4iv_fp dglVertex4iv; DEFVAR glVertex4s_fp dglVertex4s; DEFVAR glVertex4sv_fp dglVertex4sv; DEFVAR glVertexPointer_fp dglVertexPointer; DEFVAR glViewport_fp dglViewport; DEFVAR glMultiTexCoord2fARB_fp dglMultiTexCoord2fARB; DEFVAR glActiveTextureARB_fp dglActiveTextureARB; DEFVAR glMultiTexCoord2fSGIS_fp dglMultiTexCoord2fSGIS; DEFVAR glSelectTextureSGIS_fp dglSelectTextureSGIS; DEFVAR glColorTableEXT_fp dglColorTableEXT; DEFVAR glCombinerParameteriNV_fp dglCombinerParameteriNV; DEFVAR glCombinerInputNV_fp dglCombinerInputNV; DEFVAR glCombinerOutputNV_fp dglCombinerOutputNV; DEFVAR glFinalCombinerInputNV_fp dglFinalCombinerInputNV; #ifdef _WIN32 DEFVAR wglCopyContext_fp dwglCopyContext; DEFVAR wglCreateContext_fp dwglCreateContext; DEFVAR wglCreateLayerContext_fp dwglCreateLayerContext; DEFVAR wglDeleteContext_fp dwglDeleteContext; DEFVAR wglGetCurrentContext_fp dwglGetCurrentContext; DEFVAR wglGetCurrentDC_fp dwglGetCurrentDC; DEFVAR wglGetProcAddress_fp dwglGetProcAddress; DEFVAR wglMakeCurrent_fp dwglMakeCurrent; DEFVAR wglShareLists_fp dwglShareLists; DEFVAR wglUseFontBitmapsA_fp dwglUseFontBitmapsA; DEFVAR wglUseFontBitmapsW_fp dwglUseFontBitmapsW; DEFVAR wglUseFontOutlinesA_fp dwglUseFontOutlinesA; DEFVAR wglUseFontOutlinesW_fp dwglUseFontOutlinesW; DEFVAR wglDescribeLayerPlane_fp dwglDescribeLayerPlane; DEFVAR wglSetLayerPaletteEntries_fp dwglSetLayerPaletteEntries; DEFVAR wglGetLayerPaletteEntries_fp dwglGetLayerPaletteEntries; DEFVAR wglRealizeLayerPalette_fp dwglRealizeLayerPalette; DEFVAR wglSwapLayerBuffers_fp dwglSwapLayerBuffers; #if (WINVER >= 0x0500) DEFVAR wglSwapMultipleBuffers_fp dwglSwapMultipleBuffers; #endif #endif #ifdef DECLARE_VARS // Dynamic module load functions #ifdef _WIN32 void *dll_LoadModule(const char *name) { HINSTANCE handle; handle = LoadLibrary(name); return (void *)handle; } void dll_UnloadModule(void *hdl) { HINSTANCE handle; handle = (HINSTANCE)hdl; if(hdl) { FreeLibrary(handle); } } void *dll_GetSymbol(void *dllhandle,const char *symname) { if(!dllhandle) return NULL; return (void *)GetProcAddress((HINSTANCE)dllhandle,symname); } #endif #ifdef __unix__ #include void *dll_LoadModule(const char *name) { return (void *)dlopen(name,RTLD_NOW|RTLD_GLOBAL); } void dll_UnloadModule(void *hdl) { if(hdl) { dlclose(hdl); } } void *dll_GetSymbol(void *dllhandle,const char *symname) { if(!dllhandle) return NULL; return dlsym(dllhandle,symname); } #endif #ifdef macintosh #include void *dll_LoadModule(const char *name) { return SDL_GL_LoadLibrary(name) ? NULL : (void *) -1; // return pointer is not dereferenced } void dll_UnloadModule(void *hdl) { hdl = hdl; // SDL_GL_UnloadLibrary not exported by SDL } void *dll_GetSymbol(void *dllhandle,const char *symname) { if(!dllhandle) return NULL; return SDL_GL_GetProcAddress(symname); } #endif #endif //DECLARE_VARS void OpenGL_SetFuncsToNull(void); extern char *OglLibPath; #ifndef DECLARE_VARS // pass true to load the library // pass false to unload it bool OpenGL_LoadLibrary(bool load);//load=true removed because not c++ #else void *OpenGLModuleHandle=NULL; //char *OglLibPath="opengl32.dll"; bool OpenGL_LoadLibrary(bool load) { if(load && OpenGLModuleHandle) return true; OpenGL_SetFuncsToNull(); if(!load) { if(OpenGLModuleHandle) { dll_UnloadModule(OpenGLModuleHandle); OpenGLModuleHandle = NULL; } return true; }else { OpenGLModuleHandle = dll_LoadModule(OglLibPath); if(!OpenGLModuleHandle) return false; dglAccum = (glAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glAccum"); dglAlphaFunc = (glAlphaFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glAlphaFunc"); dglAreTexturesResident = (glAreTexturesResident_fp)dll_GetSymbol(OpenGLModuleHandle,"glAreTexturesResident"); dglArrayElement = (glArrayElement_fp)dll_GetSymbol(OpenGLModuleHandle,"glArrayElement"); dglBegin = (glBegin_fp)dll_GetSymbol(OpenGLModuleHandle,"glBegin"); dglBindTexture = (glBindTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glBindTexture"); dglBitmap = (glBitmap_fp)dll_GetSymbol(OpenGLModuleHandle,"glBitmap"); dglBlendFunc = (glBlendFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glBlendFunc"); dglCallList = (glCallList_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallList"); dglCallLists = (glCallLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glCallLists"); dglClear = (glClear_fp)dll_GetSymbol(OpenGLModuleHandle,"glClear"); dglClearAccum = (glClearAccum_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearAccum"); dglClearColor = (glClearColor_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearColor"); dglClearDepth = (glClearDepth_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearDepth"); dglClearIndex = (glClearIndex_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearIndex"); dglClearStencil = (glClearStencil_fp)dll_GetSymbol(OpenGLModuleHandle,"glClearStencil"); dglClipPlane = (glClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glClipPlane"); dglColor3b = (glColor3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3b"); dglColor3bv = (glColor3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3bv"); dglColor3d = (glColor3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3d"); dglColor3dv = (glColor3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3dv"); dglColor3f = (glColor3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3f"); dglColor3fv = (glColor3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3fv"); dglColor3i = (glColor3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3i"); dglColor3iv = (glColor3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3iv"); dglColor3s = (glColor3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3s"); dglColor3sv = (glColor3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3sv"); dglColor3ub = (glColor3ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ub"); dglColor3ubv = (glColor3ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ubv"); dglColor3ui = (glColor3ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3ui"); dglColor3uiv = (glColor3uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3uiv"); dglColor3us = (glColor3us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3us"); dglColor3usv = (glColor3usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor3usv"); dglColor4b = (glColor4b_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4b"); dglColor4bv = (glColor4bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4bv"); dglColor4d = (glColor4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4d"); dglColor4dv = (glColor4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4dv"); dglColor4f = (glColor4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4f"); dglColor4fv = (glColor4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4fv"); dglColor4i = (glColor4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4i"); dglColor4iv = (glColor4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4iv"); dglColor4s = (glColor4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4s"); dglColor4sv = (glColor4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4sv"); dglColor4ub = (glColor4ub_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ub"); dglColor4ubv = (glColor4ubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ubv"); dglColor4ui = (glColor4ui_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4ui"); dglColor4uiv = (glColor4uiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4uiv"); dglColor4us = (glColor4us_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4us"); dglColor4usv = (glColor4usv_fp)dll_GetSymbol(OpenGLModuleHandle,"glColor4usv"); dglColorMask = (glColorMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMask"); dglColorMaterial = (glColorMaterial_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorMaterial"); dglColorPointer = (glColorPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glColorPointer"); dglCopyPixels = (glCopyPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyPixels"); dglCopyTexImage1D = (glCopyTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage1D"); dglCopyTexImage2D = (glCopyTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexImage2D"); dglCopyTexSubImage1D = (glCopyTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage1D"); dglCopyTexSubImage2D = (glCopyTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glCopyTexSubImage2D"); dglCullFace = (glCullFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glCullFace"); dglDeleteLists = (glDeleteLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteLists"); dglDeleteTextures = (glDeleteTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glDeleteTextures"); dglDepthFunc = (glDepthFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthFunc"); dglDepthMask = (glDepthMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthMask"); dglDepthRange = (glDepthRange_fp)dll_GetSymbol(OpenGLModuleHandle,"glDepthRange"); dglDisable = (glDisable_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisable"); dglDisableClientState = (glDisableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glDisableClientState"); dglDrawArrays = (glDrawArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawArrays"); dglDrawBuffer = (glDrawBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawBuffer"); dglDrawElements = (glDrawElements_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawElements"); dglDrawPixels = (glDrawPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glDrawPixels"); dglEdgeFlag = (glEdgeFlag_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlag"); dglEdgeFlagPointer = (glEdgeFlagPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagPointer"); dglEdgeFlagv = (glEdgeFlagv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEdgeFlagv"); dglEnable = (glEnable_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnable"); dglEnableClientState = (glEnableClientState_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnableClientState"); dglEnd = (glEnd_fp)dll_GetSymbol(OpenGLModuleHandle,"glEnd"); dglEndList = (glEndList_fp)dll_GetSymbol(OpenGLModuleHandle,"glEndList"); dglEvalCoord1d = (glEvalCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1d"); dglEvalCoord1dv = (glEvalCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1dv"); dglEvalCoord1f = (glEvalCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1f"); dglEvalCoord1fv = (glEvalCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord1fv"); dglEvalCoord2d = (glEvalCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2d"); dglEvalCoord2dv = (glEvalCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2dv"); dglEvalCoord2f = (glEvalCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2f"); dglEvalCoord2fv = (glEvalCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalCoord2fv"); dglEvalMesh1 = (glEvalMesh1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh1"); dglEvalMesh2 = (glEvalMesh2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalMesh2"); dglEvalPoint1 = (glEvalPoint1_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint1"); dglEvalPoint2 = (glEvalPoint2_fp)dll_GetSymbol(OpenGLModuleHandle,"glEvalPoint2"); dglFeedbackBuffer = (glFeedbackBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glFeedbackBuffer"); dglFinish = (glFinish_fp)dll_GetSymbol(OpenGLModuleHandle,"glFinish"); dglFlush = (glFlush_fp)dll_GetSymbol(OpenGLModuleHandle,"glFlush"); dglFogf = (glFogf_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogf"); dglFogfv = (glFogfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogfv"); dglFogi = (glFogi_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogi"); dglFogiv = (glFogiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glFogiv"); dglFrontFace = (glFrontFace_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrontFace"); dglFrustum = (glFrustum_fp)dll_GetSymbol(OpenGLModuleHandle,"glFrustum"); dglGenLists = (glGenLists_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenLists"); dglGenTextures = (glGenTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glGenTextures"); dglGetBooleanv = (glGetBooleanv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetBooleanv"); dglGetClipPlane = (glGetClipPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetClipPlane"); dglGetDoublev = (glGetDoublev_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetDoublev"); dglGetError = (glGetError_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetError"); dglGetFloatv = (glGetFloatv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetFloatv"); dglGetIntegerv = (glGetIntegerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetIntegerv"); dglGetLightfv = (glGetLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightfv"); dglGetLightiv = (glGetLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetLightiv"); dglGetMapdv = (glGetMapdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapdv"); dglGetMapfv = (glGetMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapfv"); dglGetMapiv = (glGetMapiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMapiv"); dglGetMaterialfv = (glGetMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialfv"); dglGetMaterialiv = (glGetMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetMaterialiv"); dglGetPixelMapfv = (glGetPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapfv"); dglGetPixelMapuiv = (glGetPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapuiv"); dglGetPixelMapusv = (glGetPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPixelMapusv"); dglGetPointerv = (glGetPointerv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPointerv"); dglGetPolygonStipple = (glGetPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetPolygonStipple"); dglGetString = (glGetString_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetString"); dglGetTexEnvfv = (glGetTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnvfv"); dglGetTexEnviv = (glGetTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexEnviv"); dglGetTexGendv = (glGetTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGendv"); dglGetTexGenfv = (glGetTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGenfv"); dglGetTexGeniv = (glGetTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexGeniv"); dglGetTexImage = (glGetTexImage_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexImage"); dglGetTexLevelParameterfv = (glGetTexLevelParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameterfv"); dglGetTexLevelParameteriv = (glGetTexLevelParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexLevelParameteriv"); dglGetTexParameterfv = (glGetTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameterfv"); dglGetTexParameteriv = (glGetTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glGetTexParameteriv"); dglHint = (glHint_fp)dll_GetSymbol(OpenGLModuleHandle,"glHint"); dglIndexMask = (glIndexMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexMask"); dglIndexPointer = (glIndexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexPointer"); dglIndexd = (glIndexd_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexd"); dglIndexdv = (glIndexdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexdv"); dglIndexf = (glIndexf_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexf"); dglIndexfv = (glIndexfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexfv"); dglIndexi = (glIndexi_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexi"); dglIndexiv = (glIndexiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexiv"); dglIndexs = (glIndexs_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexs"); dglIndexsv = (glIndexsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexsv"); dglIndexub = (glIndexub_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexub"); dglIndexubv = (glIndexubv_fp)dll_GetSymbol(OpenGLModuleHandle,"glIndexubv"); dglInitNames = (glInitNames_fp)dll_GetSymbol(OpenGLModuleHandle,"glInitNames"); dglInterleavedArrays = (glInterleavedArrays_fp)dll_GetSymbol(OpenGLModuleHandle,"glInterleavedArrays"); dglIsEnabled = (glIsEnabled_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsEnabled"); dglIsList = (glIsList_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsList"); dglIsTexture = (glIsTexture_fp)dll_GetSymbol(OpenGLModuleHandle,"glIsTexture"); dglLightModelf = (glLightModelf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelf"); dglLightModelfv = (glLightModelfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModelfv"); dglLightModeli = (glLightModeli_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeli"); dglLightModeliv = (glLightModeliv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightModeliv"); dglLightf = (glLightf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightf"); dglLightfv = (glLightfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightfv"); dglLighti = (glLighti_fp)dll_GetSymbol(OpenGLModuleHandle,"glLighti"); dglLightiv = (glLightiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glLightiv"); dglLineStipple = (glLineStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineStipple"); dglLineWidth = (glLineWidth_fp)dll_GetSymbol(OpenGLModuleHandle,"glLineWidth"); dglListBase = (glListBase_fp)dll_GetSymbol(OpenGLModuleHandle,"glListBase"); dglLoadIdentity = (glLoadIdentity_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadIdentity"); dglLoadMatrixd = (glLoadMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixd"); dglLoadMatrixf = (glLoadMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadMatrixf"); dglLoadName = (glLoadName_fp)dll_GetSymbol(OpenGLModuleHandle,"glLoadName"); dglLogicOp = (glLogicOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glLogicOp"); dglMap1d = (glMap1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1d"); dglMap1f = (glMap1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap1f"); dglMap2d = (glMap2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2d"); dglMap2f = (glMap2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMap2f"); dglMapGrid1d = (glMapGrid1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1d"); dglMapGrid1f = (glMapGrid1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid1f"); dglMapGrid2d = (glMapGrid2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2d"); dglMapGrid2f = (glMapGrid2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glMapGrid2f"); dglMaterialf = (glMaterialf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialf"); dglMaterialfv = (glMaterialfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialfv"); dglMateriali = (glMateriali_fp)dll_GetSymbol(OpenGLModuleHandle,"glMateriali"); dglMaterialiv = (glMaterialiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glMaterialiv"); dglMatrixMode = (glMatrixMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glMatrixMode"); dglMultMatrixd = (glMultMatrixd_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixd"); dglMultMatrixf = (glMultMatrixf_fp)dll_GetSymbol(OpenGLModuleHandle,"glMultMatrixf"); dglNewList = (glNewList_fp)dll_GetSymbol(OpenGLModuleHandle,"glNewList"); dglNormal3b = (glNormal3b_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3b"); dglNormal3bv = (glNormal3bv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3bv"); dglNormal3d = (glNormal3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3d"); dglNormal3dv = (glNormal3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3dv"); dglNormal3f = (glNormal3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3f"); dglNormal3fv = (glNormal3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3fv"); dglNormal3i = (glNormal3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3i"); dglNormal3iv = (glNormal3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3iv"); dglNormal3s = (glNormal3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3s"); dglNormal3sv = (glNormal3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormal3sv"); dglNormalPointer = (glNormalPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glNormalPointer"); dglOrtho = (glOrtho_fp)dll_GetSymbol(OpenGLModuleHandle,"glOrtho"); dglPassThrough = (glPassThrough_fp)dll_GetSymbol(OpenGLModuleHandle,"glPassThrough"); dglPixelMapfv = (glPixelMapfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapfv"); dglPixelMapuiv = (glPixelMapuiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapuiv"); dglPixelMapusv = (glPixelMapusv_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelMapusv"); dglPixelStoref = (glPixelStoref_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStoref"); dglPixelStorei = (glPixelStorei_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelStorei"); dglPixelTransferf = (glPixelTransferf_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferf"); dglPixelTransferi = (glPixelTransferi_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelTransferi"); dglPixelZoom = (glPixelZoom_fp)dll_GetSymbol(OpenGLModuleHandle,"glPixelZoom"); dglPointSize = (glPointSize_fp)dll_GetSymbol(OpenGLModuleHandle,"glPointSize"); dglPolygonMode = (glPolygonMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonMode"); dglPolygonOffset = (glPolygonOffset_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonOffset"); dglPolygonStipple = (glPolygonStipple_fp)dll_GetSymbol(OpenGLModuleHandle,"glPolygonStipple"); dglPopAttrib = (glPopAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopAttrib"); dglPopClientAttrib = (glPopClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopClientAttrib"); dglPopMatrix = (glPopMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopMatrix"); dglPopName = (glPopName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPopName"); dglPrioritizeTextures = (glPrioritizeTextures_fp)dll_GetSymbol(OpenGLModuleHandle,"glPrioritizeTextures"); dglPushAttrib = (glPushAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushAttrib"); dglPushClientAttrib = (glPushClientAttrib_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushClientAttrib"); dglPushMatrix = (glPushMatrix_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushMatrix"); dglPushName = (glPushName_fp)dll_GetSymbol(OpenGLModuleHandle,"glPushName"); dglRasterPos2d = (glRasterPos2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2d"); dglRasterPos2dv = (glRasterPos2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2dv"); dglRasterPos2f = (glRasterPos2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2f"); dglRasterPos2fv = (glRasterPos2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2fv"); dglRasterPos2i = (glRasterPos2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2i"); dglRasterPos2iv = (glRasterPos2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2iv"); dglRasterPos2s = (glRasterPos2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2s"); dglRasterPos2sv = (glRasterPos2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos2sv"); dglRasterPos3d = (glRasterPos3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3d"); dglRasterPos3dv = (glRasterPos3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3dv"); dglRasterPos3f = (glRasterPos3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3f"); dglRasterPos3fv = (glRasterPos3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3fv"); dglRasterPos3i = (glRasterPos3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3i"); dglRasterPos3iv = (glRasterPos3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3iv"); dglRasterPos3s = (glRasterPos3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3s"); dglRasterPos3sv = (glRasterPos3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos3sv"); dglRasterPos4d = (glRasterPos4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4d"); dglRasterPos4dv = (glRasterPos4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4dv"); dglRasterPos4f = (glRasterPos4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4f"); dglRasterPos4fv = (glRasterPos4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4fv"); dglRasterPos4i = (glRasterPos4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4i"); dglRasterPos4iv = (glRasterPos4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4iv"); dglRasterPos4s = (glRasterPos4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4s"); dglRasterPos4sv = (glRasterPos4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRasterPos4sv"); dglReadBuffer = (glReadBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadBuffer"); dglReadPixels = (glReadPixels_fp)dll_GetSymbol(OpenGLModuleHandle,"glReadPixels"); dglRectd = (glRectd_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectd"); dglRectdv = (glRectdv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectdv"); dglRectf = (glRectf_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectf"); dglRectfv = (glRectfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectfv"); dglRecti = (glRecti_fp)dll_GetSymbol(OpenGLModuleHandle,"glRecti"); dglRectiv = (glRectiv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectiv"); dglRects = (glRects_fp)dll_GetSymbol(OpenGLModuleHandle,"glRects"); dglRectsv = (glRectsv_fp)dll_GetSymbol(OpenGLModuleHandle,"glRectsv"); dglRenderMode = (glRenderMode_fp)dll_GetSymbol(OpenGLModuleHandle,"glRenderMode"); dglRotated = (glRotated_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotated"); dglRotatef = (glRotatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glRotatef"); dglScaled = (glScaled_fp)dll_GetSymbol(OpenGLModuleHandle,"glScaled"); dglScalef = (glScalef_fp)dll_GetSymbol(OpenGLModuleHandle,"glScalef"); dglScissor = (glScissor_fp)dll_GetSymbol(OpenGLModuleHandle,"glScissor"); dglSelectBuffer = (glSelectBuffer_fp)dll_GetSymbol(OpenGLModuleHandle,"glSelectBuffer"); dglShadeModel = (glShadeModel_fp)dll_GetSymbol(OpenGLModuleHandle,"glShadeModel"); dglStencilFunc = (glStencilFunc_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilFunc"); dglStencilMask = (glStencilMask_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilMask"); dglStencilOp = (glStencilOp_fp)dll_GetSymbol(OpenGLModuleHandle,"glStencilOp"); dglTexCoord1d = (glTexCoord1d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1d"); dglTexCoord1dv = (glTexCoord1dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1dv"); dglTexCoord1f = (glTexCoord1f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1f"); dglTexCoord1fv = (glTexCoord1fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1fv"); dglTexCoord1i = (glTexCoord1i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1i"); dglTexCoord1iv = (glTexCoord1iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1iv"); dglTexCoord1s = (glTexCoord1s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1s"); dglTexCoord1sv = (glTexCoord1sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord1sv"); dglTexCoord2d = (glTexCoord2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2d"); dglTexCoord2dv = (glTexCoord2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2dv"); dglTexCoord2f = (glTexCoord2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2f"); dglTexCoord2fv = (glTexCoord2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2fv"); dglTexCoord2i = (glTexCoord2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2i"); dglTexCoord2iv = (glTexCoord2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2iv"); dglTexCoord2s = (glTexCoord2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2s"); dglTexCoord2sv = (glTexCoord2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord2sv"); dglTexCoord3d = (glTexCoord3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3d"); dglTexCoord3dv = (glTexCoord3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3dv"); dglTexCoord3f = (glTexCoord3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3f"); dglTexCoord3fv = (glTexCoord3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3fv"); dglTexCoord3i = (glTexCoord3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3i"); dglTexCoord3iv = (glTexCoord3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3iv"); dglTexCoord3s = (glTexCoord3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3s"); dglTexCoord3sv = (glTexCoord3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord3sv"); dglTexCoord4d = (glTexCoord4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4d"); dglTexCoord4dv = (glTexCoord4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4dv"); dglTexCoord4f = (glTexCoord4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4f"); dglTexCoord4fv = (glTexCoord4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4fv"); dglTexCoord4i = (glTexCoord4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4i"); dglTexCoord4iv = (glTexCoord4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4iv"); dglTexCoord4s = (glTexCoord4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4s"); dglTexCoord4sv = (glTexCoord4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoord4sv"); dglTexCoordPointer = (glTexCoordPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexCoordPointer"); dglTexEnvf = (glTexEnvf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvf"); dglTexEnvfv = (glTexEnvfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvfv"); dglTexEnvi = (glTexEnvi_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnvi"); dglTexEnviv = (glTexEnviv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexEnviv"); dglTexGend = (glTexGend_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGend"); dglTexGendv = (glTexGendv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGendv"); dglTexGenf = (glTexGenf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenf"); dglTexGenfv = (glTexGenfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGenfv"); dglTexGeni = (glTexGeni_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeni"); dglTexGeniv = (glTexGeniv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexGeniv"); dglTexImage1D = (glTexImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage1D"); dglTexImage2D = (glTexImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexImage2D"); dglTexParameterf = (glTexParameterf_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterf"); dglTexParameterfv = (glTexParameterfv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameterfv"); dglTexParameteri = (glTexParameteri_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteri"); dglTexParameteriv = (glTexParameteriv_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexParameteriv"); dglTexSubImage1D = (glTexSubImage1D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage1D"); dglTexSubImage2D = (glTexSubImage2D_fp)dll_GetSymbol(OpenGLModuleHandle,"glTexSubImage2D"); dglTranslated = (glTranslated_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslated"); dglTranslatef = (glTranslatef_fp)dll_GetSymbol(OpenGLModuleHandle,"glTranslatef"); dglVertex2d = (glVertex2d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2d"); dglVertex2dv = (glVertex2dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2dv"); dglVertex2f = (glVertex2f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2f"); dglVertex2fv = (glVertex2fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2fv"); dglVertex2i = (glVertex2i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2i"); dglVertex2iv = (glVertex2iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2iv"); dglVertex2s = (glVertex2s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2s"); dglVertex2sv = (glVertex2sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex2sv"); dglVertex3d = (glVertex3d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3d"); dglVertex3dv = (glVertex3dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3dv"); dglVertex3f = (glVertex3f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3f"); dglVertex3fv = (glVertex3fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3fv"); dglVertex3i = (glVertex3i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3i"); dglVertex3iv = (glVertex3iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3iv"); dglVertex3s = (glVertex3s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3s"); dglVertex3sv = (glVertex3sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex3sv"); dglVertex4d = (glVertex4d_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4d"); dglVertex4dv = (glVertex4dv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4dv"); dglVertex4f = (glVertex4f_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4f"); dglVertex4fv = (glVertex4fv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4fv"); dglVertex4i = (glVertex4i_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4i"); dglVertex4iv = (glVertex4iv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4iv"); dglVertex4s = (glVertex4s_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4s"); dglVertex4sv = (glVertex4sv_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertex4sv"); dglVertexPointer = (glVertexPointer_fp)dll_GetSymbol(OpenGLModuleHandle,"glVertexPointer"); dglViewport = (glViewport_fp)dll_GetSymbol(OpenGLModuleHandle,"glViewport"); #ifdef _WIN32 dwglCopyContext = (wglCopyContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCopyContext"); dwglCreateContext = (wglCreateContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateContext"); dwglCreateLayerContext = (wglCreateLayerContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglCreateLayerContext"); dwglDeleteContext = (wglDeleteContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDeleteContext"); dwglGetCurrentContext = (wglGetCurrentContext_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentContext"); dwglGetCurrentDC = (wglGetCurrentDC_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetCurrentDC"); dwglGetProcAddress = (wglGetProcAddress_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetProcAddress"); dwglMakeCurrent = (wglMakeCurrent_fp)dll_GetSymbol(OpenGLModuleHandle,"wglMakeCurrent"); dwglShareLists = (wglShareLists_fp)dll_GetSymbol(OpenGLModuleHandle,"wglShareLists"); dwglUseFontBitmapsA = (wglUseFontBitmapsA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsA"); dwglUseFontBitmapsW = (wglUseFontBitmapsW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontBitmapsW"); dwglUseFontOutlinesA = (wglUseFontOutlinesA_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesA"); dwglUseFontOutlinesW = (wglUseFontOutlinesW_fp)dll_GetSymbol(OpenGLModuleHandle,"wglUseFontOutlinesW"); dwglDescribeLayerPlane = (wglDescribeLayerPlane_fp)dll_GetSymbol(OpenGLModuleHandle,"wglDescribeLayerPlane"); dwglSetLayerPaletteEntries = (wglSetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSetLayerPaletteEntries"); dwglGetLayerPaletteEntries = (wglGetLayerPaletteEntries_fp)dll_GetSymbol(OpenGLModuleHandle,"wglGetLayerPaletteEntries"); dwglRealizeLayerPalette = (wglRealizeLayerPalette_fp)dll_GetSymbol(OpenGLModuleHandle,"wglRealizeLayerPalette"); dwglSwapLayerBuffers = (wglSwapLayerBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapLayerBuffers"); #if (WINVER >= 0x0500) dwglSwapMultipleBuffers = (wglSwapMultipleBuffers_fp)dll_GetSymbol(OpenGLModuleHandle,"wglSwapMultipleBuffers"); #endif #endif } return true; } void OpenGL_SetFuncsToNull(void) { dglAccum = NULL; dglAlphaFunc = NULL; dglAreTexturesResident = NULL; dglArrayElement = NULL; dglBegin = NULL; dglBindTexture = NULL; dglBitmap = NULL; dglBlendFunc = NULL; dglCallList = NULL; dglCallLists = NULL; dglClear = NULL; dglClearAccum = NULL; dglClearColor = NULL; dglClearDepth = NULL; dglClearIndex = NULL; dglClearStencil = NULL; dglClipPlane = NULL; dglColor3b = NULL; dglColor3bv = NULL; dglColor3d = NULL; dglColor3dv = NULL; dglColor3f = NULL; dglColor3fv = NULL; dglColor3i = NULL; dglColor3iv = NULL; dglColor3s = NULL; dglColor3sv = NULL; dglColor3ub = NULL; dglColor3ubv = NULL; dglColor3ui = NULL; dglColor3uiv = NULL; dglColor3us = NULL; dglColor3usv = NULL; dglColor4b = NULL; dglColor4bv = NULL; dglColor4d = NULL; dglColor4dv = NULL; dglColor4f = NULL; dglColor4fv = NULL; dglColor4i = NULL; dglColor4iv = NULL; dglColor4s = NULL; dglColor4sv = NULL; dglColor4ub = NULL; dglColor4ubv = NULL; dglColor4ui = NULL; dglColor4uiv = NULL; dglColor4us = NULL; dglColor4usv = NULL; dglColorMask = NULL; dglColorMaterial = NULL; dglColorPointer = NULL; dglCopyPixels = NULL; dglCopyTexImage1D = NULL; dglCopyTexImage2D = NULL; dglCopyTexSubImage1D = NULL; dglCopyTexSubImage2D = NULL; dglCullFace = NULL; dglDeleteLists = NULL; dglDeleteTextures = NULL; dglDepthFunc = NULL; dglDepthMask = NULL; dglDepthRange = NULL; dglDisable = NULL; dglDisableClientState = NULL; dglDrawArrays = NULL; dglDrawBuffer = NULL; dglDrawElements = NULL; dglDrawPixels = NULL; dglEdgeFlag = NULL; dglEdgeFlagPointer = NULL; dglEdgeFlagv = NULL; dglEnable = NULL; dglEnableClientState = NULL; dglEnd = NULL; dglEndList = NULL; dglEvalCoord1d = NULL; dglEvalCoord1dv = NULL; dglEvalCoord1f = NULL; dglEvalCoord1fv = NULL; dglEvalCoord2d = NULL; dglEvalCoord2dv = NULL; dglEvalCoord2f = NULL; dglEvalCoord2fv = NULL; dglEvalMesh1 = NULL; dglEvalMesh2 = NULL; dglEvalPoint1 = NULL; dglEvalPoint2 = NULL; dglFeedbackBuffer = NULL; dglFinish = NULL; dglFlush = NULL; dglFogf = NULL; dglFogfv = NULL; dglFogi = NULL; dglFogiv = NULL; dglFrontFace = NULL; dglFrustum = NULL; dglGenLists = NULL; dglGenTextures = NULL; dglGetBooleanv = NULL; dglGetClipPlane = NULL; dglGetDoublev = NULL; dglGetError = NULL; dglGetFloatv = NULL; dglGetIntegerv = NULL; dglGetLightfv = NULL; dglGetLightiv = NULL; dglGetMapdv = NULL; dglGetMapfv = NULL; dglGetMapiv = NULL; dglGetMaterialfv = NULL; dglGetMaterialiv = NULL; dglGetPixelMapfv = NULL; dglGetPixelMapuiv = NULL; dglGetPixelMapusv = NULL; dglGetPointerv = NULL; dglGetPolygonStipple = NULL; dglGetString = NULL; dglGetTexEnvfv = NULL; dglGetTexEnviv = NULL; dglGetTexGendv = NULL; dglGetTexGenfv = NULL; dglGetTexGeniv = NULL; dglGetTexImage = NULL; dglGetTexLevelParameterfv = NULL; dglGetTexLevelParameteriv = NULL; dglGetTexParameterfv = NULL; dglGetTexParameteriv = NULL; dglHint = NULL; dglIndexMask = NULL; dglIndexPointer = NULL; dglIndexd = NULL; dglIndexdv = NULL; dglIndexf = NULL; dglIndexfv = NULL; dglIndexi = NULL; dglIndexiv = NULL; dglIndexs = NULL; dglIndexsv = NULL; dglIndexub = NULL; dglIndexubv = NULL; dglInitNames = NULL; dglInterleavedArrays = NULL; dglIsEnabled = NULL; dglIsList = NULL; dglIsTexture = NULL; dglLightModelf = NULL; dglLightModelfv = NULL; dglLightModeli = NULL; dglLightModeliv = NULL; dglLightf = NULL; dglLightfv = NULL; dglLighti = NULL; dglLightiv = NULL; dglLineStipple = NULL; dglLineWidth = NULL; dglListBase = NULL; dglLoadIdentity = NULL; dglLoadMatrixd = NULL; dglLoadMatrixf = NULL; dglLoadName = NULL; dglLogicOp = NULL; dglMap1d = NULL; dglMap1f = NULL; dglMap2d = NULL; dglMap2f = NULL; dglMapGrid1d = NULL; dglMapGrid1f = NULL; dglMapGrid2d = NULL; dglMapGrid2f = NULL; dglMaterialf = NULL; dglMaterialfv = NULL; dglMateriali = NULL; dglMaterialiv = NULL; dglMatrixMode = NULL; dglMultMatrixd = NULL; dglMultMatrixf = NULL; dglNewList = NULL; dglNormal3b = NULL; dglNormal3bv = NULL; dglNormal3d = NULL; dglNormal3dv = NULL; dglNormal3f = NULL; dglNormal3fv = NULL; dglNormal3i = NULL; dglNormal3iv = NULL; dglNormal3s = NULL; dglNormal3sv = NULL; dglNormalPointer = NULL; dglOrtho = NULL; dglPassThrough = NULL; dglPixelMapfv = NULL; dglPixelMapuiv = NULL; dglPixelMapusv = NULL; dglPixelStoref = NULL; dglPixelStorei = NULL; dglPixelTransferf = NULL; dglPixelTransferi = NULL; dglPixelZoom = NULL; dglPointSize = NULL; dglPolygonMode = NULL; dglPolygonOffset = NULL; dglPolygonStipple = NULL; dglPopAttrib = NULL; dglPopClientAttrib = NULL; dglPopMatrix = NULL; dglPopName = NULL; dglPrioritizeTextures = NULL; dglPushAttrib = NULL; dglPushClientAttrib = NULL; dglPushMatrix = NULL; dglPushName = NULL; dglRasterPos2d = NULL; dglRasterPos2dv = NULL; dglRasterPos2f = NULL; dglRasterPos2fv = NULL; dglRasterPos2i = NULL; dglRasterPos2iv = NULL; dglRasterPos2s = NULL; dglRasterPos2sv = NULL; dglRasterPos3d = NULL; dglRasterPos3dv = NULL; dglRasterPos3f = NULL; dglRasterPos3fv = NULL; dglRasterPos3i = NULL; dglRasterPos3iv = NULL; dglRasterPos3s = NULL; dglRasterPos3sv = NULL; dglRasterPos4d = NULL; dglRasterPos4dv = NULL; dglRasterPos4f = NULL; dglRasterPos4fv = NULL; dglRasterPos4i = NULL; dglRasterPos4iv = NULL; dglRasterPos4s = NULL; dglRasterPos4sv = NULL; dglReadBuffer = NULL; dglReadPixels = NULL; dglRectd = NULL; dglRectdv = NULL; dglRectf = NULL; dglRectfv = NULL; dglRecti = NULL; dglRectiv = NULL; dglRects = NULL; dglRectsv = NULL; dglRenderMode = NULL; dglRotated = NULL; dglRotatef = NULL; dglScaled = NULL; dglScalef = NULL; dglScissor = NULL; dglSelectBuffer = NULL; dglShadeModel = NULL; dglStencilFunc = NULL; dglStencilMask = NULL; dglStencilOp = NULL; dglTexCoord1d = NULL; dglTexCoord1dv = NULL; dglTexCoord1f = NULL; dglTexCoord1fv = NULL; dglTexCoord1i = NULL; dglTexCoord1iv = NULL; dglTexCoord1s = NULL; dglTexCoord1sv = NULL; dglTexCoord2d = NULL; dglTexCoord2dv = NULL; dglTexCoord2f = NULL; dglTexCoord2fv = NULL; dglTexCoord2i = NULL; dglTexCoord2iv = NULL; dglTexCoord2s = NULL; dglTexCoord2sv = NULL; dglTexCoord3d = NULL; dglTexCoord3dv = NULL; dglTexCoord3f = NULL; dglTexCoord3fv = NULL; dglTexCoord3i = NULL; dglTexCoord3iv = NULL; dglTexCoord3s = NULL; dglTexCoord3sv = NULL; dglTexCoord4d = NULL; dglTexCoord4dv = NULL; dglTexCoord4f = NULL; dglTexCoord4fv = NULL; dglTexCoord4i = NULL; dglTexCoord4iv = NULL; dglTexCoord4s = NULL; dglTexCoord4sv = NULL; dglTexCoordPointer = NULL; dglTexEnvf = NULL; dglTexEnvfv = NULL; dglTexEnvi = NULL; dglTexEnviv = NULL; dglTexGend = NULL; dglTexGendv = NULL; dglTexGenf = NULL; dglTexGenfv = NULL; dglTexGeni = NULL; dglTexGeniv = NULL; dglTexImage1D = NULL; dglTexImage2D = NULL; dglTexParameterf = NULL; dglTexParameterfv = NULL; dglTexParameteri = NULL; dglTexParameteriv = NULL; dglTexSubImage1D = NULL; dglTexSubImage2D = NULL; dglTranslated = NULL; dglTranslatef = NULL; dglVertex2d = NULL; dglVertex2dv = NULL; dglVertex2f = NULL; dglVertex2fv = NULL; dglVertex2i = NULL; dglVertex2iv = NULL; dglVertex2s = NULL; dglVertex2sv = NULL; dglVertex3d = NULL; dglVertex3dv = NULL; dglVertex3f = NULL; dglVertex3fv = NULL; dglVertex3i = NULL; dglVertex3iv = NULL; dglVertex3s = NULL; dglVertex3sv = NULL; dglVertex4d = NULL; dglVertex4dv = NULL; dglVertex4f = NULL; dglVertex4fv = NULL; dglVertex4i = NULL; dglVertex4iv = NULL; dglVertex4s = NULL; dglVertex4sv = NULL; dglVertexPointer = NULL; dglViewport = NULL; dglMultiTexCoord2fARB = NULL; dglActiveTextureARB = NULL; dglMultiTexCoord2fSGIS = NULL; dglSelectTextureSGIS = NULL; dglColorTableEXT = NULL; dglCombinerParameteriNV = NULL; dglCombinerInputNV = NULL; dglCombinerOutputNV = NULL; dglFinalCombinerInputNV = NULL; #ifdef _WIN32 dwglCopyContext = NULL; dwglCreateContext = NULL; dwglCreateLayerContext = NULL; dwglDeleteContext = NULL; dwglGetCurrentContext = NULL; dwglGetCurrentDC = NULL; dwglGetProcAddress = NULL; dwglMakeCurrent = NULL; dwglShareLists = NULL; dwglUseFontBitmapsA = NULL; dwglUseFontBitmapsW = NULL; dwglUseFontOutlinesA = NULL; dwglUseFontOutlinesW = NULL; dwglDescribeLayerPlane = NULL; dwglSetLayerPaletteEntries = NULL; dwglGetLayerPaletteEntries = NULL; dwglRealizeLayerPalette = NULL; dwglSwapLayerBuffers = NULL; #if (WINVER >= 0x0500) dwglSwapMultipleBuffers = NULL; #endif #endif } #endif #endif //!__LOADGL_H__ dxx-rebirth-0.58.1-d2x/include/makesig.h000066400000000000000000000007601217717237500177730ustar00rootroot00000000000000/* * $Source: /cvsroot/dxx-rebirth/d2x-rebirth/include/makesig.h,v $ * $Revision: 1.1.1.1 $ * $Author: zicodxx $ * $Date: 2006/03/17 20:01:26 $ * * Macro to make file signatures * * $Log: makesig.h,v $ * Revision 1.1.1.1 2006/03/17 20:01:26 zicodxx * initial import * * Revision 1.1 2001/11/11 23:39:22 bradleyb * Created header for MAKE_SIG macro * * */ #ifndef _MAKESIG_H #define _MAKESIG_H #define MAKE_SIG(a,b,c,d) (((long)(a)<<24)+((long)(b)<<16)+((c)<<8)+(d)) #endif dxx-rebirth-0.58.1-d2x/include/maths.h000066400000000000000000000056301217717237500174700ustar00rootroot00000000000000/* Maths.h library header file */ #ifndef _MATHS_H #define _MATHS_H #include #include "pstypes.h" #define D_RAND_MAX 32767 void d_srand (unsigned int seed); int d_rand (); // Random number function which returns in the range 0-0x7FFF //=============================== FIXED POINT =============================== typedef int64_t fix64; //64 bits int, for timers typedef int32_t fix; //16 bits int, 16 bits frac typedef int16_t fixang; //angles typedef struct quadint // integer 64 bit, previously called "quad" { u_int32_t low; int32_t high; } quadint; //Convert an int to a fix/fix64 and back #define i2f(i) ((i)<<16) #define f2i(f) ((f)>>16) //Get the int part of a fix, with rounding #define f2ir(f) (((f)+f0_5)>>16) //Convert fix to float and float to fix #define f2fl(f) (((float) (f)) / 65536.0) #define f2db(f) (((double) (f)) / 65536.0) #define fl2f(f) ((fix) ((f) * 65536)) //Some handy constants #define f0_0 0 #define f1_0 0x10000 #define f2_0 0x20000 #define f3_0 0x30000 #define f10_0 0xa0000 #define f0_5 0x8000 #define f0_1 0x199a #define F0_0 f0_0 #define F1_0 f1_0 #define F2_0 f2_0 #define F3_0 f3_0 #define F10_0 f10_0 #define F0_5 f0_5 #define F0_1 f0_1 //multiply two fixes, return a fix(64) fix fixmul (fix a, fix b); fix64 fixmul64 (fix a, fix b); //divide two fixes, return a fix fix fixdiv (fix a, fix b); //multiply two fixes, then divide by a third, return a fix fix fixmuldiv (fix a, fix b, fix c); //multiply two fixes, and add 64-bit product to a quadint void fixmulaccum (quadint * q, fix a, fix b); //extract a fix from a quadint product fix fixquadadjust (quadint * q); //divide a quadint by a long int32_t fixdivquadlong (u_int32_t qlow, u_int32_t qhigh, u_int32_t d); //negate a quadint void fixquadnegate (quadint * q); //computes the square root of a long, returning a short ushort long_sqrt (int32_t a); //computes the square root of a quadint, returning a long u_int32_t quad_sqrt (u_int32_t low, int32_t high); //unsigned long quad_sqrt (long low, long high); //computes the square root of a fix, returning a fix fix fix_sqrt (fix a); //compute sine and cosine of an angle, filling in the variables //either of the pointers can be NULL void fix_sincos (fix a, fix * s, fix * c); //with interpolation void fix_fastsincos (fix a, fix * s, fix * c); //no interpolation //compute inverse sine & cosine fixang fix_asin (fix v); fixang fix_acos (fix v); //given cos & sin of an angle, return that angle. //parms need not be normalized, that is, the ratio of the parms cos/sin must //equal the ratio of the actual cos & sin for the result angle, but the parms //need not be the actual cos & sin. //NOTE: this is different from the standard C atan2, since it is left-handed. fixang fix_atan2 (fix cos, fix sin); extern const ubyte guess_table[256]; extern const short sincos_table[321]; extern const ushort asin_table[258]; extern const ushort acos_table[258]; #endif dxx-rebirth-0.58.1-d2x/include/ogl_init.h000066400000000000000000000060741217717237500201630ustar00rootroot00000000000000/* interface to OpenGL functions * Added 9/15/99 Matthew Mueller * Got rid of OpenGL-internal stuff 2004-5-16 Martin Schaffner */ #ifndef _OGL_INIT_H_ #define _OGL_INIT_H_ #ifdef _MSC_VER #include #include #endif #ifdef _WIN32 #include "loadgl.h" int ogl_init_load_library(void); #else # define GL_GLEXT_LEGACY # if defined(__APPLE__) && defined(__MACH__) # include # include # else # define GL_GLEXT_PROTOTYPES # ifdef OGLES # include # else # include # endif # endif # ifndef GL_CLAMP_TO_EDGE // hack for Mac OS 9, others? # define GL_CLAMP_TO_EDGE GL_CLAMP # endif #endif #include "gr.h" #include "palette.h" #include "pstypes.h" #ifndef GL_VERSION_1_1 #ifdef GL_EXT_texture #define GL_INTENSITY4 GL_INTENSITY4_EXT #define GL_INTENSITY8 GL_INTENSITY8_EXT #endif #endif #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #endif #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF #endif /* we need to export ogl_texture for 2d/font.c */ typedef struct _ogl_texture { GLuint handle; GLint internalformat; GLenum format; int w,h,tw,th,lw; int bytesu; int bytes; GLfloat u,v; GLfloat prio; int wrapstate; unsigned long numrend; } ogl_texture; extern ogl_texture* ogl_get_free_texture(); void ogl_init_texture(ogl_texture* t, int w, int h, int flags); extern int ogl_rgba_internalformat; extern int ogl_rgb_internalformat; void ogl_init_shared_palette(void); extern int gl_initialized; extern int active_texture_unit; extern GLfloat ogl_maxanisotropy; void ogl_setActiveTexture(int t); int ogl_init_window(int x, int y);//create a window/switch modes/etc #define OGL_FLAG_MIPMAP (1 << 0) #define OGL_FLAG_NOCOLOR (1 << 1) #define OGL_FLAG_ALPHA (1 << 31) // not required for ogl_loadbmtexture, since it uses the BM_FLAG_TRANSPARENT, but is needed for ogl_init_texture. void ogl_loadbmtexture_f(grs_bitmap *bm, int texfilt); void ogl_freebmtexture(grs_bitmap *bm); void ogl_start_frame(void); void ogl_end_frame(void); void ogl_swap_buffers_internal(void); void ogl_set_screen_mode(void); void ogl_cache_level_textures(void); void ogl_urect(int left, int top, int right, int bot); bool ogl_ubitmapm_cs(int x, int y,int dw, int dh, grs_bitmap *bm,int c, int scale); bool ogl_ubitblt_i(int dw, int dh, int dx, int dy, int sw, int sh, int sx, int sy, grs_bitmap * src, grs_bitmap * dest, int texfilt); bool ogl_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest); void ogl_upixelc(int x, int y, int c); unsigned char ogl_ugpixel( grs_bitmap * bitmap, int x, int y ); void ogl_ulinec(int left, int top, int right, int bot, int c); #include "3d.h" bool g3_draw_tmap_2(int nv,const g3s_point **pointlist,g3s_uvl *uvl_list,g3s_lrgb *light_rgb, grs_bitmap *bmbot,grs_bitmap *bm, int orient); void ogl_draw_vertex_reticle(int cross,int primary,int secondary,int color,int alpha,int size_offs); void ogl_toggle_depth_test(int enable); void ogl_set_blending(); int pow2ize(int x);//from ogl.c #endif /* _OGL_INIT_H_ */ dxx-rebirth-0.58.1-d2x/include/palette.h000066400000000000000000000026461217717237500200160ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Protoypes for palette functions * */ #ifndef _PALETTE_H #define _PALETTE_H #define DEFAULT_LEVEL_PALETTE "groupa.256" //don't confuse with D2_DEFAULT_PALETTE extern void gr_palette_set_gamma( int gamma ); extern int gr_palette_get_gamma(); extern void gr_palette_clear(); extern void gr_palette_load( ubyte * pal ); extern void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b ); extern void gr_make_blend_table(ubyte *blend_table, ubyte r, ubyte g, ubyte b); extern int gr_find_closest_color_current( int r, int g, int b ); extern void gr_palette_read(ubyte * palette); extern void init_computed_colors(void); extern ubyte gr_palette_gamma; extern ubyte gr_current_pal[256*3]; #endif dxx-rebirth-0.58.1-d2x/include/pcx.h000066400000000000000000000031161217717237500171430ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to read/write pcx images. * */ #ifndef _PCX_H #define _PCX_H #define PCX_ERROR_NONE 0 #define PCX_ERROR_OPENING 1 #define PCX_ERROR_NO_HEADER 2 #define PCX_ERROR_WRONG_VERSION 3 #define PCX_ERROR_READING 4 #define PCX_ERROR_NO_PALETTE 5 #define PCX_ERROR_WRITING 6 #define PCX_ERROR_MEMORY 7 // Reads filename into bitmap bmp, and fills in palette. If bmp->bm_data==NULL, // then bmp->bm_data is allocated and the w,h are filled. // If palette==NULL the palette isn't read in. Returns error code. extern int pcx_read_bitmap( char * filename, grs_bitmap * bmp, int bitmap_type, ubyte * palette ); // Writes the bitmap bmp to filename, using palette. Returns error code. extern int pcx_write_bitmap( char * filename, grs_bitmap * bmp, ubyte * palette ); extern const char *pcx_errormsg(int error_number); #endif dxx-rebirth-0.58.1-d2x/include/physfsrwops.h000066400000000000000000000066041217717237500207650ustar00rootroot00000000000000/* * This code provides a glue layer between PhysicsFS and Simple Directmedia * Layer's (SDL) RWops i/o abstraction. * * License: this code is public domain. I make no warranty that it is useful, * correct, harmless, or environmentally safe. * * This particular file may be used however you like, including copying it * verbatim into a closed-source project, exploiting it commercially, and * removing any trace of my name from the source (although I hope you won't * do that). I welcome enhancements and corrections to this file, but I do * not require you to send me patches if you make changes. This code has * NO WARRANTY. * * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. * Please see LICENSE in the root of the source tree. * * SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/ * * This file was written by Ryan C. Gordon. (icculus@clutteredmind.org). */ #ifndef _INCLUDE_PHYSFSRWOPS_H_ #define _INCLUDE_PHYSFSRWOPS_H_ #if 1 //!(defined(__APPLE__) && defined(__MACH__)) #include #else #include #endif #include #ifdef __cplusplus extern "C" { #endif /** * Open a platform-independent filename for reading, and make it accessible * via an SDL_RWops structure. The file will be closed in PhysicsFS when the * RWops is closed. PhysicsFS should be configured to your liking before * opening files through this method. * * @param filename File to open in platform-independent notation. * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openRead(const char *fname); /** * Open a platform-independent filename for writing, and make it accessible * via an SDL_RWops structure. The file will be closed in PhysicsFS when the * RWops is closed. PhysicsFS should be configured to your liking before * opening files through this method. * * @param filename File to open in platform-independent notation. * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname); /** * Open a platform-independent filename for appending, and make it accessible * via an SDL_RWops structure. The file will be closed in PhysicsFS when the * RWops is closed. PhysicsFS should be configured to your liking before * opening files through this method. * * @param filename File to open in platform-independent notation. * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ __EXPORT__ SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname); /** * Make a SDL_RWops from an existing PhysicsFS file handle. You should * dispose of any references to the handle after successful creation of * the RWops. The actual PhysicsFS handle will be destroyed when the * RWops is closed. * * @param handle a valid PhysicsFS file handle. * @return A valid SDL_RWops structure on success, NULL on error. Specifics * of the error can be gleaned from PHYSFS_getLastError(). */ __EXPORT__ SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle); #ifdef __cplusplus } #endif #endif /* include-once blocker */ /* end of physfsrwops.h ... */ dxx-rebirth-0.58.1-d2x/include/physfsx.h000066400000000000000000000161721217717237500200630ustar00rootroot00000000000000 /* * * Some simple physfs extensions * */ #ifndef PHYSFSX_H #define PHYSFSX_H #include #include // When PhysicsFS can *easily* be built as a framework on Mac OS X, // the framework form will be supported again -kreatordxx #if 1 //!(defined(__APPLE__) && defined(__MACH__)) #include #else #include #endif #include "pstypes.h" #include "strutil.h" #include "u_mem.h" #include "dxxerror.h" #include "vecmat.h" #include "ignorecase.h" #include "byteswap.h" extern void PHYSFSX_init(int argc, char *argv[]); static inline int PHYSFSX_readSXE16(PHYSFS_file *file, int swap) { PHYSFS_sint16 val; PHYSFS_read(file, &val, sizeof(val), 1); return swap ? SWAPSHORT(val) : val; } static inline int PHYSFSX_readSXE32(PHYSFS_file *file, int swap) { PHYSFS_sint32 val; PHYSFS_read(file, &val, sizeof(val), 1); return swap ? SWAPINT(val) : val; } static inline void PHYSFSX_readVectorX(PHYSFS_file *file, vms_vector *v, int swap) { v->x = PHYSFSX_readSXE32(file, swap); v->y = PHYSFSX_readSXE32(file, swap); v->z = PHYSFSX_readSXE32(file, swap); } static inline void PHYSFSX_readAngleVecX(PHYSFS_file *file, vms_angvec *v, int swap) { v->p = PHYSFSX_readSXE16(file, swap); v->b = PHYSFSX_readSXE16(file, swap); v->h = PHYSFSX_readSXE16(file, swap); } static inline int PHYSFSX_readString(PHYSFS_file *file, char *s) { char *ptr = s; if (PHYSFS_eof(file)) *ptr = 0; else do PHYSFS_read(file, ptr, 1, 1); while (!PHYSFS_eof(file) && *ptr++ != 0); return strlen(s); } static inline int PHYSFSX_gets(PHYSFS_file *file, char *s) { char *ptr = s; if (PHYSFS_eof(file)) *ptr = 0; else do PHYSFS_read(file, ptr, 1, 1); while (!PHYSFS_eof(file) && *ptr++ != '\n'); return strlen(s); } static inline int PHYSFSX_writeU8(PHYSFS_file *file, PHYSFS_uint8 val) { return PHYSFS_write(file, &val, 1, 1); } static inline int PHYSFSX_writeString(PHYSFS_file *file, const char *s) { return PHYSFS_write(file, s, 1, strlen(s) + 1); } static inline int PHYSFSX_puts(PHYSFS_file *file, const char *s) { return PHYSFS_write(file, s, 1, strlen(s)); } static inline int PHYSFSX_putc(PHYSFS_file *file, int c) { unsigned char ch = (unsigned char)c; if (PHYSFS_write(file, &ch, 1, 1) < 1) return -1; else return (int)c; } static inline int PHYSFSX_fgetc(PHYSFS_file *const fp) { unsigned char c; if (PHYSFS_read(fp, &c, 1, 1) != 1) return EOF; return c; } static inline int PHYSFSX_fseek(PHYSFS_file *fp, long int offset, int where) { int c, goal_position; switch(where) { case SEEK_SET: goal_position = offset; break; case SEEK_CUR: goal_position = PHYSFS_tell(fp) + offset; break; case SEEK_END: goal_position = PHYSFS_fileLength(fp) + offset; break; default: return 1; } c = PHYSFS_seek(fp, goal_position); return !c; } static inline char * PHYSFSX_fgets(char *buf, size_t n, PHYSFS_file *const fp) { size_t i; int c; for (i = 0; i < n - 1; i++) { do { c = PHYSFSX_fgetc(fp); if (c == EOF) { *buf = 0; return NULL; } if (c == 0 || c == 10) // Unix line ending break; if (c == 13) // Mac or DOS line ending { int c1; c1 = PHYSFSX_fgetc(fp); if (c1 != EOF) // The file could end with a Mac line ending PHYSFSX_fseek(fp, -1, SEEK_CUR); if (c1 == 10) // DOS line ending continue; else // Mac line ending break; } } while (c == 13); if (c == 13) // because cr-lf is a bad thing on the mac c = '\n'; // and anyway -- 0xod is CR on mac, not 0x0a if (c == '\n') break; *buf++ = c; } *buf = 0; return buf; } static inline int PHYSFSX_printf(PHYSFS_file *file, const char *format, ...) { char buffer[1024]; va_list args; va_start(args, format); vsprintf(buffer, format, args); return PHYSFSX_puts(file, buffer); } #define PHYSFSX_writeFix PHYSFS_writeSLE32 #define PHYSFSX_writeFixAng PHYSFS_writeSLE16 static inline int PHYSFSX_writeVector(PHYSFS_file *file, vms_vector *v) { if (PHYSFSX_writeFix(file, v->x) < 1 || PHYSFSX_writeFix(file, v->y) < 1 || PHYSFSX_writeFix(file, v->z) < 1) return 0; return 1; } static inline int PHYSFSX_writeAngleVec(PHYSFS_file *file, vms_angvec *v) { if (PHYSFSX_writeFixAng(file, v->p) < 1 || PHYSFSX_writeFixAng(file, v->b) < 1 || PHYSFSX_writeFixAng(file, v->h) < 1) return 0; return 1; } static inline int PHYSFSX_writeMatrix(PHYSFS_file *file, vms_matrix *m) { if (PHYSFSX_writeVector(file, &m->rvec) < 1 || PHYSFSX_writeVector(file, &m->uvec) < 1 || PHYSFSX_writeVector(file, &m->fvec) < 1) return 0; return 1; } static inline int PHYSFSX_readInt(PHYSFS_file *file) { int i; if (!PHYSFS_readSLE32(file, &i)) { Error("Error reading int in PHYSFSX_readInt()"); } return i; } static inline short PHYSFSX_readShort(PHYSFS_file *file) { int16_t s; if (!PHYSFS_readSLE16(file, &s)) { Error("Error reading short in PHYSFSX_readShort()"); } return s; } static inline sbyte PHYSFSX_readByte(PHYSFS_file *file) { sbyte b; if (PHYSFS_read(file, &b, sizeof(b), 1) != 1) { Error("Error reading byte in PHYSFSX_readByte()"); } return b; } static inline fix PHYSFSX_readFix(PHYSFS_file *file) { int f; // a fix is defined as a long for Mac OS 9, and MPW can't convert from (long *) to (int *) if (!PHYSFS_readSLE32(file, &f)) { Error("Error reading fix in PHYSFSX_readFix()"); } return f; } static inline fixang PHYSFSX_readFixAng(PHYSFS_file *file) { fixang f; if (!PHYSFS_readSLE16(file, &f)) { Error("Error reading fixang in PHYSFSX_readFixAng()"); } return f; } static inline void PHYSFSX_readVector(vms_vector *v, PHYSFS_file *file) { v->x = PHYSFSX_readFix(file); v->y = PHYSFSX_readFix(file); v->z = PHYSFSX_readFix(file); } static inline void PHYSFSX_readAngleVec(vms_angvec *v, PHYSFS_file *file) { v->p = PHYSFSX_readFixAng(file); v->b = PHYSFSX_readFixAng(file); v->h = PHYSFSX_readFixAng(file); } static inline void PHYSFSX_readMatrix(vms_matrix *m,PHYSFS_file *file) { PHYSFSX_readVector(&m->rvec,file); PHYSFSX_readVector(&m->uvec,file); PHYSFSX_readVector(&m->fvec,file); } #define PHYSFSX_contfile_init PHYSFSX_addRelToSearchPath #define PHYSFSX_contfile_close PHYSFSX_removeRelFromSearchPath extern int PHYSFSX_addRelToSearchPath(const char *relname, int add_to_end); extern int PHYSFSX_removeRelFromSearchPath(const char *relname); extern int PHYSFSX_fsize(const char *hogname); extern void PHYSFSX_listSearchPathContent(); extern int PHYSFSX_checkSupportedArchiveTypes(); extern int PHYSFSX_getRealPath(const char *stdPath, char *realPath); extern int PHYSFSX_isNewPath(const char *path); extern int PHYSFSX_rename(const char *oldpath, const char *newpath); extern char **PHYSFSX_findFiles(const char *path, const char *const *exts); extern char **PHYSFSX_findabsoluteFiles(const char *path, const char *realpath, const char *const *exts); extern PHYSFS_sint64 PHYSFSX_getFreeDiskSpace(); extern int PHYSFSX_exists(const char *filename, int ignorecase); extern PHYSFS_file *PHYSFSX_openReadBuffered(const char *filename); extern PHYSFS_file *PHYSFSX_openWriteBuffered(const char *filename); extern void PHYSFSX_addArchiveContent(); extern void PHYSFSX_removeArchiveContent(); #endif /* PHYSFSX_H */ dxx-rebirth-0.58.1-d2x/include/pngfile.h000066400000000000000000000005521217717237500177760ustar00rootroot00000000000000#ifndef PNGFILE_H #define PNGFILE_H typedef struct _png_data { unsigned int width; unsigned int height; unsigned int depth; unsigned int channels; unsigned paletted:1; unsigned color:1; unsigned alpha:1; unsigned char *data; unsigned char *palette; unsigned int num_palette; } png_data; extern int read_png(char *filename, png_data *pdata); #endif dxx-rebirth-0.58.1-d2x/include/pstypes.h000066400000000000000000000042161217717237500200620ustar00rootroot00000000000000/* * * Common types and defines * */ #ifndef _TYPES_H #define _TYPES_H #ifndef macintosh #include #endif #include // define a dboolean typedef int dboolean; //define a signed byte typedef signed char sbyte; //define unsigned types; typedef unsigned char ubyte; #if defined(_WIN32) || defined(macintosh) typedef unsigned short ushort; typedef unsigned int uint; #endif #if defined(_WIN32) || defined(__sun__) // platforms missing (u_)int??_t # include #elif defined(macintosh) // misses (u_)int??_t and does not like SDL_types.h # include typedef SInt16 int16_t; typedef SInt32 int32_t; typedef SInt64 int64_t; typedef UInt16 u_int16_t; typedef UInt32 u_int32_t; typedef UInt64 u_int64_t; #endif // macintosh #if defined(_WIN32) || defined(__sun__) // platforms missing u_int??_t typedef Uint16 u_int16_t; typedef Uint32 u_int32_t; typedef Uint64 u_int64_t; #endif // defined(_WIN32) || defined(__sun__) #ifdef _MSC_VER # include // this is where min and max are defined #endif #ifndef min #define min(a,b) (((a)>(b))?(b):(a)) #endif #ifndef max #define max(a,b) (((a)<(b))?(b):(a)) #endif #ifndef PATH_MAX #define PATH_MAX 4096 #endif #ifndef bool //define a boolean typedef ubyte bool; #endif #ifndef NULL #define NULL 0 #endif // the following stuff has nothing to do with types but needed everywhere, // and since this file is included everywhere, it's here. #if defined(__i386__) || defined(__ia64__) || defined(_WIN32) || \ (defined(__alpha__) || defined(__alpha)) || \ defined(__arm__) || defined(ARM) || \ (defined(__mips__) && defined(__MIPSEL__)) || \ defined(__SYMBIAN32__) || \ defined(__x86_64__) || \ defined(__LITTLE_ENDIAN__) // from physfs_internal.h //# define WORDS_BIGENDIAN 0 #else # define WORDS_BIGENDIAN 1 #endif #ifdef __GNUC__ # define __pack__ __attribute__((packed)) #elif defined(_MSC_VER) # pragma pack(push, packing) # pragma pack(1) # define __pack__ #elif defined(macintosh) # pragma options align=packed # define __pack__ #else # error "This program will not work without packed structures" #endif #ifdef _MSC_VER # define inline __inline #endif #endif //_TYPES_H dxx-rebirth-0.58.1-d2x/include/rbaudio.h000066400000000000000000000042321217717237500177760ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifndef _RBAUDIO_H #define _RBAUDIO_H #define RBA_MEDIA_CHANGED -1 typedef struct _RBACHANNELCTL { unsigned int out0in, out0vol; unsigned int out1in, out1vol; unsigned int out2in, out2vol; unsigned int out3in, out3vol; } RBACHANNELCTL; extern void RBAInit(void); extern void RBAExit(); extern long RBAGetDeviceStatus(void); extern int RBAPlayTrack(int track); extern int RBAPlayTracks(int first, int last, void (*hook_finished)(void)); //plays tracks first through last, inclusive extern int RBACheckMediaChange(); extern long RBAGetHeadLoc(int *min, int *sec, int *frame); extern int RBAPeekPlayStatus(void); extern void RBAStop(void); extern void RBAEjectDisk(void); extern void RBASetStereoAudio(RBACHANNELCTL *channels); extern void RBASetQuadAudio(RBACHANNELCTL *channels); extern void RBAGetAudioInfo(RBACHANNELCTL *channels); extern void RBASetChannelVolume(int channel, int volume); extern void RBASetVolume(int volume); extern int RBAEnabled(void); extern void RBADisable(void); extern void RBAEnable(void); extern int RBAGetNumberOfTracks(void); extern void RBACheckFinishedHook(); extern void RBAPause(); extern int RBAResume(); extern int RBAPauseResume(); //return the track number currently playing. Useful if RBAPlayTracks() //is called. Returns 0 if no track playing, else track number int RBAGetTrackNum(); // get the cddb discid for the current cd. unsigned long RBAGetDiscID(); // List the tracks on the CD void RBAList(void); #endif dxx-rebirth-0.58.1-d2x/include/rle.h000066400000000000000000000030531217717237500171330ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Protypes for rle functions. * */ #ifndef _RLE_H #define _RLE_H #include "pstypes.h" #include "gr.h" void gr_rle_decode( ubyte * src, ubyte * dest ); int gr_rle_encode( int org_size, ubyte *src, ubyte *dest ); int gr_rle_getsize( int org_size, ubyte *src ); ubyte * gr_rle_find_xth_pixel( ubyte *src, int x,int * count, ubyte color ); int gr_bitmap_rle_compress( grs_bitmap * bmp ); void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 ); void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 ); grs_bitmap * rle_expand_texture( grs_bitmap * bmp ); void rle_cache_close(); void rle_cache_flush(); void rle_swap_0_255(grs_bitmap *bmp); void rle_remap(grs_bitmap *bmp, ubyte *colormap); void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2 ); #endif dxx-rebirth-0.58.1-d2x/include/strio.h000066400000000000000000000002511217717237500175060ustar00rootroot00000000000000/* fileio.c in /misc for d1x file reading */ #ifndef _STRIO_H #define _STRIO_H char* fgets_unlimited(PHYSFS_file *f); char *splitword(char *s, char splitchar); #endif dxx-rebirth-0.58.1-d2x/include/strutil.h000066400000000000000000000031351217717237500200600ustar00rootroot00000000000000#ifndef _STRUTILS_H #define _STRUTILS_H #if defined(macintosh) extern void snprintf(char *out_string, int size, char * format, ... ); #endif extern int d_stricmp( const char *s1, const char *s2 ); extern int d_strnicmp( const char *s1, const char *s2, int n ); extern void d_strlwr( char *s1 ); extern void d_strupr( char *s1 ); extern void d_strrev( char *s1 ); extern char *d_strdup(char *str); // remove extension from filename, doesn't work with paths. void removeext(const char *filename, char *out); //give a filename a new extension, doesn't work with paths with no extension already there extern void change_filename_extension( char *dest, const char *src, char *new_ext ); extern void d_splitpath(char *name, char *drive, char *path, char *base, char *ext); // create a growing 2D array with a single growing buffer for the text // this system is likely to cause less memory fragmentation than having one malloc'd buffer per string int string_array_new(char ***list, char **list_buf, int *num_str, int *max_str, int *max_buf); // add a string to a growing 2D array int string_array_add(char ***list, char **list_buf, int *num_str, int *max_str, int *max_buf, const char *str); // sort function passed to qsort - also useful for 2d string arrays with individual string pointers int string_array_sort_func(char **e0, char **e1); // reallocate pointers to save memory, sort list alphabetically and remove duplicates according to 'comp' void string_array_tidy(char ***list, char **list_buf, int *num_str, int *max_str, int *max_buf, int offset, int (*comp)( const char *, const char * )); #endif /* _STRUTILS_H */ dxx-rebirth-0.58.1-d2x/include/texmap.h000066400000000000000000000113241217717237500176470ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * $Source: /cvsroot/dxx-rebirth/d2x-rebirth/include/texmap.h,v $ * $Revision: 1.1.1.1 $ * $Author: zicodxx $ * $Date: 2006/03/17 20:01:30 $ * * Include file for entities using texture mapper library. * */ #ifndef _TEXMAP_H #define _TEXMAP_H #include "fix.h" #include "3d.h" #include "gr.h" #define NUM_LIGHTING_LEVELS 32 #define MAX_TMAP_VERTS 25 #define MAX_LIGHTING_VALUE ((NUM_LIGHTING_LEVELS-1)*F1_0/NUM_LIGHTING_LEVELS) #define MIN_LIGHTING_VALUE (F1_0/NUM_LIGHTING_LEVELS) #define FIX_RECIP_TABLE_SIZE 641 //increased from 321 to 641, since this res is now quite achievable.. slight fps boost -MM // ------------------------------------------------------------------------------------------------------- extern fix compute_lighting_value(g3s_point *vertptr); // ------------------------------------------------------------------------------------------------------- // This is the main texture mapper call. // tmap_num references a texture map defined in Texmap_ptrs. // nverts = number of vertices // vertbuf is a pointer to an array of vertex pointers extern void draw_tmap(grs_bitmap *bp, int nverts, g3s_point **vertbuf); //function that takes the same parms as draw_tmap, but renders as flat poly //we need this to do the cloaked effect extern void draw_tmap_flat(grs_bitmap *bp,int nverts,g3s_point **vertbuf); // ------------------------------------------------------------------------------------------------------- // Texture map vertex. // The fields r,g,b and l are mutually exclusive. r,g,b are used for rgb lighting. // l is used for intensity based lighting. typedef struct g3ds_vertex { fix x,y,z; fix u,v; fix x2d,y2d; fix l; fix r,g,b; } g3ds_vertex; // A texture map is defined as a polygon with u,v coordinates associated with // one point in the polygon, and a pair of vectors describing the orientation // of the texture map in the world, from which the deltas Du_dx, Dv_dy, etc. // are computed. typedef struct g3ds_tmap { int nv; // number of vertices g3ds_vertex verts[MAX_TMAP_VERTS]; // up to 8 vertices, this is inefficient, change } g3ds_tmap; // ------------------------------------------------------------------------------------------------------- // Note: Not all interpolation method and lighting combinations are supported. // Set Interpolation_method to 0/1/2 for linear/linear, perspective/linear, perspective/perspective extern int Interpolation_method; // Set Lighting_on to 0/1/2 for no lighting/intensity lighting/rgb lighting extern int Lighting_on; // HACK INTERFACE: how far away the current segment (& thus texture) is extern int Current_seg_depth; extern int Max_flat_depth; // Deepest segment at which flat shading will be used. (If not flat shading, then what?) // These are pointers to texture maps. If you want to render texture map #7, then you will render // the texture map defined by Texmap_ptrs[7]. extern grs_bitmap Texmap_ptrs[]; extern grs_bitmap Texmap4_ptrs[]; // Interface for sky renderer extern void texture_map_lin_lin_sky(grs_bitmap *srcb, g3ds_tmap *t); extern void texture_map_lin_lin_sky_v(grs_bitmap *srcb, g3ds_tmap *t); extern void texture_map_hyp_lin_v(grs_bitmap *srcb, g3ds_tmap *t); extern void ntexture_map_lighted_linear(grs_bitmap *srcb, g3ds_tmap *t); // This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible // (ie, avoids cracking) edge/delta computation. void gr_upoly_tmap(int nverts, int *vert ); //This is like gr_upoly_tmap() but instead of drawing, it calls the specified //function with ylr values void gr_upoly_tmap_ylr(int nverts, int *vert, void (*ylr_func)(int, fix, fix) ); extern int Transparency_on,per2_flag; // Set to !0 to enable Sim City 2000 (or Eric's Drive Through, or Eric's Game) specific code. extern int SC2000; extern int Window_clip_left, Window_clip_bot, Window_clip_right, Window_clip_top; // for ugly hack put in to be sure we don't overflow render buffer #define FIX_XLIMIT (639 * F1_0) #define FIX_YLIMIT (479 * F1_0) extern void init_interface_vars_to_assembler(void); #endif dxx-rebirth-0.58.1-d2x/include/timer.h000066400000000000000000000017011217717237500174670ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for timer functions * */ #ifndef _TIMER_H #define _TIMER_H #include "pstypes.h" #include "fix.h" void timer_update(); fix64 timer_query(); void timer_delay(fix seconds); void timer_delay2(int fps); #endif dxx-rebirth-0.58.1-d2x/include/u_mem.h000066400000000000000000000044121217717237500174530ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #ifndef _U_MEM_H #define _U_MEM_H #include #define MEM_K 1.5 // Dynamic array growth factor void mem_init(void); #if !defined(NDEBUG) void mem_display_blocks(); extern void * mem_malloc( unsigned int size, const char * var, const char * file, unsigned line); void * mem_calloc( size_t nmemb, size_t size, const char * var, const char * filename, unsigned line); extern void * mem_realloc( void * buffer, unsigned int size, const char * var, const char * file, int line ); extern void mem_free( void * buffer ); /* DPH: Changed malloc, etc. to d_malloc. Overloading system calls is very evil and error prone */ // Checks to see if any blocks are overwritten void mem_validate_heap(); #define mem_calloc(nmemb,size,var,file,line) ((mem_calloc)((size) ? (nmemb) : 0, (size), (var), (file), (line))) #else #define mem_malloc(size,var,file,line) malloc((size)) #define mem_calloc(nmemb,size,var,file,line) calloc((nmemb), (size)) #define mem_realloc(ptr,size,var,file,line) realloc((ptr),(size)) #define mem_free free #endif #define MALLOC( var, type, count ) (var=(type *)mem_malloc((count)*sizeof(type),#var, __FILE__,__LINE__ )) #define CALLOC( var, type, count ) (var=(type *)mem_calloc((count),sizeof(type),#var, __FILE__,__LINE__ )) #define d_malloc(size) mem_malloc((size),"Unknown", __FILE__,__LINE__ ) #define d_calloc(nmemb,size) mem_calloc((nmemb),(size),"Unknown", __FILE__,__LINE__ ) #define d_realloc(ptr,size) mem_realloc((ptr),(size),"Unknown", __FILE__,__LINE__ ) #define d_free(ptr) (mem_free(ptr), ptr=NULL) #endif // _U_MEM_H dxx-rebirth-0.58.1-d2x/include/ui.h000066400000000000000000000276411217717237500167770ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header file for user interface * */ #ifndef _UI_H #define _UI_H struct d_event; enum event_type; struct window; typedef struct { char description[100]; char * buttontext[17]; int numkeys; short keycode[100]; int function_number[100]; } UI_KEYPAD; typedef struct { unsigned int frame; int type; int data; } UI_EVENT; #define BASE_GADGET \ short kind; \ struct _gadget * prev; \ struct _gadget * next; \ struct _gadget * when_tab; \ struct _gadget * when_btab; \ struct _gadget * when_up; \ struct _gadget * when_down; \ struct _gadget * when_left; \ struct _gadget * when_right; \ struct _gadget * parent; \ int status; \ int oldstatus; \ grs_canvas * canvas; \ int hotkey; \ short x1,y1,x2,y2; typedef struct _gadget { BASE_GADGET unsigned char rsvd[256]; } UI_GADGET; typedef struct { BASE_GADGET int trap_key; int (*user_function)(void); } UI_GADGET_KEYTRAP; typedef struct { BASE_GADGET short width, height; short b1_held_down; short b1_clicked; short b1_double_clicked; short b1_dragging; short b1_drag_x1, b1_drag_y1; short b1_drag_x2, b1_drag_y2; short b1_done_dragging; int keypress; short mouse_onme; short mouse_x, mouse_y; grs_bitmap * bitmap; } UI_GADGET_USERBOX; typedef struct { BASE_GADGET short width, height; char * text; short position; short oldposition; short pressed; int (*user_function)(void); int (*user_function1)(void); int hotkey1; int dim_if_no_function; } UI_GADGET_BUTTON; typedef struct { BASE_GADGET short width, height; char * text; short length; short slength; short position; short oldposition; short pressed; short first_time; } UI_GADGET_INPUTBOX; typedef struct { BASE_GADGET short width, height; char * text; short position; short oldposition; short pressed; short group; short flag; } UI_GADGET_RADIO; typedef struct { BASE_GADGET char *text; short width, height; sbyte flag; sbyte pressed; sbyte position; sbyte oldposition; int trap_key; int (*user_function)(void); } UI_GADGET_ICON; typedef struct { BASE_GADGET short width, height; char * text; short position; short oldposition; short pressed; short group; short flag; } UI_GADGET_CHECKBOX; typedef struct { BASE_GADGET short horz; short width, height; int start; int stop; int position; int window_size; int fake_length; int fake_position; int fake_size; UI_GADGET_BUTTON * up_button; UI_GADGET_BUTTON * down_button; fix64 last_scrolled; short drag_x, drag_y; int drag_starting; int dragging; int moved; } UI_GADGET_SCROLLBAR; typedef struct { BASE_GADGET short width, height; char **list; int num_items; int num_items_displayed; int first_item; int old_first_item; int current_item; int selected_item; int old_current_item; fix64 last_scrolled; int dragging; int textheight; UI_GADGET_SCROLLBAR * scrollbar; int moved; } UI_GADGET_LISTBOX; enum dialog_flags { DF_BORDER = 1, DF_FILLED = 2, DF_SAVE_BG = 4, DF_DIALOG = (4+2+1), DF_MODAL = 8 // modal = accept all user input exclusively }; typedef struct _ui_window { struct window *wind; int (*callback)(struct _ui_window *, struct d_event *, void *); UI_GADGET * gadget; UI_GADGET * keyboard_focus_gadget; void *userdata; short x, y; short width, height; short text_x, text_y; enum dialog_flags flags; } UI_DIALOG; #define B1_JUST_PRESSED (event->type == EVENT_MOUSE_BUTTON_DOWN && event_mouse_get_button(event) == 0) #define B1_JUST_RELEASED (event->type == EVENT_MOUSE_BUTTON_UP && event_mouse_get_button(event) == 0) #define B1_DOUBLE_CLICKED (event->type == EVENT_MOUSE_DOUBLE_CLICKED && event_mouse_get_button(event) == 0) extern grs_font * ui_small_font; extern unsigned char CBLACK,CGREY,CWHITE,CBRIGHT,CRED; extern UI_GADGET * selected_gadget; extern void Hline(short x1, short x2, short y ); extern void Vline(short y1, short y2, short x ); extern void ui_string_centered( short x, short y, char * s ); extern void ui_draw_box_out( short x1, short y1, short x2, short y2 ); extern void ui_draw_box_in( short x1, short y1, short x2, short y2 ); extern void ui_draw_line_in( short x1, short y1, short x2, short y2 ); extern void ui_draw_frame( short x1, short y1, short x2, short y2 ); extern void ui_draw_shad( short x1, short y1, short x2, short y2, short c1, short c2 ); void ui_init(); void ui_close(); int ui_messagebox( short x, short y, int NumButtons, char * text, ... ); void ui_string_centered( short x, short y, char * s ); int PopupMenu( int NumItems, char * text[] ); extern UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, enum dialog_flags flags, int (*callback)(UI_DIALOG *, struct d_event *, void *), void *userdata ); extern struct window *ui_dialog_get_window(UI_DIALOG *dlg); extern void ui_dialog_set_current_canvas(UI_DIALOG *dlg); extern void ui_close_dialog( UI_DIALOG * dlg ); #define GADGET_PRESSED(g) ((event->type == EVENT_UI_GADGET_PRESSED) && (ui_event_get_gadget(event) == (UI_GADGET *)g)) extern UI_GADGET * ui_gadget_add( UI_DIALOG * dlg, short kind, short x1, short y1, short x2, short y2 ); extern UI_GADGET_BUTTON * ui_add_gadget_button( UI_DIALOG * dlg, short x, short y, short w, short h, char * text, int (*function_to_call)(void) ); extern void ui_gadget_delete_all( UI_DIALOG * dlg ); extern int ui_gadget_send_event(UI_DIALOG *dlg, enum event_type type, UI_GADGET *gadget); extern UI_GADGET *ui_event_get_gadget(struct d_event *event); extern int ui_dialog_do_gadgets( UI_DIALOG * dlg, struct d_event *event ); extern void ui_draw_button( UI_DIALOG *dlg, UI_GADGET_BUTTON * button ); extern int ui_mouse_on_gadget( UI_GADGET * gadget ); extern int ui_button_do( UI_DIALOG *dlg, UI_GADGET_BUTTON * button, struct d_event *event ); extern int ui_listbox_do( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox, struct d_event *event ); extern void ui_draw_listbox( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox ); extern UI_GADGET_LISTBOX *ui_add_gadget_listbox(UI_DIALOG *dlg, short x, short y, short w, short h, short numitems, char **list); extern void ui_mega_process(); extern void ui_get_button_size( char * text, int * width, int * height ); extern UI_GADGET_SCROLLBAR * ui_add_gadget_scrollbar( UI_DIALOG * dlg, short x, short y, short w, short h, int start, int stop, int position, int window_size ); extern int ui_scrollbar_do( UI_DIALOG *dlg, UI_GADGET_SCROLLBAR * scrollbar, struct d_event *event ); extern void ui_draw_scrollbar( UI_DIALOG *dlg, UI_GADGET_SCROLLBAR * scrollbar ); extern void ui_dprintf( UI_DIALOG * dlg, char * format, ... ); extern void ui_dprintf_at( UI_DIALOG * dlg, short x, short y, char * format, ... ); extern void ui_draw_radio( UI_DIALOG *dlg, UI_GADGET_RADIO * radio ); extern UI_GADGET_RADIO * ui_add_gadget_radio( UI_DIALOG * dlg, short x, short y, short w, short h, short group, char * text ); extern int ui_radio_do( UI_DIALOG *dlg, UI_GADGET_RADIO * radio, struct d_event *event ); extern void ui_radio_set_value(UI_GADGET_RADIO *radio, int value); extern void ui_draw_checkbox( UI_DIALOG *dlg, UI_GADGET_CHECKBOX * checkbox ); extern UI_GADGET_CHECKBOX * ui_add_gadget_checkbox( UI_DIALOG * dlg, short x, short y, short w, short h, short group, char * text ); extern int ui_checkbox_do( UI_DIALOG *dlg, UI_GADGET_CHECKBOX * checkbox, struct d_event *event ); extern void ui_checkbox_check(UI_GADGET_CHECKBOX * checkbox, int check); extern UI_GADGET * ui_gadget_get_prev( UI_GADGET * gadget ); extern UI_GADGET * ui_gadget_get_next( UI_GADGET * gadget ); extern void ui_gadget_calc_keys( UI_DIALOG * dlg); extern void ui_listbox_change(UI_DIALOG *dlg, UI_GADGET_LISTBOX *listbox, short numitems, char **list); extern void ui_draw_inputbox( UI_DIALOG *dlg, UI_GADGET_INPUTBOX * inputbox ); extern UI_GADGET_INPUTBOX * ui_add_gadget_inputbox( UI_DIALOG * dlg, short x, short y, short w, short h, char * text ); extern int ui_inputbox_do( UI_DIALOG *dlg, UI_GADGET_INPUTBOX * inputbox, struct d_event *event ); extern void ui_inputbox_set_text(UI_GADGET_INPUTBOX *inputbox, char *text); extern int ui_userbox_do( UI_DIALOG *dlg, UI_GADGET_USERBOX * userbox, struct d_event *event ); extern UI_GADGET_USERBOX * ui_add_gadget_userbox( UI_DIALOG * dlg, short x, short y, short w, short h ); extern void ui_draw_userbox( UI_DIALOG *dlg, UI_GADGET_USERBOX * userbox ); extern int MenuX( int x, int y, int NumButtons, char * text[] ); char **file_getdirlist(int *NumFiles, char *dir); char **file_getfilelist(int *NumDirs, char *filespec, char *dir); int ui_get_filename( char * filename, char * Filespec, char * message ); void * ui_malloc( int size ); void ui_free( void * buffer ); UI_GADGET_KEYTRAP * ui_add_gadget_keytrap( UI_DIALOG * dlg, int key_to_trap, int (*function_to_call)(void) ); int ui_keytrap_do( UI_GADGET_KEYTRAP * keytrap, struct d_event *event ); #define UI_RECORD_MOUSE 1 #define UI_RECORD_KEYS 2 #define UI_STATUS_NORMAL 0 #define UI_STATUS_RECORDING 1 #define UI_STATUS_PLAYING 2 #define UI_STATUS_FASTPLAY 3 int ui_record_events( int NumberOfEvents, UI_EVENT * buffer, int Flags ); int ui_play_events_realtime( int NumberOfEvents, UI_EVENT * buffer ); int ui_play_events_fast( int NumberOfEvents, UI_EVENT * buffer ); int ui_recorder_status(); void ui_set_playback_speed( int speed ); extern unsigned int ui_number_of_events; extern unsigned int ui_event_counter; int ui_get_file( char * filename, char * Filespec ); int ui_messagebox_n( short xc, short yc, int NumButtons, char * text, char * Button[] ); void ui_draw_icon( UI_GADGET_ICON * icon ); int ui_icon_do( UI_DIALOG *dlg, UI_GADGET_ICON * icon, struct d_event *event ); UI_GADGET_ICON * ui_add_gadget_icon( UI_DIALOG * dlg, char * text, short x, short y, short w, short h, int k,int (*f)(void) ); int GetKeyCode(char * text); int DecodeKeyText( char * text ); void GetKeyDescription( char * text, int keypress ); extern void menubar_init(char * filename ); extern void menubar_close(); extern void menubar_hide(); extern void menubar_show(); void ui_pad_init(); void ui_pad_close(); void ui_pad_activate( UI_DIALOG * dlg, int x, int y ); void ui_pad_deactivate(); void ui_pad_goto(int n); void ui_pad_goto_next(); void ui_pad_goto_prev(); void ui_pad_read( int n, char * filename ); int ui_pad_get_current(); void ui_pad_draw(UI_DIALOG *dlg, int x, int y); void ui_barbox_open( char * text, int length ); void ui_barbox_update( int position ); void ui_barbox_close(); extern int ui_button_any_drawn; #endif dxx-rebirth-0.58.1-d2x/include/vecmat.h000066400000000000000000000311231217717237500176270ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header file for vector/matrix library * */ #ifndef _VECMAT_H #define _VECMAT_H #include "maths.h" //#define INLINE 1 //are some of these functions inline? //The basic fixed-point vector. Access elements by name or position typedef struct vms_vector { fix x, y, z; } __pack__ vms_vector; typedef struct vms_vector_array { fix xyz[3]; } __pack__ vms_vector_array; //Short vector, used for pre-rotation points. //Access elements by name or position typedef struct vms_svec { short sv_x, sv_y, sv_z; } __pack__ vms_svec; //Angle vector. Used to store orientations typedef struct vms_angvec { fixang p, b, h; } __pack__ vms_angvec; //A 3x3 rotation matrix. Sorry about the numbering starting with one. //Ordering is across then down, so is the first row typedef struct vms_matrix { vms_vector rvec, uvec, fvec; } __pack__ vms_matrix; // Quaternion structure typedef struct vms_quaternion { signed short w, x, y, z; } __pack__ vms_quaternion; //Macros/functions to fill in fields of structures //macro to check if vector is zero #define IS_VEC_NULL(v) (v->x == 0 && v->y == 0 && v->z == 0) //macro to set a vector to zero. we could do this with an in-line assembly //macro, but it's probably better to let the compiler optimize it. //Note: NO RETURN VALUE #define vm_vec_zero(v) (v)->x=(v)->y=(v)->z=0 //macro set set a matrix to the identity. Note: NO RETURN VALUE // DPH (18/9/98): Begin mod to fix linefeed problem under linux. Uses an // inline function instead of a multi-line macro to fix CR/LF problems. #ifdef __unix__ static inline void vm_set_identity(vms_matrix *m) { m->rvec.x = m->uvec.y = m->fvec.z = f1_0; m->rvec.y = m->rvec.z = m->uvec.x = m->uvec.z = m->fvec.x = m->fvec.y = 0; } #else #define vm_set_identity(m) do {m->rvec.x = m->uvec.y = m->fvec.z = f1_0; \ m->rvec.y = m->rvec.z = \ m->uvec.x = m->uvec.z = \ m->fvec.x = m->fvec.y = 0;} while (0) #endif // DPH (19/8/98): End changes. vms_vector * vm_vec_make (vms_vector * v, fix x, fix y, fix z); #ifdef __WATCOMC__ #pragma aux vm_vec_make "*_" parm [eax] [edx] [ebx] [ecx] value [eax] modify exact [] = \ "mov 0[eax],edx" \ "mov 4[eax],ebx" \ "mov 8[eax],ecx"; #endif vms_angvec * vm_angvec_make (vms_angvec * v, fixang p, fixang b, fixang h); #ifdef __WATCOMC__ #pragma aux vm_angvec_make "*_" parm [eax] [dx] [bx] [cx] value [eax] modify exact [] = \ "mov 0[eax],dx" \ "mov 2[eax],bx" \ "mov 4[eax],cx"; #endif //Global constants extern const vms_vector vmd_zero_vector; extern const vms_matrix vmd_identity_matrix; //Here's a handy constant #define ZERO_VECTOR {0,0,0} #define IDENTITY_MATRIX { {f1_0,0,0}, {0,f1_0,0}, {0,0,f1_0} } //#define vm_vec_make(v,_x,_y,_z) (((v)->x=(_x), (v)->y=(_y), (v)->z=(_z)), (v)) //#pragma off (unreferenced) ////make this local, so compiler can in-line it //static vms_vector *vm_vec_make(vms_vector *v,fix x,fix y,fix z) //{ // v->x = x; // v->y = y; // v->z = z; // // return v; //} //#pragma on (unreferenced) ////macro to fill in elements of a matrix, also for Mike /* #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \ do { (m)->m1=(_m1); (m)->m2=(_m2); (m)->m3=(_m3); \ (m)->m4=(_m4); (m)->m5=(_m5); (m)->m6=(_m6); \ (m)->m7=(_m7); (m)->m8=(_m8); (m)->m9=(_m9);} while (0) */ #if 0 //kill this, since bogus with new matrix ordering //macro to fill in elements of a matrix, also for Mike #define vm_mat_make(m,_m1,_m2,_m3,_m4,_m5,_m6,_m7,_m8,_m9) \ (((m)->m1 = (_m1), (m)->m2 = (_m2), (m)->m3 = (_m3), \ (m)->m4 = (_m4), (m)->m5 = (_m5), (m)->m6 = (_m6), \ (m)->m7 = (_m7), (m)->m8 = (_m8), (m)->m9 = (_m9)), (m)) #endif /* 0 */ ////fills in fields of an angle vector //#define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v)) //negate a vector #define vm_vec_negate(v) do {(v)->x = - (v)->x; (v)->y = - (v)->y; (v)->z = - (v)->z;} while (0); //Functions in library #ifndef INLINE //adds two vectors, fills in dest, returns ptr to dest //ok for dest to equal either source, but should use vm_vec_add2() if so vms_vector * vm_vec_add (vms_vector * dest, const vms_vector * src0, const vms_vector * src1); //subs two vectors, fills in dest, returns ptr to dest //ok for dest to equal either source, but should use vm_vec_sub2() if so vms_vector * vm_vec_sub (vms_vector * dest, const vms_vector * src0, const vms_vector * src1); //adds one vector to another. returns ptr to dest //dest can equal source vms_vector * vm_vec_add2 (vms_vector * dest, const vms_vector * src); //subs one vector from another, returns ptr to dest //dest can equal source vms_vector * vm_vec_sub2 (vms_vector * dest, const vms_vector * src); #else /* INLINE */ #define vm_vec_add(dest,src0,src1) do { \ (dest)->x = (src0)->x + (src1)->x; \ (dest)->y = (src0)->y + (src1)->y; \ (dest)->z = (src0)->z + (src1)->z; \ } while (0); #define vm_vec_sub(dest,src0,src1) do { \ (dest)->x = (src0)->x - (src1)->x; \ (dest)->y = (src0)->y - (src1)->y; \ (dest)->z = (src0)->z - (src1)->z; \ } while (0); #define vm_vec_add2(dest,src) do { \ (dest)->x += (src)->x; \ (dest)->y += (src)->y; \ (dest)->z += (src)->z; \ } while (0); #define vm_vec_sub2(dest,src) do { \ (dest)->x -= (src)->x; \ (dest)->y -= (src)->y; \ (dest)->z -= (src)->z; \ } while (0); #endif /* INLINE */ //averages two vectors. returns ptr to dest //dest can equal either source vms_vector * vm_vec_avg (vms_vector * dest, const vms_vector * src0, const vms_vector * src1); //averages four vectors. returns ptr to dest //dest can equal any source vms_vector * vm_vec_avg4 (vms_vector * dest, const vms_vector * src0, const vms_vector * src1, const vms_vector * src2, const vms_vector * src3); //scales a vector in place. returns ptr to vector vms_vector * vm_vec_scale (vms_vector * dest, fix s); //scales and copies a vector. returns ptr to dest vms_vector * vm_vec_copy_scale (vms_vector * dest, const vms_vector * src, fix s); //scales a vector, adds it to another, and stores in a 3rd vector //dest = src1 + k * src2 vms_vector * vm_vec_scale_add (vms_vector * dest, const vms_vector * src1, const vms_vector * src2, fix k); //scales a vector and adds it to another //dest += k * src vms_vector * vm_vec_scale_add2 (vms_vector * dest, const vms_vector * src, fix k); //scales a vector in place, taking n/d for scale. returns ptr to vector //dest *= n/d vms_vector * vm_vec_scale2 (vms_vector * dest, fix n, fix d); //returns magnitude of a vector fix vm_vec_mag (const vms_vector * v); //computes the distance between two points. (does sub and mag) fix vm_vec_dist (const vms_vector * v0, const vms_vector * v1); //computes an approximation of the magnitude of the vector //uses dist = largest + next_largest*3/8 + smallest*3/16 fix vm_vec_mag_quick (const vms_vector * v); //computes an approximation of the distance between two points. //uses dist = largest + next_largest*3/8 + smallest*3/16 fix vm_vec_dist_quick (const vms_vector * v0, const vms_vector * v1); //normalize a vector. returns mag of source vec fix vm_vec_copy_normalize (vms_vector * dest, const vms_vector * src); fix vm_vec_normalize (vms_vector * v); //normalize a vector. returns mag of source vec. uses approx mag fix vm_vec_copy_normalize_quick (vms_vector * dest, const vms_vector * src); fix vm_vec_normalize_quick (vms_vector * v); //return the normalized direction vector between two points //dest = normalized(end - start). Returns mag of direction vector //NOTE: the order of the parameters matches the vector subtraction fix vm_vec_normalized_dir (vms_vector * dest, const vms_vector * end, const vms_vector * start); fix vm_vec_normalized_dir_quick (vms_vector * dest, const vms_vector * end, const vms_vector * start); ////returns dot product of two vectors fix vm_vec_dotprod (const vms_vector * v0, const vms_vector * v1); #define vm_vec_dot(v0,v1) vm_vec_dotprod((v0),(v1)) #ifdef INLINE #ifdef __WATCOMC__ #pragma aux vm_vec_dotprod parm [esi] [edi] value [eax] modify exact [eax ebx ecx edx] = \ "mov eax,[esi]" \ "imul dword ptr [edi]" \ "mov ebx,eax" \ "mov ecx,edx" \ \ "mov eax,4[esi]" \ "imul dword ptr 4[edi]" \ "add ebx,eax" \ "adc ecx,edx" \ \ "mov eax,8[esi]" \ "imul dword ptr 8[edi]" \ "add eax,ebx" \ "adc edx,ecx" \ \ "shrd eax,edx,16"; #endif #endif /* INLINE */ //computes cross product of two vectors. returns ptr to dest //dest CANNOT equal either source vms_vector * vm_vec_crossprod (vms_vector * dest, const vms_vector * src0, const vms_vector * src1); #define vm_vec_cross(dest,src0,src1) vm_vec_crossprod((dest),(src0),(src1)) //computes surface normal from three points. result is normalized //returns ptr to dest //dest CANNOT equal either source vms_vector * vm_vec_normal (vms_vector * dest, const vms_vector * p0, const vms_vector * p1, const vms_vector * p2); //computes non-normalized surface normal from three points. //returns ptr to dest //dest CANNOT equal either source vms_vector * vm_vec_perp (vms_vector * dest, const vms_vector * p0, const vms_vector * p1, const vms_vector * p2); //computes the delta angle between two vectors. //vectors need not be normalized. if they are, call vm_vec_delta_ang_norm() //the forward vector (third parameter) can be NULL, in which case the absolute //value of the angle in returned. Otherwise the angle around that vector is //returned. fixang vm_vec_delta_ang (const vms_vector * v0, const vms_vector * v1, const vms_vector * fvec); //computes the delta angle between two normalized vectors. fixang vm_vec_delta_ang_norm (const vms_vector * v0, const vms_vector * v1, const vms_vector * fvec); //computes a matrix from a set of three angles. returns ptr to matrix vms_matrix * vm_angles_2_matrix (vms_matrix * m, const vms_angvec * a); //computes a matrix from a forward vector and an angle vms_matrix * vm_vec_ang_2_matrix (vms_matrix * m, const vms_vector * v, fixang a); //computes a matrix from one or more vectors. The forward vector is required, //with the other two being optional. If both up & right vectors are passed, //the up vector is used. If only the forward vector is passed, a bank of //zero is assumed //returns ptr to matrix vms_matrix * vm_vector_2_matrix (vms_matrix * m, vms_vector * fvec, vms_vector * uvec, vms_vector * rvec); //rotates a vector through a matrix. returns ptr to dest vector //dest CANNOT equal either source vms_vector * vm_vec_rotate (vms_vector * dest, const vms_vector * src, const vms_matrix * m); //transpose a matrix in place. returns ptr to matrix vms_matrix * vm_transpose_matrix (vms_matrix * m); #define vm_transpose(m) vm_transpose_matrix(m) //copy and transpose a matrix. returns ptr to matrix //dest CANNOT equal source. use vm_transpose_matrix() if this is the case vms_matrix * vm_copy_transpose_matrix (vms_matrix * dest, const vms_matrix * src); #define vm_copy_transpose(dest,src) vm_copy_transpose_matrix((dest),(src)) //mulitply 2 matrices, fill in dest. returns ptr to dest //dest CANNOT equal either source vms_matrix * vm_matrix_x_matrix (vms_matrix * dest, const vms_matrix * src0, const vms_matrix * src1); //extract angles from a matrix vms_angvec * vm_extract_angles_matrix (vms_angvec * a, const vms_matrix * m); //extract heading and pitch from a vector, assuming bank==0 vms_angvec * vm_extract_angles_vector (vms_angvec * a, const vms_vector * v); //compute the distance from a point to a plane. takes the normalized normal //of the plane (ebx), a point on the plane (edi), and the point to check (esi). //returns distance in eax //distance is signed, so negative dist is on the back of the plane fix vm_dist_to_plane (const vms_vector * checkp, const vms_vector * norm, const vms_vector * planep); //fills in fields of an angle vector #define vm_angvec_make(v,_p,_b,_h) (((v)->p=(_p), (v)->b=(_b), (v)->h=(_h)), (v)) // convert from quaternion to vector matrix and back void vms_quaternion_from_matrix(vms_quaternion * q, const vms_matrix * m); void vms_matrix_from_quaternion(vms_matrix * m, const vms_quaternion * q); #endif /* !_VECMAT_H */ dxx-rebirth-0.58.1-d2x/libmve/000077500000000000000000000000001217717237500160325ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/libmve/decoder16.c000066400000000000000000000336031217717237500177570ustar00rootroot00000000000000/* 16 bit decoding routines */ #include #include #include #include "decoders.h" #include "console.h" static unsigned short *backBuf1, *backBuf2; static int lookup_initialized; static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb); static void genLoopkupTable(); void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) { unsigned char *pOrig; unsigned char *pOffData; unsigned short offset; unsigned short *FramePtr = (unsigned short *)pFrame; int length; int op; int i, j; int xb, yb; if (!lookup_initialized) { genLoopkupTable(); } backBuf1 = (unsigned short *)g_vBackBuf1; backBuf2 = (unsigned short *)g_vBackBuf2; xb = g_width >> 3; yb = g_height >> 3; offset = pData[0]|(pData[1]<<8); pOffData = pData + offset; pData += 2; pOrig = pData; length = offset - 2; /*dataRemain-2;*/ for (j=0; j= backBuf1 + g_width*g_height) con_printf(CON_CRITICAL, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf); */ op = ((*pMap) >> 4) & 0xf; dispatchDecoder16(&FramePtr, op, &pData, &pOffData, &dataRemain, &i, &j); /* if (FramePtr < backBuf1) con_printf(CON_CRITICAL, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); else if (FramePtr >= backBuf1 + g_width*g_height) con_printf(CON_CRITICAL, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); */ ++pMap; --mapRemain; } FramePtr += 7*g_width; } if ((length-(pData-pOrig)) != 0) { con_printf(CON_CRITICAL, "DEBUG: junk left over: %d,%d,%d\n", (int)(pData-pOrig), length, (int)(length-(pData-pOrig))); } } static unsigned short GETPIXEL(unsigned char **buf, int off) { unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8); return val; } static unsigned short GETPIXELI(unsigned char **buf, int off) { unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8); (*buf) += 2; return val; } static void relClose(int i, int *x, int *y) { int ma, mi; ma = i >> 4; mi = i & 0xf; *x = mi - 8; *y = ma - 8; } static void relFar(int i, int sign, int *x, int *y) { if (i < 56) { *x = sign * (8 + (i % 7)); *y = sign * (i / 7); } else { *x = sign * (-14 + (i - 56) % 29); *y = sign * (8 + (i - 56) / 29); } } static int close_table[512]; static int far_p_table[512]; static int far_n_table[512]; static void genLoopkupTable() { int i; int x, y; for (i = 0; i < 256; i++) { relClose(i, &x, &y); close_table[i*2+0] = x; close_table[i*2+1] = y; relFar(i, 1, &x, &y); far_p_table[i*2+0] = x; far_p_table[i*2+1] = y; relFar(i, -1, &x, &y); far_n_table[i*2+0] = x; far_n_table[i*2+1] = y; } lookup_initialized = 1; } static void copyFrame(unsigned short *pDest, unsigned short *pSrc) { int i; for (i=0; i<8; i++) { memcpy(pDest, pSrc, 16); pDest += g_width; pSrc += g_width; } } static void patternRow4Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned short *p) { unsigned short mask=0x0003; unsigned short shift=0; unsigned short pattern = (pat1 << 8) | pat0; while (mask != 0) { *pFrame++ = p[(mask & pattern) >> shift]; mask <<= 2; shift += 2; } } static void patternRow4Pixels2(unsigned short *pFrame, unsigned char pat0, unsigned short *p) { unsigned char mask=0x03; unsigned char shift=0; unsigned short pel; /* ORIGINAL VERSION IS BUGGY int skip=1; while (mask != 0) { pel = p[(mask & pat0) >> shift]; pFrame[0] = pel; pFrame[2] = pel; pFrame[g_width + 0] = pel; pFrame[g_width + 2] = pel; pFrame += skip; skip = 4 - skip; mask <<= 2; shift += 2; } */ while (mask != 0) { pel = p[(mask & pat0) >> shift]; pFrame[0] = pel; pFrame[1] = pel; pFrame[g_width + 0] = pel; pFrame[g_width + 1] = pel; pFrame += 2; mask <<= 2; shift += 2; } } static void patternRow4Pixels2x1(unsigned short *pFrame, unsigned char pat, unsigned short *p) { unsigned char mask=0x03; unsigned char shift=0; unsigned short pel; while (mask != 0) { pel = p[(mask & pat) >> shift]; pFrame[0] = pel; pFrame[1] = pel; pFrame += 2; mask <<= 2; shift += 2; } } static void patternQuadrant4Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned short *p) { unsigned long mask = 0x00000003UL; int shift=0; int i; unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; for (i=0; i<16; i++) { pFrame[i&3] = p[(pat & mask) >> shift]; if ((i&3) == 3) pFrame += g_width; mask <<= 2; shift += 2; } } static void patternRow2Pixels(unsigned short *pFrame, unsigned char pat, unsigned short *p) { unsigned char mask=0x01; while (mask != 0) { *pFrame++ = p[(mask & pat) ? 1 : 0]; mask <<= 1; } } static void patternRow2Pixels2(unsigned short *pFrame, unsigned char pat, unsigned short *p) { unsigned short pel; unsigned char mask=0x1; /* ORIGINAL VERSION IS BUGGY int skip=1; while (mask != 0x10) { pel = p[(mask & pat) ? 1 : 0]; pFrame[0] = pel; pFrame[2] = pel; pFrame[g_width + 0] = pel; pFrame[g_width + 2] = pel; pFrame += skip; skip = 4 - skip; mask <<= 1; } */ while (mask != 0x10) { pel = p[(mask & pat) ? 1 : 0]; pFrame[0] = pel; pFrame[1] = pel; pFrame[g_width + 0] = pel; pFrame[g_width + 1] = pel; pFrame += 2; mask <<= 1; } } static void patternQuadrant2Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned short *p) { unsigned short mask = 0x0001; int i; unsigned short pat = (pat1 << 8) | pat0; for (i=0; i<16; i++) { pFrame[i&3] = p[(pat & mask) ? 1 : 0]; if ((i&3) == 3) pFrame += g_width; mask <<= 1; } } static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb) { unsigned short p[4]; unsigned char pat[16]; int i, j, k; int x, y; unsigned short *pDstBak; pDstBak = *pFrame; switch(codeType) { case 0x0: copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1)); case 0x1: break; case 0x2: /* relFar(*(*pOffData)++, 1, &x, &y); */ k = *(*pOffData)++; x = far_p_table[k*2+0]; y = far_p_table[k*2+1]; copyFrame(*pFrame, *pFrame + x + y*g_width); --*pDataRemain; break; case 0x3: /* relFar(*(*pOffData)++, -1, &x, &y); */ k = *(*pOffData)++; x = far_n_table[k*2+0]; y = far_n_table[k*2+1]; copyFrame(*pFrame, *pFrame + x + y*g_width); --*pDataRemain; break; case 0x4: /* relClose(*(*pOffData)++, &x, &y); */ k = *(*pOffData)++; x = close_table[k*2+0]; y = close_table[k*2+1]; copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width); --*pDataRemain; break; case 0x5: x = (char)*(*pData)++; y = (char)*(*pData)++; copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width); *pDataRemain -= 2; break; case 0x6: con_printf(CON_CRITICAL, "STUB: encoding 6 not tested\n"); for (i=0; i<2; i++) { *pFrame += 16; if (++*curXb == (g_width >> 3)) { *pFrame += 7*g_width; *curXb = 0; if (++*curYb == (g_height >> 3)) return; } } break; case 0x7: p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); if (!((p[0]/*|p[1]*/)&0x8000)) { for (i=0; i<8; i++) { patternRow2Pixels(*pFrame, *(*pData), p); (*pData)++; *pFrame += g_width; } } else { for (i=0; i<2; i++) { patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); *pFrame += 2*g_width; patternRow2Pixels2(*pFrame, *(*pData) >> 4, p); (*pData)++; *pFrame += 2*g_width; } } break; case 0x8: p[0] = GETPIXEL(pData, 0); if (!(p[0] & 0x8000)) { for (i=0; i<4; i++) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; (*pData) += 2; patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { p[2] = GETPIXEL(pData, 8); if (!(p[2]&0x8000)) { for (i=0; i<4; i++) { if ((i & 1) == 0) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); } pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { for (i=0; i<8; i++) { if ((i & 3) == 0) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); } patternRow2Pixels(*pFrame, *(*pData), p); (*pData)++; *pFrame += g_width; } } } break; case 0x9: p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); p[2] = GETPIXELI(pData, 0); p[3] = GETPIXELI(pData, 0); *pDataRemain -= 8; if (!(p[0] & 0x8000)) { if (!(p[2] & 0x8000)) { for (i=0; i<8; i++) { pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; (*pData) += 2; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; } *pDataRemain -= 16; } else { patternRow4Pixels2(*pFrame, (*pData)[0], p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, (*pData)[1], p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, (*pData)[2], p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, (*pData)[3], p); (*pData) += 4; *pDataRemain -= 4; } } else { if (!(p[2] & 0x8000)) { for (i=0; i<8; i++) { pat[0] = (*pData)[0]; (*pData) += 1; patternRow4Pixels2x1(*pFrame, pat[0], p); *pFrame += g_width; } *pDataRemain -= 8; } else { for (i=0; i<4; i++) { pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; (*pData) += 2; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; } *pDataRemain -= 8; } } break; case 0xa: p[0] = GETPIXEL(pData, 0); if (!(p[0] & 0x8000)) { for (i=0; i<4; i++) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); p[2] = GETPIXELI(pData, 0); p[3] = GETPIXELI(pData, 0); pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; pat[2] = (*pData)[2]; pat[3] = (*pData)[3]; (*pData) += 4; patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { p[0] = GETPIXEL(pData, 16); if (!(p[0] & 0x8000)) { for (i=0; i<4; i++) { if ((i&1) == 0) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); p[2] = GETPIXELI(pData, 0); p[3] = GETPIXELI(pData, 0); } pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; pat[2] = (*pData)[2]; pat[3] = (*pData)[3]; (*pData) += 4; patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { for (i=0; i<8; i++) { if ((i&3) == 0) { p[0] = GETPIXELI(pData, 0); p[1] = GETPIXELI(pData, 0); p[2] = GETPIXELI(pData, 0); p[3] = GETPIXELI(pData, 0); } pat[0] = (*pData)[0]; pat[1] = (*pData)[1]; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; (*pData) += 2; } } } break; case 0xb: for (i=0; i<8; i++) { memcpy(*pFrame, *pData, 16); *pFrame += g_width; *pData += 16; *pDataRemain -= 16; } break; case 0xc: for (i=0; i<4; i++) { p[0] = GETPIXEL(pData, 0); p[1] = GETPIXEL(pData, 2); p[2] = GETPIXEL(pData, 4); p[3] = GETPIXEL(pData, 6); for (j=0; j<2; j++) { for (k=0; k<4; k++) { (*pFrame)[j+2*k] = p[k]; (*pFrame)[g_width+j+2*k] = p[k]; } *pFrame += g_width; } *pData += 8; *pDataRemain -= 8; } break; case 0xd: for (i=0; i<2; i++) { p[0] = GETPIXEL(pData, 0); p[1] = GETPIXEL(pData, 2); for (j=0; j<4; j++) { for (k=0; k<4; k++) { (*pFrame)[k*g_width+j] = p[0]; (*pFrame)[k*g_width+j+4] = p[1]; } } *pFrame += 4*g_width; *pData += 4; *pDataRemain -= 4; } break; case 0xe: p[0] = GETPIXEL(pData, 0); for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) { (*pFrame)[j] = p[0]; } *pFrame += g_width; } *pData += 2; *pDataRemain -= 2; break; case 0xf: p[0] = GETPIXEL(pData, 0); p[1] = GETPIXEL(pData, 1); for (i=0; i<8; i++) { for (j=0; j<8; j++) { (*pFrame)[j] = p[(i+j)&1]; } *pFrame += g_width; } *pData += 4; *pDataRemain -= 4; break; default: break; } *pFrame = pDstBak+8; } dxx-rebirth-0.58.1-d2x/libmve/decoder8.c000066400000000000000000000550331217717237500177010ustar00rootroot00000000000000/* 8 bit decoding routines */ #include #include #include "decoders.h" #include "console.h" static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb); void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) { int i, j; int xb, yb; xb = g_width >> 3; yb = g_height >> 3; for (j=0; j= ((unsigned char *)g_vBackBuf1) + g_width*g_height) con_printf(CON_CRITICAL, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf); dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j); if (pFrame < (unsigned char *)g_vBackBuf1) con_printf(CON_CRITICAL, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width*g_height) con_printf(CON_CRITICAL, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); ++pMap; --mapRemain; } pFrame += 7*g_width; } } static void relClose(int i, int *x, int *y) { int ma, mi; ma = i >> 4; mi = i & 0xf; *x = mi - 8; *y = ma - 8; } static void relFar(int i, int sign, int *x, int *y) { if (i < 56) { *x = sign * (8 + (i % 7)); *y = sign * (i / 7); } else { *x = sign * (-14 + (i - 56) % 29); *y = sign * (8 + (i - 56) / 29); } } /* copies an 8x8 block from pSrc to pDest. pDest and pSrc are both g_width bytes wide */ static void copyFrame(unsigned char *pDest, unsigned char *pSrc) { int i; for (i=0; i<8; i++) { memcpy(pDest, pSrc, 8); pDest += g_width; pSrc += g_width; } } // Fill in the next eight bytes with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0 and pat1 static void patternRow4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p) { unsigned short mask=0x0003; unsigned short shift=0; unsigned short pattern = (pat1 << 8) | pat0; while (mask != 0) { *pFrame++ = p[(mask & pattern) >> shift]; mask <<= 2; shift += 2; } } // Fill in the next four 2x2 pixel blocks with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0. static void patternRow4Pixels2(unsigned char *pFrame, unsigned char pat0, unsigned char *p) { unsigned char mask=0x03; unsigned char shift=0; unsigned char pel; while (mask != 0) { pel = p[(mask & pat0) >> shift]; pFrame[0] = pel; pFrame[1] = pel; pFrame[g_width + 0] = pel; pFrame[g_width + 1] = pel; pFrame += 2; mask <<= 2; shift += 2; } } // Fill in the next four 2x1 pixel blocks with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat. static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p) { unsigned char mask=0x03; unsigned char shift=0; unsigned char pel; while (mask != 0) { pel = p[(mask & pat) >> shift]; pFrame[0] = pel; pFrame[1] = pel; pFrame += 2; mask <<= 2; shift += 2; } } // Fill in the next 4x4 pixel block with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0, pat1, pat2, and pat3. static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p) { unsigned long mask = 0x00000003UL; int shift=0; int i; unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; for (i=0; i<16; i++) { pFrame[i&3] = p[(pat & mask) >> shift]; if ((i&3) == 3) pFrame += g_width; mask <<= 2; shift += 2; } } // fills the next 8 pixels with either p[0] or p[1], depending on pattern static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p) { unsigned char mask=0x01; while (mask != 0) { *pFrame++ = p[(mask & pat) ? 1 : 0]; mask <<= 1; } } // fills the next four 2 x 2 pixel boxes with either p[0] or p[1], depending on pattern static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p) { unsigned char pel; unsigned char mask=0x1; while (mask != 0x10) { pel = p[(mask & pat) ? 1 : 0]; pFrame[0] = pel; // upper-left pFrame[1] = pel; // upper-right pFrame[g_width + 0] = pel; // lower-left pFrame[g_width + 1] = pel; // lower-right pFrame += 2; mask <<= 1; } } // fills pixels in the next 4 x 4 pixel boxes with either p[0] or p[1], depending on pat0 and pat1. static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p) { unsigned char pel; unsigned short mask = 0x0001; int i, j; unsigned short pat = (pat1 << 8) | pat0; for (i=0; i<4; i++) { for (j=0; j<4; j++) { pel = p[(pat & mask) ? 1 : 0]; pFrame[j + i * g_width] = pel; mask <<= 1; } } } static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb) { unsigned char p[4]; unsigned char pat[16]; int i, j, k; int x, y; /* Data is processed in 8x8 pixel blocks. There are 16 ways to encode each block. */ switch(codeType) { case 0x0: /* block is copied from block in current frame */ copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1)); case 0x1: /* block is unchanged from two frames ago */ *pFrame += 8; break; case 0x2: /* Block is copied from nearby (below and/or to the right) within the new frame. The offset within the buffer from which to grab the patch of 8 pixels is given by grabbing a byte B from the data stream, which is broken into a positive x and y offset according to the following mapping: if B < 56: x = 8 + (B % 7) y = B / 7 else x = -14 + ((B - 56) % 29) y = 8 + ((B - 56) / 29) */ relFar(*(*pData)++, 1, &x, &y); copyFrame(*pFrame, *pFrame + x + y*g_width); *pFrame += 8; --*pDataRemain; break; case 0x3: /* Block is copied from nearby (above and/or to the left) within the new frame. if B < 56: x = -(8 + (B % 7)) y = -(B / 7) else x = -(-14 + ((B - 56) % 29)) y = -( 8 + ((B - 56) / 29)) */ relFar(*(*pData)++, -1, &x, &y); copyFrame(*pFrame, *pFrame + x + y*g_width); *pFrame += 8; --*pDataRemain; break; case 0x4: /* Similar to 0x2 and 0x3, except this method copies from the "current" frame, rather than the "new" frame, and instead of the lopsided mapping they use, this one uses one which is symmetric and centered around the top-left corner of the block. This uses only 1 byte still, though, so the range is decreased, since we have to encode all directions in a single byte. The byte we pull from the data stream, I'll call B. Call the highest 4 bits of B BH and the lowest 4 bytes BL. Then the offset from which to copy the data is: x = -8 + BL y = -8 + BH */ relClose(*(*pData)++, &x, &y); copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y*g_width); *pFrame += 8; --*pDataRemain; break; case 0x5: /* Similar to 0x4, but instead of one byte for the offset, this uses two bytes to encode a larger range, the first being the x offset as a signed 8-bit value, and the second being the y offset as a signed 8-bit value. */ x = (signed char)*(*pData)++; y = (signed char)*(*pData)++; copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y*g_width); *pFrame += 8; *pDataRemain -= 2; break; case 0x6: /* I can't figure out how any file containing a block of this type could still be playable, since it appears that it would leave the internal bookkeeping in an inconsistent state in the BG player code. Ahh, well. Perhaps it was a bug in the BG player code that just didn't happen to be exposed by any of the included movies. Anyway, this skips the next two blocks, doing nothing to them. Note that if you've reached the end of a row, this means going on to the next row. */ for (i=0; i<2; i++) { *pFrame += 16; if (++*curXb == (g_width >> 3)) { *pFrame += 7*g_width; *curXb = 0; if (++*curYb == (g_height >> 3)) return; } } break; case 0x7: /* Ok, here's where it starts to get really...interesting. This is, incidentally, the part where they started using self-modifying code. So, most of the following encodings are "patterned" blocks, where we are given a number of pixel values and then bitmapped values to specify which pixel values belong to which squares. For this encoding, we are given the following in the data stream: P0 P1 These are pixel values (i.e. 8-bit indices into the palette). If P0 <= P1, we then get 8 more bytes from the data stream, one for each row in the block: B0 B1 B2 B3 B4 B5 B6 B7 For each row, the leftmost pixel is represented by the low-order bit, and the rightmost by the high-order bit. Use your imagination in between. If a bit is set, the pixel value is P1 and if it is unset, the pixel value is P0. So, for example, if we had: 11 22 fe 83 83 83 83 83 83 fe This would represent the following layout: 11 22 22 22 22 22 22 22 ; fe == 11111110 22 22 11 11 11 11 11 22 ; 83 == 10000011 22 22 11 11 11 11 11 22 ; 83 == 10000011 22 22 11 11 11 11 11 22 ; 83 == 10000011 22 22 11 11 11 11 11 22 ; 83 == 10000011 22 22 11 11 11 11 11 22 ; 83 == 10000011 22 22 11 11 11 11 11 22 ; 83 == 10000011 11 22 22 22 22 22 22 22 ; fe == 11111110 If, on the other hand, P0 > P1, we get two more bytes from the data stream: B0 B1 Each of these bytes contains two 4-bit patterns. These patterns work like the patterns above with 8 bytes, except each bit represents a 2x2 pixel region. B0 contains the pattern for the top two rows and B1 contains the pattern for the bottom two rows. Note that the low-order nibble of each byte contains the pattern for the upper of the two rows that that byte controls. So if we had: 22 11 7e 83 The output would be: 11 11 22 22 22 22 22 22 ; e == 1 1 1 0 11 11 22 22 22 22 22 22 ; 22 22 22 22 22 22 11 11 ; 7 == 0 1 1 1 22 22 22 22 22 22 11 11 ; 11 11 11 11 11 11 22 22 ; 3 == 1 0 0 0 11 11 11 11 11 11 22 22 ; 22 22 22 22 11 11 11 11 ; 8 == 0 0 1 1 22 22 22 22 11 11 11 11 ; */ p[0] = *(*pData)++; p[1] = *(*pData)++; if (p[0] <= p[1]) { for (i=0; i<8; i++) { patternRow2Pixels(*pFrame, *(*pData)++, p); *pFrame += g_width; } } else { for (i=0; i<2; i++) { patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); *pFrame += 2*g_width; patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p); *pFrame += 2*g_width; } } *pFrame -= (8*g_width - 8); break; case 0x8: /* Ok, this one is basically like encoding 0x7, only more complicated. Again, we start out by getting two bytes on the data stream: P0 P1 if P0 <= P1 then we get the following from the data stream: B0 B1 P2 P3 B2 B3 P4 P5 B4 B5 P6 P7 B6 B7 P0 P1 and B0 B1 are used for the top-left corner, P2 P3 B2 B3 for the bottom-left corner, P4 P5 B4 B5 for the top-right, P6 P7 B6 B7 for the bottom-right. (So, each codes for a 4x4 pixel array.) Since we have 16 bits in B0 B1, there is one bit for each pixel in the array. The convention for the bit-mapping is, again, left to right and top to bottom. So, basically, the top-left quarter of the block is an arbitrary pattern with 2 pixels, the bottom-left a different arbitrary pattern with 2 different pixels, and so on. For example if the next 16 bytes were: 00 22 f9 9f 44 55 aa 55 11 33 cc 33 66 77 01 ef We'd draw: 22 22 22 22 | 11 11 33 33 ; f = 1111, c = 1100 22 00 00 22 | 11 11 33 33 ; 9 = 1001, c = 1100 22 00 00 22 | 33 33 11 11 ; 9 = 1001, 3 = 0011 22 22 22 22 | 33 33 11 11 ; f = 1111, 3 = 0011 ------------+------------ 44 55 44 55 | 66 66 66 66 ; a = 1010, 0 = 0000 44 55 44 55 | 77 66 66 66 ; a = 1010, 1 = 0001 55 44 55 44 | 66 77 77 77 ; 5 = 0101, e = 1110 55 44 55 44 | 77 77 77 77 ; 5 = 0101, f = 1111 I've added a dividing line in the above to clearly delineate the quadrants. Now, if P0 > P1 then we get 10 more bytes from the data stream: B0 B1 B2 B3 P2 P3 B4 B5 B6 B7 Now, if P2 <= P3, then the first six bytes [P0 P1 B0 B1 B2 B3] represent the left half of the block and the latter six bytes [P2 P3 B4 B5 B6 B7] represent the right half. For example: 22 00 01 37 f7 31 11 66 8c e6 73 31 yeilds: 22 22 22 22 | 11 11 11 66 ; 0: 0000 | 8: 1000 00 22 22 22 | 11 11 66 66 ; 1: 0001 | C: 1100 00 00 22 22 | 11 66 66 66 ; 3: 0011 | e: 1110 00 00 00 22 | 11 66 11 66 ; 7: 0111 | 6: 0101 00 00 00 00 | 66 66 66 11 ; f: 1111 | 7: 0111 00 00 00 22 | 66 66 11 11 ; 7: 0111 | 3: 0011 00 00 22 22 | 66 66 11 11 ; 3: 0011 | 3: 0011 00 22 22 22 | 66 11 11 11 ; 1: 0001 | 1: 0001 On the other hand, if P0 > P1 and P2 > P3, then [P0 P1 B0 B1 B2 B3] represent the top half of the block and [P2 P3 B4 B5 B6 B7] represent the bottom half. For example: 22 00 cc 66 33 19 66 11 18 24 42 81 yeilds: 22 22 00 00 22 22 00 00 ; cc: 11001100 22 00 00 22 22 00 00 22 ; 66: 01100110 00 00 22 22 00 00 22 22 ; 33: 00110011 00 22 22 00 00 22 22 22 ; 19: 00011001 ----------------------- 66 66 66 11 11 66 66 66 ; 18: 00011000 66 66 11 66 66 11 66 66 ; 24: 00100100 66 11 66 66 66 66 11 66 ; 42: 01000010 11 66 66 66 66 66 66 11 ; 81: 10000001 */ if ( (*pData)[0] <= (*pData)[1]) { // four quadrant case for (i=0; i<4; i++) { p[0] = *(*pData)++; p[1] = *(*pData)++; pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); // alternate between moving down and moving up and right if (i & 1) *pFrame += 4 - 4*g_width; // up and right else *pFrame += 4*g_width; // down } } else if ( (*pData)[6] <= (*pData)[7]) { // split horizontal for (i=0; i<4; i++) { if ((i & 1) == 0) { p[0] = *(*pData)++; p[1] = *(*pData)++; } pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { // split vertical for (i=0; i<8; i++) { if ((i & 3) == 0) { p[0] = *(*pData)++; p[1] = *(*pData)++; } patternRow2Pixels(*pFrame, *(*pData)++, p); *pFrame += g_width; } *pFrame -= (8*g_width - 8); } break; case 0x9: /* Similar to the previous 2 encodings, only more complicated. And it will get worse before it gets better. No longer are we dealing with patterns over two pixel values. Now we are dealing with patterns over 4 pixel values with 2 bits assigned to each pixel (or block of pixels). So, first on the data stream are our 4 pixel values: P0 P1 P2 P3 Now, if P0 <= P1 AND P2 <= P3, we get 16 bytes of pattern, each 2 bits representing a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). The ordering is again left to right and top to bottom. The most significant bits represent the left side at the top, and so on. If P0 <= P1 AND P2 > P3, we get 4 bytes of pattern, each 2 bits representing a 2x2 pixel. Ordering is left to right and top to bottom. if P0 > P1 AND P2 <= P3, we get 8 bytes of pattern, each 2 bits representing a 2x1 pixel (i.e. 2 pixels wide, and 1 high). if P0 > P1 AND P2 > P3, we get 8 bytes of pattern, each 2 bits representing a 1x2 pixel (i.e. 1 pixel wide, and 2 high). */ if ( (*pData)[0] <= (*pData)[1]) { if ( (*pData)[2] <= (*pData)[3]) { p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; for (i=0; i<8; i++) { pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; } *pFrame -= (8*g_width - 8); } else { p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; patternRow4Pixels2(*pFrame, *(*pData)++, p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, *(*pData)++, p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, *(*pData)++, p); *pFrame += 2*g_width; patternRow4Pixels2(*pFrame, *(*pData)++, p); *pFrame -= (6*g_width - 8); } } else { if ( (*pData)[2] <= (*pData)[3]) { // draw 2x1 strips p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; for (i=0; i<8; i++) { pat[0] = *(*pData)++; patternRow4Pixels2x1(*pFrame, pat[0], p); *pFrame += g_width; } *pFrame -= (8*g_width - 8); } else { // draw 1x2 strips p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; for (i=0; i<4; i++) { pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; } *pFrame -= (8*g_width - 8); } } break; case 0xa: /* Similar to the previous, only a little more complicated. We are still dealing with patterns over 4 pixel values with 2 bits assigned to each pixel (or block of pixels). So, first on the data stream are our 4 pixel values: P0 P1 P2 P3 Now, if P0 <= P1, the block is divided into 4 quadrants, ordered (as with opcode 0x8) TL, BL, TR, BR. In this case the next data in the data stream should be: B0 B1 B2 B3 P4 P5 P6 P7 B4 B5 B6 B7 P8 P9 P10 P11 B8 B9 B10 B11 P12 P13 P14 P15 B12 B13 B14 B15 Each 2 bits represent a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). The ordering is again left to right and top to bottom. The most significant bits represent the right side at the top, and so on. If P0 > P1 then the next data on the data stream is: B0 B1 B2 B3 B4 B5 B6 B7 P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15 Now, in this case, if P4 <= P5, [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the left half of the block and the other bytes represent the right half. If P4 > P5, then [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the top half of the block and the other bytes represent the bottom half. */ if ( (*pData)[0] <= (*pData)[1]) { for (i=0; i<4; i++) { p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; pat[0] = *(*pData)++; pat[1] = *(*pData)++; pat[2] = *(*pData)++; pat[3] = *(*pData)++; patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { if ( (*pData)[12] <= (*pData)[13]) { // split vertical for (i=0; i<4; i++) { if ((i&1) == 0) { p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; } pat[0] = *(*pData)++; pat[1] = *(*pData)++; pat[2] = *(*pData)++; pat[3] = *(*pData)++; patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); if (i & 1) *pFrame -= (4*g_width - 4); else *pFrame += 4*g_width; } } else { // split horizontal for (i=0; i<8; i++) { if ((i&3) == 0) { p[0] = *(*pData)++; p[1] = *(*pData)++; p[2] = *(*pData)++; p[3] = *(*pData)++; } pat[0] = *(*pData)++; pat[1] = *(*pData)++; patternRow4Pixels(*pFrame, pat[0], pat[1], p); *pFrame += g_width; } *pFrame -= (8*g_width - 8); } } break; case 0xb: /* In this encoding we get raw pixel data in the data stream -- 64 bytes of pixel data. 1 byte for each pixel, and in the standard order (l->r, t->b). */ for (i=0; i<8; i++) { memcpy(*pFrame, *pData, 8); *pFrame += g_width; *pData += 8; *pDataRemain -= 8; } *pFrame -= (8*g_width - 8); break; case 0xc: /* In this encoding we get raw pixel data in the data stream -- 16 bytes of pixel data. 1 byte for each block of 2x2 pixels, and in the standard order (l->r, t->b). */ for (i=0; i<4; i++) { for (j=0; j<2; j++) { for (k=0; k<4; k++) { (*pFrame)[2*k] = (*pData)[k]; (*pFrame)[2*k+1] = (*pData)[k]; } *pFrame += g_width; } *pData += 4; *pDataRemain -= 4; } *pFrame -= (8*g_width - 8); break; case 0xd: /* In this encoding we get raw pixel data in the data stream -- 4 bytes of pixel data. 1 byte for each block of 4x4 pixels, and in the standard order (l->r, t->b). */ for (i=0; i<2; i++) { for (j=0; j<4; j++) { for (k=0; k<4; k++) { (*pFrame)[k*g_width+j] = (*pData)[0]; (*pFrame)[k*g_width+j+4] = (*pData)[1]; } } *pFrame += 4*g_width; *pData += 2; *pDataRemain -= 2; } *pFrame -= (8*g_width - 8); break; case 0xe: /* This encoding represents a solid 8x8 frame. We get 1 byte of pixel data from the data stream. */ for (i=0; i<8; i++) { memset(*pFrame, **pData, 8); *pFrame += g_width; } ++*pData; --*pDataRemain; *pFrame -= (8*g_width - 8); break; case 0xf: /* This encoding represents a "dithered" frame, which is checkerboarded with alternate pixels of two colors. We get 2 bytes of pixel data from the data stream, and these bytes are alternated: P0 P1 P0 P1 P0 P1 P0 P1 P1 P0 P1 P0 P1 P0 P1 P0 ... P0 P1 P0 P1 P0 P1 P0 P1 P1 P0 P1 P0 P1 P0 P1 P0 */ for (i=0; i<8; i++) { for (j=0; j<8; j++) { (*pFrame)[j] = (*pData)[(i+j)&1]; } *pFrame += g_width; } *pData += 2; *pDataRemain -= 2; *pFrame -= (8*g_width - 8); break; default: break; } } dxx-rebirth-0.58.1-d2x/libmve/decoders.h000066400000000000000000000007061217717237500177760ustar00rootroot00000000000000/* * * INTERNAL header - not to be included outside of libmve * */ #ifndef _DECODERS_H #define _DECODERS_H extern int g_width, g_height; extern void *g_vBackBuf1, *g_vBackBuf2; extern void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain); extern void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain); #endif // _DECODERS_H dxx-rebirth-0.58.1-d2x/libmve/mve_audio.c000066400000000000000000000056071217717237500201560ustar00rootroot00000000000000static int audio_exp_table[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47, 51, 56, 61, 66, 72, 79, 86, 94, 102, 112, 122, 133, 145, 158, 173, 189, 206, 225, 245, 267, 292, 318, 348, 379, 414, 452, 493, 538, 587, 640, 699, 763, 832, 908, 991, 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, -1081, -991, -908, -832, -763, -699, -640, -587, -538, -493, -452, -414, -379, -348, -318, -292, -267, -245, -225, -206, -189, -173, -158, -145, -133, -122, -112, -102, -94, -86, -79, -72, -66, -61, -56, -51, -47, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1 }; static int getWord(unsigned char **fin) { int value = ((*fin)[1] << 8) | (*fin)[0]; *fin += 2; return value; } static void sendWord(short **fout, int nOffset) { *(*fout)++ = nOffset; } static void processSwath(short *fout, unsigned char *data, int swath, int *offsets) { int i; for (i=0; i #include #include #include #ifdef _WIN32 # include #endif #include #include "libmve.h" static SDL_Surface *g_screen; static unsigned char g_palette[768]; static int g_truecolor; static int doPlay(const char *filename); static void usage(void) { fprintf(stderr, "usage: mveplay filename\n"); exit(1); } int main(int c, char **v) { if (c != 2) usage(); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); return doPlay(v[1]); } static unsigned int fileRead(void *handle, void *buf, unsigned int count) { unsigned numread; numread = fread(buf, 1, count, (FILE *)handle); return (numread == count); } static void showFrame(unsigned char *buf, int dstx, int dsty, int bufw, int bufh, int sw, int sh) { int i; unsigned char *pal; SDL_Surface *sprite; SDL_Rect srcRect, destRect; if (dstx == -1) // center it dstx = (sw - bufw) / 2; if (dsty == -1) // center it dsty = (sh - bufh) / 2; if (g_truecolor) sprite = SDL_CreateRGBSurfaceFrom(buf, bufw, bufh, 16, 2 * bufw, 0x7C00, 0x03E0, 0x001F, 0); else { sprite = SDL_CreateRGBSurfaceFrom(buf, bufw, bufh, 8, bufw, 0x7C00, 0x03E0, 0x001F, 0); pal = g_palette; for(i = 0; i < 256; i++) { sprite->format->palette->colors[i].r = (*pal++) << 2; sprite->format->palette->colors[i].g = (*pal++) << 2; sprite->format->palette->colors[i].b = (*pal++) << 2; sprite->format->palette->colors[i].unused = 0; } } srcRect.x = 0; srcRect.y = 0; srcRect.w = bufw; srcRect.h = bufh; destRect.x = dstx; destRect.y = dsty; destRect.w = bufw; destRect.h = bufh; SDL_BlitSurface(sprite, &srcRect, g_screen, &destRect); if ( (g_screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) SDL_Flip(g_screen); else SDL_UpdateRects(g_screen, 1, &destRect); SDL_FreeSurface(sprite); } static void setPalette(unsigned char *p, unsigned start, unsigned count) { //Set color 0 to be black g_palette[0] = g_palette[1] = g_palette[2] = 0; //Set color 255 to be our subtitle color g_palette[765] = g_palette[766] = g_palette[767] = 50; //movie libs palette into our array memcpy(g_palette + start*3, p+start*3, count*3); } static int pollEvents() { SDL_Event event; while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: return 1; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: case SDLK_q: return 1; case SDLK_f: SDL_WM_ToggleFullScreen(g_screen); break; default: break; } break; default: break; } } return 0; } static int doPlay(const char *filename) { int result; int done = 0; int bpp = 0; FILE *mve; MVE_videoSpec vSpec; mve = fopen(filename, "rb"); if (mve == NULL) { fprintf(stderr, "can't open MVE file\n"); return 1; } memset(g_palette, 0, 768); MVE_sndInit(1); MVE_memCallbacks((mve_cb_Alloc)malloc, free); MVE_ioCallbacks(fileRead); MVE_sfCallbacks(showFrame); MVE_palCallbacks(setPalette); MVE_rmPrepMovie(mve, -1, -1, 1); MVE_getVideoSpec(&vSpec); bpp = vSpec.truecolor?16:8; g_screen = SDL_SetVideoMode(vSpec.screenWidth, vSpec.screenHeight, bpp, SDL_ANYFORMAT); g_truecolor = vSpec.truecolor; while (!done && (result = MVE_rmStepMovie()) == 0) { done = pollEvents(); } MVE_rmEndMovie(); fclose(mve); return 0; } dxx-rebirth-0.58.1-d2x/libmve/mvelib.c000066400000000000000000000264161217717237500174650ustar00rootroot00000000000000#include // for mem* functions #if !defined(_WIN32) && !defined(macintosh) #include #include #include #include #endif #include "mvelib.h" static const char MVE_HEADER[] = "Interplay MVE File\x1A"; static const short MVE_HDRCONST1 = 0x001A; static const short MVE_HDRCONST2 = 0x0100; static const short MVE_HDRCONST3 = 0x1133; mve_cb_Read mve_read; mve_cb_Alloc mve_alloc; mve_cb_Free mve_free; mve_cb_ShowFrame mve_showframe; mve_cb_SetPalette mve_setpalette; /* * private utility functions */ static short _mve_get_short(unsigned char *data); static unsigned short _mve_get_ushort(unsigned char *data); /* * private functions for mvefile */ static MVEFILE *_mvefile_alloc(void); static void _mvefile_free(MVEFILE *movie); static int _mvefile_open(MVEFILE *movie, void *stream); static void _mvefile_reset(MVEFILE *movie); static int _mvefile_read_header(MVEFILE *movie); static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size); static int _mvefile_fetch_next_chunk(MVEFILE *movie); /* * private functions for mvestream */ static MVESTREAM *_mvestream_alloc(void); static void _mvestream_free(MVESTREAM *movie); static int _mvestream_open(MVESTREAM *movie, void *stream); static void _mvestream_reset(MVESTREAM *movie); /************************************************************ * public MVEFILE functions ************************************************************/ /* * open an MVE file */ MVEFILE *mvefile_open(void *stream) { MVEFILE *file; /* create the file */ file = _mvefile_alloc(); if (! _mvefile_open(file, stream)) { _mvefile_free(file); return NULL; } /* initialize the file */ _mvefile_set_buffer_size(file, 1024); /* verify the file's header */ if (! _mvefile_read_header(file)) { _mvefile_free(file); return NULL; } /* now, prefetch the next chunk */ _mvefile_fetch_next_chunk(file); return file; } /* * close a MVE file */ void mvefile_close(MVEFILE *movie) { _mvefile_free(movie); } /* * reset a MVE file */ void mvefile_reset(MVEFILE *file) { _mvefile_reset(file); /* initialize the file */ _mvefile_set_buffer_size(file, 1024); /* verify the file's header */ if (! _mvefile_read_header(file)) { _mvefile_free(file); //return NULL; } /* now, prefetch the next chunk */ _mvefile_fetch_next_chunk(file); } /* * get the size of the next segment */ int mvefile_get_next_segment_size(MVEFILE *movie) { /* if nothing is cached, fail */ if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) return -1; /* if we don't have enough data to get a segment, fail */ if (movie->cur_fill - movie->next_segment < 4) return -1; /* otherwise, get the data length */ return _mve_get_short(movie->cur_chunk + movie->next_segment); } /* * get type of next segment in chunk (0xff if no more segments in chunk) */ unsigned char mvefile_get_next_segment_major(MVEFILE *movie) { /* if nothing is cached, fail */ if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) return 0xff; /* if we don't have enough data to get a segment, fail */ if (movie->cur_fill - movie->next_segment < 4) return 0xff; /* otherwise, get the data length */ return movie->cur_chunk[movie->next_segment + 2]; } /* * get subtype (version) of next segment in chunk (0xff if no more segments in * chunk) */ unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) { /* if nothing is cached, fail */ if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) return 0xff; /* if we don't have enough data to get a segment, fail */ if (movie->cur_fill - movie->next_segment < 4) return 0xff; /* otherwise, get the data length */ return movie->cur_chunk[movie->next_segment + 3]; } /* * see next segment (return NULL if no next segment) */ unsigned char *mvefile_get_next_segment(MVEFILE *movie) { /* if nothing is cached, fail */ if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) return NULL; /* if we don't have enough data to get a segment, fail */ if (movie->cur_fill - movie->next_segment < 4) return NULL; /* otherwise, get the data length */ return movie->cur_chunk + movie->next_segment + 4; } /* * advance to next segment */ void mvefile_advance_segment(MVEFILE *movie) { /* if nothing is cached, fail */ if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) return; /* if we don't have enough data to get a segment, fail */ if (movie->cur_fill - movie->next_segment < 4) return; /* else, advance to next segment */ movie->next_segment += (4 + _mve_get_ushort(movie->cur_chunk + movie->next_segment)); } /* * fetch the next chunk (return 0 if at end of stream) */ int mvefile_fetch_next_chunk(MVEFILE *movie) { return _mvefile_fetch_next_chunk(movie); } /************************************************************ * public MVESTREAM functions ************************************************************/ /* * open an MVE stream */ MVESTREAM *mve_open(void *stream) { MVESTREAM *movie; /* allocate */ movie = _mvestream_alloc(); /* open */ if (! _mvestream_open(movie, stream)) { _mvestream_free(movie); return NULL; } return movie; } /* * close an MVE stream */ void mve_close(MVESTREAM *movie) { _mvestream_free(movie); } /* * reset an MVE stream */ void mve_reset(MVESTREAM *movie) { _mvestream_reset(movie); } /* * set segment type handler */ void mve_set_handler(MVESTREAM *movie, unsigned char major, MVESEGMENTHANDLER handler) { if (major < 32) movie->handlers[major] = handler; } /* * set segment handler context */ void mve_set_handler_context(MVESTREAM *movie, void *context) { movie->context = context; } /* * play next chunk */ int mve_play_next_chunk(MVESTREAM *movie) { unsigned char major, minor; unsigned char *data; int len; /* loop over segments */ major = mvefile_get_next_segment_major(movie->movie); while (major != 0xff) { /* check whether to handle the segment */ if (major < 32 && movie->handlers[major] != NULL) { minor = mvefile_get_next_segment_minor(movie->movie); len = mvefile_get_next_segment_size(movie->movie); data = mvefile_get_next_segment(movie->movie); if (! movie->handlers[major](major, minor, data, len, movie->context)) return 0; } /* advance to next segment */ mvefile_advance_segment(movie->movie); major = mvefile_get_next_segment_major(movie->movie); } if (! mvefile_fetch_next_chunk(movie->movie)) return 0; /* return status */ return 1; } /************************************************************ * private functions ************************************************************/ /* * allocate an MVEFILE */ static MVEFILE *_mvefile_alloc(void) { MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE)); file->stream = NULL; file->cur_chunk = NULL; file->buf_size = 0; file->cur_fill = 0; file->next_segment = 0; return file; } /* * free an MVE file */ static void _mvefile_free(MVEFILE *movie) { /* free the stream */ movie->stream = NULL; /* free the buffer */ if (movie->cur_chunk) mve_free(movie->cur_chunk); movie->cur_chunk = NULL; /* not strictly necessary */ movie->buf_size = 0; movie->cur_fill = 0; movie->next_segment = 0; /* free the struct */ mve_free(movie); } /* * open the file stream in thie object */ static int _mvefile_open(MVEFILE *file, void *stream) { file->stream = stream; if (! file->stream) return 0; return 1; } /* * allocate an MVEFILE */ static void _mvefile_reset(MVEFILE *file) { #if 0 file->cur_chunk = NULL; file->buf_size = 0; file->cur_fill = 0; file->next_segment = 0; #endif } /* * read and verify the header of the recently opened file */ static int _mvefile_read_header(MVEFILE *movie) { unsigned char buffer[26]; /* check the file is open */ if (! movie->stream) return 0; /* check the file is long enough */ if (! mve_read(movie->stream, buffer, 26)) return 0; /* check the signature */ if (memcmp(buffer, MVE_HEADER, 20)) return 0; /* check the hard-coded constants */ if (_mve_get_short(buffer+20) != MVE_HDRCONST1) return 0; if (_mve_get_short(buffer+22) != MVE_HDRCONST2) return 0; if (_mve_get_short(buffer+24) != MVE_HDRCONST3) return 0; return 1; } static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size) { unsigned char *new_buffer; int new_len; /* check if this would be a redundant operation */ if (buf_size <= movie->buf_size) return; /* allocate new buffer */ new_len = 100 + buf_size; new_buffer = (unsigned char *)mve_alloc(new_len); /* copy old data */ if (movie->cur_chunk && movie->cur_fill) memcpy(new_buffer, movie->cur_chunk, movie->cur_fill); /* free old buffer */ if (movie->cur_chunk) { mve_free(movie->cur_chunk); movie->cur_chunk = 0; } /* install new buffer */ movie->cur_chunk = new_buffer; movie->buf_size = new_len; } static int _mvefile_fetch_next_chunk(MVEFILE *movie) { unsigned char buffer[4]; unsigned short length; /* fail if not open */ if (! movie->stream) return 0; /* fail if we can't read the next segment descriptor */ if (! mve_read(movie->stream, buffer, 4)) return 0; /* pull out the next length */ length = _mve_get_short(buffer); /* make sure we've got sufficient space */ _mvefile_set_buffer_size(movie, length); /* read the chunk */ if (! mve_read(movie->stream, movie->cur_chunk, length)) return 0; movie->cur_fill = length; movie->next_segment = 0; return 1; } static short _mve_get_short(unsigned char *data) { short value; value = data[0] | (data[1] << 8); return value; } static unsigned short _mve_get_ushort(unsigned char *data) { unsigned short value; value = data[0] | (data[1] << 8); return value; } /* * allocate an MVESTREAM */ static MVESTREAM *_mvestream_alloc(void) { MVESTREAM *movie; /* allocate and zero-initialize everything */ movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM)); movie->movie = NULL; movie->context = 0; memset(movie->handlers, 0, sizeof(movie->handlers)); return movie; } /* * free an MVESTREAM */ static void _mvestream_free(MVESTREAM *movie) { /* close MVEFILE */ if (movie->movie) mvefile_close(movie->movie); movie->movie = NULL; /* clear context and handlers */ movie->context = NULL; memset(movie->handlers, 0, sizeof(movie->handlers)); /* free the struct */ mve_free(movie); } /* * open an MVESTREAM object */ static int _mvestream_open(MVESTREAM *movie, void *stream) { movie->movie = mvefile_open(stream); return (movie->movie == NULL) ? 0 : 1; } /* * reset an MVESTREAM */ static void _mvestream_reset(MVESTREAM *movie) { mvefile_reset(movie->movie); } dxx-rebirth-0.58.1-d2x/libmve/mvelib.h000066400000000000000000000043761217717237500174730ustar00rootroot00000000000000#ifndef INCLUDED_MVELIB_H #define INCLUDED_MVELIB_H #include #include #include "libmve.h" extern mve_cb_Read mve_read; extern mve_cb_Alloc mve_alloc; extern mve_cb_Free mve_free; extern mve_cb_ShowFrame mve_showframe; extern mve_cb_SetPalette mve_setpalette; /* * structure for maintaining info on a MVEFILE stream */ typedef struct MVEFILE { void *stream; unsigned char *cur_chunk; int buf_size; int cur_fill; int next_segment; } MVEFILE; /* * open a .MVE file */ MVEFILE *mvefile_open(void *stream); /* * close a .MVE file */ void mvefile_close(MVEFILE *movie); /* * get size of next segment in chunk (-1 if no more segments in chunk) */ int mvefile_get_next_segment_size(MVEFILE *movie); /* * get type of next segment in chunk (0xff if no more segments in chunk) */ unsigned char mvefile_get_next_segment_major(MVEFILE *movie); /* * get subtype (version) of next segment in chunk (0xff if no more segments in * chunk) */ unsigned char mvefile_get_next_segment_minor(MVEFILE *movie); /* * see next segment (return NULL if no next segment) */ unsigned char *mvefile_get_next_segment(MVEFILE *movie); /* * advance to next segment */ void mvefile_advance_segment(MVEFILE *movie); /* * fetch the next chunk (return 0 if at end of stream) */ int mvefile_fetch_next_chunk(MVEFILE *movie); /* * callback for segment type */ typedef int (*MVESEGMENTHANDLER)(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context); /* * structure for maintaining an MVE stream */ typedef struct MVESTREAM { MVEFILE *movie; void *context; MVESEGMENTHANDLER handlers[32]; } MVESTREAM; /* * open an MVE stream */ MVESTREAM *mve_open(void *stream); /* * close an MVE stream */ void mve_close(MVESTREAM *movie); /* * reset an MVE stream */ void mve_reset(MVESTREAM *movie); /* * set segment type handler */ void mve_set_handler(MVESTREAM *movie, unsigned char major, MVESEGMENTHANDLER handler); /* * set segment handler context */ void mve_set_handler_context(MVESTREAM *movie, void *context); /* * play next chunk */ int mve_play_next_chunk(MVESTREAM *movie); #endif /* INCLUDED_MVELIB_H */ dxx-rebirth-0.58.1-d2x/libmve/mveplay.c000066400000000000000000000512501217717237500176560ustar00rootroot00000000000000//#define DEBUG #include #ifdef _WIN32 # include #else # include # include # include # ifdef macintosh # include # include # else # include # include # include # include # endif // macintosh #endif // _WIN32 #include #ifdef USE_SDLMIXER #if !(defined(__APPLE__) && defined(__MACH__)) #include #else #include #endif #endif #include "digi.h" #include "mvelib.h" #include "mve_audio.h" #include "decoders.h" #include "libmve.h" #include "args.h" #include "console.h" #define MVE_OPCODE_ENDOFSTREAM 0x00 #define MVE_OPCODE_ENDOFCHUNK 0x01 #define MVE_OPCODE_CREATETIMER 0x02 #define MVE_OPCODE_INITAUDIOBUFFERS 0x03 #define MVE_OPCODE_STARTSTOPAUDIO 0x04 #define MVE_OPCODE_INITVIDEOBUFFERS 0x05 #define MVE_OPCODE_DISPLAYVIDEO 0x07 #define MVE_OPCODE_AUDIOFRAMEDATA 0x08 #define MVE_OPCODE_AUDIOFRAMESILENCE 0x09 #define MVE_OPCODE_INITVIDEOMODE 0x0A #define MVE_OPCODE_SETPALETTE 0x0C #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D #define MVE_OPCODE_SETDECODINGMAP 0x0F #define MVE_OPCODE_VIDEODATA 0x11 #define MVE_AUDIO_FLAGS_STEREO 1 #define MVE_AUDIO_FLAGS_16BIT 2 #define MVE_AUDIO_FLAGS_COMPRESSED 4 int g_spdFactorNum=0; static int g_spdFactorDenom=10; static int g_frameUpdated = 0; static short get_short(unsigned char *data) { short value; value = data[0] | (data[1] << 8); return value; } static unsigned short get_ushort(unsigned char *data) { unsigned short value; value = data[0] | (data[1] << 8); return value; } static int get_int(unsigned char *data) { int value; value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); return value; } static unsigned int unhandled_chunks[32*256]; static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { unhandled_chunks[major<<8|minor]++; //con_printf(CON_CRITICAL, "unknown chunk type %02x/%02x\n", major, minor); return 1; } /************************* * general handlers *************************/ static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { return 0; } /************************* * timer handlers *************************/ #if !defined(HAVE_STRUCT_TIMEVAL) || !HAVE_STRUCT_TIMEVAL struct timeval { long tv_sec; long tv_usec; }; #endif /* * timer variables */ static int timer_created = 0; static int micro_frame_delay=0; static int timer_started=0; static struct timeval timer_expire = {0, 0}; #if !defined(HAVE_STRUCT_TIMESPEC) || !HAVE_STRUCT_TIMESPEC struct timespec { long int tv_sec; /* Seconds. */ long int tv_nsec; /* Nanoseconds. */ }; #endif #if defined(_WIN32) || defined(macintosh) int gettimeofday(struct timeval *tv, void *tz) { static int counter = 0; #ifdef _WIN32 DWORD now = GetTickCount(); #else long now = TickCount(); #endif counter++; tv->tv_sec = now / 1000; tv->tv_usec = (now % 1000) * 1000 + counter; return 0; } #endif // defined(_WIN32) || defined(macintosh) static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { #if !defined(_WIN32) && !defined(macintosh) // FIXME __extension__ long long temp; #else long temp; #endif if (timer_created) return 1; else timer_created = 1; micro_frame_delay = get_int(data) * (int)get_short(data+4); if (g_spdFactorNum != 0) { temp = micro_frame_delay; temp *= g_spdFactorNum; temp /= g_spdFactorDenom; micro_frame_delay = (int)temp; } return 1; } static void timer_stop(void) { timer_expire.tv_sec = 0; timer_expire.tv_usec = 0; timer_started = 0; } static void timer_start(void) { int nsec=0; gettimeofday(&timer_expire, NULL); timer_expire.tv_usec += micro_frame_delay; if (timer_expire.tv_usec > 1000000) { nsec = timer_expire.tv_usec / 1000000; timer_expire.tv_sec += nsec; timer_expire.tv_usec -= nsec*1000000; } timer_started=1; } static void do_timer_wait(void) { int nsec=0; struct timespec ts; struct timeval tv; if (! timer_started) return; gettimeofday(&tv, NULL); if (tv.tv_sec > timer_expire.tv_sec) goto end; else if (tv.tv_sec == timer_expire.tv_sec && tv.tv_usec >= timer_expire.tv_usec) goto end; ts.tv_sec = timer_expire.tv_sec - tv.tv_sec; ts.tv_nsec = 1000 * (timer_expire.tv_usec - tv.tv_usec); if (ts.tv_nsec < 0) { ts.tv_nsec += 1000000000UL; --ts.tv_sec; } #ifdef _WIN32 Sleep(ts.tv_sec * 1000 + ts.tv_nsec / 1000000); #elif defined(macintosh) Delay(ts.tv_sec * 1000 + ts.tv_nsec / 1000000, NULL); #else if (nanosleep(&ts, NULL) == -1 && errno == EINTR) exit(1); #endif end: timer_expire.tv_usec += micro_frame_delay; if (timer_expire.tv_usec > 1000000) { nsec = timer_expire.tv_usec / 1000000; timer_expire.tv_sec += nsec; timer_expire.tv_usec -= nsec*1000000; } } /************************* * audio handlers *************************/ #define TOTAL_AUDIO_BUFFERS 64 static int audiobuf_created = 0; static void mve_audio_callback(void *userdata, unsigned char *stream, int len); static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS]; static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS]; static int mve_audio_curbuf_curpos=0; static int mve_audio_bufhead=0; static int mve_audio_buftail=0; static int mve_audio_playing=0; static int mve_audio_canplay=0; static int mve_audio_compressed=0; static int mve_audio_enabled = 1; static SDL_AudioSpec *mve_audio_spec=NULL; static void mve_audio_callback(void *userdata, unsigned char *stream, int len) { int total=0; int length; if (mve_audio_bufhead == mve_audio_buftail) return /* 0 */; //con_printf(CON_CRITICAL, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */ && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */ { length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos; memcpy(stream, /* cur output position */ ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */ length); /* cur input length */ total += length; stream += length; /* advance output */ len -= length; /* decrement avail ospace */ mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */ mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */ mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */ if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ mve_audio_bufhead = 0; mve_audio_curbuf_curpos = 0; } //con_printf(CON_CRITICAL, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total); /* return total; */ if (len != 0 /* ospace remaining */ && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */ { memcpy(stream, /* dest */ ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */ len); /* length */ mve_audio_curbuf_curpos += len; /* advance input */ stream += len; /* advance output (unnecessary) */ len -= len; /* advance output (unnecessary) */ if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */ { mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */ mve_audio_buffers[mve_audio_bufhead]=NULL; mve_audio_buflens[mve_audio_bufhead]=0; if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ mve_audio_bufhead = 0; mve_audio_curbuf_curpos = 0; } } //con_printf(CON_CRITICAL, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); } static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { int flags; int sample_rate; int desired_buffer; int stereo; int bitsize; int compressed; int format; if (!mve_audio_enabled) return 1; if (audiobuf_created) return 1; else audiobuf_created = 1; flags = get_ushort(data + 2); sample_rate = get_ushort(data + 4); desired_buffer = get_int(data + 6); stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0; bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0; if (minor > 0) { compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0; } else { compressed = 0; } mve_audio_compressed = compressed; if (bitsize == 1) { #ifdef WORDS_BIGENDIAN format = AUDIO_S16MSB; #else format = AUDIO_S16LSB; #endif } else { format = AUDIO_U8; } #ifdef USE_SDLMIXER if (GameArg.SndDisableSdlMixer) #endif { con_printf(CON_CRITICAL, "creating audio buffers:\n"); con_printf(CON_CRITICAL, "sample rate = %d, desired buffer = %d, stereo = %d, bitsize = %d, compressed = %d\n", sample_rate, desired_buffer, stereo, bitsize ? 16 : 8, compressed); } mve_audio_spec = (SDL_AudioSpec *)mve_alloc(sizeof(SDL_AudioSpec)); mve_audio_spec->freq = sample_rate; mve_audio_spec->format = format; mve_audio_spec->channels = (stereo) ? 2 : 1; mve_audio_spec->samples = 4096; mve_audio_spec->callback = mve_audio_callback; mve_audio_spec->userdata = NULL; // MD2211: if using SDL_Mixer, we never reinit the sound system #ifdef USE_SDLMIXER if (GameArg.SndDisableSdlMixer) #endif { if (SDL_OpenAudio(mve_audio_spec, NULL) >= 0) { con_printf(CON_CRITICAL, " success\n"); mve_audio_canplay = 1; } else { con_printf(CON_CRITICAL, " failure : %s\n", SDL_GetError()); mve_audio_canplay = 0; } } #ifdef USE_SDLMIXER else { // MD2211: using the same old SDL audio callback as a postmixer in SDL_mixer Mix_SetPostMix(mve_audio_spec->callback, mve_audio_spec->userdata); mve_audio_canplay = 1; } #endif memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); return 1; } static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail) { #ifdef USE_SDLMIXER if (GameArg.SndDisableSdlMixer) #endif SDL_PauseAudio(0); #ifdef USE_SDLMIXER else Mix_Pause(0); #endif mve_audio_playing = 1; } return 1; } static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { #ifdef USE_SDLMIXER // MD2211: for audio conversion SDL_AudioCVT cvt; int clen; int out_freq; Uint16 out_format; int out_channels; // end MD2211 #endif static const int selected_chan=1; int chan; int nsamp; if (mve_audio_canplay) { if (mve_audio_playing) SDL_LockAudio(); chan = get_ushort(data + 2); nsamp = get_ushort(data + 4); if (chan & selected_chan) { /* HACK: +4 mveaudio_uncompress adds 4 more bytes */ if (major == MVE_OPCODE_AUDIOFRAMEDATA) { if (mve_audio_compressed) { nsamp += 4; mve_audio_buflens[mve_audio_buftail] = nsamp; mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */ } else { nsamp -= 8; data += 8; mve_audio_buflens[mve_audio_buftail] = nsamp; mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp); } } else { mve_audio_buflens[mve_audio_buftail] = nsamp; mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */ } // MD2211: the following block does on-the-fly audio conversion for SDL_mixer #ifdef USE_SDLMIXER if (!GameArg.SndDisableSdlMixer) { // build converter: in = MVE format, out = SDL_mixer output Mix_QuerySpec(&out_freq, &out_format, &out_channels); // get current output settings SDL_BuildAudioCVT(&cvt, mve_audio_spec->format, mve_audio_spec->channels, mve_audio_spec->freq, out_format, out_channels, out_freq); clen = nsamp * cvt.len_mult; cvt.buf = malloc(clen); cvt.len = nsamp; // read the audio buffer into the conversion buffer memcpy(cvt.buf, mve_audio_buffers[mve_audio_buftail], nsamp); // do the conversion if (SDL_ConvertAudio(&cvt)) con_printf(CON_DEBUG,"audio conversion failed!\n"); // copy back to the audio buffer mve_free(mve_audio_buffers[mve_audio_buftail]); // free the old audio buffer mve_audio_buflens[mve_audio_buftail] = clen; mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(clen); memcpy(mve_audio_buffers[mve_audio_buftail], cvt.buf, clen); } #endif if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS) mve_audio_buftail = 0; if (mve_audio_buftail == mve_audio_bufhead) con_printf(CON_CRITICAL, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead); } if (mve_audio_playing) SDL_UnlockAudio(); } return 1; } /************************* * video handlers *************************/ static int videobuf_created = 0; static int video_initialized = 0; int g_width, g_height; void *g_vBuffers = NULL, *g_vBackBuf1, *g_vBackBuf2; static int g_destX, g_destY; static int g_screenWidth, g_screenHeight; static unsigned char *g_pCurMap=NULL; static int g_nMapLength=0; static int g_truecolor; static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { short w, h, #ifdef DEBUG count, #endif truecolor; if (videobuf_created) return 1; else videobuf_created = 1; w = get_short(data); h = get_short(data+2); #ifdef DEBUG if (minor > 0) { count = get_short(data+4); } else { count = 1; } #endif if (minor > 1) { truecolor = get_short(data+6); } else { truecolor = 0; } g_width = w << 3; g_height = h << 3; /* TODO: * 4 causes crashes on some files */ /* only malloc once */ if (g_vBuffers == NULL) g_vBackBuf1 = g_vBuffers = mve_alloc(g_width * g_height * 8); if (truecolor) { g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height); } else { g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height); } memset(g_vBackBuf1, 0, g_width * g_height * 4); #ifdef DEBUG con_printf(CON_CRITICAL, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor); #endif g_truecolor = truecolor; return 1; } static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { mve_showframe(g_vBackBuf1, g_destX, g_destY, g_width, g_height, g_screenWidth, g_screenHeight); g_frameUpdated = 1; return 1; } static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { short width, height; if (video_initialized) return 1; /* maybe we actually need to change width/height here? */ else video_initialized = 1; width = get_short(data); height = get_short(data+2); g_screenWidth = width; g_screenHeight = height; return 1; } static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { short start, count; unsigned char *p; start = get_short(data); count = get_short(data+2); p = data + 4; mve_setpalette(p - 3*start, start, count); return 1; } static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { g_pCurMap = data; g_nMapLength = len; return 1; } static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { unsigned short nFlags; unsigned char *temp; // don't need those but kept for further reference // nFrameHot = get_short(data); // nFrameCold = get_short(data+2); // nXoffset = get_short(data+4); // nYoffset = get_short(data+6); // nXsize = get_short(data+8); // nYsize = get_short(data+10); nFlags = get_ushort(data+12); if (nFlags & 1) { temp = (unsigned char *)g_vBackBuf1; g_vBackBuf1 = g_vBackBuf2; g_vBackBuf2 = temp; } /* convert the frame */ if (g_truecolor) { decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14); } else { decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14); } return 1; } static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { g_pCurMap=NULL; return 1; } static MVESTREAM *mve = NULL; void MVE_ioCallbacks(mve_cb_Read io_read) { mve_read = io_read; } void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free) { mve_alloc = mem_alloc; mve_free = mem_free; } void MVE_sfCallbacks(mve_cb_ShowFrame showframe) { mve_showframe = showframe; } void MVE_palCallbacks(mve_cb_SetPalette setpalette) { mve_setpalette = setpalette; } int MVE_rmPrepMovie(void *src, int x, int y, int track) { int i; if (mve) { mve_reset(mve); return 0; } mve = mve_open(src); if (!mve) return 1; g_destX = x; g_destY = y; for (i = 0; i < 32; i++) mve_set_handler(mve, i, default_seg_handler); mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler); mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler); mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler); mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler); mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler); mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler); mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler); mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler); mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler); mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler); mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler); mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler); mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler); mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler); mve_play_next_chunk(mve); /* video initialization chunk */ mve_play_next_chunk(mve); /* audio initialization chunk */ return 0; } void MVE_getVideoSpec(MVE_videoSpec *vSpec) { vSpec->screenWidth = g_screenWidth; vSpec->screenHeight = g_screenHeight; vSpec->width = g_width; vSpec->height = g_height; vSpec->truecolor = g_truecolor; } int MVE_rmStepMovie() { static int init_timer=0; int cont=1; if (!timer_started) timer_start(); while (cont && !g_frameUpdated) // make a "step" be a frame, not a chunk... cont = mve_play_next_chunk(mve); g_frameUpdated = 0; if (!cont) return MVE_ERR_EOF; if (micro_frame_delay && !init_timer) { timer_start(); init_timer = 1; } do_timer_wait(); return 0; } void MVE_rmEndMovie() { int i; timer_stop(); timer_created = 0; if (mve_audio_canplay) { // MD2211: if using SDL_Mixer, we never reinit sound, hence never close it #ifdef USE_SDLMIXER if (GameArg.SndDisableSdlMixer) #endif { SDL_CloseAudio(); } mve_audio_canplay = 0; } for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++) if (mve_audio_buffers[i] != NULL) mve_free(mve_audio_buffers[i]); memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); mve_audio_curbuf_curpos=0; mve_audio_bufhead=0; mve_audio_buftail=0; mve_audio_playing=0; mve_audio_canplay=0; mve_audio_compressed=0; if (mve_audio_spec) mve_free(mve_audio_spec); mve_audio_spec=NULL; audiobuf_created = 0; mve_free(g_vBuffers); g_vBuffers = NULL; g_pCurMap=NULL; g_nMapLength=0; videobuf_created = 0; video_initialized = 0; mve_close(mve); mve = NULL; } void MVE_rmHoldMovie() { timer_started = 0; } void MVE_sndInit(int x) { mve_audio_enabled = (x == -1 ? 0 : 1); } dxx-rebirth-0.58.1-d2x/libmve/mveplayer.1000066400000000000000000000043061217717237500201230ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH MVEPLAYER 1 "July 10, 2003" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME mveplayer \- Standalone MVE movie player. .SH SYNOPSIS .B mveplayer .RI [ options ] .RI filename.mv[e|l] .br .SH DESCRIPTION This manual page documents briefly the .B mveplayer command. This manual page was written for the Debian distribution because the original program does not have a manual page. .PP .B mveplayer is a standalone player for MVE movie files, like that found in the DESCENT II videogame and played by the D2X package. It supports all MVE files around, so if you find one that doesn't work, please report this as a bug. Note that the MVE files found in the Macintosh version of Descent II are not really MVE files, they appear to be some sort of quicktime-related format. If you give to .B mveplayer the name of an MVL file, i.e. an archive containing one ore more MVE files, it will print the full contents of the archive to stdout. You'll find some MVE files as part of the Descent II Registered datafiles. .SH OPTIONS A summary of options is included below. These command-line options do not appear to be documented elsewhere, so the only authoritive source is the source code itself. .TP .B \-h Usage screen. .TP .B \-f Fullscreen mode. .TP .B \-l Loop mode. Loop forever or until you press the Esc key. .TP .B \-s \fP\fIspeed factor\fP A decimal integer indicating the requested speed factor. .SH SEE ALSO .BR mvlextract (1), .BR mvlcreate (1), .BR hogextract (1), .BR hogcreate (1). .SH AUTHOR This manual page was written by Paolo Ulivi , for the Debian GNU/Linux system (but may be used by others). dxx-rebirth-0.58.1-d2x/main/000077500000000000000000000000001217717237500155005ustar00rootroot00000000000000dxx-rebirth-0.58.1-d2x/main/ai.c000066400000000000000000002016011217717237500162350ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Autonomous Individual movement. * */ #include #include #include #include "inferno.h" #include "game.h" #include "console.h" #include "3d.h" #include "object.h" #include "render.h" #include "dxxerror.h" #include "ai.h" #include "laser.h" #include "fvi.h" #include "polyobj.h" #include "bm.h" #include "weapon.h" #include "physics.h" #include "collide.h" #include "player.h" #include "wall.h" #include "vclip.h" #include "fireball.h" #include "morph.h" #include "effects.h" #include "timer.h" #include "sounds.h" #include "cntrlcen.h" #include "multibot.h" #ifdef NETWORK #include "multi.h" #endif #include "gameseq.h" #include "key.h" #include "powerup.h" #include "gauges.h" #include "text.h" #include "fuelcen.h" #include "controls.h" #include "kconfig.h" #ifdef EDITOR #include "editor/editor.h" #endif #include "string.h" #ifndef NDEBUG #include #endif // ---------- John: These variables must be saved as part of gamesave. -------- int Ai_initialized = 0; int Overall_agitation; ai_local Ai_local_info[MAX_OBJECTS]; point_seg Point_segs[MAX_POINT_SEGS]; point_seg *Point_segs_free_ptr = Point_segs; ai_cloak_info Ai_cloak_info[MAX_AI_CLOAK_INFO]; fix64 Boss_cloak_start_time = 0; fix64 Boss_cloak_end_time = 0; fix64 Last_teleport_time = 0; fix Boss_teleport_interval = F1_0*8; fix Boss_cloak_interval = F1_0*10; // Time between cloaks fix Boss_cloak_duration = BOSS_CLOAK_DURATION; fix64 Last_gate_time = 0; fix Gate_interval = F1_0*6; fix64 Boss_dying_start_time; fix64 Boss_hit_time; int Boss_dying; sbyte Boss_dying_sound_playing, unused123, unused234; // -- MK, 10/21/95, unused! -- int Boss_been_hit=0; // ------ John: End of variables which must be saved as part of gamesave. ----- // -- ubyte Boss_cloaks[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can cloak const ubyte Boss_teleports[NUM_D2_BOSSES] = {1,1,1,1,1,1, 1,1}; // Set byte if this boss can teleport const ubyte Boss_spew_more[NUM_D2_BOSSES] = {0,1,0,0,0,0, 0,0}; // If set, 50% of time, spew two bots. const ubyte Boss_spews_bots_energy[NUM_D2_BOSSES] = {1,1,0,1,0,1, 1,1}; // Set byte if boss spews bots when hit by energy weapon. const ubyte Boss_spews_bots_matter[NUM_D2_BOSSES] = {0,0,1,1,1,1, 0,1}; // Set byte if boss spews bots when hit by matter weapon. const ubyte Boss_invulnerable_energy[NUM_D2_BOSSES] = {0,0,1,1,0,0, 0,0}; // Set byte if boss is invulnerable to energy weapons. const ubyte Boss_invulnerable_matter[NUM_D2_BOSSES] = {0,0,0,0,1,1, 1,0}; // Set byte if boss is invulnerable to matter weapons. const ubyte Boss_invulnerable_spot[NUM_D2_BOSSES] = {0,0,0,0,0,1, 0,1}; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) int ai_evaded=0; // -- sbyte Super_boss_gate_list[MAX_GATE_INDEX] = {0, 1, 8, 9, 10, 11, 12, 15, 16, 18, 19, 20, 22, 0, 8, 11, 19, 20, 8, 20, 8}; int Animation_enabled = 1; #ifndef NDEBUG int Ai_info_enabled=0; #endif // These globals are set by a call to find_vector_intersection, which is a slow routine, // so we don't want to call it again (for this object) unless we have to. vms_vector Hit_pos; int Hit_type, Hit_seg; fvi_info Hit_data; int Num_awareness_events = 0; awareness_event Awareness_events[MAX_AWARENESS_EVENTS]; vms_vector Believed_player_pos; int Believed_player_seg; #ifndef NDEBUG // Index into this array with ailp->mode static const char mode_text[18][16] = { "STILL", "WANDER", "FOL_PATH", "CHASE_OBJ", "RUN_FROM", "BEHIND", "FOL_PATH2", "OPEN_DOOR", "GOTO_PLR", "GOTO_OBJ", "SN_ATT", "SN_FIRE", "SN_RETR", "SN_RTBK", "SN_WAIT", "TH_ATTACK", "TH_RETREAT", "TH_WAIT", }; // Index into this array with aip->behavior static const char behavior_text[6][9] = { "STILL ", "NORMAL ", "HIDE ", "RUN_FROM", "FOLPATH ", "STATION " }; // Index into this array with aip->GOAL_STATE or aip->CURRENT_STATE static const char state_text[8][5] = { "NONE", "REST", "SRCH", "LOCK", "FLIN", "FIRE", "RECO", "ERR_", }; #endif // Current state indicates where the robot current is, or has just done. // Transition table between states for an AI object. // First dimension is trigger event. // Second dimension is current state. // Third dimension is goal state. // Result is new goal state. // ERR_ means something impossible has happened. static const sbyte Ai_transition_table[AI_MAX_EVENT][AI_MAX_STATE][AI_MAX_STATE] = { { // Event = AIE_FIRE, a nearby object fired // none rest srch lock flin fire reco // CURRENT is rows, GOAL is columns { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO }, // none { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO }, // rest { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO }, // search { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO }, // lock { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO }, // flinch { AIS_ERR_, AIS_FIRE, AIS_FIRE, AIS_FIRE, AIS_FLIN, AIS_FIRE, AIS_RECO }, // fire { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE } // recoil }, // Event = AIE_HITT, a nearby object was hit (or a wall was hit) { { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE} }, // Event = AIE_COLL, player collided with robot { { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_LOCK, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_REST, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FIRE, AIS_RECO}, { AIS_ERR_, AIS_LOCK, AIS_LOCK, AIS_LOCK, AIS_FLIN, AIS_FIRE, AIS_FIRE} }, // Event = AIE_HURT, player hurt robot (by firing at and hitting it) // Note, this doesn't necessarily mean the robot JUST got hit, only that that is the most recent thing that happened. { { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN}, { AIS_ERR_, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN, AIS_FLIN} } }; fix Dist_to_last_fired_upon_player_pos = 0; // ---------------------------------------------------------------------------- void init_ai_frame(void) { int ab_state; Dist_to_last_fired_upon_player_pos = vm_vec_dist_quick(&Last_fired_upon_player_pos, &Believed_player_pos); ab_state = Afterburner_charge && Controls.afterburner_state && (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER); if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) || (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT_ON) || ab_state) { ai_do_cloak_stuff(); } } // ---------------------------------------------------------------------------- // Return firing status. // If ready to fire a weapon, return true, else return false. // Ready to fire a weapon if next_fire <= 0 or next_fire2 <= 0. int ready_to_fire(robot_info *robptr, ai_local *ailp) { if (robptr->weapon_type2 != -1) return (ailp->next_fire <= 0) || (ailp->next_fire2 <= 0); else return (ailp->next_fire <= 0); } // ---------------------------------------------------------------------------- // Make a robot near the player snipe. #define MNRS_SEG_MAX 70 void make_nearby_robot_snipe(void) { int bfs_length, i; short bfs_list[MNRS_SEG_MAX]; create_bfs_list(ConsoleObject->segnum, bfs_list, &bfs_length, MNRS_SEG_MAX); for (i=0; iid]; if ((objp->type == OBJ_ROBOT) && (objp->id != ROBOT_BRAIN)) { if ((objp->ctype.ai_info.behavior != AIB_SNIPE) && (objp->ctype.ai_info.behavior != AIB_RUN_FROM) && !Robot_info[objp->id].boss_flag && !robptr->companion) { objp->ctype.ai_info.behavior = AIB_SNIPE; Ai_local_info[objnum].mode = AIM_SNIPE_ATTACK; return; } } objnum = objp->next; } } } int Ai_last_missile_camera = -1; // -------------------------------------------------------------------------------------------------------------------- void do_ai_frame(object *obj) { int objnum = obj-Objects; ai_static *aip = &obj->ctype.ai_info; ai_local *ailp = &Ai_local_info[objnum]; fix dist_to_player; vms_vector vec_to_player; fix dot; robot_info *robptr; int player_visibility=-1; int obj_ref; int object_animates; int new_goal_state; int visibility_and_vec_computed = 0; int previous_visibility; vms_vector gun_point; vms_vector vis_vec_pos; ailp->next_action_time -= FrameTime; if (aip->SKIP_AI_COUNT) { aip->SKIP_AI_COUNT--; if (obj->mtype.phys_info.flags & PF_USES_THRUST) { obj->mtype.phys_info.rotthrust.x = (obj->mtype.phys_info.rotthrust.x * 15)/16; obj->mtype.phys_info.rotthrust.y = (obj->mtype.phys_info.rotthrust.y * 15)/16; obj->mtype.phys_info.rotthrust.z = (obj->mtype.phys_info.rotthrust.z * 15)/16; if (!aip->SKIP_AI_COUNT) obj->mtype.phys_info.flags &= ~PF_USES_THRUST; } return; } robptr = &Robot_info[obj->id]; Assert(robptr->always_0xabcd == 0xabcd); if (do_any_robot_dying_frame(obj)) return; // Kind of a hack. If a robot is flinching, but it is time for it to fire, unflinch it. // Else, you can turn a big nasty robot into a wimp by firing flares at it. // This also allows the player to see the cool flinch effect for mechs without unbalancing the game. if ((aip->GOAL_STATE == AIS_FLIN) && ready_to_fire(robptr, ailp)) { aip->GOAL_STATE = AIS_FIRE; } #ifndef NDEBUG if ((aip->behavior == AIB_RUN_FROM) && (ailp->mode != AIM_RUN_FROM_OBJECT)) Int3(); // This is peculiar. Behavior is run from, but mode is not. Contact Mike. if (!Do_ai_flag) return; if (Break_on_object != -1) if ((obj-Objects) == Break_on_object) Int3(); // Contact Mike: This is a debug break #endif //Assert((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR)); if (!((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR))) { aip->behavior = AIB_NORMAL; } Assert(obj->segnum != -1); Assert(obj->id < N_robot_types); obj_ref = objnum ^ d_tick_count; if (ailp->next_fire > -F1_0*8) ailp->next_fire -= FrameTime; if (robptr->weapon_type2 != -1) { if (ailp->next_fire2 > -F1_0*8) ailp->next_fire2 -= FrameTime; } else ailp->next_fire2 = F1_0*8; if (ailp->time_since_processed < F1_0*256) ailp->time_since_processed += FrameTime; previous_visibility = ailp->previous_visibility; // Must get this before we toast the master copy! // -- (No robots have this behavior...) // -- // Deal with cloaking for robots which are cloaked except just before firing. // -- if (robptr->cloak_type == RI_CLOAKED_EXCEPT_FIRING) // -- if (ailp->next_fire < F1_0/2) // -- aip->CLOAKED = 1; // -- else // -- aip->CLOAKED = 0; // If only awake because of a camera, make that the believed player position. if ((aip->SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE) && (Ai_last_missile_camera != -1)) Believed_player_pos = Objects[Ai_last_missile_camera].pos; else { if (cheats.robotskillrobots) { vis_vec_pos = obj->pos; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility) { int ii, min_obj = -1; fix min_dist = F1_0*200, cur_dist; for (ii=0; ii<=Highest_object_index; ii++) if ((Objects[ii].type == OBJ_ROBOT) && (ii != objnum)) { cur_dist = vm_vec_dist_quick(&obj->pos, &Objects[ii].pos); if (cur_dist < F1_0*100) if (object_to_object_visibility(obj, &Objects[ii], FQ_TRANSWALL)) if (cur_dist < min_dist) { min_obj = ii; min_dist = cur_dist; } } if (min_obj != -1) { Believed_player_pos = Objects[min_obj].pos; Believed_player_seg = Objects[min_obj].segnum; vm_vec_normalized_dir_quick(&vec_to_player, &Believed_player_pos, &obj->pos); } else goto _exit_cheat; } else goto _exit_cheat; } else { _exit_cheat: visibility_and_vec_computed = 0; if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) Believed_player_pos = ConsoleObject->pos; else Believed_player_pos = Ai_cloak_info[objnum & (MAX_AI_CLOAK_INFO-1)].last_position; } } dist_to_player = vm_vec_dist_quick(&Believed_player_pos, &obj->pos); // If this robot can fire, compute visibility from gun position. // Don't want to compute visibility twice, as it is expensive. (So is call to calc_gun_point). if ((previous_visibility || !(obj_ref & 3)) && ready_to_fire(robptr, ailp) && (dist_to_player < F1_0*200) && (robptr->n_guns) && !(robptr->attack_type)) { // Since we passed ready_to_fire(), either next_fire or next_fire2 <= 0. calc_gun_point from relevant one. // If both are <= 0, we will deal with the mess in ai_do_actual_firing_stuff if (ailp->next_fire <= 0) calc_gun_point(&gun_point, obj, aip->CURRENT_GUN); else calc_gun_point(&gun_point, obj, 0); vis_vec_pos = gun_point; } else { vis_vec_pos = obj->pos; vm_vec_zero(&gun_point); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Occasionally make non-still robots make a path to the player. Based on agitation and distance from player. if ((aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM) && (aip->behavior != AIB_STILL) && !(Game_mode & GM_MULTI) && (robptr->companion != 1) && (robptr->thief != 1)) if (Overall_agitation > 70) { if ((dist_to_player < F1_0*200) && (d_rand() < FrameTime/4)) { if (d_rand() * (Overall_agitation - 40) > F1_0*5) { create_path_to_player(obj, 4 + Overall_agitation/8 + Difficulty_level, 1); return; } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // If retry count not 0, then add it into consecutive_retries. // If it is 0, cut down consecutive_retries. // This is largely a hack to speed up physics and deal with stupid // AI. This is low level communication between systems of a sort // that should not be done. if ((ailp->retry_count) && !(Game_mode & GM_MULTI)) { ailp->consecutive_retries += ailp->retry_count; ailp->retry_count = 0; if (ailp->consecutive_retries > 3) { switch (ailp->mode) { case AIM_GOTO_PLAYER: // -- Buddy_got_stuck = 1; move_towards_segment_center(obj); create_path_to_player(obj, 100, 1); // -- Buddy_got_stuck = 0; break; case AIM_GOTO_OBJECT: Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; //if (obj->segnum == ConsoleObject->segnum) { // if (Point_segs[aip->hide_index + aip->cur_path_index].segnum == obj->segnum) // if ((aip->cur_path_index + aip->PATH_DIR >= 0) && (aip->cur_path_index + aip->PATH_DIR < aip->path_length-1)) // aip->cur_path_index += aip->PATH_DIR; //} break; case AIM_CHASE_OBJECT: create_path_to_player(obj, 4 + Overall_agitation/8 + Difficulty_level, 1); break; case AIM_STILL: if (robptr->attack_type) move_towards_segment_center(obj); else if (!((aip->behavior == AIB_STILL) || (aip->behavior == AIB_STATION) || (aip->behavior == AIB_FOLLOW))) // Behavior is still, so don't follow path. attempt_to_resume_path(obj); break; case AIM_FOLLOW_PATH: if (Game_mode & GM_MULTI) { ailp->mode = AIM_STILL; } else attempt_to_resume_path(obj); break; case AIM_RUN_FROM_OBJECT: move_towards_segment_center(obj); obj->mtype.phys_info.velocity.x = 0; obj->mtype.phys_info.velocity.y = 0; obj->mtype.phys_info.velocity.z = 0; create_n_segment_path(obj, 5, -1); ailp->mode = AIM_RUN_FROM_OBJECT; break; case AIM_BEHIND: move_towards_segment_center(obj); obj->mtype.phys_info.velocity.x = 0; obj->mtype.phys_info.velocity.y = 0; obj->mtype.phys_info.velocity.z = 0; break; case AIM_OPEN_DOOR: create_n_segment_path_to_door(obj, 5, -1); break; #ifndef NDEBUG case AIM_FOLLOW_PATH_2: Int3(); // Should never happen! break; #endif } ailp->consecutive_retries = 0; } } else ailp->consecutive_retries /= 2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // If in materialization center, exit if (!(Game_mode & GM_MULTI) && (Segment2s[obj->segnum].special == SEGMENT_IS_ROBOTMAKER)) { if (Station[Segment2s[obj->segnum].value].Enabled) { ai_follow_path(obj, 1, 1, NULL); // 1 = player is visible, which might be a lie, but it works. return; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Decrease player awareness due to the passage of time. if (ailp->player_awareness_type) { if (ailp->player_awareness_time > 0) { ailp->player_awareness_time -= FrameTime; if (ailp->player_awareness_time <= 0) { ailp->player_awareness_time = F1_0*2; //new: 11/05/94 ailp->player_awareness_type--; //new: 11/05/94 } } else { ailp->player_awareness_type--; ailp->player_awareness_time = F1_0*2; //aip->GOAL_STATE = AIS_REST; } } else aip->GOAL_STATE = AIS_REST; //new: 12/13/94 if (Player_is_dead && (ailp->player_awareness_type == 0)) if ((dist_to_player < F1_0*200) && (d_rand() < FrameTime/8)) { if ((aip->behavior != AIB_STILL) && (aip->behavior != AIB_RUN_FROM)) { if (!ai_multiplayer_awareness(obj, 30)) return; #ifndef SHAREWARE ai_multi_send_robot_position(objnum, -1); #endif if (!((ailp->mode == AIM_FOLLOW_PATH) && (aip->cur_path_index < aip->path_length-1))) if ((aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM)) { if (dist_to_player < F1_0*30) create_n_segment_path(obj, 5, 1); else create_path_to_player(obj, 20, 1); } } } // -- // Make sure that if this guy got hit or bumped, then he's chasing player. // -- if ((ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) || (ailp->player_awareness_type >= PA_PLAYER_COLLISION)) { // -- if ((ailp->mode != AIM_BEHIND) && (aip->behavior != AIB_STILL) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_RUN_FROM) && (!robptr->companion) && (!robptr->thief) && (obj->id != ROBOT_BRAIN)) { // -- ailp->mode = AIM_CHASE_OBJECT; // -- ailp->player_awareness_type = 0; // -- ailp->player_awareness_time = 0; // -- } // -- } // Make sure that if this guy got hit or bumped, then he's chasing player. if ((ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) || (ailp->player_awareness_type >= PA_PLAYER_COLLISION)) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 1) // Only increase visibility if unobstructed, else claw guys attack through doors. player_visibility = 2; } else if (((obj_ref&3) == 0) && !previous_visibility && (dist_to_player < F1_0*100)) { fix sval, rval; rval = d_rand(); sval = (dist_to_player * (Difficulty_level+1))/64; if ((fixmul(rval, sval) < FrameTime) || (Players[Player_num].flags & PLAYER_FLAGS_HEADLIGHT_ON)) { ailp->player_awareness_type = PA_PLAYER_COLLISION; ailp->player_awareness_time = F1_0*3; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 1) { player_visibility = 2; } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ((aip->GOAL_STATE == AIS_FLIN) && (aip->CURRENT_STATE == AIS_FLIN)) aip->GOAL_STATE = AIS_LOCK; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Note: Should only do these two function calls for objects which animate if (Animation_enabled && (dist_to_player < F1_0*100)) { // && !(Game_mode & GM_MULTI)) { object_animates = do_silly_animation(obj); if (object_animates) ai_frame_animation(obj); } else { // If Object is supposed to animate, but we don't let it animate due to distance, then // we must change its state, else it will never update. aip->CURRENT_STATE = aip->GOAL_STATE; object_animates = 0; // If we're not doing the animation, then should pretend it doesn't animate. } switch (Robot_info[obj->id].boss_flag) { case 0: break; case 1: case 2: // FIXME!!!! break; default: { int pv; if (aip->GOAL_STATE == AIS_FLIN) aip->GOAL_STATE = AIS_FIRE; if (aip->CURRENT_STATE == AIS_FLIN) aip->CURRENT_STATE = AIS_FIRE; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); pv = player_visibility; // If player cloaked, visibility is screwed up and superboss will gate in robots when not supposed to. if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { pv = 0; } do_boss_stuff(obj, pv); } break; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Time-slice, don't process all the time, purely an efficiency hack. // Guys whose behavior is station and are not at their hide segment get processed anyway. if (!((aip->behavior == AIB_SNIPE) && (ailp->mode != AIM_SNIPE_WAIT)) && !robptr->companion && !robptr->thief && (ailp->player_awareness_type < PA_WEAPON_ROBOT_COLLISION-1)) { // If robot got hit, he gets to attack player always! #ifndef NDEBUG if (Break_on_object != objnum) { // don't time slice if we're interested in this object. #endif if ((aip->behavior == AIB_STATION) && (ailp->mode == AIM_FOLLOW_PATH) && (aip->hide_segment != obj->segnum)) { if (dist_to_player > F1_0*250) // station guys not at home always processed until 250 units away. return; } else if ((!ailp->previous_visibility) && ((dist_to_player >> 7) > ailp->time_since_processed)) { // 128 units away (6.4 segments) processed after 1 second. return; } #ifndef NDEBUG } #endif } // Reset time since processed, but skew objects so not everything // processed synchronously, else we get fast frames with the // occasional very slow frame. // AI_proc_time = ailp->time_since_processed; ailp->time_since_processed = - ((objnum & 0x03) * FrameTime ) / 2; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Perform special ability switch (obj->id) { case ROBOT_BRAIN: // Robots function nicely if behavior is Station. This // means they won't move until they can see the player, at // which time they will start wandering about opening doors. if (ConsoleObject->segnum == obj->segnum) { if (!ai_multiplayer_awareness(obj, 97)) return; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); move_away_from_player(obj, &vec_to_player, 0); ai_multi_send_robot_position(objnum, -1); } else if (ailp->mode != AIM_STILL) { int r; r = openable_doors_in_segment(obj->segnum); if (r != -1) { ailp->mode = AIM_OPEN_DOOR; aip->GOALSIDE = r; } else if (ailp->mode != AIM_FOLLOW_PATH) { if (!ai_multiplayer_awareness(obj, 50)) return; create_n_segment_path_to_door(obj, 8+Difficulty_level, -1); // third parameter is avoid_seg, -1 means avoid nothing. ai_multi_send_robot_position(objnum, -1); } if (ailp->next_action_time < 0) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility) { make_nearby_robot_snipe(); ailp->next_action_time = (NDL - Difficulty_level) * 2*F1_0; } } } else { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility) { if (!ai_multiplayer_awareness(obj, 50)) return; create_n_segment_path_to_door(obj, 8+Difficulty_level, -1); // third parameter is avoid_seg, -1 means avoid nothing. ai_multi_send_robot_position(objnum, -1); } } break; default: break; } if (aip->behavior == AIB_SNIPE) { if ((Game_mode & GM_MULTI) && !robptr->thief) { aip->behavior = AIB_NORMAL; ailp->mode = AIM_CHASE_OBJECT; return; } if (!(obj_ref & 3) || previous_visibility) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); // If this sniper is in still mode, if he was hit or can see player, switch to snipe mode. if (ailp->mode == AIM_STILL) if (player_visibility || (ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION)) ailp->mode = AIM_SNIPE_ATTACK; if (!robptr->thief && (ailp->mode != AIM_STILL)) do_snipe_frame(obj, dist_to_player, player_visibility, &vec_to_player); } else if (!robptr->thief && !robptr->companion) return; } // More special ability stuff, but based on a property of a robot, not its ID. if (robptr->companion) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); do_escort_frame(obj, dist_to_player, player_visibility); if (obj->ctype.ai_info.danger_laser_num != -1) { object *dobjp = &Objects[obj->ctype.ai_info.danger_laser_num]; if ((dobjp->type == OBJ_WEAPON) && (dobjp->signature == obj->ctype.ai_info.danger_laser_signature)) { fix circle_distance; circle_distance = robptr->circle_distance[Difficulty_level] + ConsoleObject->size; ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, circle_distance, 1, player_visibility); } } if (ready_to_fire(robptr, ailp)) { int do_stuff = 0; if (openable_doors_in_segment(obj->segnum) != -1) do_stuff = 1; else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + aip->PATH_DIR].segnum) != -1) do_stuff = 1; else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + 2*aip->PATH_DIR].segnum) != -1) do_stuff = 1; else if ((ailp->mode == AIM_GOTO_PLAYER) && (dist_to_player < 3*MIN_ESCORT_DISTANCE/2) && (vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player) > -F1_0/4)) { do_stuff = 1; } if (do_stuff) { Laser_create_new_easy( &obj->orient.fvec, &obj->pos, obj-Objects, FLARE_ID, 1); ailp->next_fire = F1_0/2; if (!Buddy_allowed_to_talk) // If buddy not talking, make him fire flares less often. ailp->next_fire += d_rand()*4; } } } if (robptr->thief) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); do_thief_frame(obj, dist_to_player, player_visibility, &vec_to_player); if (ready_to_fire(robptr, ailp)) { int do_stuff = 0; if (openable_doors_in_segment(obj->segnum) != -1) do_stuff = 1; else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + aip->PATH_DIR].segnum) != -1) do_stuff = 1; else if (openable_doors_in_segment(Point_segs[aip->hide_index + aip->cur_path_index + 2*aip->PATH_DIR].segnum) != -1) do_stuff = 1; if (do_stuff) { // @mk, 05/08/95: Firing flare from center of object, this is dumb... Laser_create_new_easy( &obj->orient.fvec, &obj->pos, obj-Objects, FLARE_ID, 1); ailp->next_fire = F1_0/2; if (Stolen_item_index == 0) // If never stolen an item, fire flares less often (bad: Stolen_item_index wraps, but big deal) ailp->next_fire += d_rand()*4; } } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - switch (ailp->mode) { case AIM_CHASE_OBJECT: { // chasing player, sort of, chase if far, back off if close, circle in between fix circle_distance; circle_distance = robptr->circle_distance[Difficulty_level] + ConsoleObject->size; // Green guy doesn't get his circle distance boosted, else he might never attack. if (robptr->attack_type != 1) circle_distance += (objnum&0xf) * F1_0/2; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); // @mk, 12/27/94, structure here was strange. Would do both clauses of what are now this if/then/else. Used to be if/then, if/then. if ((player_visibility < 2) && (previous_visibility == 2)) { // this is redundant: mk, 01/15/95: && (ailp->mode == AIM_CHASE_OBJECT)) { if (!ai_multiplayer_awareness(obj, 53)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } create_path_to_player(obj, 8, 1); ai_multi_send_robot_position(objnum, -1); } else if ((player_visibility == 0) && (dist_to_player > F1_0*80) && (!(Game_mode & GM_MULTI))) { // If pretty far from the player, player cannot be seen // (obstructed) and in chase mode, switch to follow path mode. // This has one desirable benefit of avoiding physics retries. if (aip->behavior == AIB_STATION) { ailp->goal_segment = aip->hide_segment; create_path_to_station(obj, 15); } // -- this looks like a dumb thing to do...robots following paths far away from you! else create_n_segment_path(obj, 5, -1); break; } if ((aip->CURRENT_STATE == AIS_REST) && (aip->GOAL_STATE == AIS_REST)) { if (player_visibility) { if (d_rand() < FrameTime*player_visibility) { if (dist_to_player/256 < d_rand()*player_visibility) { aip->GOAL_STATE = AIS_SRCH; aip->CURRENT_STATE = AIS_SRCH; } } } } if (GameTime64 - ailp->time_player_seen > CHASE_TIME_LENGTH) { if (Game_mode & GM_MULTI) if (!player_visibility && (dist_to_player > F1_0*70)) { ailp->mode = AIM_STILL; return; } if (!ai_multiplayer_awareness(obj, 64)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } } else if ((aip->CURRENT_STATE != AIS_REST) && (aip->GOAL_STATE != AIS_REST)) { if (!ai_multiplayer_awareness(obj, 70)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, circle_distance, 0, player_visibility); if ((obj_ref & 1) && ((aip->GOAL_STATE == AIS_SRCH) || (aip->GOAL_STATE == AIS_LOCK))) { if (player_visibility) // == 2) ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); } if (ai_evaded) { ai_multi_send_robot_position(objnum, 1); ai_evaded = 0; } else ai_multi_send_robot_position(objnum, -1); do_firing_stuff(obj, player_visibility, &vec_to_player); } break; } case AIM_RUN_FROM_OBJECT: compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility) { if (ailp->player_awareness_type == 0) ailp->player_awareness_type = PA_WEAPON_ROBOT_COLLISION; } // If in multiplayer, only do if player visible. If not multiplayer, do always. if (!(Game_mode & GM_MULTI) || player_visibility) if (ai_multiplayer_awareness(obj, 75)) { ai_follow_path(obj, player_visibility, previous_visibility, &vec_to_player); ai_multi_send_robot_position(objnum, -1); } if (aip->GOAL_STATE != AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; else if (aip->CURRENT_STATE == AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; // Bad to let run_from robot fire at player because it // will cause a war in which it turns towards the player // to fire and then towards its goal to move. // do_firing_stuff(obj, player_visibility, &vec_to_player); // Instead, do this: // (Note, only drop if player is visible. This prevents // the bombs from being a giveaway, and also ensures that // the robot is moving while it is dropping. Also means // fewer will be dropped.) if ((ailp->next_fire <= 0) && (player_visibility)) { vms_vector fire_vec, fire_pos; if (!ai_multiplayer_awareness(obj, 75)) return; fire_vec = obj->orient.fvec; vm_vec_negate(&fire_vec); vm_vec_add(&fire_pos, &obj->pos, &fire_vec); if (aip->SUB_FLAGS & SUB_FLAGS_SPROX) Laser_create_new_easy( &fire_vec, &fire_pos, obj-Objects, ROBOT_SUPERPROX_ID, 1); else Laser_create_new_easy( &fire_vec, &fire_pos, obj-Objects, PROXIMITY_ID, 1); ailp->next_fire = (F1_0/2)*(NDL+5 - Difficulty_level); // Drop a proximity bomb every 5 seconds. #ifdef NETWORK #ifndef SHAREWARE if (Game_mode & GM_MULTI) { ai_multi_send_robot_position(obj-Objects, -1); if (aip->SUB_FLAGS & SUB_FLAGS_SPROX) multi_send_robot_fire(obj-Objects, -2, &fire_vec); else multi_send_robot_fire(obj-Objects, -1, &fire_vec); } #endif #endif } break; case AIM_GOTO_PLAYER: case AIM_GOTO_OBJECT: ai_follow_path(obj, 2, previous_visibility, &vec_to_player); // Follows path as if player can see robot. ai_multi_send_robot_position(objnum, -1); break; case AIM_FOLLOW_PATH: { int anger_level = 65; if (aip->behavior == AIB_STATION) if (Point_segs[aip->hide_index + aip->path_length - 1].segnum == aip->hide_segment) { anger_level = 64; } compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (!ai_multiplayer_awareness(obj, anger_level)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); } return; } ai_follow_path(obj, player_visibility, previous_visibility, &vec_to_player); if (aip->GOAL_STATE != AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; else if (aip->CURRENT_STATE == AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; if (aip->behavior != AIB_RUN_FROM) do_firing_stuff(obj, player_visibility, &vec_to_player); if ((player_visibility == 2) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_FOLLOW) && (aip->behavior != AIB_RUN_FROM) && (obj->id != ROBOT_BRAIN) && (robptr->companion != 1) && (robptr->thief != 1)) { if (robptr->attack_type == 0) ailp->mode = AIM_CHASE_OBJECT; // This should not just be distance based, but also time-since-player-seen based. } else if ((dist_to_player > F1_0*(20*(2*Difficulty_level + robptr->pursuit))) && (GameTime64 - ailp->time_player_seen > (F1_0/2*(Difficulty_level+robptr->pursuit))) && (player_visibility == 0) && (aip->behavior == AIB_NORMAL) && (ailp->mode == AIM_FOLLOW_PATH)) { ailp->mode = AIM_STILL; aip->hide_index = -1; aip->path_length = 0; } ai_multi_send_robot_position(objnum, -1); break; } case AIM_BEHIND: if (!ai_multiplayer_awareness(obj, 71)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); } return; } compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 2) { // Get behind the player. // Method: // If vec_to_player dot player_rear_vector > 0, behind is goal. // Else choose goal with larger dot from left, right. vms_vector goal_point, goal_vector, vec_to_goal, rand_vec; fix dot; dot = vm_vec_dot(&ConsoleObject->orient.fvec, &vec_to_player); if (dot > 0) { // Remember, we're interested in the rear vector dot being < 0. goal_vector = ConsoleObject->orient.fvec; vm_vec_negate(&goal_vector); } else { fix dot; dot = vm_vec_dot(&ConsoleObject->orient.rvec, &vec_to_player); goal_vector = ConsoleObject->orient.rvec; if (dot > 0) { vm_vec_negate(&goal_vector); } } vm_vec_scale(&goal_vector, 2*(ConsoleObject->size + obj->size + (((objnum*4 + d_tick_count) & 63) << 12))); vm_vec_add(&goal_point, &ConsoleObject->pos, &goal_vector); make_random_vector(&rand_vec); vm_vec_scale_add2(&goal_point, &rand_vec, F1_0*8); vm_vec_sub(&vec_to_goal, &goal_point, &obj->pos); vm_vec_normalize_quick(&vec_to_goal); move_towards_vector(obj, &vec_to_goal, 0); ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); } if (aip->GOAL_STATE != AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; else if (aip->CURRENT_STATE == AIS_FLIN) aip->GOAL_STATE = AIS_LOCK; ai_multi_send_robot_position(objnum, -1); break; case AIM_STILL: if ((dist_to_player < F1_0*120+Difficulty_level*F1_0*20) || (ailp->player_awareness_type >= PA_WEAPON_ROBOT_COLLISION-1)) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); // turn towards vector if visible this time or last time, or rand // new! if ((player_visibility == 2) || (previous_visibility == 2)) { // -- MK, 06/09/95: || ((d_rand() > 0x4000) && !(Game_mode & GM_MULTI))) { if (!ai_multiplayer_awareness(obj, 71)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_multi_send_robot_position(objnum, -1); } do_firing_stuff(obj, player_visibility, &vec_to_player); if (player_visibility == 2) { // Changed @mk, 09/21/95: Require that they be looking to evade. Change, MK, 01/03/95 for Multiplayer reasons. If robots can't see you (even with eyes on back of head), then don't do evasion. if (robptr->attack_type == 1) { aip->behavior = AIB_NORMAL; if (!ai_multiplayer_awareness(obj, 80)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 0, player_visibility); if (ai_evaded) { ai_multi_send_robot_position(objnum, 1); ai_evaded = 0; } else ai_multi_send_robot_position(objnum, -1); } else { // Robots in hover mode are allowed to evade at half normal speed. if (!ai_multiplayer_awareness(obj, 81)) { if (maybe_ai_do_actual_firing_stuff(obj, aip)) ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 1, player_visibility); if (ai_evaded) { ai_multi_send_robot_position(objnum, -1); ai_evaded = 0; } else ai_multi_send_robot_position(objnum, -1); } } else if ((obj->segnum != aip->hide_segment) && (dist_to_player > F1_0*80) && (!(Game_mode & GM_MULTI))) { // If pretty far from the player, player cannot be // seen (obstructed) and in chase mode, switch to // follow path mode. // This has one desirable benefit of avoiding physics retries. if (aip->behavior == AIB_STATION) { ailp->goal_segment = aip->hide_segment; create_path_to_station(obj, 15); } break; } } break; case AIM_OPEN_DOOR: { // trying to open a door. vms_vector center_point, goal_vector; Assert(obj->id == ROBOT_BRAIN); // Make sure this guy is allowed to be in this mode. if (!ai_multiplayer_awareness(obj, 62)) return; compute_center_point_on_side(¢er_point, &Segments[obj->segnum], aip->GOALSIDE); vm_vec_sub(&goal_vector, ¢er_point, &obj->pos); vm_vec_normalize_quick(&goal_vector); ai_turn_towards_vector(&goal_vector, obj, robptr->turn_time[Difficulty_level]); move_towards_vector(obj, &goal_vector, 0); ai_multi_send_robot_position(objnum, -1); break; } case AIM_SNIPE_WAIT: break; case AIM_SNIPE_RETREAT: // -- if (ai_multiplayer_awareness(obj, 53)) // -- if (ailp->next_fire < -F1_0) // -- ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); break; case AIM_SNIPE_RETREAT_BACKWARDS: case AIM_SNIPE_ATTACK: case AIM_SNIPE_FIRE: if (ai_multiplayer_awareness(obj, 53)) { ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); if (robptr->thief) ai_move_relative_to_player(obj, ailp, dist_to_player, &vec_to_player, 0, 0, player_visibility); break; } break; case AIM_THIEF_WAIT: case AIM_THIEF_ATTACK: case AIM_THIEF_RETREAT: case AIM_WANDER: // Used for Buddy Bot break; default: ailp->mode = AIM_CHASE_OBJECT; break; } // end: switch (ailp->mode) { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // If the robot can see you, increase his awareness of you. // This prevents the problem of a robot looking right at you but doing nothing. // Assert(player_visibility != -1); // Means it didn't get initialized! compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if ((player_visibility == 2) && (aip->behavior != AIB_FOLLOW) && (!robptr->thief)) { if ((ailp->player_awareness_type == 0) && (aip->SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE)) aip->SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; else if (ailp->player_awareness_type == 0) ailp->player_awareness_type = PA_PLAYER_COLLISION; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (!object_animates) { aip->CURRENT_STATE = aip->GOAL_STATE; } Assert(ailp->player_awareness_type <= AIE_MAX); Assert(aip->CURRENT_STATE < AIS_MAX); Assert(aip->GOAL_STATE < AIS_MAX); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (ailp->player_awareness_type) { new_goal_state = Ai_transition_table[ailp->player_awareness_type-1][aip->CURRENT_STATE][aip->GOAL_STATE]; if (ailp->player_awareness_type == PA_WEAPON_ROBOT_COLLISION) { // Decrease awareness, else this robot will flinch every frame. ailp->player_awareness_type--; ailp->player_awareness_time = F1_0*3; } if (new_goal_state == AIS_ERR_) new_goal_state = AIS_REST; if (aip->CURRENT_STATE == AIS_NONE) aip->CURRENT_STATE = AIS_REST; aip->GOAL_STATE = new_goal_state; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // If new state = fire, then set all gun states to fire. if ((aip->GOAL_STATE == AIS_FIRE) ) { int i,num_guns; num_guns = Robot_info[obj->id].n_guns; for (i=0; igoal_state[i] = AIS_FIRE; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Hack by mk on 01/04/94, if a guy hasn't animated to the firing state, but his next_fire says ok to fire, bash him there if (ready_to_fire(robptr, ailp) && (aip->GOAL_STATE == AIS_FIRE)) aip->CURRENT_STATE = AIS_FIRE; if ((aip->GOAL_STATE != AIS_FLIN) && (obj->id != ROBOT_BRAIN)) { switch (aip->CURRENT_STATE) { case AIS_NONE: compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); dot = vm_vec_dot(&obj->orient.fvec, &vec_to_player); if (dot >= F1_0/2) if (aip->GOAL_STATE == AIS_REST) aip->GOAL_STATE = AIS_SRCH; break; case AIS_REST: if (aip->GOAL_STATE == AIS_REST) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (ready_to_fire(robptr, ailp) && (player_visibility)) { aip->GOAL_STATE = AIS_FIRE; } } break; case AIS_SRCH: if (!ai_multiplayer_awareness(obj, 60)) return; compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 2) { ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_multi_send_robot_position(objnum, -1); } break; case AIS_LOCK: compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (!(Game_mode & GM_MULTI) || (player_visibility)) { if (!ai_multiplayer_awareness(obj, 68)) return; if (player_visibility == 2) { // @mk, 09/21/95, require that they be looking towards you to turn towards you. ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_multi_send_robot_position(objnum, -1); } } break; case AIS_FIRE: compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 2) { if (!ai_multiplayer_awareness(obj, (ROBOT_FIRE_AGITATION-1))) { if (Game_mode & GM_MULTI) { ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); return; } } ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_multi_send_robot_position(objnum, -1); } // Fire at player, if appropriate. ai_do_actual_firing_stuff(obj, aip, ailp, robptr, &vec_to_player, dist_to_player, &gun_point, player_visibility, object_animates, aip->CURRENT_GUN); break; case AIS_RECO: if (!(obj_ref & 3)) { compute_vis_and_vec(obj, &vis_vec_pos, ailp, &vec_to_player, &player_visibility, robptr, &visibility_and_vec_computed); if (player_visibility == 2) { if (!ai_multiplayer_awareness(obj, 69)) return; ai_turn_towards_vector(&vec_to_player, obj, robptr->turn_time[Difficulty_level]); ai_multi_send_robot_position(objnum, -1); } // -- MK, 06/09/95: else if (!(Game_mode & GM_MULTI)) { } break; case AIS_FLIN: break; default: aip->GOAL_STATE = AIS_REST; aip->CURRENT_STATE = AIS_REST; break; } } // end of: if (aip->GOAL_STATE != AIS_FLIN) { // Switch to next gun for next fire. if (player_visibility == 0) { aip->CURRENT_GUN++; if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) { if ((robptr->n_guns == 1) || (robptr->weapon_type2 == -1)) // Two weapon types hack. aip->CURRENT_GUN = 0; else aip->CURRENT_GUN = 1; } } } // ---------------------------------------------------------------------------- void ai_do_cloak_stuff(void) { int i; for (i=0; ipos; Ai_cloak_info[i].last_segment = ConsoleObject->segnum; Ai_cloak_info[i].last_time = GameTime64; } // Make work for control centers. Believed_player_pos = Ai_cloak_info[0].last_position; Believed_player_seg = Ai_cloak_info[0].last_segment; } // ---------------------------------------------------------------------------- // Returns false if awareness is considered too puny to add, else returns true. int add_awareness_event(object *objp, int type) { // If player cloaked and hit a robot, then increase awareness if ((type == PA_WEAPON_ROBOT_COLLISION) || (type == PA_WEAPON_WALL_COLLISION) || (type == PA_PLAYER_COLLISION)) ai_do_cloak_stuff(); if (Num_awareness_events < MAX_AWARENESS_EVENTS) { if ((type == PA_WEAPON_WALL_COLLISION) || (type == PA_WEAPON_ROBOT_COLLISION)) if (objp->id == VULCAN_ID) if (d_rand() > 3276) return 0; // For vulcan cannon, only about 1/10 actually cause awareness Awareness_events[Num_awareness_events].segnum = objp->segnum; Awareness_events[Num_awareness_events].pos = objp->pos; Awareness_events[Num_awareness_events].type = type; Num_awareness_events++; } else { //Int3(); // Hey -- Overflowed Awareness_events, make more or something // This just gets ignored, so you can just // continue. } return 1; } // ---------------------------------------------------------------------------------- // Robots will become aware of the player based on something that occurred. // The object (probably player or weapon) which created the awareness is objp. void create_awareness_event(object *objp, int type) { // If not in multiplayer, or in multiplayer with robots, do this, else unnecessary! if (!(Game_mode & GM_MULTI) || (Game_mode & GM_MULTI_ROBOTS)) { if (add_awareness_event(objp, type)) { if (((d_rand() * (type+4)) >> 15) > 4) Overall_agitation++; if (Overall_agitation > OVERALL_AGITATION_MAX) Overall_agitation = OVERALL_AGITATION_MAX; } } } sbyte New_awareness[MAX_SEGMENTS]; // ---------------------------------------------------------------------------------- void pae_aux(int segnum, int type, int level) { int j; if (New_awareness[segnum] < type) New_awareness[segnum] = type; // Process children. for (j=0; j Ai_local_info[i].player_awareness_type) { Ai_local_info[i].player_awareness_type = New_awareness[Objects[i].segnum]; Ai_local_info[i].player_awareness_time = PLAYER_AWARENESS_INITIAL_TIME; } // Clear the bit that says this robot is only awake because a camera woke it up. if (New_awareness[Objects[i].segnum] > Ai_local_info[i].player_awareness_type) Objects[i].ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; } } #ifndef NDEBUG int Ai_dump_enable = 0; FILE *Ai_dump_file = NULL; char Ai_error_message[128] = ""; // ---------------------------------------------------------------------------------- void force_dump_ai_objects_all(char *msg) { int tsave; tsave = Ai_dump_enable; Ai_dump_enable = 1; sprintf(Ai_error_message, "%s\n", msg); //dump_ai_objects_all(); Ai_error_message[0] = 0; Ai_dump_enable = tsave; } // ---------------------------------------------------------------------------------- void turn_off_ai_dump(void) { if (Ai_dump_file != NULL) fclose(Ai_dump_file); Ai_dump_file = NULL; } #endif extern void do_boss_dying_frame(object *objp); // ---------------------------------------------------------------------------------- // Do things which need to get done for all AI objects each frame. // This includes: // Setting player_awareness (a fix, time in seconds which object is aware of player) void do_ai_frame_all(void) { #ifndef NDEBUG //dump_ai_objects_all(); #endif set_player_awareness_all(); if (Ai_last_missile_camera > -1) { // Clear if supposed misisle camera is not a weapon, or just every so often, just in case. if (((d_tick_count & 0x0f) == 0) || (Objects[Ai_last_missile_camera].type != OBJ_WEAPON)) { int i; Ai_last_missile_camera = -1; for (i=0; i<=Highest_object_index; i++) if (Objects[i].type == OBJ_ROBOT) Objects[i].ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_CAMERA_AWAKE; } } // (Moved here from do_boss_stuff() because that only gets called if robot aware of player.) if (Boss_dying) { int i; for (i=0; i<=Highest_object_index; i++) if (Objects[i].type == OBJ_ROBOT) if (Robot_info[Objects[i].id].boss_flag) do_boss_dying_frame(&Objects[i]); } } extern int Final_boss_is_dead; extern fix Boss_invulnerable_dot; // Initializations to be performed for all robots for a new level. void init_robots_for_level(void) { Overall_agitation = 0; Final_boss_is_dead=0; Buddy_objnum = 0; Buddy_allowed_to_talk = 0; Boss_invulnerable_dot = F1_0/4 - i2f(Difficulty_level)/8; Boss_dying_start_time = 0; Ai_last_missile_camera = -1; } // Following functions convert ai_local/ai_cloak_info to ai_local/ai_cloak_info_rw to be written to/read from Savegames. Convertin back is not done here - reading is done specifically together with swapping (if necessary). These structs differ in terms of timer values (fix/fix64). as we reset GameTime64 for writing so it can fit into fix it's not necessary to increment savegame version. But if we once store something else into object which might be useful after restoring, it might be handy to increment Savegame version and actually store these new infos. void state_ai_local_to_ai_local_rw(ai_local *ail, ai_local_rw *ail_rw) { int i = 0; ail_rw->player_awareness_type = ail->player_awareness_type; ail_rw->retry_count = ail->retry_count; ail_rw->consecutive_retries = ail->consecutive_retries; ail_rw->mode = ail->mode; ail_rw->previous_visibility = ail->previous_visibility; ail_rw->rapidfire_count = ail->rapidfire_count; ail_rw->goal_segment = ail->goal_segment; ail_rw->next_action_time = ail->next_action_time; ail_rw->next_fire = ail->next_fire; ail_rw->next_fire2 = ail->next_fire2; ail_rw->player_awareness_time = ail->player_awareness_time; if (ail->time_player_seen - GameTime64 < F1_0*(-18000)) ail_rw->time_player_seen = F1_0*(-18000); else ail_rw->time_player_seen = ail->time_player_seen - GameTime64; if (ail->time_player_sound_attacked - GameTime64 < F1_0*(-18000)) ail_rw->time_player_sound_attacked = F1_0*(-18000); else ail_rw->time_player_sound_attacked = ail->time_player_sound_attacked - GameTime64; ail_rw->time_player_sound_attacked = ail->time_player_sound_attacked; ail_rw->next_misc_sound_time = ail->next_misc_sound_time - GameTime64; ail_rw->time_since_processed = ail->time_since_processed; for (i = 0; i < MAX_SUBMODELS; i++) { ail_rw->goal_angles[i].p = ail->goal_angles[i].p; ail_rw->goal_angles[i].b = ail->goal_angles[i].b; ail_rw->goal_angles[i].h = ail->goal_angles[i].h; ail_rw->delta_angles[i].p = ail->delta_angles[i].p; ail_rw->delta_angles[i].b = ail->delta_angles[i].b; ail_rw->delta_angles[i].h = ail->delta_angles[i].h; ail_rw->goal_state[i] = ail->goal_state[i]; ail_rw->achieved_state[i] = ail->achieved_state[i]; } } void state_ai_cloak_info_to_ai_cloak_info_rw(ai_cloak_info *aic, ai_cloak_info_rw *aic_rw) { if (aic->last_time - GameTime64 < F1_0*(-18000)) aic_rw->last_time = F1_0*(-18000); else aic_rw->last_time = aic->last_time - GameTime64; aic_rw->last_segment = aic->last_segment; aic_rw->last_position.x = aic->last_position.x; aic_rw->last_position.x = aic->last_position.y; aic_rw->last_position.z = aic->last_position.z; } int ai_save_state(PHYSFS_file *fp) { int i = 0; fix tmptime32 = 0; PHYSFS_write(fp, &Ai_initialized, sizeof(int), 1); PHYSFS_write(fp, &Overall_agitation, sizeof(int), 1); //PHYSFS_write(fp, Ai_local_info, sizeof(ai_local) * MAX_OBJECTS, 1); for (i = 0; i < MAX_OBJECTS; i++) { ai_local_rw *ail_rw; CALLOC(ail_rw, ai_local_rw, 1); state_ai_local_to_ai_local_rw(&Ai_local_info[i], ail_rw); PHYSFS_write(fp, ail_rw, sizeof(ai_local_rw), 1); d_free(ail_rw); } PHYSFS_write(fp, Point_segs, sizeof(point_seg) * MAX_POINT_SEGS, 1); //PHYSFS_write(fp, Ai_cloak_info, sizeof(ai_cloak_info) * MAX_AI_CLOAK_INFO, 1); for (i = 0; i < MAX_AI_CLOAK_INFO; i++) { ai_cloak_info_rw *aic_rw; CALLOC(aic_rw, ai_cloak_info_rw, 1); state_ai_cloak_info_to_ai_cloak_info_rw(&Ai_cloak_info[i], aic_rw); PHYSFS_write(fp, aic_rw, sizeof(ai_cloak_info_rw), 1); d_free(aic_rw); } if (Boss_cloak_start_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Boss_cloak_start_time - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); if (Boss_cloak_end_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Boss_cloak_end_time - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); if (Last_teleport_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Last_teleport_time - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); PHYSFS_write(fp, &Boss_teleport_interval, sizeof(fix), 1); PHYSFS_write(fp, &Boss_cloak_interval, sizeof(fix), 1); PHYSFS_write(fp, &Boss_cloak_duration, sizeof(fix), 1); if (Last_gate_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Last_gate_time - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); PHYSFS_write(fp, &Gate_interval, sizeof(fix), 1); if (Boss_dying_start_time == 0) // if Boss not dead, yet we expect this to be 0, so do not convert! { tmptime32 = 0; } else { if (Boss_dying_start_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Boss_dying_start_time - GameTime64; if (tmptime32 == 0) // now if our converted value went 0 we should do something against it tmptime32 = -1; } PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); PHYSFS_write(fp, &Boss_dying, sizeof(int), 1); PHYSFS_write(fp, &Boss_dying_sound_playing, sizeof(int), 1); if (Boss_hit_time - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Boss_hit_time - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); PHYSFS_write(fp, &Escort_kill_object, sizeof(Escort_kill_object), 1); if (Escort_last_path_created - GameTime64 < F1_0*(-18000)) tmptime32 = F1_0*(-18000); else tmptime32 = Escort_last_path_created - GameTime64; PHYSFS_write(fp, &tmptime32, sizeof(fix), 1); PHYSFS_write(fp, &Escort_goal_object, sizeof(Escort_goal_object), 1); PHYSFS_write(fp, &Escort_special_goal, sizeof(Escort_special_goal), 1); PHYSFS_write(fp, &Escort_goal_index, sizeof(Escort_goal_index), 1); PHYSFS_write(fp, &Stolen_items, sizeof(Stolen_items[0])*MAX_STOLEN_ITEMS, 1); { int temp; temp = Point_segs_free_ptr - Point_segs; PHYSFS_write(fp, &temp, sizeof(int), 1); } PHYSFS_write(fp, &Num_boss_teleport_segs, sizeof(Num_boss_teleport_segs), 1); PHYSFS_write(fp, &Num_boss_gate_segs, sizeof(Num_boss_gate_segs), 1); if (Num_boss_gate_segs) PHYSFS_write(fp, Boss_gate_segs, sizeof(Boss_gate_segs[0]), Num_boss_gate_segs); if (Num_boss_teleport_segs) PHYSFS_write(fp, Boss_teleport_segs, sizeof(Boss_teleport_segs[0]), Num_boss_teleport_segs); return 1; } void ai_local_read_n_swap(ai_local *ail, int n, int swap, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++, ail++) { int j; fix tmptime32 = 0; ail->player_awareness_type = PHYSFSX_readSXE32(fp, swap); ail->retry_count = PHYSFSX_readSXE32(fp, swap); ail->consecutive_retries = PHYSFSX_readSXE32(fp, swap); ail->mode = PHYSFSX_readSXE32(fp, swap); ail->previous_visibility = PHYSFSX_readSXE32(fp, swap); ail->rapidfire_count = PHYSFSX_readSXE32(fp, swap); ail->goal_segment = PHYSFSX_readSXE32(fp, swap); ail->next_action_time = PHYSFSX_readSXE32(fp, swap); ail->next_fire = PHYSFSX_readSXE32(fp, swap); ail->next_fire2 = PHYSFSX_readSXE32(fp, swap); ail->player_awareness_time = PHYSFSX_readSXE32(fp, swap); tmptime32 = PHYSFSX_readSXE32(fp, swap); ail->time_player_seen = (fix64)tmptime32; tmptime32 = PHYSFSX_readSXE32(fp, swap); ail->time_player_sound_attacked = (fix64)tmptime32; tmptime32 = PHYSFSX_readSXE32(fp, swap); ail->next_misc_sound_time = (fix64)tmptime32; ail->time_since_processed = PHYSFSX_readSXE32(fp, swap); for (j = 0; j < MAX_SUBMODELS; j++) PHYSFSX_readAngleVecX(fp, &ail->goal_angles[j], swap); for (j = 0; j < MAX_SUBMODELS; j++) PHYSFSX_readAngleVecX(fp, &ail->delta_angles[j], swap); for (j = 0; j < MAX_SUBMODELS; j++) ail->goal_state[j] = PHYSFSX_readByte(fp); for (j = 0; j < MAX_SUBMODELS; j++) ail->achieved_state[j] = PHYSFSX_readByte(fp); } } void point_seg_read_n_swap(point_seg *ps, int n, int swap, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++, ps++) { ps->segnum = PHYSFSX_readSXE32(fp, swap); PHYSFSX_readVectorX(fp, &ps->point, swap); } } void ai_cloak_info_read_n_swap(ai_cloak_info *ci, int n, int swap, PHYSFS_file *fp) { int i; fix tmptime32 = 0; for (i = 0; i < n; i++, ci++) { tmptime32 = PHYSFSX_readSXE32(fp, swap); ci->last_time = (fix64)tmptime32; ci->last_segment = PHYSFSX_readSXE32(fp, swap); PHYSFSX_readVectorX(fp, &ci->last_position, swap); } } int ai_restore_state(PHYSFS_file *fp, int version, int swap) { fix tmptime32 = 0; Ai_initialized = PHYSFSX_readSXE32(fp, swap); Overall_agitation = PHYSFSX_readSXE32(fp, swap); ai_local_read_n_swap(Ai_local_info, MAX_OBJECTS, swap, fp); point_seg_read_n_swap(Point_segs, MAX_POINT_SEGS, swap, fp); ai_cloak_info_read_n_swap(Ai_cloak_info, MAX_AI_CLOAK_INFO, swap, fp); tmptime32 = PHYSFSX_readSXE32(fp, swap); Boss_cloak_start_time = (fix64)tmptime32; tmptime32 = PHYSFSX_readSXE32(fp, swap); Boss_cloak_end_time = (fix64)tmptime32; tmptime32 = PHYSFSX_readSXE32(fp, swap); Last_teleport_time = (fix64)tmptime32; Boss_teleport_interval = PHYSFSX_readSXE32(fp, swap); Boss_cloak_interval = PHYSFSX_readSXE32(fp, swap); Boss_cloak_duration = PHYSFSX_readSXE32(fp, swap); tmptime32 = PHYSFSX_readSXE32(fp, swap); Last_gate_time = (fix64)tmptime32; Gate_interval = PHYSFSX_readSXE32(fp, swap); tmptime32 = PHYSFSX_readSXE32(fp, swap); Boss_dying_start_time = (fix64)tmptime32; Boss_dying = PHYSFSX_readSXE32(fp, swap); Boss_dying_sound_playing = PHYSFSX_readSXE32(fp, swap); tmptime32 = PHYSFSX_readSXE32(fp, swap); Boss_hit_time = (fix64)tmptime32; // -- MK, 10/21/95, unused! -- PHYSFS_read(fp, &Boss_been_hit, sizeof(int), 1); if (version >= 8) { Escort_kill_object = PHYSFSX_readSXE32(fp, swap); tmptime32 = PHYSFSX_readSXE32(fp, swap); Escort_last_path_created = (fix64)tmptime32; Escort_goal_object = PHYSFSX_readSXE32(fp, swap); Escort_special_goal = PHYSFSX_readSXE32(fp, swap); Escort_goal_index = PHYSFSX_readSXE32(fp, swap); PHYSFS_read(fp, &Stolen_items, sizeof(Stolen_items[0]) * MAX_STOLEN_ITEMS, 1); } else { int i; Escort_kill_object = -1; Escort_last_path_created = 0; Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; Escort_special_goal = -1; Escort_goal_index = -1; for (i=0; i= 15) { int temp; temp = PHYSFSX_readSXE32(fp, swap); Point_segs_free_ptr = &Point_segs[temp]; } else ai_reset_all_paths(); if (version >= 21) { int i; Num_boss_teleport_segs = PHYSFSX_readSXE32(fp, swap); Num_boss_gate_segs = PHYSFSX_readSXE32(fp, swap); for (i = 0; i < Num_boss_gate_segs; i++) Boss_gate_segs[i] = PHYSFSX_readSXE16(fp, swap); for (i = 0; i < Num_boss_teleport_segs; i++) Boss_teleport_segs[i] = PHYSFSX_readSXE16(fp, swap); } return 1; } dxx-rebirth-0.58.1-d2x/main/ai.h000066400000000000000000000315631217717237500162520ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header file for AI system. * */ #ifndef _AI_H #define _AI_H #include #include "object.h" #include "fvi.h" #include "robot.h" #define PLAYER_AWARENESS_INITIAL_TIME (3*F1_0) #define MAX_PATH_LENGTH 30 // Maximum length of path in ai path following. #define MAX_DEPTH_TO_SEARCH_FOR_PLAYER 10 #define BOSS_GATE_MATCEN_NUM -1 #define MAX_BOSS_TELEPORT_SEGS 100 #define ROBOT_BRAIN 7 #define ROBOT_BOSS1 17 #define ROBOT_FIRE_AGITATION 94 #define BOSS_D2 21 // Minimum D2 boss value. #define BOSS_COOL 21 #define BOSS_WATER 22 #define BOSS_FIRE 23 #define BOSS_ICE 24 #define BOSS_ALIEN1 25 #define BOSS_ALIEN2 26 #define NUM_D2_BOSSES 8 extern const ubyte Boss_teleports[NUM_D2_BOSSES]; // Set byte if this boss can teleport extern const ubyte Boss_spew_more[NUM_D2_BOSSES]; // Set byte if this boss can teleport //extern ubyte Boss_cloaks[NUM_D2_BOSSES]; // Set byte if this boss can cloak extern const ubyte Boss_spews_bots_energy[NUM_D2_BOSSES]; // Set byte if boss spews bots when hit by energy weapon. extern const ubyte Boss_spews_bots_matter[NUM_D2_BOSSES]; // Set byte if boss spews bots when hit by matter weapon. extern const ubyte Boss_invulnerable_energy[NUM_D2_BOSSES]; // Set byte if boss is invulnerable to energy weapons. extern const ubyte Boss_invulnerable_matter[NUM_D2_BOSSES]; // Set byte if boss is invulnerable to matter weapons. extern const ubyte Boss_invulnerable_spot[NUM_D2_BOSSES]; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) extern fix64 Boss_cloak_start_time, Boss_cloak_end_time; extern int Num_boss_teleport_segs; extern short Boss_teleport_segs[MAX_BOSS_TELEPORT_SEGS]; extern fix64 Last_teleport_time; extern fix Boss_cloak_duration; extern int Boss_dying; extern ai_local Ai_local_info[MAX_OBJECTS]; extern vms_vector Believed_player_pos; extern int Believed_player_seg; extern void move_towards_segment_center(object *objp); extern int gate_in_robot(int type, int segnum); extern void do_ai_movement(object *objp); extern void ai_move_to_new_segment( object * obj, short newseg, int first_time ); // extern void ai_follow_path( object * obj, short newseg, int first_time ); extern void ai_recover_from_wall_hit(object *obj, int segnum); extern void ai_move_one(object *objp); extern void do_ai_frame(object *objp); extern void init_ai_object(int objnum, int initial_mode, int hide_segment); extern void update_player_awareness(object *objp, fix new_awareness); extern void create_awareness_event(object *objp, int type); // object *objp can create awareness of player, amount based on "type" extern void do_ai_frame_all(void); extern void reset_ai_states(object *objp); extern int create_path_points(object *objp, int start_seg, int end_seg, point_seg *point_segs, short *num_points, int max_depth, int random_flag, int safety_flag, int avoid_seg); extern void create_all_paths(void); extern void create_path_to_station(object *objp, int max_length); extern void ai_follow_path(object *objp, int player_visibility, int previous_visibility, vms_vector *vec_to_player); extern void ai_turn_towards_vector(vms_vector *vec_to_player, object *obj, fix rate); extern void ai_turn_towards_vel_vec(object *objp, fix rate); extern void init_ai_objects(void); extern void do_ai_robot_hit(object *robot, int type); extern void create_n_segment_path(object *objp, int path_length, int avoid_seg); extern void create_n_segment_path_to_door(object *objp, int path_length, int avoid_seg); extern void make_random_vector(vms_vector *vec); extern void init_robots_for_level(void); extern int ai_behavior_to_mode(int behavior); extern void create_path_to_segment(object *objp, int goalseg, int max_length, int safety_flag); extern int ready_to_fire(robot_info *robptr, ai_local *ailp); extern int polish_path(object *objp, point_seg *psegs, int num_points); extern void move_towards_player(object *objp, vms_vector *vec_to_player); // max_length is maximum depth of path to create. // If -1, use default: MAX_DEPTH_TO_SEARCH_FOR_PLAYER extern void create_path_to_player(object *objp, int max_length, int safety_flag); extern void attempt_to_resume_path(object *objp); // When a robot and a player collide, some robots attack! extern void do_ai_robot_hit_attack(object *robot, object *player, vms_vector *collision_point); extern void ai_open_doors_in_segment(object *robot); extern int ai_door_is_openable(object *objp, segment *segp, int sidenum); extern int player_is_visible_from_object(object *objp, vms_vector *pos, fix field_of_view, vms_vector *vec_to_player); extern void ai_reset_all_paths(void); // Reset all paths. Call at the start of a level. extern int ai_multiplayer_awareness(object *objp, int awareness_level); // In escort.c extern void do_escort_frame(object *objp, fix dist_to_player, int player_visibility); extern void do_snipe_frame(object *objp, fix dist_to_player, int player_visibility, vms_vector *vec_to_player); extern void do_thief_frame(object *objp, fix dist_to_player, int player_visibility, vms_vector *vec_to_player); #ifndef NDEBUG extern void force_dump_ai_objects_all(char *msg); #else #define force_dump_ai_objects_all(msg) #endif extern void start_boss_death_sequence(object *objp); extern void ai_init_boss_for_ship(void); extern int Boss_been_hit; extern fix AI_proc_time; // Stuff moved from ai.c by MK on 05/25/95. #define ANIM_RATE (F1_0/16) #define DELTA_ANG_SCALE 16 #define OVERALL_AGITATION_MAX 100 #define MAX_AI_CLOAK_INFO 8 // Must be a power of 2! #define BOSS_CLOAK_DURATION (F1_0*7) #define BOSS_DEATH_DURATION (F1_0*6) #define CHASE_TIME_LENGTH (F1_0*8) #define DEFAULT_ROBOT_SOUND_VOLUME F1_0 extern fix Dist_to_last_fired_upon_player_pos; extern vms_vector Last_fired_upon_player_pos; #define MAX_AWARENESS_EVENTS 64 typedef struct awareness_event { short segnum; // segment the event occurred in short type; // type of event, defines behavior vms_vector pos; // absolute 3 space location of event } awareness_event; #define AIS_MAX 8 #define AIE_MAX 4 #define ESCORT_GOAL_UNSPECIFIED -1 #define ESCORT_GOAL_UNSPECIFIED -1 #define ESCORT_GOAL_BLUE_KEY 1 #define ESCORT_GOAL_GOLD_KEY 2 #define ESCORT_GOAL_RED_KEY 3 #define ESCORT_GOAL_CONTROLCEN 4 #define ESCORT_GOAL_EXIT 5 // Custom escort goals. #define ESCORT_GOAL_ENERGY 6 #define ESCORT_GOAL_ENERGYCEN 7 #define ESCORT_GOAL_SHIELD 8 #define ESCORT_GOAL_POWERUP 9 #define ESCORT_GOAL_ROBOT 10 #define ESCORT_GOAL_HOSTAGE 11 #define ESCORT_GOAL_PLAYER_SPEW 12 #define ESCORT_GOAL_SCRAM 13 #define ESCORT_GOAL_EXIT2 14 #define ESCORT_GOAL_BOSS 15 #define ESCORT_GOAL_MARKER1 16 #define ESCORT_GOAL_MARKER2 17 #define ESCORT_GOAL_MARKER3 18 #define ESCORT_GOAL_MARKER4 19 #define ESCORT_GOAL_MARKER5 20 #define ESCORT_GOAL_MARKER6 21 #define ESCORT_GOAL_MARKER7 22 #define ESCORT_GOAL_MARKER8 23 #define ESCORT_GOAL_MARKER9 24 #define MAX_ESCORT_GOALS 25 #define MAX_ESCORT_DISTANCE (F1_0*80) #define MIN_ESCORT_DISTANCE (F1_0*40) #define FUELCEN_CHECK 1000 extern fix64 Escort_last_path_created; extern int Escort_goal_object, Escort_special_goal, Escort_goal_index; #define GOAL_WIDTH 11 #define SNIPE_RETREAT_TIME (F1_0*5) #define SNIPE_ABORT_RETREAT_TIME (SNIPE_RETREAT_TIME/2) // Can abort a retreat with this amount of time left in retreat #define SNIPE_ATTACK_TIME (F1_0*10) #define SNIPE_WAIT_TIME (F1_0*5) #define SNIPE_FIRE_TIME (F1_0*2) #define THIEF_PROBABILITY 16384 // 50% chance of stealing an item at each attempt #define MAX_STOLEN_ITEMS 10 // Maximum number kept track of, will keep stealing, causes stolen weapons to be lost! extern int Max_escort_length; extern int Escort_kill_object; extern ubyte Stolen_items[MAX_STOLEN_ITEMS]; extern fix64 Escort_last_path_created; extern int Escort_goal_object, Escort_special_goal, Escort_goal_index; extern void create_buddy_bot(void); extern int Max_escort_length; extern void ai_multi_send_robot_position(int objnum, int force); // Amount of time since the current robot was last processed for things such as movement. // It is not valid to use FrameTime because robots do not get moved every frame. extern int Num_boss_teleport_segs; extern short Boss_teleport_segs[MAX_BOSS_TELEPORT_SEGS]; extern int Num_boss_gate_segs; extern short Boss_gate_segs[MAX_BOSS_TELEPORT_SEGS]; // --------- John: These variables must be saved as part of gamesave. --------- extern int Ai_initialized; extern int Overall_agitation; extern ai_local Ai_local_info[MAX_OBJECTS]; extern point_seg Point_segs[MAX_POINT_SEGS]; extern point_seg *Point_segs_free_ptr; extern ai_cloak_info Ai_cloak_info[MAX_AI_CLOAK_INFO]; extern fix64 Boss_cloak_start_time; extern fix64 Boss_cloak_end_time; extern fix64 Last_teleport_time; extern fix Boss_teleport_interval; extern fix Boss_cloak_interval; // Time between cloaks extern fix Boss_cloak_duration; extern fix64 Last_gate_time; extern fix Gate_interval; extern fix64 Boss_dying_start_time; extern sbyte Boss_dying_sound_playing; extern fix64 Boss_hit_time; // -- extern int Boss_been_hit; // ------ John: End of variables which must be saved as part of gamesave. ----- extern int ai_evaded; extern sbyte Super_boss_gate_list[]; #define MAX_GATE_INDEX 25 extern int Ai_info_enabled; // These globals are set by a call to find_vector_intersection, which is a slow routine, // so we don't want to call it again (for this object) unless we have to. extern vms_vector Hit_pos; extern int Hit_type, Hit_seg; extern fvi_info Hit_data; extern int Num_awareness_events; extern awareness_event Awareness_events[MAX_AWARENESS_EVENTS]; extern vms_vector Believed_player_pos; #ifndef NDEBUG // Index into this array with ailp->mode // Index into this array with aip->behavior // Index into this array with aip->GOAL_STATE or aip->CURRENT_STATE extern int Do_ai_flag, Break_on_object; #endif //ifndef NDEBUG extern int Stolen_item_index; // Used in ai.c for controlling rate of Thief flare firing. extern void ai_frame_animation(object *objp); extern int do_silly_animation(object *objp); extern int openable_doors_in_segment(int segnum); extern void compute_vis_and_vec(object *objp, vms_vector *pos, ai_local *ailp, vms_vector *vec_to_player, int *player_visibility, robot_info *robptr, int *flag); extern void do_firing_stuff(object *obj, int player_visibility, vms_vector *vec_to_player); extern int maybe_ai_do_actual_firing_stuff(object *obj, ai_static *aip); extern void ai_do_actual_firing_stuff(object *obj, ai_static *aip, ai_local *ailp, robot_info *robptr, vms_vector *vec_to_player, fix dist_to_player, vms_vector *gun_point, int player_visibility, int object_animates, int gun_num); extern void do_super_boss_stuff(object *objp, fix dist_to_player, int player_visibility); extern void do_boss_stuff(object *objp, int player_visibility); // -- unused, 08/07/95 -- extern void ai_turn_randomly(vms_vector *vec_to_player, object *obj, fix rate, int previous_visibility); extern void ai_move_relative_to_player(object *objp, ai_local *ailp, fix dist_to_player, vms_vector *vec_to_player, fix circle_distance, int evade_only, int player_visibility); extern void move_away_from_player(object *objp, vms_vector *vec_to_player, int attack_type); extern void move_towards_vector(object *objp, vms_vector *vec_goal, int dot_based); extern void init_ai_frame(void); extern void create_bfs_list(int start_seg, short bfs_list[], int *length, int max_segs); extern void init_thief_for_level(); extern int Escort_goal_object; extern int ai_save_state(PHYSFS_file * fp); extern int ai_restore_state(PHYSFS_file *fp, int version, int swap); extern int Buddy_objnum, Buddy_allowed_to_talk; extern void start_robot_death_sequence(object *objp); extern int do_any_robot_dying_frame(object *objp); extern void buddy_message(char * format, ... ); #define SPECIAL_REACTOR_ROBOT 65 extern void special_reactor_stuff(void); #endif /* _AI_H */ dxx-rebirth-0.58.1-d2x/main/ai2.c000066400000000000000000002364211217717237500163270ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Split ai.c into two files: ai.c, ai2.c. * */ #include #include #include #include "inferno.h" #include "game.h" #include "3d.h" #include "u_mem.h" #include "object.h" #include "render.h" #include "dxxerror.h" #include "ai.h" #include "laser.h" #include "fvi.h" #include "polyobj.h" #include "bm.h" #include "weapon.h" #include "physics.h" #include "collide.h" #include "player.h" #include "wall.h" #include "vclip.h" #include "digi.h" #include "fireball.h" #include "morph.h" #include "effects.h" #include "timer.h" #include "sounds.h" #include "cntrlcen.h" #include "multibot.h" #ifdef NETWORK #include "multi.h" #endif #include "gameseq.h" #include "key.h" #include "powerup.h" #include "gauges.h" #include "text.h" #include "args.h" #ifdef EDITOR #include "editor/editor.h" #include "editor/esegment.h" #include "editor/kdefs.h" #endif #ifndef NDEBUG #include "string.h" #include #endif void teleport_boss(object *objp); int boss_fits_in_seg(object *boss_objp, int segnum); enum { Flinch_scale = 4, Attack_scale = 24, }; static const sbyte Mike_to_matt_xlate[] = {AS_REST, AS_REST, AS_ALERT, AS_ALERT, AS_FLINCH, AS_FIRE, AS_RECOIL, AS_REST}; // Amount of time since the current robot was last processed for things such as movement. // It is not valid to use FrameTime because robots do not get moved every frame. int Num_boss_teleport_segs; short Boss_teleport_segs[MAX_BOSS_TELEPORT_SEGS]; int Num_boss_gate_segs; short Boss_gate_segs[MAX_BOSS_TELEPORT_SEGS]; // --------------------------------------------------------------------------------------------------------------------- // Given a behavior, set initial mode. int ai_behavior_to_mode(int behavior) { switch (behavior) { case AIB_STILL: return AIM_STILL; case AIB_NORMAL: return AIM_CHASE_OBJECT; case AIB_BEHIND: return AIM_BEHIND; case AIB_RUN_FROM: return AIM_RUN_FROM_OBJECT; case AIB_SNIPE: return AIM_STILL; // Changed, 09/13/95, MK, snipers are still until they see you or are hit. case AIB_STATION: return AIM_STILL; case AIB_FOLLOW: return AIM_FOLLOW_PATH; default: Int3(); // Contact Mike: Error, illegal behavior type } return AIM_STILL; } // --------------------------------------------------------------------------------------------------------------------- // Call every time the player starts a new ship. void ai_init_boss_for_ship(void) { Boss_hit_time = -F1_0*10; } // --------------------------------------------------------------------------------------------------------------------- // initial_mode == -1 means leave mode unchanged. void init_ai_object(int objnum, int behavior, int hide_segment) { object *objp = &Objects[objnum]; ai_static *aip = &objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objnum]; robot_info *robptr = &Robot_info[objp->id]; memset(ailp, 0, sizeof(ai_local)); if (behavior == 0) { behavior = AIB_NORMAL; aip->behavior = behavior; } // mode is now set from the Robot dialog, so this should get overwritten. ailp->mode = AIM_STILL; ailp->previous_visibility = 0; if (behavior != -1) { aip->behavior = behavior; ailp->mode = ai_behavior_to_mode(aip->behavior); } else if (!((aip->behavior >= MIN_BEHAVIOR) && (aip->behavior <= MAX_BEHAVIOR))) { aip->behavior = AIB_NORMAL; } if (robptr->companion) { ailp->mode = AIM_GOTO_PLAYER; Escort_kill_object = -1; } if (robptr->thief) { aip->behavior = AIB_SNIPE; ailp->mode = AIM_THIEF_WAIT; } if (robptr->attack_type) { aip->behavior = AIB_NORMAL; ailp->mode = ai_behavior_to_mode(aip->behavior); } // This is astonishingly stupid! This routine gets called by matcens! KILL KILL KILL!!! Point_segs_free_ptr = Point_segs; vm_vec_zero(&objp->mtype.phys_info.velocity); // -- ailp->wait_time = F1_0*5; ailp->player_awareness_time = 0; ailp->player_awareness_type = 0; aip->GOAL_STATE = AIS_SRCH; aip->CURRENT_STATE = AIS_REST; ailp->time_player_seen = GameTime64; ailp->next_misc_sound_time = GameTime64; ailp->time_player_sound_attacked = GameTime64; if ((behavior == AIB_SNIPE) || (behavior == AIB_STATION) || (behavior == AIB_RUN_FROM) || (behavior == AIB_FOLLOW)) { aip->hide_segment = hide_segment; ailp->goal_segment = hide_segment; aip->hide_index = -1; // This means the path has not yet been created. aip->cur_path_index = 0; } aip->SKIP_AI_COUNT = 0; if (robptr->cloak_type == RI_CLOAKED_ALWAYS) aip->CLOAKED = 1; else aip->CLOAKED = 0; objp->mtype.phys_info.flags |= (PF_BOUNCE | PF_TURNROLL); aip->REMOTE_OWNER = -1; aip->dying_sound_playing = 0; aip->dying_start_time = 0; aip->danger_laser_num = -1; } extern object * create_morph_robot( segment *segp, vms_vector *object_pos, int object_id); // -------------------------------------------------------------------------------------------------------------------- // Create a Buddy bot. // This automatically happens when you bring up the Buddy menu in a debug version. // It is available as a cheat in a non-debug (release) version. void create_buddy_bot(void) { int buddy_id; vms_vector object_pos; for (buddy_id=0; buddy_idsegnum]); create_morph_robot( &Segments[ConsoleObject->segnum], &object_pos, buddy_id); } #define QUEUE_SIZE 256 // -------------------------------------------------------------------------------------------------------------------- // Create list of segments boss is allowed to teleport to at segptr. // Set *num_segs. // Boss is allowed to teleport to segments he fits in (calls object_intersects_wall) and // he can reach from his initial position (calls find_connected_distance). // If size_check is set, then only add segment if boss can fit in it, else any segment is legal. // one_wall_hack added by MK, 10/13/95: A mega-hack! Set to !0 to ignore the void init_boss_segments(short segptr[], int *num_segs, int size_check, int one_wall_hack) { int boss_objnum=-1; int i; *num_segs = 0; #ifdef EDITOR N_selected_segs = 0; #endif // See if there is a boss. If not, quick out. for (i=0; i<=Highest_object_index; i++) if ((Objects[i].type == OBJ_ROBOT) && (Robot_info[Objects[i].id].boss_flag)) boss_objnum = i; // if != 1 then there is more than one boss here. if (boss_objnum != -1) { int original_boss_seg; vms_vector original_boss_pos; object *boss_objp = &Objects[boss_objnum]; int head, tail; int seg_queue[QUEUE_SIZE]; //ALREADY IN RENDER.H sbyte visited[MAX_SEGMENTS]; fix boss_size_save; boss_size_save = boss_objp->size; // -- Causes problems!! -- boss_objp->size = fixmul((F1_0/4)*3, boss_objp->size); original_boss_seg = boss_objp->segnum; original_boss_pos = boss_objp->pos; head = 0; tail = 0; seg_queue[head++] = original_boss_seg; segptr[(*num_segs)++] = original_boss_seg; #ifdef EDITOR Selected_segs[N_selected_segs++] = original_boss_seg; #endif for (i=0; i<=Highest_segment_index; i++) visited[i] = 0; while (tail != head) { int sidenum; segment *segp = &Segments[seg_queue[tail++]]; tail &= QUEUE_SIZE-1; for (sidenum=0; sidenumchildren[sidenum])) { if (one_wall_hack) one_wall_hack--; } else continue; if (visited[segp->children[sidenum]] == 0) { seg_queue[head++] = segp->children[sidenum]; visited[segp->children[sidenum]] = 1; head &= QUEUE_SIZE-1; if (head > tail) { if (head == tail + QUEUE_SIZE-1) Int3(); // queue overflow. Make it bigger! } else if (head+QUEUE_SIZE == tail + QUEUE_SIZE-1) Int3(); // queue overflow. Make it bigger! if ((!size_check) || boss_fits_in_seg(boss_objp, segp->children[sidenum])) { segptr[(*num_segs)++] = segp->children[sidenum]; #ifdef EDITOR Selected_segs[N_selected_segs++] = segp->children[sidenum]; #endif if (*num_segs >= MAX_BOSS_TELEPORT_SEGS) { tail = head; sidenum=MAX_SIDES_PER_SEGMENT; break; } } } } } } boss_objp->size = boss_size_save; boss_objp->pos = original_boss_pos; obj_relink(boss_objnum, original_boss_seg); } } extern void init_buddy_for_level(void); // --------------------------------------------------------------------------------------------------------------------- void init_ai_objects(void) { int i; Point_segs_free_ptr = Point_segs; for (i=0; icontrol_type == CT_AI) init_ai_object(i, objp->ctype.ai_info.behavior, objp->ctype.ai_info.hide_segment); } init_boss_segments(Boss_gate_segs, &Num_boss_gate_segs, 0, 0); init_boss_segments(Boss_teleport_segs, &Num_boss_teleport_segs, 1, 0); if (Num_boss_teleport_segs == 1) init_boss_segments(Boss_teleport_segs, &Num_boss_teleport_segs, 1, 1); Boss_dying_sound_playing = 0; Boss_dying = 0; // -- unused! MK, 10/21/95 -- Boss_been_hit = 0; Gate_interval = F1_0*4 - Difficulty_level*i2f(2)/3; Ai_initialized = 1; ai_do_cloak_stuff(); init_buddy_for_level(); if (Current_mission && (Current_level_num == Last_level)) { Boss_teleport_interval = F1_0*10; Boss_cloak_interval = F1_0*15; // Time between cloaks } else { Boss_teleport_interval = F1_0*7; Boss_cloak_interval = F1_0*10; // Time between cloaks } } // ---------------------------------------------------------------- // Do *dest = *delta unless: // *delta is pretty small // and they are of different signs. void set_rotvel_and_saturate(fix *dest, fix delta) { if ((delta ^ *dest) < 0) { if (abs(delta) < F1_0/8) { *dest = delta/4; } else *dest = delta; } else { *dest = delta; } } //--debug-- #ifndef NDEBUG //--debug-- int Total_turns=0; //--debug-- int Prevented_turns=0; //--debug-- #endif #define AI_TURN_SCALE 1 #define BABY_SPIDER_ID 14 #define FIRE_AT_NEARBY_PLAYER_THRESHOLD (F1_0*40) extern void physics_turn_towards_vector(vms_vector *goal_vector, object *obj, fix rate); extern fix Seismic_tremor_magnitude; //------------------------------------------------------------------------------------------- void ai_turn_towards_vector(vms_vector *goal_vector, object *objp, fix rate) { vms_vector new_fvec; fix dot; // Not all robots can turn, eg, SPECIAL_REACTOR_ROBOT if (rate == 0) return; if ((objp->id == BABY_SPIDER_ID) && (objp->type == OBJ_ROBOT)) { physics_turn_towards_vector(goal_vector, objp, rate); return; } new_fvec = *goal_vector; dot = vm_vec_dot(goal_vector, &objp->orient.fvec); if (dot < (F1_0 - FrameTime/2)) { fix mag; fix new_scale = fixdiv(FrameTime * AI_TURN_SCALE, rate); vm_vec_scale(&new_fvec, new_scale); vm_vec_add2(&new_fvec, &objp->orient.fvec); mag = vm_vec_normalize_quick(&new_fvec); if (mag < F1_0/256) { new_fvec = *goal_vector; // if degenerate vector, go right to goal } } if (Seismic_tremor_magnitude) { vms_vector rand_vec; fix scale; make_random_vector(&rand_vec); scale = fixdiv(2*Seismic_tremor_magnitude, Robot_info[objp->id].mass); vm_vec_scale_add2(&new_fvec, &rand_vec, scale); } vm_vector_2_matrix(&objp->orient, &new_fvec, NULL, &objp->orient.rvec); } // -- unused, 08/07/95 -- // -------------------------------------------------------------------------------------------------------------------- // -- unused, 08/07/95 -- void ai_turn_randomly(vms_vector *vec_to_player, object *obj, fix rate, int previous_visibility) // -- unused, 08/07/95 -- { // -- unused, 08/07/95 -- vms_vector curvec; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- // -- MK, 06/09/95 // Random turning looks too stupid, so 1/4 of time, cheat. // -- unused, 08/07/95 -- // -- MK, 06/09/95 if (previous_visibility) // -- unused, 08/07/95 -- // -- MK, 06/09/95 if (d_rand() > 0x7400) { // -- unused, 08/07/95 -- // -- MK, 06/09/95 ai_turn_towards_vector(vec_to_player, obj, rate); // -- unused, 08/07/95 -- // -- MK, 06/09/95 return; // -- unused, 08/07/95 -- // -- MK, 06/09/95 } // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- curvec = obj->mtype.phys_info.rotvel; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- curvec.y += F1_0/64; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- curvec.x += curvec.y/6; // -- unused, 08/07/95 -- curvec.y += curvec.z/4; // -- unused, 08/07/95 -- curvec.z += curvec.x/10; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- if (abs(curvec.x) > F1_0/8) curvec.x /= 4; // -- unused, 08/07/95 -- if (abs(curvec.y) > F1_0/8) curvec.y /= 4; // -- unused, 08/07/95 -- if (abs(curvec.z) > F1_0/8) curvec.z /= 4; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- obj->mtype.phys_info.rotvel = curvec; // -- unused, 08/07/95 -- // -- unused, 08/07/95 -- } // Overall_agitation affects: // Widens field of view. Field of view is in range 0..1 (specified in bitmaps.tbl as N/360 degrees). // Overall_agitation/128 subtracted from field of view, making robots see wider. // Increases distance to which robot will search to create path to player by Overall_agitation/8 segments. // Decreases wait between fire times by Overall_agitation/64 seconds. // -------------------------------------------------------------------------------------------------------------------- // Returns: // 0 Player is not visible from object, obstruction or something. // 1 Player is visible, but not in field of view. // 2 Player is visible and in field of view. // Note: Uses Believed_player_pos as player's position for cloak effect. // NOTE: Will destructively modify *pos if *pos is outside the mine. int player_is_visible_from_object(object *objp, vms_vector *pos, fix field_of_view, vms_vector *vec_to_player) { fix dot; fvi_query fq; // Assume that robot's gun tip is in same segment as robot's center. if (objp->control_type == CT_AI) objp->ctype.ai_info.SUB_FLAGS &= ~SUB_FLAGS_GUNSEG; fq.p0 = pos; if ((pos->x != objp->pos.x) || (pos->y != objp->pos.y) || (pos->z != objp->pos.z)) { int segnum = find_point_seg(pos, objp->segnum); if (segnum == -1) { fq.startseg = objp->segnum; *pos = objp->pos; move_towards_segment_center(objp); } else { if (segnum != objp->segnum) { if (objp->control_type == CT_AI) objp->ctype.ai_info.SUB_FLAGS |= SUB_FLAGS_GUNSEG; } fq.startseg = segnum; } } else fq.startseg = objp->segnum; fq.p1 = &Believed_player_pos; fq.rad = F1_0/4; fq.thisobjnum = objp-Objects; fq.ignore_obj_list = NULL; fq.flags = FQ_TRANSWALL; // -- Why were we checking objects? | FQ_CHECK_OBJS; //what about trans walls??? Hit_type = find_vector_intersection(&fq,&Hit_data); Hit_pos = Hit_data.hit_pnt; Hit_seg = Hit_data.hit_seg; // -- when we stupidly checked objects -- if ((Hit_type == HIT_NONE) || ((Hit_type == HIT_OBJECT) && (Hit_data.hit_object == Players[Player_num].objnum))) { if (Hit_type == HIT_NONE) { dot = vm_vec_dot(vec_to_player, &objp->orient.fvec); if (dot > field_of_view - (Overall_agitation << 9)) { return 2; } else { return 1; } } else { return 0; } } // ------------------------------------------------------------------------------------------------------------------ // Return 1 if animates, else return 0 int do_silly_animation(object *objp) { int objnum = objp-Objects; const jointpos *jp_list; int robot_type, gun_num, robot_state, num_joint_positions; polyobj_info *pobj_info = &objp->rtype.pobj_info; ai_static *aip = &objp->ctype.ai_info; // ai_local *ailp = &Ai_local_info[objnum]; int num_guns, at_goal; int attack_type; int flinch_attack_scale = 1; robot_type = objp->id; num_guns = Robot_info[robot_type].n_guns; attack_type = Robot_info[robot_type].attack_type; if (num_guns == 0) { return 0; } // This is a hack. All positions should be based on goal_state, not GOAL_STATE. robot_state = Mike_to_matt_xlate[aip->GOAL_STATE]; // previous_robot_state = Mike_to_matt_xlate[aip->CURRENT_STATE]; if (attack_type) // && ((robot_state == AS_FIRE) || (robot_state == AS_RECOIL))) flinch_attack_scale = Attack_scale; else if ((robot_state == AS_FLINCH) || (robot_state == AS_RECOIL)) flinch_attack_scale = Flinch_scale; at_goal = 1; for (gun_num=0; gun_num <= num_guns; gun_num++) { int joint; num_joint_positions = robot_get_anim_state(&jp_list, robot_type, gun_num, robot_state); for (joint=0; jointanim_angles[jointnum]; if (jointnum >= Polygon_models[objp->rtype.pobj_info.model_num].n_models) { Int3(); // Contact Mike: incompatible data, illegal jointnum, problem in pof file? continue; } if (jp->p != pobjp->p) { if (gun_num == 0) at_goal = 0; Ai_local_info[objnum].goal_angles[jointnum].p = jp->p; delta_angle = jp->p - pobjp->p; if (delta_angle >= F1_0/2) delta_2 = -ANIM_RATE; else if (delta_angle >= 0) delta_2 = ANIM_RATE; else if (delta_angle >= -F1_0/2) delta_2 = -ANIM_RATE; else delta_2 = ANIM_RATE; if (flinch_attack_scale != 1) delta_2 *= flinch_attack_scale; Ai_local_info[objnum].delta_angles[jointnum].p = delta_2/DELTA_ANG_SCALE; // complete revolutions per second } if (jp->b != pobjp->b) { if (gun_num == 0) at_goal = 0; Ai_local_info[objnum].goal_angles[jointnum].b = jp->b; delta_angle = jp->b - pobjp->b; if (delta_angle >= F1_0/2) delta_2 = -ANIM_RATE; else if (delta_angle >= 0) delta_2 = ANIM_RATE; else if (delta_angle >= -F1_0/2) delta_2 = -ANIM_RATE; else delta_2 = ANIM_RATE; if (flinch_attack_scale != 1) delta_2 *= flinch_attack_scale; Ai_local_info[objnum].delta_angles[jointnum].b = delta_2/DELTA_ANG_SCALE; // complete revolutions per second } if (jp->h != pobjp->h) { if (gun_num == 0) at_goal = 0; Ai_local_info[objnum].goal_angles[jointnum].h = jp->h; delta_angle = jp->h - pobjp->h; if (delta_angle >= F1_0/2) delta_2 = -ANIM_RATE; else if (delta_angle >= 0) delta_2 = ANIM_RATE; else if (delta_angle >= -F1_0/2) delta_2 = -ANIM_RATE; else delta_2 = ANIM_RATE; if (flinch_attack_scale != 1) delta_2 *= flinch_attack_scale; Ai_local_info[objnum].delta_angles[jointnum].h = delta_2/DELTA_ANG_SCALE; // complete revolutions per second } } if (at_goal) { //ai_static *aip = &objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objp-Objects]; ailp->achieved_state[gun_num] = ailp->goal_state[gun_num]; if (ailp->achieved_state[gun_num] == AIS_RECO) ailp->goal_state[gun_num] = AIS_FIRE; if (ailp->achieved_state[gun_num] == AIS_FLIN) ailp->goal_state[gun_num] = AIS_LOCK; } } if (at_goal == 1) //num_guns) aip->CURRENT_STATE = aip->GOAL_STATE; return 1; } // ------------------------------------------------------------------------------------------ // Move all sub-objects in an object towards their goals. // Current orientation of object is at: pobj_info.anim_angles // Goal orientation of object is at: ai_info.goal_angles // Delta orientation of object is at: ai_info.delta_angles void ai_frame_animation(object *objp) { int objnum = objp-Objects; int joint; int num_joints; num_joints = Polygon_models[objp->rtype.pobj_info.model_num].n_models; for (joint=1; jointrtype.pobj_info.anim_angles[joint]; vms_angvec *goalangp = &Ai_local_info[objnum].goal_angles[joint]; vms_angvec *deltaangp = &Ai_local_info[objnum].delta_angles[joint]; delta_to_goal = goalangp->p - curangp->p; if (delta_to_goal > 32767) delta_to_goal = delta_to_goal - 65536; else if (delta_to_goal < -32767) delta_to_goal = 65536 + delta_to_goal; if (delta_to_goal) { scaled_delta_angle = fixmul(deltaangp->p, FrameTime) * DELTA_ANG_SCALE; curangp->p += scaled_delta_angle; if (abs(delta_to_goal) < abs(scaled_delta_angle)) curangp->p = goalangp->p; } delta_to_goal = goalangp->b - curangp->b; if (delta_to_goal > 32767) delta_to_goal = delta_to_goal - 65536; else if (delta_to_goal < -32767) delta_to_goal = 65536 + delta_to_goal; if (delta_to_goal) { scaled_delta_angle = fixmul(deltaangp->b, FrameTime) * DELTA_ANG_SCALE; curangp->b += scaled_delta_angle; if (abs(delta_to_goal) < abs(scaled_delta_angle)) curangp->b = goalangp->b; } delta_to_goal = goalangp->h - curangp->h; if (delta_to_goal > 32767) delta_to_goal = delta_to_goal - 65536; else if (delta_to_goal < -32767) delta_to_goal = 65536 + delta_to_goal; if (delta_to_goal) { scaled_delta_angle = fixmul(deltaangp->h, FrameTime) * DELTA_ANG_SCALE; curangp->h += scaled_delta_angle; if (abs(delta_to_goal) < abs(scaled_delta_angle)) curangp->h = goalangp->h; } } } // ---------------------------------------------------------------------------------- void set_next_fire_time(object *objp, ai_local *ailp, robot_info *robptr, int gun_num) { // For guys in snipe mode, they have a 50% shot of getting this shot in free. if ((gun_num != 0) || (robptr->weapon_type2 == -1)) if ((objp->ctype.ai_info.behavior != AIB_SNIPE) || (d_rand() > 16384)) ailp->rapidfire_count++; // Old way, 10/15/95: Continuous rapidfire if rapidfire_count set. // -- if (((robptr->weapon_type2 == -1) || (gun_num != 0)) && (ailp->rapidfire_count < robptr->rapidfire_count[Difficulty_level])) { // -- ailp->next_fire = min(F1_0/8, robptr->firing_wait[Difficulty_level]/2); // -- } else { // -- if ((robptr->weapon_type2 == -1) || (gun_num != 0)) { // -- ailp->rapidfire_count = 0; // -- ailp->next_fire = robptr->firing_wait[Difficulty_level]; // -- } else // -- ailp->next_fire2 = robptr->firing_wait2[Difficulty_level]; // -- } if (((gun_num != 0) || (robptr->weapon_type2 == -1)) && (ailp->rapidfire_count < robptr->rapidfire_count[Difficulty_level])) { ailp->next_fire = min(F1_0/8, robptr->firing_wait[Difficulty_level]/2); } else { if ((robptr->weapon_type2 == -1) || (gun_num != 0)) { ailp->next_fire = robptr->firing_wait[Difficulty_level]; if (ailp->rapidfire_count >= robptr->rapidfire_count[Difficulty_level]) ailp->rapidfire_count = 0; } else ailp->next_fire2 = robptr->firing_wait2[Difficulty_level]; } } // ---------------------------------------------------------------------------------- // When some robots collide with the player, they attack. // If player is cloaked, then robot probably didn't actually collide, deal with that here. void do_ai_robot_hit_attack(object *robot, object *playerobj, vms_vector *collision_point) { ai_local *ailp = &Ai_local_info[robot-Objects]; robot_info *robptr = &Robot_info[robot->id]; //#ifndef NDEBUG if (cheats.robotfiringsuspended) return; //#endif // If player is dead, stop firing. if (Objects[Players[Player_num].objnum].type == OBJ_GHOST) return; if (robptr->attack_type == 1) { if (ailp->next_fire <= 0) { if (!(Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) if (vm_vec_dist_quick(&ConsoleObject->pos, &robot->pos) < robot->size + ConsoleObject->size + F1_0*2) { collide_player_and_nasty_robot( playerobj, robot, collision_point ); if (robptr->energy_drain && Players[Player_num].energy) { Players[Player_num].energy -= robptr->energy_drain * F1_0; if (Players[Player_num].energy < 0) Players[Player_num].energy = 0; // -- unused, use claw_sound in bitmaps.tbl -- digi_link_sound_to_pos( SOUND_ROBOT_SUCKED_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); } } robot->ctype.ai_info.GOAL_STATE = AIS_RECO; set_next_fire_time(robot, ailp, robptr, 1); // 1 = gun_num: 0 is special (uses next_fire2) } } } #ifndef _OBJECT_H extern int Player_exploded; #endif #define FIRE_K 8 // Controls average accuracy of robot firing. Smaller numbers make firing worse. Being power of 2 doesn't matter. // ==================================================================================================================== #define MIN_LEAD_SPEED (F1_0*4) #define MAX_LEAD_DISTANCE (F1_0*200) #define LEAD_RANGE (F1_0/2) // -------------------------------------------------------------------------------------------------------------------- // Computes point at which projectile fired by robot can hit player given positions, player vel, elapsed time fix compute_lead_component(fix player_pos, fix robot_pos, fix player_vel, fix elapsed_time) { return fixdiv(player_pos - robot_pos, elapsed_time) + player_vel; } // -------------------------------------------------------------------------------------------------------------------- // Lead the player, returning point to fire at in fire_point. // Rules: // Player not cloaked // Player must be moving at a speed >= MIN_LEAD_SPEED // Player not farther away than MAX_LEAD_DISTANCE // dot(vector_to_player, player_direction) must be in -LEAD_RANGE..LEAD_RANGE // if firing a matter weapon, less leading, based on skill level. int lead_player(object *objp, vms_vector *fire_point, vms_vector *believed_player_pos, int gun_num, vms_vector *fire_vec) { fix dot, player_speed, dist_to_player, max_weapon_speed, projected_time; vms_vector player_movement_dir, vec_to_player; int weapon_type; weapon_info *wptr; robot_info *robptr; if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) return 0; player_movement_dir = ConsoleObject->mtype.phys_info.velocity; player_speed = vm_vec_normalize_quick(&player_movement_dir); if (player_speed < MIN_LEAD_SPEED) return 0; vm_vec_sub(&vec_to_player, believed_player_pos, fire_point); dist_to_player = vm_vec_normalize_quick(&vec_to_player); if (dist_to_player > MAX_LEAD_DISTANCE) return 0; dot = vm_vec_dot(&vec_to_player, &player_movement_dir); if ((dot < -LEAD_RANGE) || (dot > LEAD_RANGE)) return 0; // Looks like it might be worth trying to lead the player. robptr = &Robot_info[objp->id]; weapon_type = robptr->weapon_type; if (robptr->weapon_type2 != -1) if (gun_num == 0) weapon_type = robptr->weapon_type2; wptr = &Weapon_info[weapon_type]; max_weapon_speed = wptr->speed[Difficulty_level]; if (max_weapon_speed < F1_0) return 0; // Matter weapons: // At Rookie or Trainee, don't lead at all. // At higher skill levels, don't lead as well. Accomplish this by screwing up max_weapon_speed. if (wptr->matter) { if (Difficulty_level <= 1) return 0; else max_weapon_speed *= (NDL-Difficulty_level); } projected_time = fixdiv(dist_to_player, max_weapon_speed); fire_vec->x = compute_lead_component(believed_player_pos->x, fire_point->x, ConsoleObject->mtype.phys_info.velocity.x, projected_time); fire_vec->y = compute_lead_component(believed_player_pos->y, fire_point->y, ConsoleObject->mtype.phys_info.velocity.y, projected_time); fire_vec->z = compute_lead_component(believed_player_pos->z, fire_point->z, ConsoleObject->mtype.phys_info.velocity.z, projected_time); vm_vec_normalize_quick(fire_vec); Assert(vm_vec_dot(fire_vec, &objp->orient.fvec) < 3*F1_0/2); // Make sure not firing at especially strange angle. If so, try to correct. If still bad, give up after one try. if (vm_vec_dot(fire_vec, &objp->orient.fvec) < F1_0/2) { vm_vec_add2(fire_vec, &vec_to_player); vm_vec_scale(fire_vec, F1_0/2); if (vm_vec_dot(fire_vec, &objp->orient.fvec) < F1_0/2) { return 0; } } return 1; } // -------------------------------------------------------------------------------------------------------------------- // Note: Parameter vec_to_player is only passed now because guns which aren't on the forward vector from the // center of the robot will not fire right at the player. We need to aim the guns at the player. Barring that, we cheat. // When this routine is complete, the parameter vec_to_player should not be necessary. void ai_fire_laser_at_player(object *obj, vms_vector *fire_point, int gun_num, vms_vector *believed_player_pos) { int objnum = obj-Objects; ai_local *ailp = &Ai_local_info[objnum]; robot_info *robptr = &Robot_info[obj->id]; vms_vector fire_vec; vms_vector bpp_diff; int weapon_type; fix aim, dot; int count; Assert(robptr->attack_type == 0); // We should never be coming here for the green guy, as he has no laser! // If this robot is only awake because a camera woke it up, don't fire. if (obj->ctype.ai_info.SUB_FLAGS & SUB_FLAGS_CAMERA_AWAKE) return; if (cheats.robotfiringsuspended) return; if (obj->control_type == CT_MORPH) return; // If player is exploded, stop firing. if (Player_exploded) return; if (obj->ctype.ai_info.dying_start_time) return; // No firing while in death roll. // Don't let the boss fire while in death roll. Sorry, this is the easiest way to do this. // If you try to key the boss off obj->ctype.ai_info.dying_start_time, it will hose the endlevel stuff. if (Boss_dying_start_time && Robot_info[obj->id].boss_flag) return; // If player is cloaked, maybe don't fire based on how long cloaked and randomness. if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { fix64 cloak_time = Ai_cloak_info[objnum % MAX_AI_CLOAK_INFO].last_time; if (GameTime64 - cloak_time > CLOAK_TIME_MAX/4) if (d_rand() > fixdiv(GameTime64 - cloak_time, CLOAK_TIME_MAX)/2) { set_next_fire_time(obj, ailp, robptr, gun_num); return; } } // Handle problem of a robot firing through a wall because its gun tip is on the other // side of the wall than the robot's center. For speed reasons, we normally only compute // the vector from the gun point to the player. But we need to know whether the gun point // is separated from the robot's center by a wall. If so, don't fire! if (obj->ctype.ai_info.SUB_FLAGS & SUB_FLAGS_GUNSEG) { // Well, the gun point is in a different segment than the robot's center. // This is almost always ok, but it is not ok if something solid is in between. int conn_side; int gun_segnum = find_point_seg(fire_point, obj->segnum); // See if these segments are connected, which should almost always be the case. conn_side = find_connect_side(&Segments[gun_segnum], &Segments[obj->segnum]); if (conn_side != -1) { // They are connected via conn_side in segment obj->segnum. // See if they are unobstructed. if (!(WALL_IS_DOORWAY(&Segments[obj->segnum], conn_side) & WID_FLY_FLAG)) { // Can't fly through, so don't let this bot fire through! return; } } else { // Well, they are not directly connected, so use find_vector_intersection to see if they are unobstructed. fvi_query fq; fvi_info hit_data; int fate; fq.startseg = obj->segnum; fq.p0 = &obj->pos; fq.p1 = fire_point; fq.rad = 0; fq.thisobjnum = obj-Objects; fq.ignore_obj_list = NULL; fq.flags = FQ_TRANSWALL; fate = find_vector_intersection(&fq, &hit_data); if (fate != HIT_NONE) { Int3(); // This bot's gun is poking through a wall, so don't fire. move_towards_segment_center(obj); // And decrease chances it will happen again. return; } } } // Set position to fire at based on difficulty level and robot's aiming ability aim = FIRE_K*F1_0 - (FIRE_K-1)*(robptr->aim << 8); // F1_0 in bitmaps.tbl = same as used to be. Worst is 50% more error. // Robots aim more poorly during seismic disturbance. if (Seismic_tremor_magnitude) { fix temp; temp = F1_0 - abs(Seismic_tremor_magnitude); if (temp < F1_0/2) temp = F1_0/2; aim = fixmul(aim, temp); } // Lead the player half the time. // Note that when leading the player, aim is perfect. This is probably acceptable since leading is so hacked in. // Problem is all robots will lead equally badly. if (d_rand() < 16384) { if (lead_player(obj, fire_point, believed_player_pos, gun_num, &fire_vec)) // Stuff direction to fire at in fire_point. goto player_led; } dot = 0; count = 0; // Don't want to sit in this loop forever... while ((count < 4) && (dot < F1_0/4)) { bpp_diff.x = believed_player_pos->x + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); bpp_diff.y = believed_player_pos->y + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); bpp_diff.z = believed_player_pos->z + fixmul((d_rand()-16384) * (NDL-Difficulty_level-1) * 4, aim); vm_vec_normalized_dir_quick(&fire_vec, &bpp_diff, fire_point); dot = vm_vec_dot(&obj->orient.fvec, &fire_vec); count++; } player_led: ; weapon_type = robptr->weapon_type; if (robptr->weapon_type2 != -1) if (gun_num == 0) weapon_type = robptr->weapon_type2; Laser_create_new_easy( &fire_vec, fire_point, obj-Objects, weapon_type, 1); #ifdef NETWORK if (Game_mode & GM_MULTI) { ai_multi_send_robot_position(objnum, -1); multi_send_robot_fire(objnum, obj->ctype.ai_info.CURRENT_GUN, &fire_vec); } #endif create_awareness_event(obj, PA_NEARBY_ROBOT_FIRED); set_next_fire_time(obj, ailp, robptr, gun_num); } // -------------------------------------------------------------------------------------------------------------------- // vec_goal must be normalized, or close to it. // if dot_based set, then speed is based on direction of movement relative to heading void move_towards_vector(object *objp, vms_vector *vec_goal, int dot_based) { physics_info *pptr = &objp->mtype.phys_info; fix speed, dot, max_speed; robot_info *robptr = &Robot_info[objp->id]; vms_vector vel; // Trying to move towards player. If forward vector much different than velocity vector, // bash velocity vector twice as much towards player as usual. vel = pptr->velocity; vm_vec_normalize_quick(&vel); dot = vm_vec_dot(&vel, &objp->orient.fvec); if (robptr->thief) dot = (F1_0+dot)/2; if (dot_based && (dot < 3*F1_0/4)) { // This funny code is supposed to slow down the robot and move his velocity towards his direction // more quickly than the general code pptr->velocity.x = pptr->velocity.x/2 + fixmul(vec_goal->x, FrameTime*32); pptr->velocity.y = pptr->velocity.y/2 + fixmul(vec_goal->y, FrameTime*32); pptr->velocity.z = pptr->velocity.z/2 + fixmul(vec_goal->z, FrameTime*32); } else { pptr->velocity.x += fixmul(vec_goal->x, FrameTime*64) * (Difficulty_level+5)/4; pptr->velocity.y += fixmul(vec_goal->y, FrameTime*64) * (Difficulty_level+5)/4; pptr->velocity.z += fixmul(vec_goal->z, FrameTime*64) * (Difficulty_level+5)/4; } speed = vm_vec_mag_quick(&pptr->velocity); max_speed = robptr->max_speed[Difficulty_level]; // Green guy attacks twice as fast as he moves away. if ((robptr->attack_type == 1) || robptr->thief || robptr->kamikaze) max_speed *= 2; if (speed > max_speed) { pptr->velocity.x = (pptr->velocity.x*3)/4; pptr->velocity.y = (pptr->velocity.y*3)/4; pptr->velocity.z = (pptr->velocity.z*3)/4; } } // -------------------------------------------------------------------------------------------------------------------- void move_towards_player(object *objp, vms_vector *vec_to_player) // vec_to_player must be normalized, or close to it. { move_towards_vector(objp, vec_to_player, 1); } // -------------------------------------------------------------------------------------------------------------------- // I am ashamed of this: fast_flag == -1 means normal slide about. fast_flag = 0 means no evasion. void move_around_player(object *objp, vms_vector *vec_to_player, int fast_flag) { physics_info *pptr = &objp->mtype.phys_info; fix speed; robot_info *robptr = &Robot_info[objp->id]; int dir; vms_vector evade_vector; if (fast_flag == 0) return; dir = ((objp-Objects) ^ ((d_tick_count + 3*(objp-Objects)) >> 5)) & 3; Assert((dir >= 0) && (dir <= 3)); switch (dir) { case 0: evade_vector.x = fixmul(vec_to_player->z, FrameTime*32); evade_vector.y = fixmul(vec_to_player->y, FrameTime*32); evade_vector.z = fixmul(-vec_to_player->x, FrameTime*32); break; case 1: evade_vector.x = fixmul(-vec_to_player->z, FrameTime*32); evade_vector.y = fixmul(vec_to_player->y, FrameTime*32); evade_vector.z = fixmul(vec_to_player->x, FrameTime*32); break; case 2: evade_vector.x = fixmul(-vec_to_player->y, FrameTime*32); evade_vector.y = fixmul(vec_to_player->x, FrameTime*32); evade_vector.z = fixmul(vec_to_player->z, FrameTime*32); break; case 3: evade_vector.x = fixmul(vec_to_player->y, FrameTime*32); evade_vector.y = fixmul(-vec_to_player->x, FrameTime*32); evade_vector.z = fixmul(vec_to_player->z, FrameTime*32); break; default: Error("Function move_around_player: Bad case."); } // Note: -1 means normal circling about the player. > 0 means fast evasion. if (fast_flag > 0) { fix dot; // Only take evasive action if looking at player. // Evasion speed is scaled by percentage of shields left so wounded robots evade less effectively. dot = vm_vec_dot(vec_to_player, &objp->orient.fvec); if ((dot > robptr->field_of_view[Difficulty_level]) && !(ConsoleObject->flags & PLAYER_FLAGS_CLOAKED)) { fix damage_scale; if (robptr->strength) damage_scale = fixdiv(objp->shields, robptr->strength); else damage_scale = F1_0; if (damage_scale > F1_0) damage_scale = F1_0; // Just in case... else if (damage_scale < 0) damage_scale = 0; // Just in case... vm_vec_scale(&evade_vector, i2f(fast_flag) + damage_scale); } } pptr->velocity.x += evade_vector.x; pptr->velocity.y += evade_vector.y; pptr->velocity.z += evade_vector.z; speed = vm_vec_mag_quick(&pptr->velocity); if ((objp-Objects != 1) && (speed > robptr->max_speed[Difficulty_level])) { pptr->velocity.x = (pptr->velocity.x*3)/4; pptr->velocity.y = (pptr->velocity.y*3)/4; pptr->velocity.z = (pptr->velocity.z*3)/4; } } // -------------------------------------------------------------------------------------------------------------------- void move_away_from_player(object *objp, vms_vector *vec_to_player, int attack_type) { fix speed; physics_info *pptr = &objp->mtype.phys_info; robot_info *robptr = &Robot_info[objp->id]; int objref; pptr->velocity.x -= fixmul(vec_to_player->x, FrameTime*16); pptr->velocity.y -= fixmul(vec_to_player->y, FrameTime*16); pptr->velocity.z -= fixmul(vec_to_player->z, FrameTime*16); if (attack_type) { // Get value in 0..3 to choose evasion direction. objref = ((objp-Objects) ^ ((d_tick_count + 3*(objp-Objects)) >> 5)) & 3; switch (objref) { case 0: vm_vec_scale_add2(&pptr->velocity, &objp->orient.uvec, FrameTime << 5); break; case 1: vm_vec_scale_add2(&pptr->velocity, &objp->orient.uvec, -FrameTime << 5); break; case 2: vm_vec_scale_add2(&pptr->velocity, &objp->orient.rvec, FrameTime << 5); break; case 3: vm_vec_scale_add2(&pptr->velocity, &objp->orient.rvec, -FrameTime << 5); break; default: Int3(); // Impossible, bogus value on objref, must be in 0..3 } } speed = vm_vec_mag_quick(&pptr->velocity); if (speed > robptr->max_speed[Difficulty_level]) { pptr->velocity.x = (pptr->velocity.x*3)/4; pptr->velocity.y = (pptr->velocity.y*3)/4; pptr->velocity.z = (pptr->velocity.z*3)/4; } } // -------------------------------------------------------------------------------------------------------------------- // Move towards, away_from or around player. // Also deals with evasion. // If the flag evade_only is set, then only allowed to evade, not allowed to move otherwise (must have mode == AIM_STILL). void ai_move_relative_to_player(object *objp, ai_local *ailp, fix dist_to_player, vms_vector *vec_to_player, fix circle_distance, int evade_only, int player_visibility) { object *dobjp; robot_info *robptr = &Robot_info[objp->id]; Assert(player_visibility != -1); // See if should take avoidance. // New way, green guys don't evade: if ((robptr->attack_type == 0) && (objp->ctype.ai_info.danger_laser_num != -1)) { if (objp->ctype.ai_info.danger_laser_num != -1) { dobjp = &Objects[objp->ctype.ai_info.danger_laser_num]; if ((dobjp->type == OBJ_WEAPON) && (dobjp->signature == objp->ctype.ai_info.danger_laser_signature)) { fix dot, dist_to_laser, field_of_view; vms_vector vec_to_laser, laser_fvec; field_of_view = Robot_info[objp->id].field_of_view[Difficulty_level]; vm_vec_sub(&vec_to_laser, &dobjp->pos, &objp->pos); dist_to_laser = vm_vec_normalize_quick(&vec_to_laser); dot = vm_vec_dot(&vec_to_laser, &objp->orient.fvec); if ((dot > field_of_view) || (robptr->companion)) { fix laser_robot_dot; vms_vector laser_vec_to_robot; // The laser is seen by the robot, see if it might hit the robot. // Get the laser's direction. If it's a polyobj, it can be gotten cheaply from the orientation matrix. if (dobjp->render_type == RT_POLYOBJ) laser_fvec = dobjp->orient.fvec; else { // Not a polyobj, get velocity and normalize. laser_fvec = dobjp->mtype.phys_info.velocity; //dobjp->orient.fvec; vm_vec_normalize_quick(&laser_fvec); } vm_vec_sub(&laser_vec_to_robot, &objp->pos, &dobjp->pos); vm_vec_normalize_quick(&laser_vec_to_robot); laser_robot_dot = vm_vec_dot(&laser_fvec, &laser_vec_to_robot); if ((laser_robot_dot > F1_0*7/8) && (dist_to_laser < F1_0*80)) { int evade_speed; ai_evaded = 1; evade_speed = Robot_info[objp->id].evade_speed[Difficulty_level]; move_around_player(objp, vec_to_player, evade_speed); } } return; } } // If only allowed to do evade code, then done. // Hmm, perhaps brilliant insight. If want claw-type guys to keep coming, don't return here after evasion. if ((!robptr->attack_type) && (!robptr->thief) && evade_only) return; // If we fall out of above, then no object to be avoided. objp->ctype.ai_info.danger_laser_num = -1; // Green guy selects move around/towards/away based on firing time, not distance. if (robptr->attack_type == 1) { if (((ailp->next_fire > robptr->firing_wait[Difficulty_level]/4) && (dist_to_player < F1_0*30)) || Player_is_dead) { // 1/4 of time, move around player, 3/4 of time, move away from player if (d_rand() < 8192) { move_around_player(objp, vec_to_player, -1); } else { move_away_from_player(objp, vec_to_player, 1); } } else { move_towards_player(objp, vec_to_player); } } else if (robptr->thief) { move_towards_player(objp, vec_to_player); } else { int objval = ((objp-Objects) & 0x0f) ^ 0x0a; // Changes here by MK, 12/29/95. Trying to get rid of endless circling around bots in a large room. if (robptr->kamikaze) { move_towards_player(objp, vec_to_player); } else if (dist_to_player < circle_distance) move_away_from_player(objp, vec_to_player, 0); else if ((dist_to_player < (3+objval)*circle_distance/2) && (ailp->next_fire > -F1_0)) { move_around_player(objp, vec_to_player, -1); } else { if ((-ailp->next_fire > F1_0 + (objval << 12)) && player_visibility) { // Usually move away, but sometimes move around player. if ((((GameTime64 >> 18) & 0x0f) ^ objval) > 4) { move_away_from_player(objp, vec_to_player, 0); } else { move_around_player(objp, vec_to_player, -1); } } else move_towards_player(objp, vec_to_player); } } } // -------------------------------------------------------------------------------------------------------------------- // Compute a somewhat random, normalized vector. void make_random_vector(vms_vector *vec) { vec->x = (d_rand() - 16384) | 1; // make sure we don't create null vector vec->y = d_rand() - 16384; vec->z = d_rand() - 16384; vm_vec_normalize_quick(vec); } // ------------------------------------------------------------------------------------------------------------------- int Break_on_object = -1; void do_firing_stuff(object *obj, int player_visibility, vms_vector *vec_to_player) { if ((Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD ) || (player_visibility >= 1)) { // Now, if in robot's field of view, lock onto player fix dot = vm_vec_dot(&obj->orient.fvec, vec_to_player); if ((dot >= 7*F1_0/8) || (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)) { ai_static *aip = &obj->ctype.ai_info; ai_local *ailp = &Ai_local_info[obj-Objects]; switch (aip->GOAL_STATE) { case AIS_NONE: case AIS_REST: case AIS_SRCH: case AIS_LOCK: aip->GOAL_STATE = AIS_FIRE; if (ailp->player_awareness_type <= PA_NEARBY_ROBOT_FIRED) { ailp->player_awareness_type = PA_NEARBY_ROBOT_FIRED; ailp->player_awareness_time = PLAYER_AWARENESS_INITIAL_TIME; } break; } } else if (dot >= F1_0/2) { ai_static *aip = &obj->ctype.ai_info; switch (aip->GOAL_STATE) { case AIS_NONE: case AIS_REST: case AIS_SRCH: aip->GOAL_STATE = AIS_LOCK; break; } } } } // -------------------------------------------------------------------------------------------------------------------- // If a hiding robot gets bumped or hit, he decides to find another hiding place. void do_ai_robot_hit(object *objp, int type) { if (objp->control_type == CT_AI) { if ((type == PA_WEAPON_ROBOT_COLLISION) || (type == PA_PLAYER_COLLISION)) switch (objp->ctype.ai_info.behavior) { case AIB_STILL: { int r; // Attack robots (eg, green guy) shouldn't have behavior = still. Assert(Robot_info[objp->id].attack_type == 0); r = d_rand(); // 1/8 time, charge player, 1/4 time create path, rest of time, do nothing if (r < 4096) { create_path_to_player(objp, 10, 1); objp->ctype.ai_info.behavior = AIB_STATION; objp->ctype.ai_info.hide_segment = objp->segnum; Ai_local_info[objp-Objects].mode = AIM_CHASE_OBJECT; } else if (r < 4096+8192) { create_n_segment_path(objp, d_rand()/8192 + 2, -1); Ai_local_info[objp-Objects].mode = AIM_FOLLOW_PATH; } break; } } } } #ifndef NDEBUG int Do_ai_flag=1; int Cvv_test=0; int Cvv_last_time[MAX_OBJECTS]; int Gun_point_hack=0; #endif int Robot_sound_volume=DEFAULT_ROBOT_SOUND_VOLUME; // -------------------------------------------------------------------------------------------------------------------- // Note: This function could be optimized. Surely player_is_visible_from_object would benefit from the // information of a normalized vec_to_player. // Return player visibility: // 0 not visible // 1 visible, but robot not looking at player (ie, on an unobstructed vector) // 2 visible and in robot's field of view // -1 player is cloaked // If the player is cloaked, set vec_to_player based on time player cloaked and last uncloaked position. // Updates ailp->previous_visibility if player is not cloaked, in which case the previous visibility is left unchanged // and is copied to player_visibility void compute_vis_and_vec(object *objp, vms_vector *pos, ai_local *ailp, vms_vector *vec_to_player, int *player_visibility, robot_info *robptr, int *flag) { if (!*flag) { if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { fix delta_time, dist; int cloak_index = (objp-Objects) % MAX_AI_CLOAK_INFO; delta_time = GameTime64 - Ai_cloak_info[cloak_index].last_time; if (delta_time > F1_0*2) { vms_vector randvec; Ai_cloak_info[cloak_index].last_time = GameTime64; make_random_vector(&randvec); vm_vec_scale_add2(&Ai_cloak_info[cloak_index].last_position, &randvec, 8*delta_time ); } dist = vm_vec_normalized_dir_quick(vec_to_player, &Ai_cloak_info[cloak_index].last_position, pos); *player_visibility = player_is_visible_from_object(objp, pos, robptr->field_of_view[Difficulty_level], vec_to_player); // *player_visibility = 2; if ((ailp->next_misc_sound_time < GameTime64) && ((ailp->next_fire < F1_0) || (ailp->next_fire2 < F1_0)) && (dist < F1_0*20)) { ailp->next_misc_sound_time = GameTime64 + (d_rand() + F1_0) * (7 - Difficulty_level) / 1; digi_link_sound_to_pos( robptr->see_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); } } else { // Compute expensive stuff -- vec_to_player and player_visibility vm_vec_normalized_dir_quick(vec_to_player, &Believed_player_pos, pos); if ((vec_to_player->x == 0) && (vec_to_player->y == 0) && (vec_to_player->z == 0)) { vec_to_player->x = F1_0; } *player_visibility = player_is_visible_from_object(objp, pos, robptr->field_of_view[Difficulty_level], vec_to_player); // This horrible code added by MK in desperation on 12/13/94 to make robots wake up as soon as they // see you without killing frame rate. { ai_static *aip = &objp->ctype.ai_info; if ((*player_visibility == 2) && (ailp->previous_visibility != 2)) if ((aip->GOAL_STATE == AIS_REST) || (aip->CURRENT_STATE == AIS_REST)) { aip->GOAL_STATE = AIS_FIRE; aip->CURRENT_STATE = AIS_FIRE; } } if ((ailp->previous_visibility != *player_visibility) && (*player_visibility == 2)) { if (ailp->previous_visibility == 0) { if (ailp->time_player_seen + F1_0/2 < GameTime64) { digi_link_sound_to_pos( robptr->see_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); ailp->time_player_sound_attacked = GameTime64; ailp->next_misc_sound_time = GameTime64 + F1_0 + d_rand()*4; } } else if (ailp->time_player_sound_attacked + F1_0/4 < GameTime64) { digi_link_sound_to_pos( robptr->attack_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); ailp->time_player_sound_attacked = GameTime64; } } if ((*player_visibility == 2) && (ailp->next_misc_sound_time < GameTime64)) { ailp->next_misc_sound_time = GameTime64 + (d_rand() + F1_0) * (7 - Difficulty_level) / 2; digi_link_sound_to_pos( robptr->attack_sound, objp->segnum, 0, pos, 0 , Robot_sound_volume); } ailp->previous_visibility = *player_visibility; } *flag = 1; // @mk, 09/21/95: If player view is not obstructed and awareness is at least as high as a nearby collision, // act is if robot is looking at player. if (ailp->player_awareness_type >= PA_NEARBY_ROBOT_FIRED) if (*player_visibility == 1) *player_visibility = 2; if (*player_visibility) { ailp->time_player_seen = GameTime64; } } } // -------------------------------------------------------------------------------------------------------------------- // Move the object objp to a spot in which it doesn't intersect a wall. // It might mean moving it outside its current segment. void move_object_to_legal_spot(object *objp) { vms_vector original_pos = objp->pos; int i; segment *segp = &Segments[objp->segnum]; for (i=0; ichildren[i]]); vm_vec_sub(&goal_dir, &segment_center, &objp->pos); vm_vec_normalize_quick(&goal_dir); vm_vec_scale(&goal_dir, objp->size); vm_vec_add2(&objp->pos, &goal_dir); if (!object_intersects_wall(objp)) { int new_segnum = find_point_seg(&objp->pos, objp->segnum); if (new_segnum != -1) { obj_relink(objp-Objects, new_segnum); return; } } else objp->pos = original_pos; } } if (Robot_info[objp->id].boss_flag) { Int3(); // Note: Boss is poking outside mine. Will try to resolve. teleport_boss(objp); } else { apply_damage_to_robot(objp, objp->shields*2, objp-Objects); } } // -------------------------------------------------------------------------------------------------------------------- // Move object one object radii from current position towards segment center. // If segment center is nearer than 2 radii, move it to center. void move_towards_segment_center(object *objp) { /* ZICO's change of 20081103: Make move to segment center smoother by using move_towards vector. Bot's should not jump around and maybe even intersect with each other! In case it breaks something what I do not see, yet, old code is still there. */ #if 1 int segnum = objp->segnum; vms_vector vec_to_center, segment_center; compute_segment_center(&segment_center, &Segments[segnum]); vm_vec_normalized_dir_quick(&vec_to_center, &segment_center, &objp->pos); move_towards_vector(objp, &vec_to_center, 1); #else int segnum = objp->segnum; fix dist_to_center; vms_vector segment_center, goal_dir; compute_segment_center(&segment_center, &Segments[segnum]); vm_vec_sub(&goal_dir, &segment_center, &objp->pos); dist_to_center = vm_vec_normalize_quick(&goal_dir); if (dist_to_center < objp->size) { // Center is nearer than the distance we want to move, so move to center. objp->pos = segment_center; if (object_intersects_wall(objp)) { move_object_to_legal_spot(objp); } } else { int new_segnum; // Move one radii towards center. vm_vec_scale(&goal_dir, objp->size); vm_vec_add2(&objp->pos, &goal_dir); new_segnum = find_point_seg(&objp->pos, objp->segnum); if (new_segnum == -1) { objp->pos = segment_center; move_object_to_legal_spot(objp); } } #endif } extern int Buddy_objnum; //int Buddy_got_stuck = 0; // ----------------------------------------------------------------------------------------------------------- // Return true if door can be flown through by a suitable type robot. // Brains, avoid robots, companions can open doors. // objp == NULL means treat as buddy. int ai_door_is_openable(object *objp, segment *segp, int sidenum) { int wall_num; wall *wallp; if (!IS_CHILD(segp->children[sidenum])) return 0; //trap -2 (exit side) wall_num = segp->sides[sidenum].wall_num; if (wall_num == -1) //if there's no door at all... return 0; //..then say it can't be opened // The mighty console object can open all doors (for purposes of determining paths). if (objp == ConsoleObject) { if (Walls[wall_num].type == WALL_DOOR) return 1; } wallp = &Walls[wall_num]; if ((objp == NULL) || (Robot_info[objp->id].companion == 1)) { int ailp_mode; if (wallp->flags & WALL_BUDDY_PROOF) { if ((wallp->type == WALL_DOOR) && (wallp->state == WALL_DOOR_CLOSED)) return 0; else if (wallp->type == WALL_CLOSED) return 0; else if ((wallp->type == WALL_ILLUSION) && !(wallp->flags & WALL_ILLUSION_OFF)) return 0; } if (wallp->keys != KEY_NONE) { if (wallp->keys == KEY_BLUE) return (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY); else if (wallp->keys == KEY_GOLD) return (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY); else if (wallp->keys == KEY_RED) return (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY); } if ((wallp->type != WALL_DOOR) && (wallp->type != WALL_CLOSED)) return 1; // If Buddy is returning to player, don't let him think he can get through triggered doors. // It's only valid to think that if the player is going to get him through. But if he's // going to the player, the player is probably on the opposite side. if (objp == NULL) ailp_mode = Ai_local_info[Buddy_objnum].mode; else ailp_mode = Ai_local_info[objp-Objects].mode; // -- if (Buddy_got_stuck) { if (ailp_mode == AIM_GOTO_PLAYER) { if ((wallp->type == WALL_BLASTABLE) && (wallp->state != WALL_BLASTED)) return 0; if (wallp->type == WALL_CLOSED) return 0; if (wallp->type == WALL_DOOR) { if ((wallp->flags & WALL_DOOR_LOCKED) && (wallp->state == WALL_DOOR_CLOSED)) return 0; } } // -- } if ((ailp_mode != AIM_GOTO_PLAYER) && (wallp->controlling_trigger != -1)) { int clip_num = wallp->clip_num; if (clip_num == -1) return 1; else if (WallAnims[clip_num].flags & WCF_HIDDEN) { if (wallp->state == WALL_DOOR_CLOSED) return 0; else return 1; } else return 1; } if (wallp->type == WALL_DOOR) { if (wallp->type == WALL_BLASTABLE) return 1; else { int clip_num = wallp->clip_num; if (clip_num == -1) return 1; // Buddy allowed to go through secret doors to get to player. else if ((ailp_mode != AIM_GOTO_PLAYER) && (WallAnims[clip_num].flags & WCF_HIDDEN)) { if (wallp->state == WALL_DOOR_CLOSED) return 0; else return 1; } else return 1; } } } else if ((objp->id == ROBOT_BRAIN) || (objp->ctype.ai_info.behavior == AIB_RUN_FROM) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) { if (wall_num != -1) { if ((wallp->type == WALL_DOOR) && (wallp->keys == KEY_NONE) && !(wallp->flags & WALL_DOOR_LOCKED)) return 1; else if (wallp->keys != KEY_NONE) { // Allow bots to open doors to which player has keys. if (wallp->keys & Players[Player_num].flags) return 1; } } } return 0; } // ----------------------------------------------------------------------------------------------------------- // Return side of openable door in segment, if any. If none, return -1. int openable_doors_in_segment(int segnum) { int i; if ((segnum < 0) || (segnum > Highest_segment_index)) return -1; for (i=0; iobjects; while (curobjnum != -1) { object *curobjp = &Objects[curobjnum]; if ((curobjp->type == OBJ_PLAYER) || (curobjp->type == OBJ_ROBOT) || (curobjp->type == OBJ_CNTRLCEN)) { if (vm_vec_dist_quick(pos, &curobjp->pos) < size + curobjp->size) return 1; } curobjnum = curobjp->next; } return 0; } // -------------------------------------------------------------------------------------------------------------------- // Return objnum if object created, else return -1. // If pos == NULL, pick random spot in segment. int create_gated_robot( int segnum, int object_id, vms_vector *pos) { int objnum; object *objp; segment *segp = &Segments[segnum]; vms_vector object_pos; robot_info *robptr = &Robot_info[object_id]; int i, count=0; fix objsize = Polygon_models[robptr->model_num].rad; int default_behavior; if (GameTime64 - Last_gate_time < Gate_interval) return -1; for (i=0; i<=Highest_object_index; i++) if (Objects[i].type == OBJ_ROBOT) if (Objects[i].matcen_creator == BOSS_GATE_MATCEN_NUM) count++; if (count > 2*Difficulty_level + 6) { Last_gate_time = GameTime64 - 3*Gate_interval/4; return -1; } compute_segment_center(&object_pos, segp); if (pos == NULL) pick_random_point_in_seg(&object_pos, segp-Segments); else object_pos = *pos; // See if legal to place object here. If not, move about in segment and try again. if (check_object_object_intersection(&object_pos, objsize, segp)) { Last_gate_time = GameTime64 - 3*Gate_interval/4; return -1; } objnum = obj_create(OBJ_ROBOT, object_id, segnum, &object_pos, &vmd_identity_matrix, objsize, CT_AI, MT_PHYSICS, RT_POLYOBJ); if ( objnum < 0 ) { Last_gate_time = GameTime64 - 3*Gate_interval/4; return -1; } Objects[objnum].lifeleft = F1_0*30; // Gated in robots only live 30 seconds. #ifdef NETWORK Net_create_objnums[0] = objnum; // A convenient global to get objnum back to caller for multiplayer #endif objp = &Objects[objnum]; //Set polygon-object-specific data objp->rtype.pobj_info.model_num = robptr->model_num; objp->rtype.pobj_info.subobj_flags = 0; //set Physics info objp->mtype.phys_info.mass = robptr->mass; objp->mtype.phys_info.drag = robptr->drag; objp->mtype.phys_info.flags |= (PF_LEVELLING); objp->shields = robptr->strength; objp->matcen_creator = BOSS_GATE_MATCEN_NUM; // flag this robot as having been created by the boss. default_behavior = Robot_info[objp->id].behavior; init_ai_object(objp-Objects, default_behavior, -1 ); // Note, -1 = segment this robot goes to to hide, should probably be something useful object_create_explosion(segnum, &object_pos, i2f(10), VCLIP_MORPHING_ROBOT ); digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, segnum, 0, &object_pos, 0 , F1_0); morph_start(objp); Last_gate_time = GameTime64; Players[Player_num].num_robots_level++; Players[Player_num].num_robots_total++; return objp-Objects; } #define MAX_SPEW_BOT 3 int Spew_bots[NUM_D2_BOSSES][MAX_SPEW_BOT] = { {38, 40, -1}, {37, -1, -1}, {43, 57, -1}, {26, 27, 58}, {59, 58, 54}, {60, 61, 54}, {69, 29, 24}, {72, 60, 73} }; int Max_spew_bots[NUM_D2_BOSSES] = {2, 1, 2, 3, 3, 3, 3, 3}; // ---------------------------------------------------------------------------------------------------------- // objp points at a boss. He was presumably just hit and he's supposed to create a bot at the hit location *pos. int boss_spew_robot(object *objp, vms_vector *pos) { int objnum, segnum; int boss_index; boss_index = Robot_info[objp->id].boss_flag - BOSS_D2; Assert((boss_index >= 0) && (boss_index < NUM_D2_BOSSES)); segnum = find_point_seg(pos, objp->segnum); if (segnum == -1) { return -1; } objnum = create_gated_robot( segnum, Spew_bots[boss_index][(Max_spew_bots[boss_index] * d_rand()) >> 15], pos); // Make spewed robot come tumbling out as if blasted by a flash missile. if (objnum != -1) { object *newobjp = &Objects[objnum]; int force_val; force_val = F1_0/FrameTime; if (force_val) { newobjp->ctype.ai_info.SKIP_AI_COUNT += force_val; newobjp->mtype.phys_info.rotthrust.x = ((d_rand() - 16384) * force_val)/16; newobjp->mtype.phys_info.rotthrust.y = ((d_rand() - 16384) * force_val)/16; newobjp->mtype.phys_info.rotthrust.z = ((d_rand() - 16384) * force_val)/16; newobjp->mtype.phys_info.flags |= PF_USES_THRUST; // Now, give a big initial velocity to get moving away from boss. vm_vec_sub(&newobjp->mtype.phys_info.velocity, pos, &objp->pos); vm_vec_normalize_quick(&newobjp->mtype.phys_info.velocity); vm_vec_scale(&newobjp->mtype.phys_info.velocity, F1_0*128); } } return objnum; } // -------------------------------------------------------------------------------------------------------------------- // Call this each time the player starts a new ship. void init_ai_for_ship(void) { int i; for (i=0; isegnum; Ai_cloak_info[i].last_position = ConsoleObject->pos; } } // -------------------------------------------------------------------------------------------------------------------- // Make object objp gate in a robot. // The process of him bringing in a robot takes one second. // Then a robot appears somewhere near the player. // Return objnum if robot successfully created, else return -1 int gate_in_robot(int type, int segnum) { if (segnum < 0) segnum = Boss_gate_segs[(d_rand() * Num_boss_gate_segs) >> 15]; Assert((segnum >= 0) && (segnum <= Highest_segment_index)); return create_gated_robot(segnum, type, NULL); } // -------------------------------------------------------------------------------------------------------------------- int boss_fits_in_seg(object *boss_objp, int segnum) { vms_vector segcenter; int boss_objnum = boss_objp-Objects; int posnum; compute_segment_center(&segcenter, &Segments[segnum]); for (posnum=0; posnum<9; posnum++) { if (posnum > 0) { vms_vector vertex_pos; Assert((posnum-1 >= 0) && (posnum-1 < 8)); vertex_pos = Vertices[Segments[segnum].verts[posnum-1]]; vm_vec_avg(&boss_objp->pos, &vertex_pos, &segcenter); } else boss_objp->pos = segcenter; obj_relink(boss_objnum, segnum); if (!object_intersects_wall(boss_objp)) return 1; } return 0; } // -------------------------------------------------------------------------------------------------------------------- void teleport_boss(object *objp) { int rand_segnum, rand_index; vms_vector boss_dir; Assert(Num_boss_teleport_segs > 0); // Pick a random segment from the list of boss-teleportable-to segments. rand_index = (d_rand() * Num_boss_teleport_segs) >> 15; rand_segnum = Boss_teleport_segs[rand_index]; Assert((rand_segnum >= 0) && (rand_segnum <= Highest_segment_index)); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_boss_actions(objp-Objects, 1, rand_segnum, 0); #endif compute_segment_center(&objp->pos, &Segments[rand_segnum]); obj_relink(objp-Objects, rand_segnum); Last_teleport_time = GameTime64; // make boss point right at player vm_vec_sub(&boss_dir, &Objects[Players[Player_num].objnum].pos, &objp->pos); vm_vector_2_matrix(&objp->orient, &boss_dir, NULL, NULL); digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, rand_segnum, 0, &objp->pos, 0 , F1_0); digi_kill_sound_linked_to_object( objp-Objects); digi_link_sound_to_object2( Robot_info[objp->id].see_sound, objp-Objects, 1, F1_0, F1_0*512 ); // F1_0*512 means play twice as loud // After a teleport, boss can fire right away. Ai_local_info[objp-Objects].next_fire = 0; Ai_local_info[objp-Objects].next_fire2 = 0; } // ---------------------------------------------------------------------- void start_boss_death_sequence(object *objp) { if (Robot_info[objp->id].boss_flag) { Boss_dying = 1; Boss_dying_start_time = GameTime64; } } // ---------------------------------------------------------------------- // General purpose robot-dies-with-death-roll-and-groan code. // Return true if object just died. // scale: F1_0*4 for boss, much smaller for much smaller guys int do_robot_dying_frame(object *objp, fix64 start_time, fix roll_duration, sbyte *dying_sound_playing, int death_sound, fix expl_scale, fix sound_scale) { fix roll_val, temp; fix sound_duration; if (!roll_duration) roll_duration = F1_0/4; roll_val = fixdiv(GameTime64 - start_time, roll_duration); fix_sincos(fixmul(roll_val, roll_val), &temp, &objp->mtype.phys_info.rotvel.x); fix_sincos(roll_val, &temp, &objp->mtype.phys_info.rotvel.y); fix_sincos(roll_val-F1_0/8, &temp, &objp->mtype.phys_info.rotvel.z); objp->mtype.phys_info.rotvel.x = (GameTime64 - start_time)/9; objp->mtype.phys_info.rotvel.y = (GameTime64 - start_time)/5; objp->mtype.phys_info.rotvel.z = (GameTime64 - start_time)/7; if (GameArg.SndDigiSampleRate) sound_duration = fixdiv(GameSounds[digi_xlat_sound(death_sound)].length,GameArg.SndDigiSampleRate); else sound_duration = F1_0; if (start_time + roll_duration - sound_duration < GameTime64) { if (!*dying_sound_playing) { *dying_sound_playing = 1; digi_link_sound_to_object2( death_sound, objp-Objects, 0, sound_scale, sound_scale*256 ); // F1_0*512 means play twice as loud } else if (d_rand() < FrameTime*16) create_small_fireball_on_object(objp, (F1_0 + d_rand()) * (16 * expl_scale/F1_0)/8, 0); } else if (d_rand() < FrameTime*8) create_small_fireball_on_object(objp, (F1_0/2 + d_rand()) * (16 * expl_scale/F1_0)/8, 1); if (start_time + roll_duration < GameTime64 || GameTime64+(F1_0*2) < start_time) return 1; else return 0; } // ---------------------------------------------------------------------- void start_robot_death_sequence(object *objp) { objp->ctype.ai_info.dying_start_time = GameTime64; objp->ctype.ai_info.dying_sound_playing = 0; objp->ctype.ai_info.SKIP_AI_COUNT = 0; } // ---------------------------------------------------------------------- void do_boss_dying_frame(object *objp) { int rval; rval = do_robot_dying_frame(objp, Boss_dying_start_time, BOSS_DEATH_DURATION, &Boss_dying_sound_playing, Robot_info[objp->id].deathroll_sound, F1_0*4, F1_0*4); if (rval) { Boss_dying_start_time=GameTime64; // make sure following only happens one time! do_controlcen_destroyed_stuff(NULL); explode_object(objp, F1_0/4); digi_link_sound_to_object2(SOUND_BADASS_EXPLOSION, objp-Objects, 0, F2_0, F1_0*512); } } extern void recreate_thief(object *objp); // ---------------------------------------------------------------------- int do_any_robot_dying_frame(object *objp) { if (objp->ctype.ai_info.dying_start_time) { int rval, death_roll; death_roll = Robot_info[objp->id].death_roll; rval = do_robot_dying_frame(objp, objp->ctype.ai_info.dying_start_time, min(death_roll/2+1,6)*F1_0, &objp->ctype.ai_info.dying_sound_playing, Robot_info[objp->id].deathroll_sound, death_roll*F1_0/8, death_roll*F1_0/2); if (rval) { objp->ctype.ai_info.dying_start_time = GameTime64; // make sure following only happens one time! explode_object(objp, F1_0/4); digi_link_sound_to_object2(SOUND_BADASS_EXPLOSION, objp-Objects, 0, F2_0, F1_0*512); if ((Current_level_num < 0) && (Robot_info[objp->id].thief)) recreate_thief(objp); } return 1; } return 0; } // -------------------------------------------------------------------------------------------------------------------- // Called for an AI object if it is fairly aware of the player. // awareness_level is in 0..100. Larger numbers indicate greater awareness (eg, 99 if firing at player). // In a given frame, might not get called for an object, or might be called more than once. // The fact that this routine is not called for a given object does not mean that object is not interested in the player. // Objects are moved by physics, so they can move even if not interested in a player. However, if their velocity or // orientation is changing, this routine will be called. // Return value: // 0 this player IS NOT allowed to move this robot. // 1 this player IS allowed to move this robot. int ai_multiplayer_awareness(object *objp, int awareness_level) { int rval=1; #ifdef NETWORK if (Game_mode & GM_MULTI) { if (awareness_level == 0) return 0; rval = multi_can_move_robot(objp-Objects, awareness_level); } #endif return rval; } #ifndef NDEBUG fix Prev_boss_shields = -1; #endif // -------------------------------------------------------------------------------------------------------------------- // Do special stuff for a boss. void do_boss_stuff(object *objp, int player_visibility) { int boss_id, boss_index; boss_id = Robot_info[objp->id].boss_flag; Assert((boss_id >= BOSS_D2) && (boss_id < BOSS_D2 + NUM_D2_BOSSES)); boss_index = boss_id - BOSS_D2; #ifndef NDEBUG if (objp->shields != Prev_boss_shields) { Prev_boss_shields = objp->shields; } #endif // @mk, 10/13/95: Reason: // Level 4 boss behind locked door. But he's allowed to teleport out of there. So he // teleports out of there right away, and blasts player right after first door. if (!player_visibility && (GameTime64 - Boss_hit_time > F1_0*2)) return; if (!Boss_dying && Boss_teleports[boss_index]) { if (objp->ctype.ai_info.CLOAKED == 1) { Boss_hit_time = GameTime64; // Keep the cloak:teleport process going. if ((GameTime64 - Boss_cloak_start_time > BOSS_CLOAK_DURATION/3) && (Boss_cloak_end_time - GameTime64 > BOSS_CLOAK_DURATION/3) && (GameTime64 - Last_teleport_time > Boss_teleport_interval)) { if (ai_multiplayer_awareness(objp, 98)) teleport_boss(objp); } else if (GameTime64 - Boss_hit_time > F1_0*2) { Last_teleport_time -= Boss_teleport_interval/4; } if (GameTime64 > Boss_cloak_end_time || GameTime64 < Boss_cloak_start_time) objp->ctype.ai_info.CLOAKED = 0; } else if ((GameTime64 - Boss_cloak_end_time > Boss_cloak_interval) || (GameTime64 - Boss_cloak_end_time < -Boss_cloak_duration)) { if (ai_multiplayer_awareness(objp, 95)) { Boss_cloak_start_time = GameTime64; Boss_cloak_end_time = GameTime64+Boss_cloak_duration; objp->ctype.ai_info.CLOAKED = 1; #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_boss_actions(objp-Objects, 2, 0, 0); #endif } } } } #define BOSS_TO_PLAYER_GATE_DISTANCE (F1_0*200) void ai_multi_send_robot_position(int objnum, int force) { #ifdef NETWORK if (Game_mode & GM_MULTI) { if (force != -1) multi_send_robot_position(objnum, 1); else multi_send_robot_position(objnum, 0); } #endif return; } // -------------------------------------------------------------------------------------------------------------------- // Returns true if this object should be allowed to fire at the player. int maybe_ai_do_actual_firing_stuff(object *obj, ai_static *aip) { #ifdef NETWORK if (Game_mode & GM_MULTI) if ((aip->GOAL_STATE != AIS_FLIN) && (obj->id != ROBOT_BRAIN)) if (aip->CURRENT_STATE == AIS_FIRE) return 1; #endif return 0; } vms_vector Last_fired_upon_player_pos; // -------------------------------------------------------------------------------------------------------------------- // If fire_anyway, fire even if player is not visible. We're firing near where we believe him to be. Perhaps he's // lurking behind a corner. void ai_do_actual_firing_stuff(object *obj, ai_static *aip, ai_local *ailp, robot_info *robptr, vms_vector *vec_to_player, fix dist_to_player, vms_vector *gun_point, int player_visibility, int object_animates, int gun_num) { fix dot; if ((player_visibility == 2) || (Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD )) { vms_vector fire_pos; fire_pos = Believed_player_pos; // Hack: If visibility not == 2, we're here because we're firing at a nearby player. // So, fire at Last_fired_upon_player_pos instead of the player position. if (!robptr->attack_type && (player_visibility != 2)) fire_pos = Last_fired_upon_player_pos; // Changed by mk, 01/04/95, onearm would take about 9 seconds until he can fire at you. // Above comment corrected. Date changed from 1994, to 1995. Should fix some very subtle bugs, as well as not cause me to wonder, in the future, why I was writing AI code for onearm ten months before he existed. if (!object_animates || ready_to_fire(robptr, ailp)) { dot = vm_vec_dot(&obj->orient.fvec, vec_to_player); if ((dot >= 7*F1_0/8) || ((dot > F1_0/4) && robptr->boss_flag)) { if (gun_num < Robot_info[obj->id].n_guns) { if (robptr->attack_type == 1) { if (!Player_exploded && (dist_to_player < obj->size + ConsoleObject->size + F1_0*2)) { // robptr->circle_distance[Difficulty_level] + ConsoleObject->size) { if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION-2)) return; do_ai_robot_hit_attack(obj, ConsoleObject, &obj->pos); } else { return; } } else { if ((gun_point->x == 0) && (gun_point->y == 0) && (gun_point->z == 0)) { ; } else { if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) return; // New, multi-weapon-type system, 06/05/95 (life is slipping away...) if (gun_num != 0) { if (ailp->next_fire <= 0) { ai_fire_laser_at_player(obj, gun_point, gun_num, &fire_pos); Last_fired_upon_player_pos = fire_pos; } if ((ailp->next_fire2 <= 0) && (robptr->weapon_type2 != -1)) { calc_gun_point(gun_point, obj, 0); ai_fire_laser_at_player(obj, gun_point, 0, &fire_pos); Last_fired_upon_player_pos = fire_pos; } } else if (ailp->next_fire <= 0) { ai_fire_laser_at_player(obj, gun_point, gun_num, &fire_pos); Last_fired_upon_player_pos = fire_pos; } } } // Wants to fire, so should go into chase mode, probably. if ( (aip->behavior != AIB_RUN_FROM) && (aip->behavior != AIB_STILL) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_FOLLOW) && (!robptr->attack_type) && ((ailp->mode == AIM_FOLLOW_PATH) || (ailp->mode == AIM_STILL))) ailp->mode = AIM_CHASE_OBJECT; } aip->GOAL_STATE = AIS_RECO; ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; // Switch to next gun for next fire. If has 2 gun types, select gun #1, if exists. aip->CURRENT_GUN++; if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) { if ((Robot_info[obj->id].n_guns == 1) || (Robot_info[obj->id].weapon_type2 == -1)) aip->CURRENT_GUN = 0; else aip->CURRENT_GUN = 1; } } } } else if ( ((!robptr->attack_type) && (Weapon_info[Robot_info[obj->id].weapon_type].homing_flag == 1)) || (((Robot_info[obj->id].weapon_type2 != -1) && (Weapon_info[Robot_info[obj->id].weapon_type2].homing_flag == 1))) ) { // Robots which fire homing weapons might fire even if they don't have a bead on the player. if (((!object_animates) || (ailp->achieved_state[aip->CURRENT_GUN] == AIS_FIRE)) && (((ailp->next_fire <= 0) && (aip->CURRENT_GUN != 0)) || ((ailp->next_fire2 <= 0) && (aip->CURRENT_GUN == 0))) && (vm_vec_dist_quick(&Hit_pos, &obj->pos) > F1_0*40)) { if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) return; ai_fire_laser_at_player(obj, gun_point, gun_num, &Believed_player_pos); aip->GOAL_STATE = AIS_RECO; ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; // Switch to next gun for next fire. aip->CURRENT_GUN++; if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) aip->CURRENT_GUN = 0; } else { // Switch to next gun for next fire. aip->CURRENT_GUN++; if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) aip->CURRENT_GUN = 0; } } else { // --------------------------------------------------------------- vms_vector vec_to_last_pos; if (d_rand()/2 < fixmul(FrameTime, (Difficulty_level << 12) + 0x4000)) { if ((!object_animates || ready_to_fire(robptr, ailp)) && (Dist_to_last_fired_upon_player_pos < FIRE_AT_NEARBY_PLAYER_THRESHOLD)) { vm_vec_normalized_dir_quick(&vec_to_last_pos, &Believed_player_pos, &obj->pos); dot = vm_vec_dot(&obj->orient.fvec, &vec_to_last_pos); if (dot >= 7*F1_0/8) { if (aip->CURRENT_GUN < Robot_info[obj->id].n_guns) { if (robptr->attack_type == 1) { if (!Player_exploded && (dist_to_player < obj->size + ConsoleObject->size + F1_0*2)) { // robptr->circle_distance[Difficulty_level] + ConsoleObject->size) { if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION-2)) return; do_ai_robot_hit_attack(obj, ConsoleObject, &obj->pos); } else { return; } } else { if ((gun_point->x == 0) && (gun_point->y == 0) && (gun_point->z == 0)) { ; } else { if (!ai_multiplayer_awareness(obj, ROBOT_FIRE_AGITATION)) return; // New, multi-weapon-type system, 06/05/95 (life is slipping away...) if (gun_num != 0) { if (ailp->next_fire <= 0) ai_fire_laser_at_player(obj, gun_point, gun_num, &Last_fired_upon_player_pos); if ((ailp->next_fire2 <= 0) && (robptr->weapon_type2 != -1)) { calc_gun_point(gun_point, obj, 0); ai_fire_laser_at_player(obj, gun_point, 0, &Last_fired_upon_player_pos); } } else if (ailp->next_fire <= 0) ai_fire_laser_at_player(obj, gun_point, gun_num, &Last_fired_upon_player_pos); } } // Wants to fire, so should go into chase mode, probably. if ( (aip->behavior != AIB_RUN_FROM) && (aip->behavior != AIB_STILL) && (aip->behavior != AIB_SNIPE) && (aip->behavior != AIB_FOLLOW) && ((ailp->mode == AIM_FOLLOW_PATH) || (ailp->mode == AIM_STILL))) ailp->mode = AIM_CHASE_OBJECT; } aip->GOAL_STATE = AIS_RECO; ailp->goal_state[aip->CURRENT_GUN] = AIS_RECO; // Switch to next gun for next fire. aip->CURRENT_GUN++; if (aip->CURRENT_GUN >= Robot_info[obj->id].n_guns) { if (Robot_info[obj->id].n_guns == 1) aip->CURRENT_GUN = 0; else aip->CURRENT_GUN = 1; } } } } // --------------------------------------------------------------- } } dxx-rebirth-0.58.1-d2x/main/aipath.c000066400000000000000000001465701217717237500171270ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * AI path forming stuff. * */ #include // for printf() #include // for d_rand() and qsort() #include // for memset() #include "inferno.h" #include "console.h" #include "3d.h" #include "object.h" #include "dxxerror.h" #include "ai.h" #include "robot.h" #include "fvi.h" #include "physics.h" #include "wall.h" #ifdef EDITOR #include "editor/editor.h" #include "editor/esegment.h" #endif #include "player.h" #include "fireball.h" #include "game.h" #define PARALLAX 0 // If !0, then special debugging for Parallax eyes enabled. // Length in segments of avoidance path #define AVOID_SEG_LENGTH 7 #ifdef NDEBUG #define PATH_VALIDATION 0 #else #define PATH_VALIDATION 1 #endif void validate_all_paths(void); void ai_path_set_orient_and_vel(object *objp, vms_vector* goal_point, int player_visibility, vms_vector *vec_to_player); void maybe_ai_path_garbage_collect(void); void ai_path_garbage_collect(void); #if PATH_VALIDATION int validate_path(int debug_flag, point_seg* psegs, int num_points); #endif // ------------------------------------------------------------------------ void create_random_xlate(sbyte *xt) { int i; for (i=0; i= 0) && (j < MAX_SIDES_PER_SEGMENT)); temp_byte = xt[j]; xt[j] = xt[i]; xt[i] = temp_byte; } } // ----------------------------------------------------------------------------------------------------------- // Insert the point at the center of the side connecting two segments between the two points. // This is messy because we must insert into the list. The simplest (and not too slow) way to do this is to start // at the end of the list and go backwards. void insert_center_points(point_seg *psegs, int *num_points) { int i, j, last_point; int count=*num_points; last_point = *num_points-1; for (i=last_point; i>0; i--) { int connect_side, temp_segnum; vms_vector center_point, new_point; psegs[2*i] = psegs[i]; connect_side = find_connect_side(&Segments[psegs[i].segnum], &Segments[psegs[i-1].segnum]); Assert(connect_side != -1); // Impossible! These two segments must be connected, they were created by create_path_points (which was created by mk!) if (connect_side == -1) // Try to blow past the assert, this should at least prevent a hang. connect_side = 0; compute_center_point_on_side(¢er_point, &Segments[psegs[i-1].segnum], connect_side); vm_vec_sub(&new_point, &psegs[i-1].point, ¢er_point); new_point.x /= 16; new_point.y /= 16; new_point.z /= 16; vm_vec_sub(&psegs[2*i-1].point, ¢er_point, &new_point); temp_segnum = find_point_seg(&psegs[2*i-1].point, psegs[2*i].segnum); if (temp_segnum == -1) { psegs[2*i-1].point = center_point; find_point_seg(&psegs[2*i-1].point, psegs[2*i].segnum); } psegs[2*i-1].segnum = psegs[2*i].segnum; count++; } // Now, remove unnecessary center points. // A center point is unnecessary if it is close to the line between the two adjacent points. // MK, OPTIMIZE! Can get away with about half the math since every vector gets computed twice. for (i=1; i fixmul(vm_vec_mag(&temp1), vm_vec_mag(&temp2))) psegs[i].segnum = -1; } // Now, scan for points with segnum == -1 j = 0; for (i=0; i 3*F1_0/4 ) { if (abs(a.z) < F1_0/2) { if (rand_flag) { e.x = (d_rand()-16384)/2; e.y = (d_rand()-16384)/2; e.z = abs(e.x) + abs(e.y) + 1; vm_vec_normalize_quick(&e); } else { e.x = 0; e.y = 0; e.z = F1_0; } } else { if (rand_flag) { e.y = (d_rand()-16384)/2; e.z = (d_rand()-16384)/2; e.x = abs(e.y) + abs(e.z) + 1; vm_vec_normalize_quick(&e); } else { e.x = F1_0; e.y = 0; e.z = 0; } } } else { vm_vec_cross(&d, &a, &b); vm_vec_cross(&e, &c, &d); vm_vec_normalize_quick(&e); } if (vm_vec_mag_quick(&e) < F1_0/2) Int3(); segment_size = vm_vec_dist_quick(&Vertices[Segments[segnum].verts[0]], &Vertices[Segments[segnum].verts[6]]); if (segment_size > F1_0*40) segment_size = F1_0*40; vm_vec_scale_add(&goal_pos, &psegs[i].point, &e, segment_size/4); count = 3; while (count) { fvi_query fq; fvi_info hit_data; int hit_type; fq.p0 = &psegs[i].point; fq.startseg = psegs[i].segnum; fq.p1 = &goal_pos; fq.rad = objp->size; fq.thisobjnum = objp-Objects; fq.ignore_obj_list = NULL; fq.flags = 0; hit_type = find_vector_intersection(&fq, &hit_data); if (hit_type == HIT_NONE) count = 0; else { if ((count == 3) && (hit_type == HIT_BAD_P0)) Int3(); goal_pos.x = (fq.p0->x + hit_data.hit_pnt.x)/2; goal_pos.y = (fq.p0->y + hit_data.hit_pnt.y)/2; goal_pos.z = (fq.p0->z + hit_data.hit_pnt.z)/2; count--; if (count == 0) { // Couldn't move towards outside, that's ok, sometimes things can't be moved. goal_pos = psegs[i].point; } } } // Only move towards outside if remained inside segment. new_segnum = find_point_seg(&goal_pos, psegs[i].segnum); if (new_segnum == psegs[i].segnum) { new_psegs[i].point = goal_pos; new_psegs[i].segnum = new_segnum; } else { new_psegs[i].point = psegs[i].point; new_psegs[i].segnum = psegs[i].segnum; } } for (i=1; i<*num_points-1; i++) psegs[i] = new_psegs[i]; } // ----------------------------------------------------------------------------------------------------------- // Create a path from objp->pos to the center of end_seg. // Return a list of (segment_num, point_locations) at psegs // Return number of points in *num_points. // if max_depth == -1, then there is no maximum depth. // If unable to create path, return -1, else return 0. // If random_flag !0, then introduce randomness into path by looking at sides in random order. This means // that a path between two segments won't always be the same, unless it is unique. // If safety_flag is set, then additional points are added to "make sure" that points are reachable. I would // like to say that it ensures that the object can move between the points, but that would require knowing what // the object is (which isn't passed, right?) and making fvi calls (slow, right?). So, consider it the more_or_less_safe_flag. // If end_seg == -2, then end seg will never be found and this routine will drop out due to depth (probably called by create_n_segment_path). int create_path_points(object *objp, int start_seg, int end_seg, point_seg *psegs, short *num_points, int max_depth, int random_flag, int safety_flag, int avoid_seg) { int cur_seg; int sidenum; int qtail = 0, qhead = 0; int i; sbyte visited[MAX_SEGMENTS]; seg_seg seg_queue[MAX_SEGMENTS]; short depth[MAX_SEGMENTS]; int cur_depth; sbyte random_xlate[MAX_SIDES_PER_SEGMENT]; point_seg *original_psegs = psegs; int l_num_points; #if PATH_VALIDATION validate_all_paths(); #endif if ((objp->type == OBJ_ROBOT) && (objp->ctype.ai_info.behavior == AIB_RUN_FROM)) { random_flag = 1; avoid_seg = ConsoleObject->segnum; // Int3(); } if (max_depth == -1) max_depth = MAX_PATH_LENGTH; l_num_points = 0; //random_flag = Random_flag_override; //!! debug!! //safety_flag = Safety_flag_override; //!! debug!! // for (i=0; i<=Highest_segment_index; i++) { // visited[i] = 0; // depth[i] = 0; // } memset(visited, 0, sizeof(visited[0])*(Highest_segment_index+1)); memset(depth, 0, sizeof(depth[0])*(Highest_segment_index+1)); // If there is a segment we're not allowed to visit, mark it. if (avoid_seg != -1) { Assert(avoid_seg <= Highest_segment_index); if ((start_seg != avoid_seg) && (end_seg != avoid_seg)) { visited[avoid_seg] = 1; depth[avoid_seg] = 0; } } if (random_flag) create_random_xlate(random_xlate); cur_seg = start_seg; visited[cur_seg] = 1; cur_depth = 0; while (cur_seg != end_seg) { segment *segp = &Segments[cur_seg]; if (random_flag) if (d_rand() < 8192) create_random_xlate(random_xlate); for (sidenum = 0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { int snum = sidenum; if (random_flag) snum = random_xlate[sidenum]; if (IS_CHILD(segp->children[snum]) && ((WALL_IS_DOORWAY(segp, snum) & WID_FLY_FLAG) || (ai_door_is_openable(objp, segp, snum)))) { int this_seg = segp->children[snum]; Assert(this_seg != -1); if (((cur_seg == avoid_seg) || (this_seg == avoid_seg)) && (ConsoleObject->segnum == avoid_seg)) { vms_vector center_point; fvi_query fq; fvi_info hit_data; int hit_type; compute_center_point_on_side(¢er_point, segp, snum); fq.p0 = &objp->pos; fq.startseg = objp->segnum; fq.p1 = ¢er_point; fq.rad = objp->size; fq.thisobjnum = objp-Objects; fq.ignore_obj_list = NULL; fq.flags = 0; hit_type = find_vector_intersection(&fq, &hit_data); if (hit_type != HIT_NONE) { goto dont_add; } } if (!visited[this_seg]) { seg_queue[qtail].start = cur_seg; seg_queue[qtail].end = this_seg; visited[this_seg] = 1; depth[qtail++] = cur_depth+1; if (depth[qtail-1] == max_depth) { end_seg = seg_queue[qtail-1].end; goto cpp_done1; } // end if (depth[... } // end if (!visited... } // if (WALL_IS_DOORWAY(... dont_add: ; } // for (sidenum... if (qtail <= 0) break; if (qhead >= qtail) { // Couldn't get to goal, return a path as far as we got, which probably acceptable to the unparticular caller. end_seg = seg_queue[qtail-1].end; break; } cur_seg = seg_queue[qhead].end; cur_depth = depth[qhead]; qhead++; cpp_done1: ; } // while (cur_seg ... if (qtail > 0) { // Set qtail to the segment which ends at the goal. while (seg_queue[--qtail].end != end_seg) if (qtail < 0) { *num_points = l_num_points; return -1; } } else qtail = -1; #ifdef EDITOR // -- N_selected_segs = 0; #endif while (qtail >= 0) { int parent_seg, this_seg; this_seg = seg_queue[qtail].end; parent_seg = seg_queue[qtail].start; Assert((this_seg >= 0) && (this_seg <= Highest_segment_index)); psegs->segnum = this_seg; compute_segment_center(&psegs->point,&Segments[this_seg]); psegs++; l_num_points++; #ifdef EDITOR // -- Selected_segs[N_selected_segs++] = this_seg; #endif if (parent_seg == start_seg) break; while (seg_queue[--qtail].end != parent_seg) Assert(qtail >= 0); } Assert((start_seg >= 0) && (start_seg <= Highest_segment_index)); psegs->segnum = start_seg; compute_segment_center(&psegs->point,&Segments[start_seg]); psegs++; l_num_points++; #if PATH_VALIDATION validate_path(1, original_psegs, l_num_points); #endif // Now, reverse point_segs in place. for (i=0; i< l_num_points/2; i++) { point_seg temp_point_seg = *(original_psegs + i); *(original_psegs + i) = *(original_psegs + l_num_points - i - 1); *(original_psegs + l_num_points - i - 1) = temp_point_seg; } #if PATH_VALIDATION validate_path(2, original_psegs, l_num_points); #endif // Now, if safety_flag set, then insert the point at the center of the side connecting two segments // between the two points. This is messy because we must insert into the list. The simplest (and not too slow) // way to do this is to start at the end of the list and go backwards. if (safety_flag) { if (psegs - Point_segs + l_num_points + 2 > MAX_POINT_SEGS) { // Ouch! Cannot insert center points in path. So return unsafe path. ai_reset_all_paths(); *num_points = l_num_points; return -1; } else { // int old_num_points = l_num_points; insert_center_points(original_psegs, &l_num_points); } } #if PATH_VALIDATION validate_path(3, original_psegs, l_num_points); #endif // -- MK, 10/30/95 -- This code causes apparent discontinuities in the path, moving a point // into a new segment. It is not necessarily bad, but it makes it hard to track down actual // discontinuity problems. if (objp->type == OBJ_ROBOT) if (Robot_info[objp->id].companion) move_towards_outside(original_psegs, &l_num_points, objp, 0); #if PATH_VALIDATION validate_path(4, original_psegs, l_num_points); #endif *num_points = l_num_points; return 0; } int Last_buddy_polish_path_tick; // ------------------------------------------------------------------------------------------------------- // polish_path // Takes an existing path and makes it nicer. // Drops as many leading points as possible still maintaining direct accessibility // from current position to first point. // Will not shorten path to fewer than 3 points. // Returns number of points. // Starting position in psegs doesn't change. // Changed, MK, 10/18/95. I think this was causing robots to get hung up on walls. // Only drop up to the first three points. int polish_path(object *objp, point_seg *psegs, int num_points) { int i, first_point=0; if (num_points <= 4) return num_points; // Prevent the buddy from polishing his path twice in one tick, which can cause him to get hung up. Pretty ugly, huh? if (Robot_info[objp->id].companion) { if (d_tick_count == Last_buddy_polish_path_tick) return num_points; else Last_buddy_polish_path_tick = d_tick_count; } // -- MK: 10/18/95: for (i=0; ipos; fq.startseg = objp->segnum; fq.p1 = &psegs[i].point; fq.rad = objp->size; fq.thisobjnum = objp-Objects; fq.ignore_obj_list = NULL; fq.flags = 0; hit_type = find_vector_intersection(&fq, &hit_data); if (hit_type == HIT_NONE) first_point = i+1; else break; } if (first_point) { // Scrunch down all the psegs. for (i=first_point; isegnum; if ((curseg < 0) || (curseg > Highest_segment_index)) { Int3(); // Contact Mike: Debug trap for elusive, nasty bug. return 0; } if (num_points == 0) return 1; for (i=1; i Highest_segment_index)) { Int3(); // Contact Mike: Debug trap for elusive, nasty bug. return 0; } if (curseg != nextseg) { for (sidenum=0; sidenumctype.ai_info; //ai_local *ailp = &Ai_local_info[i]; if (objp->control_type == CT_AI) { if ((aip->hide_index != -1) && (aip->path_length > 0)) if (!validate_path(4, &Point_segs[aip->hide_index], aip->path_length)) { Int3(); // This path is bogus! Who corrupted it! Danger! Danger! // Contact Mike, he caused this mess. //force_dump_ai_objects_all("Error in validate_all_paths"); aip->path_length=0; // This allows people to resume without harm... } } } } #endif } #endif // ------------------------------------------------------------------------------------------------------- // Creates a path from the objects current segment (objp->segnum) to the specified segment for the object to // hide in Ai_local_info[objnum].goal_segment. // Sets objp->ctype.ai_info.hide_index, a pointer into Point_segs, the first point_seg of the path. // objp->ctype.ai_info.path_length, length of path // Point_segs_free_ptr global pointer into Point_segs array // Change, 10/07/95: Used to create path to ConsoleObject->pos. Now creates path to Believed_player_pos. void create_path_to_player(object *objp, int max_length, int safety_flag) { ai_static *aip = &objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objp-Objects]; int start_seg, end_seg; if (max_length == -1) max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; ailp->time_player_seen = GameTime64; // Prevent from resetting path quickly. ailp->goal_segment = Believed_player_seg; start_seg = objp->segnum; end_seg = ailp->goal_segment; if (end_seg == -1) { ; } else { create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, safety_flag, -1); aip->path_length = polish_path(objp, Point_segs_free_ptr, aip->path_length); aip->hide_index = Point_segs_free_ptr - Point_segs; aip->cur_path_index = 0; Point_segs_free_ptr += aip->path_length; if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { //Int3(); // Contact Mike: This is stupid. Should call maybe_ai_garbage_collect before the add. //force_dump_ai_objects_all("Error in create_path_to_player"); ai_reset_all_paths(); return; } // Assert(Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 < MAX_POINT_SEGS); aip->PATH_DIR = 1; // Initialize to moving forward. // -- UNUSED! aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. ailp->mode = AIM_FOLLOW_PATH; ailp->player_awareness_type = 0; // If robot too aware of player, will set mode to chase } maybe_ai_path_garbage_collect(); } // ------------------------------------------------------------------------------------------------------- // Creates a path from the object's current segment (objp->segnum) to segment goalseg. void create_path_to_segment(object *objp, int goalseg, int max_length, int safety_flag) { ai_static *aip = &objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objp-Objects]; int start_seg, end_seg; if (max_length == -1) max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; ailp->time_player_seen = GameTime64; // Prevent from resetting path quickly. ailp->goal_segment = goalseg; start_seg = objp->segnum; end_seg = ailp->goal_segment; if (end_seg == -1) { ; } else { create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, safety_flag, -1); aip->hide_index = Point_segs_free_ptr - Point_segs; aip->cur_path_index = 0; Point_segs_free_ptr += aip->path_length; if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { ai_reset_all_paths(); return; } aip->PATH_DIR = 1; // Initialize to moving forward. // -- UNUSED! aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. ailp->player_awareness_type = 0; // If robot too aware of player, will set mode to chase } maybe_ai_path_garbage_collect(); } // ------------------------------------------------------------------------------------------------------- // Creates a path from the objects current segment (objp->segnum) to the specified segment for the object to // hide in Ai_local_info[objnum].goal_segment // Sets objp->ctype.ai_info.hide_index, a pointer into Point_segs, the first point_seg of the path. // objp->ctype.ai_info.path_length, length of path // Point_segs_free_ptr global pointer into Point_segs array void create_path_to_station(object *objp, int max_length) { ai_static *aip = &objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objp-Objects]; int start_seg, end_seg; if (max_length == -1) max_length = MAX_DEPTH_TO_SEARCH_FOR_PLAYER; ailp->time_player_seen = GameTime64; // Prevent from resetting path quickly. start_seg = objp->segnum; end_seg = aip->hide_segment; if (end_seg == -1) { ; } else { create_path_points(objp, start_seg, end_seg, Point_segs_free_ptr, &aip->path_length, max_length, 1, 1, -1); aip->path_length = polish_path(objp, Point_segs_free_ptr, aip->path_length); aip->hide_index = Point_segs_free_ptr - Point_segs; aip->cur_path_index = 0; Point_segs_free_ptr += aip->path_length; if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { //Int3(); // Contact Mike: Stupid. //force_dump_ai_objects_all("Error in create_path_to_station"); ai_reset_all_paths(); return; } // Assert(Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 < MAX_POINT_SEGS); aip->PATH_DIR = 1; // Initialize to moving forward. // aip->SUBMODE = AISM_GOHIDE; // This forces immediate movement. ailp->mode = AIM_FOLLOW_PATH; ailp->player_awareness_type = 0; } maybe_ai_path_garbage_collect(); } // ------------------------------------------------------------------------------------------------------- // Create a path of length path_length for an object, stuffing info in ai_info field. void create_n_segment_path(object *objp, int path_length, int avoid_seg) { ai_static *aip=&objp->ctype.ai_info; ai_local *ailp = &Ai_local_info[objp-Objects]; if (create_path_points(objp, objp->segnum, -2, Point_segs_free_ptr, &aip->path_length, path_length, 1, 0, avoid_seg) == -1) { Point_segs_free_ptr += aip->path_length; while ((create_path_points(objp, objp->segnum, -2, Point_segs_free_ptr, &aip->path_length, --path_length, 1, 0, -1) == -1)) { Assert(path_length); } } aip->hide_index = Point_segs_free_ptr - Point_segs; aip->cur_path_index = 0; #if PATH_VALIDATION validate_path(8, Point_segs_free_ptr, aip->path_length); #endif Point_segs_free_ptr += aip->path_length; if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { //Int3(); // Contact Mike: This is curious, though not deadly. /eip++;g //force_dump_ai_objects_all("Error in crete_n_segment_path 2"); ai_reset_all_paths(); } aip->PATH_DIR = 1; // Initialize to moving forward. // -- UNUSED! aip->SUBMODE = -1; // Don't know what this means. ailp->mode = AIM_FOLLOW_PATH; // If this robot is visible (player_visibility is not available) and it's running away, move towards outside with // randomness to prevent a stream of bots from going away down the center of a corridor. if (Ai_local_info[objp-Objects].previous_visibility) { if (aip->path_length) { int t_num_points = aip->path_length; move_towards_outside(&Point_segs[aip->hide_index], &t_num_points, objp, 1); aip->path_length = t_num_points; } } maybe_ai_path_garbage_collect(); } // ------------------------------------------------------------------------------------------------------- void create_n_segment_path_to_door(object *objp, int path_length, int avoid_seg) { create_n_segment_path(objp, path_length, avoid_seg); } extern int Connected_segment_distance; #define Int3_if(cond) if (!cond) Int3(); // ---------------------------------------------------------------------------------------------------- void move_object_to_goal(object *objp, vms_vector *goal_point, int goal_seg) { ai_static *aip = &objp->ctype.ai_info; int segnum; if (aip->path_length < 2) return; Assert(objp->segnum != -1); Assert(aip->path_length >= 2); if (aip->cur_path_index <= 0) { if (aip->behavior == AIB_STATION) { create_path_to_station(objp, 15); return; } aip->cur_path_index = 1; aip->PATH_DIR = 1; } else if (aip->cur_path_index >= aip->path_length - 1) { if (aip->behavior == AIB_STATION) { create_path_to_station(objp, 15); if (aip->path_length == 0) { ai_local *ailp = &Ai_local_info[objp-Objects]; ailp->mode = AIM_STILL; } return; } Assert(aip->path_length != 0); aip->cur_path_index = aip->path_length-2; aip->PATH_DIR = -1; } else aip->cur_path_index += aip->PATH_DIR; //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); objp->pos = *goal_point; segnum = find_object_seg(objp); if (segnum == -1) { Int3(); // Oops, object is not in any segment. // Contact Mike: This is impossible. // Hack, move object to center of segment it used to be in. compute_segment_center(&objp->pos, &Segments[objp->segnum]); } else obj_relink(objp-Objects, segnum); } // -- too much work -- // ---------------------------------------------------------------------------------------------------------- // -- too much work -- // Return true if the object the companion wants to kill is reachable. // -- too much work -- int attack_kill_object(object *objp) // -- too much work -- { // -- too much work -- object *kill_objp; // -- too much work -- fvi_info hit_data; // -- too much work -- int fate; // -- too much work -- fvi_query fq; // -- too much work -- // -- too much work -- if (Escort_kill_object == -1) // -- too much work -- return 0; // -- too much work -- // -- too much work -- kill_objp = &Objects[Escort_kill_object]; // -- too much work -- // -- too much work -- fq.p0 = &objp->pos; // -- too much work -- fq.startseg = objp->segnum; // -- too much work -- fq.p1 = &kill_objp->pos; // -- too much work -- fq.rad = objp->size; // -- too much work -- fq.thisobjnum = objp-Objects; // -- too much work -- fq.ignore_obj_list = NULL; // -- too much work -- fq.flags = 0; // -- too much work -- // -- too much work -- fate = find_vector_intersection(&fq,&hit_data); // -- too much work -- // -- too much work -- if (fate == HIT_NONE) // -- too much work -- return 1; // -- too much work -- else // -- too much work -- return 0; // -- too much work -- } // ---------------------------------------------------------------------------------------------------------- // Optimization: If current velocity will take robot near goal, don't change velocity void ai_follow_path(object *objp, int player_visibility, int previous_visibility, vms_vector *vec_to_player) { ai_static *aip = &objp->ctype.ai_info; vms_vector goal_point, new_goal_point; fix dist_to_goal; robot_info *robptr = &Robot_info[objp->id]; int forced_break, original_dir, original_index; ai_local *ailp = &Ai_local_info[objp-Objects]; fix threshold_distance; if ((aip->hide_index == -1) || (aip->path_length == 0)) { if (ailp->mode == AIM_RUN_FROM_OBJECT) { create_n_segment_path(objp, 5, -1); //--Int3_if((aip->path_length != 0)); ailp->mode = AIM_RUN_FROM_OBJECT; } else { create_n_segment_path(objp, 5, -1); //--Int3_if((aip->path_length != 0)); } } if ((aip->hide_index + aip->path_length > Point_segs_free_ptr - Point_segs) && (aip->path_length>0)) { Int3(); // Contact Mike: Bad. Path goes into what is believed to be free space. // This is debugging code. Figure out why garbage collection // didn't compress this object's path information. ai_path_garbage_collect(); //force_dump_ai_objects_all("Error in ai_follow_path"); ai_reset_all_paths(); } if (aip->path_length < 2) { if ((aip->behavior == AIB_SNIPE) || (ailp->mode == AIM_RUN_FROM_OBJECT)) { if (ConsoleObject->segnum == objp->segnum) { create_n_segment_path(objp, AVOID_SEG_LENGTH, -1); // Can't avoid segment player is in, robot is already in it! (That's what the -1 is for) //--Int3_if((aip->path_length != 0)); } else { create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); //--Int3_if((aip->path_length != 0)); } if (aip->behavior == AIB_SNIPE) { if (robptr->thief) ailp->mode = AIM_THIEF_ATTACK; // It gets bashed in create_n_segment_path else ailp->mode = AIM_SNIPE_FIRE; // It gets bashed in create_n_segment_path } else { ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path } } else if (robptr->companion == 0) { ailp->mode = AIM_STILL; aip->path_length = 0; return; } } //--Int3_if(((aip->PATH_DIR == -1) || (aip->PATH_DIR == 1))); //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); // If running from player, only run until can't be seen. if (ailp->mode == AIM_RUN_FROM_OBJECT) { if ((player_visibility == 0) && (ailp->player_awareness_type == 0)) { fix vel_scale; vel_scale = F1_0 - FrameTime/2; if (vel_scale < F1_0/2) vel_scale = F1_0/2; vm_vec_scale(&objp->mtype.phys_info.velocity, vel_scale); return; } else if (!(d_tick_count ^ ((objp-Objects) & 0x07))) { // Done 1/8 ticks. // If player on path (beyond point robot is now at), then create a new path. point_seg *curpsp = &Point_segs[aip->hide_index]; int player_segnum = ConsoleObject->segnum; int i; // This is probably being done every frame, which is wasteful. for (i=aip->cur_path_index; ipath_length; i++) { if (curpsp[i].segnum == player_segnum) { if (player_segnum != objp->segnum) { create_n_segment_path(objp, AVOID_SEG_LENGTH, player_segnum); } else { create_n_segment_path(objp, AVOID_SEG_LENGTH, -1); } Assert(aip->path_length != 0); ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path break; } } if (player_visibility) { ailp->player_awareness_type = 1; ailp->player_awareness_time = F1_0; } } } //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); if (aip->cur_path_index < 0) { aip->cur_path_index = 0; } else if (aip->cur_path_index >= aip->path_length) { if (ailp->mode == AIM_RUN_FROM_OBJECT) { create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path Assert(aip->path_length != 0); } else { aip->cur_path_index = aip->path_length-1; } } goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; // If near goal, pick another goal point. forced_break = 0; // Gets set for short paths. original_dir = aip->PATH_DIR; original_index = aip->cur_path_index; threshold_distance = fixmul(vm_vec_mag_quick(&objp->mtype.phys_info.velocity), FrameTime)*2 + F1_0*2; new_goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); while ((dist_to_goal < threshold_distance) && !forced_break) { // Advance to next point on path. aip->cur_path_index += aip->PATH_DIR; // See if next point wraps past end of path (in either direction), and if so, deal with it based on mode. if ((aip->cur_path_index >= aip->path_length) || (aip->cur_path_index < 0)) { // Buddy bot. If he's in mode to get away from player and at end of line, // if player visible, then make a new path, else just return. if (robptr->companion) { if (Escort_special_goal == ESCORT_GOAL_SCRAM) { if (player_visibility) { create_n_segment_path(objp, 16 + d_rand() * 16, -1); aip->path_length = polish_path(objp, &Point_segs[aip->hide_index], aip->path_length); Assert(aip->path_length != 0); ailp->mode = AIM_WANDER; // Special buddy mode. //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); return; } else { ailp->mode = AIM_WANDER; // Special buddy mode. vm_vec_zero(&objp->mtype.phys_info.velocity); vm_vec_zero(&objp->mtype.phys_info.rotvel); //!!Assert((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length)); return; } } } if (aip->behavior == AIB_FOLLOW) { create_n_segment_path(objp, 10, ConsoleObject->segnum); //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } else if (aip->behavior == AIB_STATION) { create_path_to_station(objp, 15); if ((aip->hide_segment != Point_segs[aip->hide_index+aip->path_length-1].segnum) || (aip->path_length == 0)) { ailp->mode = AIM_STILL; } else { //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } return; } else if (ailp->mode == AIM_FOLLOW_PATH) { create_path_to_player(objp, 10, 1); if (aip->hide_segment != Point_segs[aip->hide_index+aip->path_length-1].segnum) { ailp->mode = AIM_STILL; return; } else { //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } } else if (ailp->mode == AIM_RUN_FROM_OBJECT) { create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path if (aip->path_length < 1) { create_n_segment_path(objp, AVOID_SEG_LENGTH, ConsoleObject->segnum); ailp->mode = AIM_RUN_FROM_OBJECT; // It gets bashed in create_n_segment_path if (aip->path_length < 1) { aip->behavior = AIB_NORMAL; ailp->mode = AIM_STILL; return; } } //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } else { // Reached end of the line. First see if opposite end point is reachable, and if so, go there. // If not, turn around. int opposite_end_index; vms_vector *opposite_end_point; fvi_info hit_data; int fate; fvi_query fq; // See which end we're nearer and look at the opposite end point. if (abs(aip->cur_path_index - aip->path_length) < aip->cur_path_index) { // Nearer to far end (ie, index not 0), so try to reach 0. opposite_end_index = 0; } else { // Nearer to 0 end, so try to reach far end. opposite_end_index = aip->path_length-1; } //--Int3_if(((opposite_end_index >= 0) && (opposite_end_index < aip->path_length))); opposite_end_point = &Point_segs[aip->hide_index + opposite_end_index].point; fq.p0 = &objp->pos; fq.startseg = objp->segnum; fq.p1 = opposite_end_point; fq.rad = objp->size; fq.thisobjnum = objp-Objects; fq.ignore_obj_list = NULL; fq.flags = 0; //what about trans walls??? fate = find_vector_intersection(&fq,&hit_data); if (fate != HIT_WALL) { // We can be circular! Do it! // Path direction is unchanged. aip->cur_path_index = opposite_end_index; } else { aip->PATH_DIR = -aip->PATH_DIR; aip->cur_path_index += aip->PATH_DIR; } //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } break; } else { new_goal_point = Point_segs[aip->hide_index + aip->cur_path_index].point; goal_point = new_goal_point; dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } // If went all the way around to original point, in same direction, then get out of here! if ((aip->cur_path_index == original_index) && (aip->PATH_DIR == original_dir)) { create_path_to_player(objp, 3, 1); //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); forced_break = 1; } //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } // end while // Set velocity (objp->mtype.phys_info.velocity) and orientation (objp->orient) for this object. //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); ai_path_set_orient_and_vel(objp, &goal_point, player_visibility, vec_to_player); //--Int3_if(((aip->cur_path_index >= 0) && (aip->cur_path_index < aip->path_length))); } typedef struct { short path_start, objnum; } obj_path; int path_index_compare(obj_path *i1, obj_path *i2) { if (i1->path_start < i2->path_start) return -1; else if (i1->path_start == i2->path_start) return 0; else return 1; } // ---------------------------------------------------------------------------------------------------------- // Set orientation matrix and velocity for objp based on its desire to get to a point. void ai_path_set_orient_and_vel(object *objp, vms_vector *goal_point, int player_visibility, vms_vector *vec_to_player) { vms_vector cur_vel = objp->mtype.phys_info.velocity; vms_vector norm_cur_vel; vms_vector norm_vec_to_goal; vms_vector cur_pos = objp->pos; vms_vector norm_fvec; fix speed_scale; fix dot; robot_info *robptr = &Robot_info[objp->id]; fix max_speed; // If evading player, use highest difficulty level speed, plus something based on diff level max_speed = robptr->max_speed[Difficulty_level]; if ((Ai_local_info[objp-Objects].mode == AIM_RUN_FROM_OBJECT) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) max_speed = max_speed*3/2; vm_vec_sub(&norm_vec_to_goal, goal_point, &cur_pos); vm_vec_normalize_quick(&norm_vec_to_goal); norm_cur_vel = cur_vel; vm_vec_normalize_quick(&norm_cur_vel); norm_fvec = objp->orient.fvec; vm_vec_normalize_quick(&norm_fvec); dot = vm_vec_dot(&norm_vec_to_goal, &norm_fvec); // If very close to facing opposite desired vector, perturb vector if (dot < -15*F1_0/16) { norm_cur_vel = norm_vec_to_goal; } else { norm_cur_vel.x += norm_vec_to_goal.x/2/((float)(F1_0/30)/FrameTime); norm_cur_vel.y += norm_vec_to_goal.y/2/((float)(F1_0/30)/FrameTime); norm_cur_vel.z += norm_vec_to_goal.z/2/((float)(F1_0/30)/FrameTime); } vm_vec_normalize_quick(&norm_cur_vel); // Set speed based on this robot type's maximum allowed speed and how hard it is turning. // How hard it is turning is based on the dot product of (vector to goal) and (current velocity vector) // Note that since 3*F1_0/4 is added to dot product, it is possible for the robot to back up. // Set speed and orientation. if (dot < 0) dot /= -4; // If in snipe mode, can move fast even if not facing that direction. if (objp->ctype.ai_info.behavior == AIB_SNIPE) if (dot < F1_0/2) dot = (dot + F1_0)/2; speed_scale = fixmul(max_speed, dot); vm_vec_scale(&norm_cur_vel, speed_scale); objp->mtype.phys_info.velocity = norm_cur_vel; if ((Ai_local_info[objp-Objects].mode == AIM_RUN_FROM_OBJECT) || (robptr->companion == 1) || (objp->ctype.ai_info.behavior == AIB_SNIPE)) { if (Ai_local_info[objp-Objects].mode == AIM_SNIPE_RETREAT_BACKWARDS) { if ((player_visibility) && (vec_to_player != NULL)) norm_vec_to_goal = *vec_to_player; else vm_vec_negate(&norm_vec_to_goal); } ai_turn_towards_vector(&norm_vec_to_goal, objp, robptr->turn_time[NDL-1]/2); } else ai_turn_towards_vector(&norm_vec_to_goal, objp, robptr->turn_time[Difficulty_level]); } int Last_tick_garbage_collected = 0; // ---------------------------------------------------------------------------------------------------------- // Garbage colledion -- Free all unused records in Point_segs and compress all paths. void ai_path_garbage_collect(void) { int free_path_index = 0; int num_path_objects = 0; int objnum; int objind; obj_path object_list[MAX_OBJECTS]; #ifndef NDEBUG force_dump_ai_objects_all("***** Start ai_path_garbage_collect *****"); #endif Last_tick_garbage_collected = d_tick_count; #if PATH_VALIDATION validate_all_paths(); #endif // Create a list of objects which have paths of length 1 or more. for (objnum=0; objnum <= Highest_object_index; objnum++) { object *objp = &Objects[objnum]; if ((objp->type == OBJ_ROBOT) && ((objp->control_type == CT_AI) || (objp->control_type == CT_MORPH))) { ai_static *aip = &objp->ctype.ai_info; if (aip->path_length) { object_list[num_path_objects].path_start = aip->hide_index; object_list[num_path_objects++].objnum = objnum; } } } qsort(object_list, num_path_objects, sizeof(object_list[0]), (int (*)(void const *,void const *))path_index_compare); for (objind=0; objind < num_path_objects; objind++) { object *objp; ai_static *aip; int i; int old_index; objnum = object_list[objind].objnum; objp = &Objects[objnum]; aip = &objp->ctype.ai_info; old_index = aip->hide_index; aip->hide_index = free_path_index; for (i=0; ipath_length; i++) Point_segs[free_path_index++] = Point_segs[old_index++]; } Point_segs_free_ptr = &Point_segs[free_path_index]; #ifndef NDEBUG { int i; force_dump_ai_objects_all("***** Finish ai_path_garbage_collect *****"); for (i=0; i<=Highest_object_index; i++) { ai_static *aip = &Objects[i].ctype.ai_info; if ((Objects[i].type == OBJ_ROBOT) && (Objects[i].control_type == CT_AI)) if ((aip->hide_index + aip->path_length > Point_segs_free_ptr - Point_segs) && (aip->path_length>0)) Int3(); // Contact Mike: Debug trap for nasty, elusive bug. } validate_all_paths(); } #endif } // ----------------------------------------------------------------------------- // Do garbage collection if not been done for awhile, or things getting really critical. void maybe_ai_path_garbage_collect(void) { if (Point_segs_free_ptr - Point_segs > MAX_POINT_SEGS - MAX_PATH_LENGTH) { if (Last_tick_garbage_collected+1 >= d_tick_count) { // This is kind of bad. Garbage collected last frame or this frame. // Just destroy all paths. Too bad for the robots. They are memory wasteful. ai_reset_all_paths(); } else { // We are really close to full, but didn't just garbage collect, so maybe this is recoverable. ai_path_garbage_collect(); } } else if (Point_segs_free_ptr - Point_segs > 3*MAX_POINT_SEGS/4) { if (Last_tick_garbage_collected + 16 < d_tick_count) { ai_path_garbage_collect(); } } else if (Point_segs_free_ptr - Point_segs > MAX_POINT_SEGS/2) { if (Last_tick_garbage_collected + 256 < d_tick_count) { ai_path_garbage_collect(); } } } // ----------------------------------------------------------------------------- // Reset all paths. Do garbage collection. // Should be called at the start of each level. void ai_reset_all_paths(void) { int i; for (i=0; i<=Highest_object_index; i++) if (Objects[i].control_type == CT_AI) { Objects[i].ctype.ai_info.hide_index = -1; Objects[i].ctype.ai_info.path_length = 0; } ai_path_garbage_collect(); } // --------------------------------------------------------------------------------------------------------- // Probably called because a robot bashed a wall, getting a bunch of retries. // Try to resume path. void attempt_to_resume_path(object *objp) { ai_static *aip = &objp->ctype.ai_info; int new_path_index; if ((aip->behavior == AIB_STATION) && (Robot_info[objp->id].companion != 1)) if (d_rand() > 8192) { ai_local *ailp = &Ai_local_info[objp-Objects]; aip->hide_segment = objp->segnum; ailp->mode = AIM_STILL; } new_path_index = aip->cur_path_index - aip->PATH_DIR; if ((new_path_index >= 0) && (new_path_index < aip->path_length)) { aip->cur_path_index = new_path_index; } else { // At end of line and have nowhere to go. move_towards_segment_center(objp); create_path_to_station(objp, 15); } } // ---------------------------------------------------------------------------------------------------------- // DEBUG FUNCTIONS FOLLOW // ---------------------------------------------------------------------------------------------------------- #ifdef EDITOR int Test_size = 1000; void test_create_path_many(void) { point_seg point_segs[200]; short num_points; int i; for (i=0; imtype.phys_info.velocity; vms_vector norm_cur_vel; vms_vector norm_vec_to_goal; vms_vector cur_pos = objp->pos; vms_vector norm_fvec; fix speed_scale; fix dot; fix max_speed; max_speed = Robot_info[objp->id].max_speed[Difficulty_level]; vm_vec_sub(&norm_vec_to_goal, goal_point, &cur_pos); vm_vec_normalize_quick(&norm_vec_to_goal); norm_cur_vel = cur_vel; vm_vec_normalize_quick(&norm_cur_vel); norm_fvec = objp->orient.fvec; vm_vec_normalize_quick(&norm_fvec); dot = vm_vec_dot(&norm_vec_to_goal, &norm_fvec); if (Ai_local_info[objp-Objects].mode == AIM_SNIPE_RETREAT_BACKWARDS) { dot = -dot; } // If very close to facing opposite desired vector, perturb vector if (dot < -15*F1_0/16) { norm_cur_vel = norm_vec_to_goal; } else { norm_cur_vel.x += norm_vec_to_goal.x/2/((float)(F1_0/30)/FrameTime); norm_cur_vel.y += norm_vec_to_goal.y/2/((float)(F1_0/30)/FrameTime); norm_cur_vel.z += norm_vec_to_goal.z/2/((float)(F1_0/30)/FrameTime); } vm_vec_normalize_quick(&norm_cur_vel); // Set speed based on this robot type's maximum allowed speed and how hard it is turning. // How hard it is turning is based on the dot product of (vector to goal) and (current velocity vector) // Note that since 3*F1_0/4 is added to dot product, it is possible for the robot to back up. // Set speed and orientation. if (dot < 0) dot /= 4; speed_scale = fixmul(max_speed, dot); vm_vec_scale(&norm_cur_vel, speed_scale); objp->mtype.phys_info.velocity = norm_cur_vel; ai_turn_towards_vector(&norm_vec_to_goal, objp, F1_0); } // ---------------------------------------------------------------------------------------------------------- // Optimization: If current velocity will take robot near goal, don't change velocity void player_follow_path(object *objp) { vms_vector goal_point; fix dist_to_goal; int count, forced_break, original_index; int goal_seg; fix threshold_distance; if (!Player_following_path_flag) return; if (Player_hide_index == -1) return; if (Player_path_length < 2) return; goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; goal_seg = Point_segs[Player_hide_index + Player_cur_path_index].segnum; Assert((goal_seg >= 0) && (goal_seg <= Highest_segment_index)); (void)goal_seg; dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); if (Player_cur_path_index < 0) Player_cur_path_index = 0; else if (Player_cur_path_index >= Player_path_length) Player_cur_path_index = Player_path_length-1; goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; count=0; // If near goal, pick another goal point. forced_break = 0; // Gets set for short paths. //original_dir = 1; original_index = Player_cur_path_index; threshold_distance = fixmul(vm_vec_mag_quick(&objp->mtype.phys_info.velocity), FrameTime)*2 + F1_0*2; while ((dist_to_goal < threshold_distance) && !forced_break) { // ----- Debug stuff ----- if (count++ > 20) { break; } // Advance to next point on path. Player_cur_path_index += 1; // See if next point wraps past end of path (in either direction), and if so, deal with it based on mode. if ((Player_cur_path_index >= Player_path_length) || (Player_cur_path_index < 0)) { Player_following_path_flag = 0; forced_break = 1; } // If went all the way around to original point, in same direction, then get out of here! if (Player_cur_path_index == original_index) { Player_following_path_flag = 0; forced_break = 1; } goal_point = Point_segs[Player_hide_index + Player_cur_path_index].point; dist_to_goal = vm_vec_dist_quick(&goal_point, &objp->pos); } // end while // Set velocity (objp->mtype.phys_info.velocity) and orientation (objp->orient) for this object. player_path_set_orient_and_vel(objp, &goal_point); } // ------------------------------------------------------------------------------------------------------------------ // Create path for player from current segment to goal segment. void create_player_path_to_segment(int segnum) { object *objp = ConsoleObject; Player_path_length=0; Player_hide_index=-1; Player_cur_path_index=0; Player_following_path_flag=0; if (create_path_points(objp, objp->segnum, segnum, Point_segs_free_ptr, &Player_path_length, 100, 0, 0, -1) == -1) con_printf(CON_DEBUG,"Unable to form path of length %i for myself\n", 100); Player_following_path_flag = 1; Player_hide_index = Point_segs_free_ptr - Point_segs; Player_cur_path_index = 0; Point_segs_free_ptr += Player_path_length; if (Point_segs_free_ptr - Point_segs + MAX_PATH_LENGTH*2 > MAX_POINT_SEGS) { //Int3(); // Contact Mike: This is curious, though not deadly. /eip++;g ai_reset_all_paths(); } } int Player_goal_segment = -1; void check_create_player_path(void) { if (Player_goal_segment != -1) create_player_path_to_segment(Player_goal_segment); Player_goal_segment = -1; } #endif // ---------------------------------------------------------------------------------------------------------- // DEBUG FUNCTIONS ENDED // ---------------------------------------------------------------------------------------------------------- dxx-rebirth-0.58.1-d2x/main/aistruct.h000066400000000000000000000270711217717237500175160ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Structs and constants for AI system. * object.h depends on this. * ai.h depends on object.h. * Get it? * */ #ifndef _AISTRUCT_H #define _AISTRUCT_H #include "inferno.h" #include "polyobj.h" #define GREEN_GUY 1 #define MAX_SEGMENTS_PER_PATH 20 #define PA_WEAPON_WALL_COLLISION 2 // Level of robot awareness after player weapon hits nearby wall //#define PA_PLAYER_VISIBLE 2 // Level of robot awareness if robot is looking towards player, and player not hidden #define PA_NEARBY_ROBOT_FIRED 1 // Level of robot awareness after nearby robot fires a weapon #define PA_PLAYER_COLLISION 3 // Level of robot awareness after player bumps into robot #define PA_WEAPON_ROBOT_COLLISION 4 // Level of robot awareness after player weapon hits nearby robot //#define PAE_WEAPON_HIT_WALL 1 // weapon hit wall, create player awareness //#define PAE_WEAPON_HIT_ROBOT 2 // weapon hit wall, create player awareness // Constants indicating currently moving forward or backward through // path. Note that you can add aip->direction to aip_path_index to // get next segment on path. #define AI_DIR_FORWARD 1 #define AI_DIR_BACKWARD (-AI_DIR_FORWARD) // Behaviors #define AIB_STILL 0x80 #define AIB_NORMAL 0x81 #define AIB_BEHIND 0x82 #define AIB_RUN_FROM 0x83 #define AIB_SNIPE 0x84 #define AIB_STATION 0x85 #define AIB_FOLLOW 0x86 #define MIN_BEHAVIOR 0x80 #define MAX_BEHAVIOR 0x86 // Modes #define AIM_STILL 0 #define AIM_WANDER 1 #define AIM_FOLLOW_PATH 2 #define AIM_CHASE_OBJECT 3 #define AIM_RUN_FROM_OBJECT 4 #define AIM_BEHIND 5 #define AIM_FOLLOW_PATH_2 6 #define AIM_OPEN_DOOR 7 #define AIM_GOTO_PLAYER 8 // Only for escort behavior #define AIM_GOTO_OBJECT 9 // Only for escort behavior #define AIM_SNIPE_ATTACK 10 #define AIM_SNIPE_FIRE 11 #define AIM_SNIPE_RETREAT 12 #define AIM_SNIPE_RETREAT_BACKWARDS 13 #define AIM_SNIPE_WAIT 14 #define AIM_THIEF_ATTACK 15 #define AIM_THIEF_RETREAT 16 #define AIM_THIEF_WAIT 17 #define AISM_GOHIDE 0 #define AISM_HIDING 1 #define AI_MAX_STATE 7 #define AI_MAX_EVENT 4 #define AIS_NONE 0 #define AIS_REST 1 #define AIS_SRCH 2 #define AIS_LOCK 3 #define AIS_FLIN 4 #define AIS_FIRE 5 #define AIS_RECO 6 #define AIS_ERR_ 7 #define AIE_FIRE 0 #define AIE_HITT 1 #define AIE_COLL 2 #define AIE_HURT 3 //typedef struct opath { // sbyte path_index; // current index of path // sbyte path_direction; // current path direction // sbyte path_length; // length of current path // sbyte nothing; // short path[MAX_SEGMENTS_PER_PATH]; // short always_0xabc; // If this is ever not 0xabc, then someone overwrote //} opath; // //typedef struct oai_state { // short mode; // // short counter; // kind of a hack, frame countdown until switch modes // opath paths[2]; // vms_vector movement_vector; // movement vector for one second //} oai_state; #define SUB_FLAGS_GUNSEG 0x01 #define SUB_FLAGS_SPROX 0x02 // If set, then this bot drops a super prox, not a prox, when it's time to drop something #define SUB_FLAGS_CAMERA_AWAKE 0x04 // If set, a camera (on a missile) woke this robot up, so don't fire at player. Can look real stupid! // Constants defining meaning of flags in ai_state #define MAX_AI_FLAGS 11 // This MUST cause word (4 bytes) alignment in ai_static, allowing for one byte mode #define CURRENT_GUN flags[0] // This is the last gun the object fired from #define CURRENT_STATE flags[1] // current behavioral state #define GOAL_STATE flags[2] // goal state #define PATH_DIR flags[3] // direction traveling path, 1 = forward, -1 = backward, other = error! #define SUB_FLAGS flags[4] // bit 0: Set -> Robot's current gun in different segment than robot's center. #define GOALSIDE flags[5] // for guys who open doors, this is the side they are going after. #define CLOAKED flags[6] // Cloaked now. #define SKIP_AI_COUNT flags[7] // Skip AI this frame, but decrement in do_ai_frame. #define REMOTE_OWNER flags[8] // Who is controlling this remote AI object (multiplayer use only) #define REMOTE_SLOT_NUM flags[9] // What slot # is this robot in for remote control purposes (multiplayer use only) #define MULTI_ANGER flags[10] // How angry is a robot in multiplayer mode // This is the stuff that is permanent for an AI object. typedef struct ai_static { ubyte behavior; // sbyte flags[MAX_AI_FLAGS]; // various flags, meaning defined by constants short hide_segment; // Segment to go to for hiding. short hide_index; // Index in Path_seg_points short path_length; // Length of hide path. sbyte cur_path_index; // Current index in path. sbyte dying_sound_playing; // !0 if this robot is playing its dying sound. short danger_laser_num; int danger_laser_signature; fix64 dying_start_time; // Time at which this robot started dying. } __pack__ ai_static; // Same as above but structure Savegames/Multiplayer objects expect typedef struct ai_static_rw { ubyte behavior; // sbyte flags[MAX_AI_FLAGS]; // various flags, meaning defined by constants short hide_segment; // Segment to go to for hiding. short hide_index; // Index in Path_seg_points short path_length; // Length of hide path. sbyte cur_path_index; // Current index in path. sbyte dying_sound_playing; // !0 if this robot is playing its dying sound. short danger_laser_num; int danger_laser_signature; fix dying_start_time; // Time at which this robot started dying. } __pack__ ai_static_rw; // Rather temporal AI stuff. typedef struct ai_local { // These used to be bytes, changed to ints so I could set watchpoints on them. int player_awareness_type; // type of awareness of player int retry_count; // number of retries in physics last time this object got moved. int consecutive_retries; // number of retries in consecutive frames (ie, without a retry_count of 0) int mode; // current mode within behavior int previous_visibility; // Visibility of player last time we checked. int rapidfire_count; // number of shots fired rapidly int goal_segment; // goal segment for current path fix next_action_time; // time in seconds until something happens, mode dependent fix next_fire; // time in seconds until can fire again fix next_fire2; // time in seconds until can fire again from second weapon fix player_awareness_time; // time in seconds robot will be aware of player, 0 means not aware of player fix64 time_player_seen; // absolute time in seconds at which player was last seen, might cause to go into follow_path mode fix64 time_player_sound_attacked; // absolute time in seconds at which player was last seen with visibility of 2. fix64 next_misc_sound_time; // absolute time in seconds at which this robot last made an angry or lurking sound. fix time_since_processed; // time since this robot last processed in do_ai_frame vms_angvec goal_angles[MAX_SUBMODELS]; // angles for each subobject vms_angvec delta_angles[MAX_SUBMODELS]; // angles for each subobject sbyte goal_state[MAX_SUBMODELS]; // Goal state for this sub-object sbyte achieved_state[MAX_SUBMODELS]; // Last achieved state } ai_local; // Same as above but structure Savegames expect typedef struct ai_local_rw { // These used to be bytes, changed to ints so I could set watchpoints on them. int player_awareness_type; // type of awareness of player int retry_count; // number of retries in physics last time this object got moved. int consecutive_retries; // number of retries in consecutive frames (ie, without a retry_count of 0) int mode; // current mode within behavior int previous_visibility; // Visibility of player last time we checked. int rapidfire_count; // number of shots fired rapidly int goal_segment; // goal segment for current path fix next_action_time; // time in seconds until something happens, mode dependent fix next_fire; // time in seconds until can fire again fix next_fire2; // time in seconds until can fire again from second weapon fix player_awareness_time; // time in seconds robot will be aware of player, 0 means not aware of player fix time_player_seen; // absolute time in seconds at which player was last seen, might cause to go into follow_path mode fix time_player_sound_attacked; // absolute time in seconds at which player was last seen with visibility of 2. fix next_misc_sound_time; // absolute time in seconds at which this robot last made an angry or lurking sound. fix time_since_processed; // time since this robot last processed in do_ai_frame vms_angvec goal_angles[MAX_SUBMODELS]; // angles for each subobject vms_angvec delta_angles[MAX_SUBMODELS]; // angles for each subobject sbyte goal_state[MAX_SUBMODELS]; // Goal state for this sub-object sbyte achieved_state[MAX_SUBMODELS]; // Last achieved state } ai_local_rw; typedef struct { fix64 last_time; int last_segment; vms_vector last_position; } ai_cloak_info; // Same as above but structure Savegames expect typedef struct { fix last_time; int last_segment; vms_vector last_position; } ai_cloak_info_rw; typedef struct { int segnum; vms_vector point; } point_seg; typedef struct { short start, end; } seg_seg; #define MAX_POINT_SEGS 2500 extern point_seg Point_segs[MAX_POINT_SEGS]; extern point_seg *Point_segs_free_ptr; extern int Overall_agitation; // These are the information for a robot describing the location of // the player last time he wasn't cloaked, and the time at which he // was uncloaked. We should store this for each robot, but that's // memory expensive. //extern fix Last_uncloaked_time; //extern vms_vector Last_uncloaked_position; extern void ai_do_cloak_stuff(void); #endif /* _AISTRUCT_H */ dxx-rebirth-0.58.1-d2x/main/automap.c000066400000000000000000001161261217717237500173210ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines for displaying the auto-map. * */ #include #include #include #ifdef OGL #include "ogl_init.h" #endif #include "dxxerror.h" #include "3d.h" #include "inferno.h" #include "u_mem.h" #include "render.h" #include "object.h" #include "vclip.h" #include "game.h" #include "polyobj.h" #include "sounds.h" #include "player.h" #include "bm.h" #include "key.h" #include "newmenu.h" #include "menu.h" #include "screens.h" #include "textures.h" #include "mouse.h" #include "timer.h" #include "segpoint.h" #include "joy.h" #include "iff.h" #include "pcx.h" #include "palette.h" #include "wall.h" #include "hostage.h" #include "fuelcen.h" #include "gameseq.h" #include "gamefont.h" #ifdef NETWORK #include "multi.h" #endif #include "kconfig.h" #include "endlevel.h" #include "text.h" #include "gauges.h" #include "powerup.h" #include "switch.h" #include "automap.h" #include "cntrlcen.h" #include "timer.h" #include "config.h" #include "playsave.h" #include "rbaudio.h" #include "window.h" #include "playsave.h" #include "args.h" #define LEAVE_TIME 0x4000 #define EF_USED 1 // This edge is used #define EF_DEFINING 2 // A structure defining edge that should always draw. #define EF_FRONTIER 4 // An edge between the known and the unknown. #define EF_SECRET 8 // An edge that is part of a secret wall. #define EF_GRATE 16 // A grate... draw it all the time. #define EF_NO_FADE 32 // An edge that doesn't fade with distance #define EF_TOO_FAR 64 // An edge that is too far away typedef struct Edge_info { int verts[2]; // 8 bytes ubyte sides[4]; // 4 bytes int segnum[4]; // 16 bytes // This might not need to be stored... If you can access the normals of a side. ubyte flags; // 1 bytes // See the EF_??? defines above. ubyte color; // 1 bytes ubyte num_faces; // 1 bytes // 31 bytes... } Edge_info; typedef struct automap { fix64 entry_time; fix64 t1, t2; int leave_mode; int pause_game; vms_angvec tangles; ushort old_wiggle; // keep 4 byte aligned int max_segments_away; int segment_limit; // Edge list variables int num_edges; int max_edges; //set each frame int highest_edge_index; Edge_info *edges; int *drawingListBright; // Screen canvas variables grs_canvas automap_view; grs_bitmap automap_background; // Rendering variables fix zoom; vms_vector view_target; vms_vector view_position; fix farthest_dist; vms_matrix viewMatrix; fix viewDist; int wall_normal_color; int wall_door_color; int wall_door_blue; int wall_door_gold; int wall_door_red; int wall_revealed_color; int hostage_color; int font_color_20; int green_31; int white_63; int blue_48; int red_48; control_info controls; } automap; #define MAX_EDGES_FROM_VERTS(v) ((v)*4) #define MAX_EDGES 6000 // Determined by loading all the levels by John & Mike, Feb 9, 1995 #define K_WALL_NORMAL_COLOR BM_XRGB(29, 29, 29 ) #define K_WALL_DOOR_COLOR BM_XRGB(5, 27, 5 ) #define K_WALL_DOOR_BLUE BM_XRGB(0, 0, 31) #define K_WALL_DOOR_GOLD BM_XRGB(31, 31, 0) #define K_WALL_DOOR_RED BM_XRGB(31, 0, 0) #define K_WALL_REVEALED_COLOR BM_XRGB(0, 0, 25 ) //what you see when you have the full map powerup #define K_HOSTAGE_COLOR BM_XRGB(0, 31, 0 ) #define K_FONT_COLOR_20 BM_XRGB(20, 20, 20 ) #define K_GREEN_31 BM_XRGB(0, 31, 0) int Automap_active = 0; void init_automap_colors(automap *am) { am->wall_normal_color = K_WALL_NORMAL_COLOR; am->wall_door_color = K_WALL_DOOR_COLOR; am->wall_door_blue = K_WALL_DOOR_BLUE; am->wall_door_gold = K_WALL_DOOR_GOLD; am->wall_door_red = K_WALL_DOOR_RED; am->wall_revealed_color = K_WALL_REVEALED_COLOR; am->hostage_color = K_HOSTAGE_COLOR; am->font_color_20 = K_FONT_COLOR_20; am->green_31 = K_GREEN_31; am->white_63 = gr_find_closest_color_current(63,63,63); am->blue_48 = gr_find_closest_color_current(0,0,48); am->red_48 = gr_find_closest_color_current(48,0,0); } // Segment visited list ubyte Automap_visited[MAX_SEGMENTS]; // Map movement defines #define PITCH_DEFAULT 9000 #define ZOOM_DEFAULT i2f(20*10) #define ZOOM_MIN_VALUE i2f(20*5) #define ZOOM_MAX_VALUE i2f(20*100) #define SLIDE_SPEED (350) #define ZOOM_SPEED_FACTOR (500) //(1500) #define ROT_SPEED_DIVISOR (115000) // Function Prototypes void adjust_segment_limit(automap *am, int SegmentLimit); void draw_all_edges(automap *am); void automap_build_edge_list(automap *am); // extern void check_and_fix_matrix(vms_matrix *m); #define MAX_DROP_MULTI 2 #define MAX_DROP_SINGLE 9 vms_vector MarkerPoint[NUM_MARKERS]; //these are only used in multi.c, and I'd get rid of them there, but when I tried to do that once, I caused some horrible bug. -MT int HighlightMarker=-1; char MarkerMessage[NUM_MARKERS][MARKER_MESSAGE_LEN]; float MarkerScale=2.0; int MarkerObject[NUM_MARKERS]; extern vms_vector Matrix_scale; //how the matrix is currently scaled # define automap_draw_line g3_draw_line // ------------------------------------------------------------- void DrawMarkerNumber (automap *am, int num) { int i; g3s_point BasePoint,FromPoint,ToPoint; float ArrayX[10][20]={ {-.25, 0.0, 0.0, 0.0, -1.0, 1.0}, {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 0.0, 1.0}, {-1.0, -1.0, -1.0, 1.0, 1.0, 1.0}, {-1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0}, {-1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0}, {-1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0} }; float ArrayY[10][20]={ {.75, 1.0, 1.0, -1.0, -1.0, -1.0}, {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 0.0, 0.0}, {1.0, 0.0, 0.0, 0.0, 1.0, -1.0}, {1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, -1.0, -1.0}, {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0}, {1.0, 1.0, 1.0, -1.0}, {1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 0.0, 0.0}, {1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 0.0, 1.0} }; int NumOfPoints[]={6,10,8,6,10,10,4,10,8}; for (i=0;iwhite_63); else gr_setcolor (am->blue_48); g3_rotate_point(&BasePoint,&Objects[MarkerObject[(Player_num*2)+num]].pos); for (i=0;ipos; if (MarkerObject[marker_num] != -1) obj_delete(MarkerObject[marker_num]); MarkerObject[marker_num] = drop_marker_object(&playerp->pos,playerp->segnum,&playerp->orient,marker_num); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_drop_marker (Player_num,playerp->pos,player_marker_num,MarkerMessage[marker_num]); #endif } void DropBuddyMarker(object *objp) { int marker_num; // Find spare marker slot. "if" code below should be an assert, but what if someone changes NUM_MARKERS or MAX_CROP_SINGLE and it never gets hit? marker_num = MAX_DROP_SINGLE+1; if (marker_num > NUM_MARKERS-1) marker_num = NUM_MARKERS-1; sprintf(MarkerMessage[marker_num], "RIP: %s",PlayerCfg.GuidebotName); MarkerPoint[marker_num] = objp->pos; if (MarkerObject[marker_num] != -1 && MarkerObject[marker_num] !=0) obj_delete(MarkerObject[marker_num]); MarkerObject[marker_num] = drop_marker_object(&objp->pos, objp->segnum, &objp->orient, marker_num); } #define MARKER_SPHERE_SIZE 0x58000 void DrawMarkers (automap *am) { int i,maxdrop; static int cyc=10,cycdir=1; g3s_point sphere_point; if (Game_mode & GM_MULTI) maxdrop=2; else maxdrop=9; for (i=0;i43) { cyc=43; cycdir=0; } else if (cyc<10) { cyc=10; cycdir=1; } } void ClearMarkers() { int i; for (i=0;ipos); g3_draw_sphere(&sphere_point,obj->size); // Draw shaft of arrow vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.fvec, obj->size*3 ); g3_rotate_point(&arrow_point,&arrow_pos); automap_draw_line(&sphere_point, &arrow_point); // Draw right head of arrow vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 ); vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*1 ); g3_rotate_point(&head_point,&head_pos); automap_draw_line(&arrow_point, &head_point); // Draw left head of arrow vm_vec_scale_add( &head_pos, &obj->pos, &obj->orient.fvec, obj->size*2 ); vm_vec_scale_add2( &head_pos, &obj->orient.rvec, obj->size*(-1) ); g3_rotate_point(&head_point,&head_pos); automap_draw_line(&arrow_point, &head_point); // Draw player's up vector vm_vec_scale_add( &arrow_pos, &obj->pos, &obj->orient.uvec, obj->size*2 ); g3_rotate_point(&arrow_point,&arrow_pos); automap_draw_line(&sphere_point, &arrow_point); } //name for each group. maybe move somewhere else static const char *const system_name[] = { "Zeta Aquilae", "Quartzon System", "Brimspark System", "Limefrost Spiral", "Baloris Prime", "Omega System"}; void name_frame(automap *am) { char name_level_left[128],name_level_right[128]; int wr,h,aw; if (Current_level_num > 0) sprintf(name_level_left, "%s %i",TXT_LEVEL, Current_level_num); else sprintf(name_level_left, "Secret Level %i",-Current_level_num); if (PLAYING_BUILTIN_MISSION && Current_level_num > 0) sprintf(name_level_right,"%s %d: ",system_name[(Current_level_num-1)/4],((Current_level_num-1)%4)+1); else strcpy(name_level_right, " "); strcat(name_level_right, Current_level_name); gr_set_curfont(GAME_FONT); gr_set_fontcolor(am->green_31,-1); gr_printf((SWIDTH/64),(SHEIGHT/48),"%s", name_level_left); gr_get_string_size(name_level_right,&wr,&h,&aw); gr_printf(grd_curcanv->cv_bitmap.bm_w-wr-(SWIDTH/64),(SHEIGHT/48),"%s", name_level_right); } void draw_automap(automap *am) { int i; int color; object * objp; g3s_point sphere_point; if ( am->leave_mode==0 && am->controls.automap_state && (timer_query()-am->entry_time)>LEAVE_TIME) am->leave_mode = 1; gr_set_current_canvas(NULL); show_fullscr(&am->automap_background); gr_set_curfont(HUGE_FONT); gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); gr_string((SWIDTH/8), (SHEIGHT/16), TXT_AUTOMAP); gr_set_curfont(GAME_FONT); gr_set_fontcolor(BM_XRGB(20, 20, 20), -1); gr_string((SWIDTH/10.666), (SHEIGHT/1.126), TXT_TURN_SHIP); gr_printf((SWIDTH/10.666), (SHEIGHT/1.083), "F9/F10 Changes viewing distance"); gr_string((SWIDTH/10.666), (SHEIGHT/1.043), TXT_AUTOMAP_MARKER); gr_set_current_canvas(&am->automap_view); gr_clear_canvas(BM_XRGB(0,0,0)); g3_start_frame(); render_start_frame(); if (!PlayerCfg.AutomapFreeFlight) vm_vec_scale_add(&am->view_position,&am->view_target,&am->viewMatrix.fvec,-am->viewDist); g3_set_view_matrix(&am->view_position,&am->viewMatrix,am->zoom); draw_all_edges(am); // Draw player... #ifdef NETWORK if (Game_mode & GM_TEAM) color = get_team(Player_num); else #endif color = Player_num; // Note link to above if! gr_setcolor(BM_XRGB(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b)); draw_player(&Objects[Players[Player_num].objnum]); DrawMarkers(am); // Draw player(s)... #ifdef NETWORK if ( (Game_mode & (GM_TEAM | GM_MULTI_COOP)) || (Netgame.game_flags & NETGAME_FLAG_SHOW_MAP) ) { for (i=0; itype ) { case OBJ_HOSTAGE: gr_setcolor(am->hostage_color); g3_rotate_point(&sphere_point,&objp->pos); g3_draw_sphere(&sphere_point,objp->size); break; case OBJ_POWERUP: if ( Automap_visited[objp->segnum] ) { if ( (objp->id==POW_KEY_RED) || (objp->id==POW_KEY_BLUE) || (objp->id==POW_KEY_GOLD) ) { switch (objp->id) { case POW_KEY_RED: gr_setcolor(BM_XRGB(63, 5, 5)); break; case POW_KEY_BLUE: gr_setcolor(BM_XRGB(5, 5, 63)); break; case POW_KEY_GOLD: gr_setcolor(BM_XRGB(63, 63, 10)); break; default: Error("Illegal key type: %i", objp->id); } g3_rotate_point(&sphere_point,&objp->pos); g3_draw_sphere(&sphere_point,objp->size*4); } } break; } } g3_end_frame(); name_frame(am); if (HighlightMarker>-1 && MarkerMessage[HighlightMarker][0]!=0) { char msg[10+MARKER_MESSAGE_LEN+1]; sprintf(msg,"Marker %d: %s",HighlightMarker+1,MarkerMessage[(Player_num*2)+HighlightMarker]); gr_printf((SWIDTH/64),(SHEIGHT/18),"%s", msg); } if (PlayerCfg.MouseFlightSim && PlayerCfg.MouseFSIndicator) show_mousefs_indicator(am->controls.raw_mouse_axis[0], am->controls.raw_mouse_axis[1], am->controls.raw_mouse_axis[2], GWIDTH-(GHEIGHT/8), GHEIGHT-(GHEIGHT/8), GHEIGHT/5); am->t2 = timer_query(); while (am->t2 - am->t1 < F1_0 / (GameCfg.VSync?MAXIMUM_FPS:GameArg.SysMaxFPS)) // ogl is fast enough that the automap can read the input too fast and you start to turn really slow. So delay a bit (and free up some cpu :) { if (GameArg.SysUseNiceFPS && !GameCfg.VSync) timer_delay(f1_0 / GameArg.SysMaxFPS - (am->t2 - am->t1)); timer_update(); am->t2 = timer_query(); } if (am->pause_game) { FrameTime=am->t2-am->t1; calc_d_tick(); } am->t1 = am->t2; } extern int set_segment_depths(int start_seg, ubyte *segbuf); #define MAP_BACKGROUND_FILENAME ((HIRESMODE && PHYSFSX_exists("mapb.pcx",1))?"MAPB.PCX":"MAP.PCX") int automap_key_command(window *wind, d_event *event, automap *am) { int c = event_key_get(event); int marker_num; char maxdrop; switch (c) { case KEY_PRINT_SCREEN: { gr_set_current_canvas(NULL); save_screen_shot(1); return 1; } case KEY_ESC: if (am->leave_mode==0) { window_close(wind); return 1; } return 1; #ifndef NDEBUG case KEY_DEBUGGED+KEY_F: { int i; for (i=0; i<=Highest_segment_index; i++ ) Automap_visited[i] = 1; automap_build_edge_list(am); am->max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); am->segment_limit = am->max_segments_away; adjust_segment_limit(am, am->segment_limit); } return 1; #endif case KEY_F9: if (am->segment_limit > 1) { am->segment_limit--; adjust_segment_limit(am, am->segment_limit); } return 1; case KEY_F10: if (am->segment_limit < am->max_segments_away) { am->segment_limit++; adjust_segment_limit(am, am->segment_limit); } return 1; case KEY_1: case KEY_2: case KEY_3: case KEY_4: case KEY_5: case KEY_6: case KEY_7: case KEY_8: case KEY_9: case KEY_0: if (Game_mode & GM_MULTI) maxdrop=2; else maxdrop=9; marker_num = c-KEY_1; if (marker_num<=maxdrop) { if (MarkerObject[marker_num] != -1) HighlightMarker=marker_num; } return 1; case KEY_D+KEY_CTRLED: if (HighlightMarker > -1 && MarkerObject[HighlightMarker] != -1) { gr_set_current_canvas(NULL); if (nm_messagebox( NULL, 2, TXT_YES, TXT_NO, "Delete Marker?" ) == 0) { obj_delete(MarkerObject[HighlightMarker]); MarkerObject[HighlightMarker]=-1; MarkerMessage[HighlightMarker][0]=0; HighlightMarker = -1; } set_screen_mode(SCREEN_GAME); } return 1; #ifndef RELEASE case KEY_F11: //KEY_COMMA: if (MarkerScale>.5) MarkerScale-=.5; return 1; case KEY_F12: //KEY_PERIOD: if (MarkerScale<30.0) MarkerScale+=.5; return 1; #endif } return 0; } int automap_process_input(window *wind, d_event *event, automap *am) { vms_matrix tempm; Controls = am->controls; kconfig_read_controls(event, 1); am->controls = Controls; memset(&Controls, 0, sizeof(control_info)); if ( !am->controls.automap_state && (am->leave_mode==1) ) { window_close(wind); return 1; } if ( am->controls.automap_count > 0) { am->controls.automap_count = 0; if (am->leave_mode==0) { window_close(wind); return 1; } } if (PlayerCfg.AutomapFreeFlight) { if ( am->controls.fire_primary_count > 0) { // Reset orientation am->viewMatrix = Objects[Players[Player_num].objnum].orient; vm_vec_scale_add(&am->view_position, &Objects[Players[Player_num].objnum].pos, &am->viewMatrix.fvec, -ZOOM_DEFAULT ); am->controls.fire_primary_count = 0; } if (am->controls.pitch_time || am->controls.heading_time || am->controls.bank_time) { vms_angvec tangles; vms_matrix new_m; tangles.p = fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR ); tangles.h = fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR ); tangles.b = fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 ); vm_angles_2_matrix(&tempm, &tangles); vm_matrix_x_matrix(&new_m,&am->viewMatrix,&tempm); am->viewMatrix = new_m; check_and_fix_matrix(&am->viewMatrix); } if ( am->controls.forward_thrust_time || am->controls.vertical_thrust_time || am->controls.sideways_thrust_time ) { vm_vec_scale_add2( &am->view_position, &am->viewMatrix.fvec, am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR ); vm_vec_scale_add2( &am->view_position, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED ); vm_vec_scale_add2( &am->view_position, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED ); // Crude wrapping check if (am->view_position.x > F1_0*32000) am->view_position.x = F1_0*32000; if (am->view_position.x < -F1_0*32000) am->view_position.x = -F1_0*32000; if (am->view_position.y > F1_0*32000) am->view_position.y = F1_0*32000; if (am->view_position.y < -F1_0*32000) am->view_position.y = -F1_0*32000; if (am->view_position.z > F1_0*32000) am->view_position.z = F1_0*32000; if (am->view_position.z < -F1_0*32000) am->view_position.z = -F1_0*32000; } } else { if ( am->controls.fire_primary_count > 0) { // Reset orientation am->viewDist = ZOOM_DEFAULT; am->tangles.p = PITCH_DEFAULT; am->tangles.h = 0; am->tangles.b = 0; am->view_target = Objects[Players[Player_num].objnum].pos; am->controls.fire_primary_count = 0; } am->viewDist -= am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR; am->tangles.p += fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR ); am->tangles.h += fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR ); am->tangles.b += fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 ); if ( am->controls.vertical_thrust_time || am->controls.sideways_thrust_time ) { vms_angvec tangles1; vms_vector old_vt; old_vt = am->view_target; tangles1 = am->tangles; vm_angles_2_matrix(&tempm,&tangles1); vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); vm_vec_scale_add2( &am->view_target, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED ); vm_vec_scale_add2( &am->view_target, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED ); if ( vm_vec_dist_quick( &am->view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) ) am->view_target = old_vt; } vm_angles_2_matrix(&tempm,&am->tangles); vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm); if ( am->viewDist < ZOOM_MIN_VALUE ) am->viewDist = ZOOM_MIN_VALUE; if ( am->viewDist > ZOOM_MAX_VALUE ) am->viewDist = ZOOM_MAX_VALUE; } return 0; } int automap_handler(window *wind, d_event *event, automap *am) { switch (event->type) { case EVENT_WINDOW_ACTIVATED: game_flush_inputs(); event_toggle_focus(1); key_toggle_repeat(0); break; case EVENT_WINDOW_DEACTIVATED: event_toggle_focus(0); key_toggle_repeat(1); break; case EVENT_IDLE: case EVENT_JOYSTICK_BUTTON_UP: case EVENT_JOYSTICK_BUTTON_DOWN: case EVENT_JOYSTICK_MOVED: case EVENT_MOUSE_BUTTON_UP: case EVENT_MOUSE_BUTTON_DOWN: case EVENT_MOUSE_MOVED: automap_process_input(wind, event, am); break; case EVENT_KEY_COMMAND: case EVENT_KEY_RELEASE: { int kret = automap_key_command(wind, event, am); if (!kret) automap_process_input(wind, event, am); return kret; } case EVENT_WINDOW_DRAW: draw_automap(am); break; case EVENT_WINDOW_CLOSE: if (!am->pause_game) ConsoleObject->mtype.phys_info.flags |= am->old_wiggle; // Restore wiggle event_toggle_focus(0); key_toggle_repeat(1); #ifdef OGL gr_free_bitmap_data(&am->automap_background); #endif d_free(am->edges); d_free(am->drawingListBright); d_free(am); window_set_visible(Game_wind, 1); Automap_active = 0; return 0; // continue closing break; default: return 0; break; } return 1; } void do_automap( int key_code ) { int pcx_error; ubyte pal[256*3]; window *automap_wind = NULL; automap *am; CALLOC(am, automap, 1); if (am) { automap_wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *)) automap_handler, am); } if (automap_wind == NULL) { Warning("Out of memory"); return; } am->leave_mode = 0; am->pause_game = 1; // Set to 1 if everything is paused during automap...No pause during net. am->max_segments_away = 0; am->segment_limit = 1; am->num_edges = 0; am->highest_edge_index = -1; am->max_edges = Num_segments*12; MALLOC(am->edges, Edge_info, am->max_edges); MALLOC(am->drawingListBright, int, am->max_edges); if (!am->edges || !am->drawingListBright) { if (am->edges) d_free(am->edges); if (am->drawingListBright) d_free(am->drawingListBright); Warning("Out of memory"); return; } am->zoom = 0x9000; am->farthest_dist = (F1_0 * 20 * 50); // 50 segments away am->viewDist = 0; init_automap_colors(am); key_code = key_code; // disable warning... if ((Game_mode & GM_MULTI) && (!Endlevel_sequence)) am->pause_game = 0; if (am->pause_game) { window_set_visible(Game_wind, 0); } if (!am->pause_game) { am->old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE; // Save old wiggle ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE; // Turn off wiggle } //Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES); //make maybe smaller than max gr_set_current_canvas(NULL); automap_build_edge_list(am); if ( am->viewDist==0 ) am->viewDist = ZOOM_DEFAULT; am->viewMatrix = Objects[Players[Player_num].objnum].orient; am->tangles.p = PITCH_DEFAULT; am->tangles.h = 0; am->tangles.b = 0; am->view_target = Objects[Players[Player_num].objnum].pos; if (PlayerCfg.AutomapFreeFlight) vm_vec_scale_add(&am->view_position, &Objects[Players[Player_num].objnum].pos, &am->viewMatrix.fvec, -ZOOM_DEFAULT ); am->t1 = am->entry_time = timer_query(); am->t2 = am->t1; //Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum am->max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited); am->segment_limit = am->max_segments_away; adjust_segment_limit(am, am->segment_limit); // ZICO - code from above to show frame in OGL correctly. Redundant, but better readable. // KREATOR - Now applies to all platforms so double buffering is supported gr_init_bitmap_data (&am->automap_background); pcx_error = pcx_read_bitmap(MAP_BACKGROUND_FILENAME, &am->automap_background, BM_LINEAR, pal); if (pcx_error != PCX_ERROR_NONE) Error("File %s - PCX error: %s", MAP_BACKGROUND_FILENAME, pcx_errormsg(pcx_error)); gr_remap_bitmap_good(&am->automap_background, pal, -1, -1); gr_init_sub_canvas(&am->automap_view, &grd_curscreen->sc_canvas, (SWIDTH/23), (SHEIGHT/6), (SWIDTH/1.1), (SHEIGHT/1.45)); gr_palette_load( gr_palette ); Automap_active = 1; } void adjust_segment_limit(automap *am, int SegmentLimit) { int i,e1; Edge_info * e; for (i=0; i<=am->highest_edge_index; i++ ) { e = &am->edges[i]; e->flags |= EF_TOO_FAR; for (e1=0; e1num_faces; e1++ ) { if ( Automap_visited[e->segnum[e1]] <= SegmentLimit ) { e->flags &= (~EF_TOO_FAR); break; } } } } void draw_all_edges(automap *am) { g3s_codes cc; int i,j,nbright; ubyte nfacing,nnfacing; Edge_info *e; vms_vector *tv1; fix distance; fix min_distance = 0x7fffffff; g3s_point *p1, *p2; nbright=0; for (i=0; i<=am->highest_edge_index; i++ ) { //e = &am->edges[Edge_used_list[i]]; e = &am->edges[i]; if (!(e->flags & EF_USED)) continue; if ( e->flags & EF_TOO_FAR) continue; if (e->flags&EF_FRONTIER) { // A line that is between what we have seen and what we haven't if ( (!(e->flags&EF_SECRET))&&(e->color==am->wall_normal_color)) continue; // If a line isn't secret and is normal color, then don't draw it } cc=rotate_list(2,e->verts); distance = Segment_points[e->verts[1]].p3_z; if (min_distance>distance ) min_distance = distance; if (!cc.uand) { //all off screen? nfacing = nnfacing = 0; tv1 = &Vertices[e->verts[0]]; j = 0; while( jnum_faces && (nfacing==0 || nnfacing==0) ) { #ifdef COMPACT_SEGS vms_vector temp_v; get_side_normal(&Segments[e->segnum[j]], e->sides[j], 0, &temp_v ); if (!g3_check_normal_facing( tv1, &temp_v ) ) #else if (!g3_check_normal_facing( tv1, &Segments[e->segnum[j]].sides[e->sides[j]].normals[0] ) ) #endif nfacing++; else nnfacing++; j++; } if ( nfacing && nnfacing ) { // a contour line am->drawingListBright[nbright++] = e-am->edges; } else if ( e->flags&(EF_DEFINING|EF_GRATE) ) { if ( nfacing == 0 ) { if ( e->flags & EF_NO_FADE ) gr_setcolor( e->color ); else gr_setcolor( gr_fade_table[e->color+256*8] ); g3_draw_line( &Segment_points[e->verts[0]], &Segment_points[e->verts[1]] ); } else { am->drawingListBright[nbright++] = e-am->edges; } } } } if ( min_distance < 0 ) min_distance = 0; // Sort the bright ones using a shell sort { int t; int i, j, incr, v1, v2; incr = nbright / 2; while( incr > 0 ) { for (i=incr; i=0 ) { // compare element j and j+incr v1 = am->edges[am->drawingListBright[j]].verts[0]; v2 = am->edges[am->drawingListBright[j+incr]].verts[0]; if (Segment_points[v1].p3_z < Segment_points[v2].p3_z) { // If not in correct order, them swap 'em t=am->drawingListBright[j+incr]; am->drawingListBright[j+incr]=am->drawingListBright[j]; am->drawingListBright[j]=t; j -= incr; } else break; } } incr = incr / 2; } } // Draw the bright ones for (i=0; iedges[am->drawingListBright[i]]; p1 = &Segment_points[e->verts[0]]; p2 = &Segment_points[e->verts[1]]; dist = p1->p3_z - min_distance; // Make distance be 1.0 to 0.0, where 0.0 is 10 segments away; if ( dist < 0 ) dist=0; if ( dist >= am->farthest_dist ) continue; if ( e->flags & EF_NO_FADE ) { gr_setcolor( e->color ); } else { dist = F1_0 - fixdiv( dist, am->farthest_dist ); color = f2i( dist*31 ); gr_setcolor( gr_fade_table[e->color+color*256] ); } g3_draw_line( p1, p2 ); } } //================================================================== // // All routines below here are used to build the Edge list // //================================================================== //finds edge, filling in edge_ptr. if found old edge, returns index, else return -1 static int automap_find_edge(automap *am, int v0,int v1,Edge_info **edge_ptr) { long vv, evv; int hash, oldhash; int ret, ev0, ev1; vv = (v1<<16) + v0; oldhash = hash = ((v0*5+v1) % am->max_edges); ret = -1; while (ret==-1) { ev0 = am->edges[hash].verts[0]; ev1 = am->edges[hash].verts[1]; evv = (ev1<<16)+ev0; if (am->edges[hash].num_faces == 0 ) ret=0; else if (evv == vv) ret=1; else { if (++hash==am->max_edges) hash=0; if (hash==oldhash) Error("Edge list full!"); } } *edge_ptr = &am->edges[hash]; if (ret == 0) return -1; else return hash; } void add_one_edge( automap *am, int va, int vb, ubyte color, ubyte side, int segnum, int hidden, int grate, int no_fade ) { int found; Edge_info *e; int tmp; if ( am->num_edges >= am->max_edges) { // GET JOHN! (And tell him that his // MAX_EDGES_FROM_VERTS formula is hosed.) // If he's not around, save the mine, // and send him mail so he can look // at the mine later. Don't modify it. // This is important if this happens. Int3(); // LOOK ABOVE!!!!!! return; } if ( va > vb ) { tmp = va; va = vb; vb = tmp; } found = automap_find_edge(am,va,vb,&e); if (found == -1) { e->verts[0] = va; e->verts[1] = vb; e->color = color; e->num_faces = 1; e->flags = EF_USED | EF_DEFINING; // Assume a normal line e->sides[0] = side; e->segnum[0] = segnum; //Edge_used_list[am->num_edges] = e-am->edges; if ( (e-am->edges) > am->highest_edge_index ) am->highest_edge_index = e - am->edges; am->num_edges++; } else { if ( color != am->wall_normal_color ) if (color != am->wall_revealed_color) e->color = color; if ( e->num_faces < 4 ) { e->sides[e->num_faces] = side; e->segnum[e->num_faces] = segnum; e->num_faces++; } } if ( grate ) e->flags |= EF_GRATE; if ( hidden ) e->flags|=EF_SECRET; // Mark this as a hidden edge if ( no_fade ) e->flags |= EF_NO_FADE; } void add_one_unknown_edge( automap *am, int va, int vb ) { int found; Edge_info *e; int tmp; if ( va > vb ) { tmp = va; va = vb; vb = tmp; } found = automap_find_edge(am,va,vb,&e); if (found != -1) e->flags|=EF_FRONTIER; // Mark as a border edge } #ifndef _GAMESEQ_H extern obj_position Player_init[]; #endif void add_segment_edges(automap *am, segment *seg) { int is_grate, no_fade; ubyte color; int sn; int segnum = seg-Segments; int hidden_flag; int ttype,trigger_num; for (sn=0;snchildren[sn] == -1) { color = am->wall_normal_color; } switch( Segment2s[segnum].special ) { case SEGMENT_IS_FUELCEN: color = BM_XRGB( 29, 27, 13 ); break; case SEGMENT_IS_CONTROLCEN: if (Control_center_present) color = BM_XRGB( 29, 0, 0 ); break; case SEGMENT_IS_ROBOTMAKER: color = BM_XRGB( 29, 0, 31 ); break; } if (seg->sides[sn].wall_num > -1) { trigger_num = Walls[seg->sides[sn].wall_num].trigger; ttype = Triggers[trigger_num].type; if (ttype==TT_SECRET_EXIT) { color = BM_XRGB( 29, 0, 31 ); no_fade=1; goto Here; } switch( Walls[seg->sides[sn].wall_num].type ) { case WALL_DOOR: if (Walls[seg->sides[sn].wall_num].keys == KEY_BLUE) { no_fade = 1; color = am->wall_door_blue; } else if (Walls[seg->sides[sn].wall_num].keys == KEY_GOLD) { no_fade = 1; color = am->wall_door_gold; } else if (Walls[seg->sides[sn].wall_num].keys == KEY_RED) { no_fade = 1; color = am->wall_door_red; } else if (!(WallAnims[Walls[seg->sides[sn].wall_num].clip_num].flags & WCF_HIDDEN)) { int connected_seg = seg->children[sn]; if (connected_seg != -1) { int connected_side = find_connect_side(seg, &Segments[connected_seg]); int keytype = Walls[Segments[connected_seg].sides[connected_side].wall_num].keys; if ((keytype != KEY_BLUE) && (keytype != KEY_GOLD) && (keytype != KEY_RED)) color = am->wall_door_color; else { switch (Walls[Segments[connected_seg].sides[connected_side].wall_num].keys) { case KEY_BLUE: color = am->wall_door_blue; no_fade = 1; break; case KEY_GOLD: color = am->wall_door_gold; no_fade = 1; break; case KEY_RED: color = am->wall_door_red; no_fade = 1; break; default: Error("Inconsistent data. Supposed to be a colored wall, but not blue, gold or red.\n"); } } } } else { color = am->wall_normal_color; hidden_flag = 1; } break; case WALL_CLOSED: // Make grates draw properly if (WALL_IS_DOORWAY(seg,sn) & WID_RENDPAST_FLAG) is_grate = 1; else hidden_flag = 1; color = am->wall_normal_color; break; case WALL_BLASTABLE: // Hostage doors color = am->wall_door_color; break; } } if (segnum==Player_init[Player_num].segnum) color = BM_XRGB(31,0,31); if ( color != 255 ) { // If they have a map powerup, draw unvisited areas in dark blue. if (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL && (!Automap_visited[segnum])) color = am->wall_revealed_color; Here: get_side_verts(vertex_list,segnum,sn); add_one_edge( am, vertex_list[0], vertex_list[1], color, sn, segnum, hidden_flag, 0, no_fade ); add_one_edge( am, vertex_list[1], vertex_list[2], color, sn, segnum, hidden_flag, 0, no_fade ); add_one_edge( am, vertex_list[2], vertex_list[3], color, sn, segnum, hidden_flag, 0, no_fade ); add_one_edge( am, vertex_list[3], vertex_list[0], color, sn, segnum, hidden_flag, 0, no_fade ); if ( is_grate ) { add_one_edge( am, vertex_list[0], vertex_list[2], color, sn, segnum, hidden_flag, 1, no_fade ); add_one_edge( am, vertex_list[1], vertex_list[3], color, sn, segnum, hidden_flag, 1, no_fade ); } } } } // Adds all the edges from a segment we haven't visited yet. void add_unknown_segment_edges(automap *am, segment *seg) { int sn; int segnum = seg-Segments; for (sn=0;snchildren[sn] == -1) { get_side_verts(vertex_list,segnum,sn); add_one_unknown_edge( am, vertex_list[0], vertex_list[1] ); add_one_unknown_edge( am, vertex_list[1], vertex_list[2] ); add_one_unknown_edge( am, vertex_list[2], vertex_list[3] ); add_one_unknown_edge( am, vertex_list[3], vertex_list[0] ); } } } void automap_build_edge_list(automap *am) { int i,e1,e2,s; Edge_info * e; // clear edge list for (i=0; imax_edges; i++) { am->edges[i].num_faces = 0; am->edges[i].flags = 0; } am->num_edges = 0; am->highest_edge_index = -1; if (cheats.fullautomap || (Players[Player_num].flags & PLAYER_FLAGS_MAP_ALL) ) { // Cheating, add all edges as visited for (s=0; s<=Highest_segment_index; s++) #ifdef EDITOR if (Segments[s].segnum != -1) #endif { add_segment_edges(am, &Segments[s]); } } else { // Not cheating, add visited edges, and then unvisited edges for (s=0; s<=Highest_segment_index; s++) #ifdef EDITOR if (Segments[s].segnum != -1) #endif if (Automap_visited[s]) { add_segment_edges(am, &Segments[s]); } for (s=0; s<=Highest_segment_index; s++) #ifdef EDITOR if (Segments[s].segnum != -1) #endif if (!Automap_visited[s]) { add_unknown_segment_edges(am, &Segments[s]); } } // Find unnecessary lines (These are lines that don't have to be drawn because they have small curvature) for (i=0; i<=am->highest_edge_index; i++ ) { e = &am->edges[i]; if (!(e->flags&EF_USED)) continue; for (e1=0; e1num_faces; e1++ ) { for (e2=1; e2num_faces; e2++ ) { if ( (e1 != e2) && (e->segnum[e1] != e->segnum[e2]) ) { #ifdef COMPACT_SEGS vms_vector v1, v2; get_side_normal(&Segments[e->segnum[e1]], e->sides[e1], 0, &v1 ); get_side_normal(&Segments[e->segnum[e2]], e->sides[e2], 0, &v2 ); if ( vm_vec_dot(&v1,&v2) > (F1_0-(F1_0/10)) ) { #else if ( vm_vec_dot( &Segments[e->segnum[e1]].sides[e->sides[e1]].normals[0], &Segments[e->segnum[e2]].sides[e->sides[e2]].normals[0] ) > (F1_0-(F1_0/10)) ) { #endif e->flags &= (~EF_DEFINING); break; } } } if (!(e->flags & EF_DEFINING)) break; } } } char Marker_input [40]; int Marker_index=0; ubyte DefiningMarkerMessage=0; ubyte MarkerBeingDefined; ubyte LastMarkerDropped; void InitMarkerInput () { int maxdrop,i; //find free marker slot if (Game_mode & GM_MULTI) maxdrop=MAX_DROP_MULTI; else maxdrop=MAX_DROP_SINGLE; for (i=0;i 0) Marker_index--; Marker_input[Marker_index] = 0; break; case KEY_ENTER: strcpy (MarkerMessage[(Player_num*2)+MarkerBeingDefined],Marker_input); DropMarker(MarkerBeingDefined); LastMarkerDropped = MarkerBeingDefined; key_toggle_repeat(0); game_flush_inputs(); DefiningMarkerMessage = 0; break; default: { int ascii = key_ascii(); if ((ascii < 255 )) if (Marker_index < 38 ) { Marker_input[Marker_index++] = ascii; Marker_input[Marker_index] = 0; } return 0; break; } } return 1; } dxx-rebirth-0.58.1-d2x/main/automap.h000066400000000000000000000023651217717237500173250ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Prototypes for auto-map stuff. * */ #ifndef _AUTOMAP_H #define _AUTOMAP_H #include "player.h" extern int Automap_active; extern char Marker_input[40]; extern void do_automap(int key_code); extern void automap_clear_visited(); extern ubyte Automap_visited[MAX_SEGMENTS]; void DropBuddyMarker(object *objp); #define NUM_MARKERS 16 #define MARKER_MESSAGE_LEN 40 extern char MarkerMessage[NUM_MARKERS][MARKER_MESSAGE_LEN]; extern int MarkerObject[NUM_MARKERS]; extern vms_vector MarkerPoint[NUM_MARKERS]; #endif dxx-rebirth-0.58.1-d2x/main/bm.c000066400000000000000000000441611217717237500162500ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Bitmap and palette loading functions. * */ #include #include #include #include "pstypes.h" #include "inferno.h" #include "gr.h" #include "bm.h" #include "u_mem.h" #include "dxxerror.h" #include "object.h" #include "vclip.h" #include "effects.h" #include "polyobj.h" #include "wall.h" #include "textures.h" #include "game.h" #ifdef NETWORK #include "multi.h" #endif #include "iff.h" #include "powerup.h" #include "sounds.h" #include "piggy.h" #include "aistruct.h" #include "robot.h" #include "weapon.h" #include "gauges.h" #include "player.h" #include "endlevel.h" #include "cntrlcen.h" #include "makesig.h" #include "interp.h" #include "console.h" #include "rle.h" ubyte Sounds[MAX_SOUNDS]; ubyte AltSounds[MAX_SOUNDS]; #ifdef EDITOR int Num_object_subtypes = 1; #endif //for each model, a model number for dying & dead variants, or -1 if none int Dying_modelnums[MAX_POLYGON_MODELS]; int Dead_modelnums[MAX_POLYGON_MODELS]; //the polygon model number to use for the marker int Marker_model_num = -1; //right now there's only one player ship, but we can have another by //adding an array and setting the pointer to the active ship. player_ship only_player_ship,*Player_ship=&only_player_ship; //----------------- Miscellaneous bitmap pointers --------------- int Num_cockpits = 0; bitmap_index cockpit_bitmap[N_COCKPIT_BITMAPS]; //---------------- Variables for wall textures ------------------ int Num_tmaps; tmap_info TmapInfo[MAX_TEXTURES]; //---------------- Variables for object textures ---------------- int First_multi_bitmap_num=-1; int N_ObjBitmaps; bitmap_index ObjBitmaps[MAX_OBJ_BITMAPS]; ushort ObjBitmapPtrs[MAX_OBJ_BITMAPS]; // These point back into ObjBitmaps, since some are used twice. /* * reads n tmap_info structs from a PHYSFS_file */ int tmap_info_read_n(tmap_info *ti, int n, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++) { ti[i].flags = PHYSFSX_readByte(fp); ti[i].pad[0] = PHYSFSX_readByte(fp); ti[i].pad[1] = PHYSFSX_readByte(fp); ti[i].pad[2] = PHYSFSX_readByte(fp); ti[i].lighting = PHYSFSX_readFix(fp); ti[i].damage = PHYSFSX_readFix(fp); ti[i].eclip_num = PHYSFSX_readShort(fp); ti[i].destroyed = PHYSFSX_readShort(fp); ti[i].slide_u = PHYSFSX_readShort(fp); ti[i].slide_v = PHYSFSX_readShort(fp); } return i; } int tmap_info_read_n_d1(tmap_info *ti, int n, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++) { PHYSFSX_fseek(fp, 13, SEEK_CUR);// skip filename ti[i].flags = PHYSFSX_readByte(fp); ti[i].lighting = PHYSFSX_readFix(fp); ti[i].damage = PHYSFSX_readFix(fp); ti[i].eclip_num = PHYSFSX_readInt(fp); } return i; } void gamedata_close() { free_polygon_models(); bm_free_extra_objbitmaps(); free_endlevel_data(); rle_cache_close(); piggy_close(); } //----------------------------------------------------------------- // Initializes game properties data (including texture caching system) and sound data. int gamedata_init() { init_polygon_models(); init_endlevel(); #ifdef EDITOR // The pc_shareware argument is currently unused for Descent 2, // but *may* be useful for loading Descent 1 Shareware texture properties. if (!gamedata_read_tbl(0)) #endif if (!properties_init()) // This calls properties_read_cmp Error("Cannot open ham file\n"); piggy_read_sounds(); return 0; } void bm_read_all(PHYSFS_file * fp) { int i,t; NumTextures = PHYSFSX_readInt(fp); bitmap_index_read_n(Textures, NumTextures, fp ); tmap_info_read_n(TmapInfo, NumTextures, fp); t = PHYSFSX_readInt(fp); PHYSFS_read( fp, Sounds, sizeof(ubyte), t ); PHYSFS_read( fp, AltSounds, sizeof(ubyte), t ); Num_vclips = PHYSFSX_readInt(fp); vclip_read_n(Vclip, Num_vclips, fp); Num_effects = PHYSFSX_readInt(fp); eclip_read_n(Effects, Num_effects, fp); Num_wall_anims = PHYSFSX_readInt(fp); wclip_read_n(WallAnims, Num_wall_anims, fp); N_robot_types = PHYSFSX_readInt(fp); robot_info_read_n(Robot_info, N_robot_types, fp); N_robot_joints = PHYSFSX_readInt(fp); jointpos_read_n(Robot_joints, N_robot_joints, fp); N_weapon_types = PHYSFSX_readInt(fp); weapon_info_read_n(Weapon_info, N_weapon_types, fp, Piggy_hamfile_version); N_powerup_types = PHYSFSX_readInt(fp); powerup_type_info_read_n(Powerup_info, N_powerup_types, fp); N_polygon_models = PHYSFSX_readInt(fp); polymodel_read_n(Polygon_models, N_polygon_models, fp); for (i=0; i N_D2_POLYGON_MODELS) free_model(&Polygon_models[--N_polygon_models]); while (N_polygon_models > exit_modelnum) free_model(&Polygon_models[--N_polygon_models]); } //type==1 means 1.1, type==2 means 1.2 (with weapons) void bm_read_extra_robots(const char *fname,int type) { PHYSFS_file *fp; int t,i,version; fp = PHYSFSX_openReadBuffered(fname); if (!fp) { Error("Failed to open HAM file \"%s\"", fname); return; } if (type == 2) { int sig; sig = PHYSFSX_readInt(fp); if (sig != MAKE_SIG('X','H','A','M')) return; version = PHYSFSX_readInt(fp); } else version = 0; (void)version; // NOTE: we do not need it, but keep it for possible further use bm_free_extra_models(); bm_free_extra_objbitmaps(); //read extra weapons t = PHYSFSX_readInt(fp); N_weapon_types = N_D2_WEAPON_TYPES+t; if (N_weapon_types >= MAX_WEAPON_TYPES) Error("Too many weapons (%d) in <%s>. Max is %d.",t,fname,MAX_WEAPON_TYPES-N_D2_WEAPON_TYPES); weapon_info_read_n(&Weapon_info[N_D2_WEAPON_TYPES], t, fp, 3); //now read robot info t = PHYSFSX_readInt(fp); N_robot_types = N_D2_ROBOT_TYPES+t; if (N_robot_types >= MAX_ROBOT_TYPES) Error("Too many robots (%d) in <%s>. Max is %d.",t,fname,MAX_ROBOT_TYPES-N_D2_ROBOT_TYPES); robot_info_read_n(&Robot_info[N_D2_ROBOT_TYPES], t, fp); t = PHYSFSX_readInt(fp); N_robot_joints = N_D2_ROBOT_JOINTS+t; if (N_robot_joints >= MAX_ROBOT_JOINTS) Error("Too many robot joints (%d) in <%s>. Max is %d.",t,fname,MAX_ROBOT_JOINTS-N_D2_ROBOT_JOINTS); jointpos_read_n(&Robot_joints[N_D2_ROBOT_JOINTS], t, fp); t = PHYSFSX_readInt(fp); N_polygon_models = N_D2_POLYGON_MODELS+t; if (N_polygon_models >= MAX_POLYGON_MODELS) Error("Too many polygon models (%d) in <%s>. Max is %d.",t,fname,MAX_POLYGON_MODELS-N_D2_POLYGON_MODELS); polymodel_read_n(&Polygon_models[N_D2_POLYGON_MODELS], t, fp); for (i=N_D2_POLYGON_MODELS; i= MAX_OBJ_BITMAPS) Error("Too many object bitmaps (%d) in <%s>. Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPS); bitmap_index_read_n(&ObjBitmaps[N_D2_OBJBITMAPS], t, fp); t = PHYSFSX_readInt(fp); if (N_D2_OBJBITMAPPTRS+t >= MAX_OBJ_BITMAPS) Error("Too many object bitmap pointers (%d) in <%s>. Max is %d.",t,fname,MAX_OBJ_BITMAPS-N_D2_OBJBITMAPPTRS); for (i = N_D2_OBJBITMAPPTRS; i < (N_D2_OBJBITMAPPTRS + t); i++) ObjBitmapPtrs[i] = PHYSFSX_readShort(fp); PHYSFS_close(fp); } int Robot_replacements_loaded = 0; void load_robot_replacements(char *level_name) { PHYSFS_file *fp; int t,i,j; char ifile_name[FILENAME_LEN]; change_filename_extension(ifile_name, level_name, ".HXM" ); fp = PHYSFSX_openReadBuffered(ifile_name); if (!fp) //no robot replacement file return; t = PHYSFSX_readInt(fp); //read id "HXM!" if (t!= 0x21584d48) Error("ID of HXM! file incorrect"); t = PHYSFSX_readInt(fp); //read version if (t<1) Error("HXM! version too old (%d)",t); t = PHYSFSX_readInt(fp); //read number of robots for (j=0;j=N_robot_types) Error("Robots number (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_types-1); robot_info_read_n(&Robot_info[i], 1, fp); } t = PHYSFSX_readInt(fp); //read number of joints for (j=0;j=N_robot_joints) Error("Robots joint (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_joints-1); jointpos_read_n(&Robot_joints[i], 1, fp); } t = PHYSFSX_readInt(fp); //read number of polygon models for (j=0;j=N_polygon_models) Error("Polygon model (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_polygon_models-1); free_model(&Polygon_models[i]); polymodel_read(&Polygon_models[i], fp); polygon_model_data_read(&Polygon_models[i], fp); Dying_modelnums[i] = PHYSFSX_readInt(fp); Dead_modelnums[i] = PHYSFSX_readInt(fp); } t = PHYSFSX_readInt(fp); //read number of objbitmaps for (j=0;j=MAX_OBJ_BITMAPS) Error("Object bitmap number (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); bitmap_index_read(&ObjBitmaps[i], fp); } t = PHYSFSX_readInt(fp); //read number of objbitmapptrs for (j=0;j=MAX_OBJ_BITMAPS) Error("Object bitmap pointer (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); ObjBitmapPtrs[i] = PHYSFSX_readShort(fp); } PHYSFS_close(fp); Robot_replacements_loaded = 1; } /* * Routines for loading exit models * * Used by d1 levels (including some add-ons), and by d2 shareware. * Could potentially be used by d2 add-on levels, but only if they * don't use "extra" robots... */ // formerly exitmodel_bm_load_sub bitmap_index read_extra_bitmap_iff( char * filename ) { bitmap_index bitmap_num; grs_bitmap * n = &GameBitmaps[extra_bitmap_num]; ubyte newpal[256*3]; int iff_error; //reference parm to avoid warning message bitmap_num.index = 0; //MALLOC( new, grs_bitmap, 1 ); iff_error = iff_read_bitmap(filename,n,BM_LINEAR,newpal); n->bm_handle=0; if (iff_error != IFF_NO_ERROR) { con_printf(CON_DEBUG, "Error loading exit model bitmap <%s> - IFF error: %s\n", filename, iff_errormsg(iff_error)); return bitmap_num; } if ( iff_has_transparency ) gr_remap_bitmap_good( n, newpal, iff_transparent_color, 254 ); else gr_remap_bitmap_good( n, newpal, -1, 254 ); n->avg_color = 0; //compute_average_pixel(new); bitmap_num.index = extra_bitmap_num; GameBitmaps[extra_bitmap_num++] = *n; //d_free( n ); return bitmap_num; } // formerly load_exit_model_bitmap grs_bitmap *bm_load_extra_objbitmap(char *name) { Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); { ObjBitmaps[N_ObjBitmaps] = read_extra_bitmap_iff(name); if (ObjBitmaps[N_ObjBitmaps].index == 0) { char *name2 = d_strdup(name); *strrchr(name2, '.') = '\0'; ObjBitmaps[N_ObjBitmaps] = read_extra_bitmap_d1_pig(name2); d_free(name2); } if (ObjBitmaps[N_ObjBitmaps].index == 0) return NULL; if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64) Error("Bitmap <%s> is not 64x64",name); ObjBitmapPtrs[N_ObjBitmaps] = N_ObjBitmaps; N_ObjBitmaps++; Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index]; } } #ifdef OGL void ogl_cache_polymodel_textures(int model_num); #endif int load_exit_models() { PHYSFS_file *exit_hamfile; int start_num; bm_free_extra_models(); bm_free_extra_objbitmaps(); start_num = N_ObjBitmaps; if (!bm_load_extra_objbitmap("steel1.bbm") || !bm_load_extra_objbitmap("rbot061.bbm") || !bm_load_extra_objbitmap("rbot062.bbm") || !bm_load_extra_objbitmap("steel1.bbm") || !bm_load_extra_objbitmap("rbot061.bbm") || !bm_load_extra_objbitmap("rbot063.bbm")) { con_printf(CON_NORMAL, "Can't load exit models!\n"); return 0; } exit_hamfile = PHYSFSX_openReadBuffered("exit.ham"); if (exit_hamfile) { exit_modelnum = N_polygon_models++; destroyed_exit_modelnum = N_polygon_models++; polymodel_read(&Polygon_models[exit_modelnum], exit_hamfile); polymodel_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile); Polygon_models[exit_modelnum].first_texture = start_num; Polygon_models[destroyed_exit_modelnum].first_texture = start_num+3; polygon_model_data_read(&Polygon_models[exit_modelnum], exit_hamfile); polygon_model_data_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile); PHYSFS_close(exit_hamfile); } else if (PHYSFSX_exists("exit01.pof",1) && PHYSFSX_exists("exit01d.pof",1)) { exit_modelnum = load_polygon_model("exit01.pof", 3, start_num, NULL); destroyed_exit_modelnum = load_polygon_model("exit01d.pof", 3, start_num + 3, NULL); #ifdef OGL ogl_cache_polymodel_textures(exit_modelnum); ogl_cache_polymodel_textures(destroyed_exit_modelnum); #endif } else if (PHYSFSX_exists(D1_PIGFILE,1)) { int offset, offset2; int hamsize; exit_hamfile = PHYSFSX_openReadBuffered(D1_PIGFILE); hamsize = PHYSFS_fileLength(exit_hamfile); switch (hamsize) { //total hack for loading models case D1_PIGSIZE: offset = 91848; /* and 92582 */ offset2 = 383390; /* and 394022 */ break; default: case D1_SHARE_BIG_PIGSIZE: case D1_SHARE_10_PIGSIZE: case D1_SHARE_PIGSIZE: case D1_10_BIG_PIGSIZE: case D1_10_PIGSIZE: Int3(); /* exit models should be in .pofs */ case D1_OEM_PIGSIZE: case D1_MAC_PIGSIZE: case D1_MAC_SHARE_PIGSIZE: con_printf(CON_NORMAL, "Can't load exit models!\n"); return 0; } PHYSFSX_fseek(exit_hamfile, offset, SEEK_SET); exit_modelnum = N_polygon_models++; destroyed_exit_modelnum = N_polygon_models++; polymodel_read(&Polygon_models[exit_modelnum], exit_hamfile); polymodel_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile); Polygon_models[exit_modelnum].first_texture = start_num; Polygon_models[destroyed_exit_modelnum].first_texture = start_num+3; PHYSFSX_fseek(exit_hamfile, offset2, SEEK_SET); polygon_model_data_read(&Polygon_models[exit_modelnum], exit_hamfile); polygon_model_data_read(&Polygon_models[destroyed_exit_modelnum], exit_hamfile); PHYSFS_close(exit_hamfile); } else { con_printf(CON_NORMAL, "Can't load exit models!\n"); return 0; } return 1; } void compute_average_rgb(grs_bitmap *bm, fix *rgb) { ubyte *buf; int i, x, y, color, count; fix t_rgb[3] = { 0, 0, 0 }; rgb[0] = rgb[1] = rgb[2] = 0; if (!bm->bm_data) return; CALLOC(buf, ubyte, bm->bm_w*bm->bm_h); if (bm->bm_flags & BM_FLAG_RLE){ unsigned char * dbits; unsigned char * sbits; int data_offset; data_offset = 1; if (bm->bm_flags & BM_FLAG_RLE_BIG) data_offset = 2; sbits = &bm->bm_data[4 + (bm->bm_h * data_offset)]; dbits = buf; for (i=0; i < bm->bm_h; i++ ) { gr_rle_decode(sbits,dbits); if ( bm->bm_flags & BM_FLAG_RLE_BIG ) sbits += (int)INTEL_SHORT(*((short *)&(bm->bm_data[4+(i*data_offset)]))); else sbits += (int)bm->bm_data[4+i]; dbits += bm->bm_w; } } else { memcpy(buf, bm->bm_data, sizeof(unsigned char)*(bm->bm_w*bm->bm_h)); } i = 0; for (x = 0; x < bm->bm_h; x++) { for (y = 0; y < bm->bm_w; y++) { color = buf[i++]; t_rgb[0] = gr_palette[color*3]; t_rgb[1] = gr_palette[color*3+1]; t_rgb[2] = gr_palette[color*3+2]; if (!(color == TRANSPARENCY_COLOR || (t_rgb[0] == t_rgb[1] && t_rgb[0] == t_rgb[2]))) { rgb[0] += t_rgb[0]; rgb[1] += t_rgb[1]; rgb[2] += t_rgb[2]; count++; } } } d_free(buf); } dxx-rebirth-0.58.1-d2x/main/bm.h000066400000000000000000000060021217717237500162450ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Bitmap and Palette loading functions. * */ #ifndef _BM_H #define _BM_H #include "gr.h" #include "piggy.h" #define MAX_TEXTURES 1200 //tmapinfo flags #define TMI_VOLATILE 1 //this material blows up when hit #define TMI_WATER 2 //this material is water #define TMI_FORCE_FIELD 4 //this is force field - flares don't stick #define TMI_GOAL_BLUE 8 //this is used to remap the blue goal #define TMI_GOAL_RED 16 //this is used to remap the red goal #define TMI_GOAL_HOARD 32 //this is used to remap the goals typedef struct { ubyte flags; //values defined above ubyte pad[3]; //keep alignment fix lighting; //how much light this casts fix damage; //how much damage being against this does (for lava) short eclip_num; //the eclip that changes this, or -1 short destroyed; //bitmap to show when destroyed, or -1 short slide_u,slide_v; //slide rates of texture, stored in 8:8 fix #ifdef EDITOR char filename[13]; //used by editor to remap textures char pad2[3]; #endif } __pack__ tmap_info; #define TMAP_INFO_SIZE 20 // how much space it takes up on disk extern int Num_object_types; #define N_COCKPIT_BITMAPS 6 struct player_ship; extern struct player_ship only_player_ship; extern int Num_cockpits; extern bitmap_index cockpit_bitmap[N_COCKPIT_BITMAPS]; extern short tmap_xlate_table[MAX_TEXTURES]; extern int Num_tmaps; #ifdef EDITOR extern int TmapList[MAX_TEXTURES]; #endif extern tmap_info TmapInfo[MAX_TEXTURES]; //the model number of the marker object extern int Marker_model_num; // Initializes the palette, bitmap system... void gamedata_close(); int gamedata_init(); void bm_close(); void bm_free_extra_objbitmaps(); // Initializes the Texture[] array of bmd_bitmap structures. void init_textures(); extern int Num_object_subtypes; // Number of possible IDs for the current type of object to be placed #define MAX_OBJ_BITMAPS 610 extern int N_ObjBitmaps; extern bitmap_index ObjBitmaps[MAX_OBJ_BITMAPS]; extern ushort ObjBitmapPtrs[MAX_OBJ_BITMAPS]; extern int First_multi_bitmap_num; void compute_average_rgb(grs_bitmap *bm, fix *rgb); // Initializes all bitmaps from BITMAPS.TBL file. int gamedata_read_tbl(int pc_shareware); extern void bm_read_all(PHYSFS_file * fp); int load_exit_models(); #endif /* _BM_H */ dxx-rebirth-0.58.1-d2x/main/bmread.c000066400000000000000000002063351217717237500171070ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to parse bitmaps.tbl * Only used for editor, since the registered version of descent 1. * */ #include #include #include #include #include #include "pstypes.h" #include "inferno.h" #include "gr.h" #include "bm.h" #include "gamepal.h" #include "u_mem.h" #include "dxxerror.h" #include "object.h" #include "vclip.h" #include "effects.h" #include "polyobj.h" #include "wall.h" #include "textures.h" #include "game.h" #ifdef NETWORK #include "multi.h" #endif #include "iff.h" #include "hostage.h" #include "powerup.h" #include "laser.h" #include "sounds.h" #include "piggy.h" #include "aistruct.h" #include "robot.h" #include "weapon.h" #include "gauges.h" #include "player.h" #include "endlevel.h" #include "cntrlcen.h" #include "args.h" #include "text.h" #include "interp.h" #include "strutil.h" #include "editor/texpage.h" #define BM_NONE -1 #define BM_COCKPIT 0 #define BM_TEXTURES 2 #define BM_UNUSED 3 #define BM_VCLIP 4 #define BM_EFFECTS 5 #define BM_ECLIP 6 #define BM_WEAPON 7 #define BM_DEMO 8 #define BM_ROBOTEX 9 #define BM_WALL_ANIMS 12 #define BM_WCLIP 13 #define BM_ROBOT 14 #define BM_GAUGES 20 #define BM_GAUGES_HIRES 21 #define MAX_BITMAPS_PER_BRUSH 30 short N_ObjBitmapPtrs=0; static int Num_robot_ais = 0; int TmapList[MAX_TEXTURES]; char Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH]; char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH]; //---------------- Internal variables --------------------------- static int SuperX = -1; static int Installed=0; static char *arg; static short tmap_count = 0; static short texture_count = 0; static short clip_count = 0; static short clip_num; static short sound_num; static short frames; static float play_time; static int hit_sound = -1; static sbyte bm_flag = BM_NONE; static int abm_flag = 0; static int rod_flag = 0; static short wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden; float vlighting=0; static int obj_eclip; static char *dest_bm; //clip number to play when destroyed static int dest_vclip; //what vclip to play when exploding static int dest_eclip; //what eclip to play when exploding static fix dest_size; //3d size of explosion static int crit_clip; //clip number to play when destroyed static int crit_flag; //flag if this is a destroyed eclip static int tmap1_flag; //flag if this is used as tmap_num (not tmap_num2) static int num_sounds=0; int linenum; //line int table currently being parsed //------------------- Useful macros and variables --------------- #define IFTOK(str) if (!strcmp(arg, str)) // For the sake of LINT, defining prototypes to module's functions void bm_read_alias(void); void bm_read_marker(void); void bm_read_robot_ai(int skip); void bm_read_powerup(int unused_flag); void bm_read_hostage(void); void bm_read_robot(int skip); void bm_read_weapon(int skip, int unused_flag); void bm_read_reactor(void); void bm_read_exitmodel(void); void bm_read_player_ship(void); void bm_read_some_file(int skip); void bm_read_sound(int skip, int pc_shareware); void bm_write_extra_robots(void); void clear_to_end_of_line(void); void verify_textures(void); //--------------------------------------------------------------- int compute_average_pixel(grs_bitmap *n) { int row, column, color; char *pptr; int total_red, total_green, total_blue; pptr = (char *)n->bm_data; total_red = 0; total_green = 0; total_blue = 0; for (row=0; rowbm_h; row++) for (column=0; columnbm_w; column++) { color = *pptr++; total_red += gr_palette[color*3]; total_green += gr_palette[color*3+1]; total_blue += gr_palette[color*3+2]; } total_red /= (n->bm_h * n->bm_w); total_green /= (n->bm_h * n->bm_w); total_blue /= (n->bm_h * n->bm_w); return BM_XRGB(total_red/2, total_green/2, total_blue/2); } //--------------------------------------------------------------- // Loads a bitmap from either the piggy file, a r64 file, or a // whatever extension is passed. bitmap_index bm_load_sub(int skip, char * filename ) { bitmap_index bitmap_num; grs_bitmap * n; ubyte newpal[256*3]; int iff_error; //reference parm to avoid warning message char fname[20]; bitmap_num.index = 0; if (skip) { return bitmap_num; } d_splitpath( filename, NULL, NULL, fname, NULL ); bitmap_num=piggy_find_bitmap( fname ); if (bitmap_num.index) { return bitmap_num; } MALLOC( n, grs_bitmap, 1 ); iff_error = iff_read_bitmap(filename,n,BM_LINEAR,newpal); n->bm_handle=0; if (iff_error != IFF_NO_ERROR) { Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum); } if ( iff_has_transparency ) gr_remap_bitmap_good( n, newpal, iff_transparent_color, SuperX ); else gr_remap_bitmap_good( n, newpal, -1, SuperX ); n->avg_color = compute_average_pixel(n); bitmap_num = piggy_register_bitmap( n, fname, 0 ); d_free( n ); return bitmap_num; } void ab_load(int skip, char * filename, bitmap_index bmp[], int *nframes ) { grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH]; bitmap_index bi; int i; int iff_error; //reference parm to avoid warning message ubyte newpal[768]; char fname[20]; char tempname[20]; if (skip) { Assert( bogus_bitmap_initialized != 0 ); bmp[0].index = 0; //index of bogus bitmap==0 (I think) //&bogus_bitmap; *nframes = 1; return; } d_splitpath( filename, NULL, NULL, fname, NULL ); for (i=0; i - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum); } for (i=0;i< *nframes; i++) { bitmap_index new_bmp; sprintf( tempname, "%s#%d", fname, i ); if ( iff_has_transparency ) gr_remap_bitmap_good( bm[i], newpal, iff_transparent_color, SuperX ); else gr_remap_bitmap_good( bm[i], newpal, -1, SuperX ); bm[i]->avg_color = compute_average_pixel(bm[i]); new_bmp = piggy_register_bitmap( bm[i], tempname, 0 ); d_free( bm[i] ); bmp[i] = new_bmp; } } int ds_load(int skip, char * filename ) { int i; PHYSFS_file * cfp; digi_sound n; char fname[20]; char rawname[100]; if (skip) { // We tell piggy_register_sound it's in the pig file, when in actual fact it's in no file // This just tells piggy_close not to attempt to free it return piggy_register_sound( &bogus_sound, "bogus", 1 ); } removeext(filename, fname); sprintf(rawname, "Sounds/%s.%s", fname, (GameArg.SndDigiSampleRate==SAMPLE_RATE_22K) ? "r22" : "raw"); i=piggy_find_sound( fname ); if (i!=255) { return i; } cfp = PHYSFSX_openReadBuffered(rawname); if (cfp!=NULL) { n.length = PHYSFS_fileLength( cfp ); MALLOC( n.data, ubyte, n.length ); PHYSFS_read( cfp, n.data, 1, n.length ); PHYSFS_close(cfp); n.bits = 8; n.freq = 11025; } else { return 255; } i = piggy_register_sound( &n, fname, 0 ); return i; } //parse a float float get_float() { char *xarg; xarg = strtok( NULL, space ); return atof( xarg ); } //parse an int int get_int() { char *xarg; xarg = strtok( NULL, space ); return atoi( xarg ); } // rotates a byte left one bit, preserving the bit falling off the right //void //rotate_left(char *c) //{ // int found; // // found = 0; // if (*c & 0x80) // found = 1; // *c = *c << 1; // if (found) // *c |= 0x01; //} //loads a texture and returns the texture num int get_texture(char *name) { char short_name[FILENAME_LEN]; int i; strcpy(short_name,name); REMOVE_DOTS(short_name); for (i=0;i>8; TmapInfo[texture_count-1].slide_v = fl2f(get_float())>>8;} else IFTOK("destroyed") {int t=texture_count-1; TmapInfo[t].destroyed = get_texture(strtok( NULL, space ));} //else IFTOK("Num_effects") Num_effects = get_int(); else IFTOK("Num_wall_anims") Num_wall_anims = get_int(); else IFTOK("clip_num") clip_num = get_int(); else IFTOK("dest_bm") dest_bm = strtok( NULL, space ); else IFTOK("dest_vclip") dest_vclip = get_int(); else IFTOK("dest_eclip") dest_eclip = get_int(); else IFTOK("dest_size") dest_size = fl2f(get_float()); else IFTOK("crit_clip") crit_clip = get_int(); else IFTOK("crit_flag") crit_flag = get_int(); else IFTOK("sound_num") sound_num = get_int(); else IFTOK("frames") frames = get_int(); else IFTOK("time") play_time = get_float(); else IFTOK("obj_eclip") obj_eclip = get_int(); else IFTOK("hit_sound") hit_sound = get_int(); else IFTOK("abm_flag") abm_flag = get_int(); else IFTOK("tmap1_flag") tmap1_flag = get_int(); else IFTOK("vlighting") vlighting = get_float(); else IFTOK("rod_flag") rod_flag = get_int(); else IFTOK("superx") get_int(); else IFTOK("open_sound") wall_open_sound = get_int(); else IFTOK("close_sound") wall_close_sound = get_int(); else IFTOK("explodes") wall_explodes = get_int(); else IFTOK("blastable") wall_blastable = get_int(); else IFTOK("hidden") wall_hidden = get_int(); else IFTOK("$ROBOT_AI") bm_read_robot_ai(skip); else IFTOK("$POWERUP") {bm_read_powerup(0); continue;} else IFTOK("$POWERUP_UNUSED") {bm_read_powerup(1); continue;} else IFTOK("$HOSTAGE") {bm_read_hostage(); continue;} else IFTOK("$ROBOT") {bm_read_robot(skip); continue;} else IFTOK("$WEAPON") {bm_read_weapon(skip, 0); continue;} else IFTOK("$WEAPON_UNUSED") {bm_read_weapon(skip, 1); continue;} else IFTOK("$REACTOR") {bm_read_reactor(); continue;} else IFTOK("$MARKER") {bm_read_marker(); continue;} else IFTOK("$PLAYER_SHIP") {bm_read_player_ship(); continue;} else IFTOK("$EXIT") { if (pc_shareware) bm_read_exitmodel(); else clear_to_end_of_line(); continue; } else { //not a special token, must be a bitmap! // Remove any illegal/unwanted spaces and tabs at this point. while ((*arg=='\t') || (*arg==' ')) arg++; if (*arg == '\0') { break; } //check for '=' in token, indicating error if (strchr(arg,'=')) Error("Unknown token <'%s'> on line %d of BITMAPS.TBL",arg,linenum); // Otherwise, 'arg' is apparently a bitmap filename. // Load bitmap and process it below: bm_read_some_file(skip); } arg = strtok( NULL, equal_space ); continue; } } NumTextures = texture_count; Num_tmaps = tmap_count; Textures[NumTextures++].index = 0; //entry for bogus tmap PHYSFS_close( InfoFile ); Assert(N_robot_types == Num_robot_ais); //should be one ai info per robot verify_textures(); //check for refereced but unused clip count for (i=0; ibm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) ) { j++; } } if (j) Error("%d textures were not 64x64.",j); for (i=0;i Num_effects) Num_effects = clip_num+1; Effects[clip_num].flags = 0; //load the dest bitmap first, so that after this routine, the last-loaded //texture will be the monitor, so that lighting parameter will be applied //to the correct texture if (dest_bm) { //deal with bitmap for blown up clip char short_name[FILENAME_LEN]; int i; strcpy(short_name,dest_bm); REMOVE_DOTS(short_name); for (i=0;i-1) && (clip_count==0) ) Error( "Wall Clip %d is already used!", clip_num ); WallAnims[clip_num].play_time = fl2f(play_time); WallAnims[clip_num].num_frames = frames; //WallAnims[clip_num].frame_time = fl2f(play_time)/frames; Assert(clip_count < frames); WallAnims[clip_num].frames[clip_count++] = texture_count; WallAnims[clip_num].open_sound = wall_open_sound; WallAnims[clip_num].close_sound = wall_close_sound; Textures[texture_count] = bitmap; set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags); set_texture_name( arg ); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; } else { bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; int nframes; if ( (WallAnims[clip_num].num_frames>-1) ) Error( "AB_Wall clip %d is already used!", clip_num ); abm_flag = 0; ab_load(0, arg, bm, &nframes ); WallAnims[clip_num].num_frames = nframes; WallAnims[clip_num].play_time = fl2f(play_time); //WallAnims[clip_num].frame_time = fl2f(play_time)/nframes; WallAnims[clip_num].open_sound = wall_open_sound; WallAnims[clip_num].close_sound = wall_close_sound; WallAnims[clip_num].close_sound = wall_close_sound; strcpy(WallAnims[clip_num].filename, arg); REMOVE_DOTS(WallAnims[clip_num].filename); if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++) { Textures[texture_count] = bm[clip_count]; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); WallAnims[clip_num].frames[clip_count] = texture_count; REMOVE_DOTS(arg); sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; } } } void bm_read_vclip(int skip) { bitmap_index bi; Assert(clip_num < VCLIP_MAXNUM); if (clip_num >= Num_vclips) Num_vclips = clip_num+1; if (!abm_flag) { if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0) ) Error( "Vclip %d is already used!", clip_num ); bi = bm_load_sub(skip, arg); Vclip[clip_num].play_time = fl2f(play_time); Vclip[clip_num].num_frames = frames; Vclip[clip_num].frame_time = fl2f(play_time)/frames; Vclip[clip_num].light_value = fl2f(vlighting); Vclip[clip_num].sound_num = sound_num; set_lighting_flag(&GameBitmaps[bi.index].bm_flags); Assert(clip_count < frames); Vclip[clip_num].frames[clip_count++] = bi; if (rod_flag) { rod_flag=0; Vclip[clip_num].flags |= VF_ROD; } } else { bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; abm_flag = 0; if ( (Vclip[clip_num].num_frames>-1) ) Error( "AB_Vclip %d is already used!", clip_num ); ab_load(skip, arg, bm, &Vclip[clip_num].num_frames ); if (rod_flag) { //int i; rod_flag=0; Vclip[clip_num].flags |= VF_ROD; } Vclip[clip_num].play_time = fl2f(play_time); Vclip[clip_num].frame_time = fl2f(play_time)/Vclip[clip_num].num_frames; Vclip[clip_num].light_value = fl2f(vlighting); Vclip[clip_num].sound_num = sound_num; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) { set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); Vclip[clip_num].frames[clip_count] = bm[clip_count]; } } } // ------------------------------------------------------------------------------ void get4fix(fix *fixp) { char *curtext; int i; for (i=0; i 179) { ff = 179; } ff = ff/360; tt = fl2f(ff); fix_sincos(tt, &temp, &fovp[i]); } } void clear_to_end_of_line(void) { arg = strtok( NULL, space ); while (arg != NULL) arg = strtok( NULL, space ); } void bm_read_sound(int skip, int pc_shareware) { int sound_num; int alt_sound_num; sound_num = get_int(); alt_sound_num = get_int(); if ( sound_num>=MAX_SOUNDS ) Error( "Too many sound files.\n" ); if (sound_num >= num_sounds) num_sounds = sound_num+1; if (Sounds[sound_num] != 255) Error("Sound num %d already used, bitmaps.tbl, line %d\n",sound_num,linenum); arg = strtok(NULL, space); Sounds[sound_num] = ds_load(skip, arg); if ( alt_sound_num == 0 ) AltSounds[sound_num] = sound_num; else if (alt_sound_num < 0 ) AltSounds[sound_num] = 255; else AltSounds[sound_num] = alt_sound_num; if (Sounds[sound_num] == 255) Error("Can't load soundfile <%s>",arg); } // ------------------------------------------------------------------------------ void bm_read_robot_ai(int skip) { char *robotnum_text; int robotnum; robot_info *robptr; robotnum_text = strtok(NULL, space); robotnum = atoi(robotnum_text); Assert(robotnum < MAX_ROBOT_TYPES); robptr = &Robot_info[robotnum]; Assert(robotnum == Num_robot_ais); //make sure valid number if (skip) { Num_robot_ais++; clear_to_end_of_line(); return; } Num_robot_ais++; get4fix(robptr->field_of_view); get4fix(robptr->firing_wait); get4fix(robptr->firing_wait2); get4byte(robptr->rapidfire_count); get4fix(robptr->turn_time); // get4fix(robptr->fire_power); // get4fix(robptr->shield); get4fix(robptr->max_speed); get4fix(robptr->circle_distance); get4byte(robptr->evade_speed); robptr->always_0xabcd = 0xabcd; adjust_field_of_view(robptr->field_of_view); } // ---------------------------------------------------------------------------------------------- //this will load a bitmap for a polygon models. it puts the bitmap into //the array ObjBitmaps[], and also deals with animating bitmaps //returns a pointer to the bitmap grs_bitmap *load_polymodel_bitmap(int skip, char *name) { Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); // Assert( N_ObjBitmaps == N_ObjBitmapPtrs ); if (name[0] == '%') { //an animating bitmap! int eclip_num; eclip_num = atoi(name+1); if (Effects[eclip_num].changing_object_texture == -1) { //first time referenced Effects[eclip_num].changing_object_texture = N_ObjBitmaps; ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; N_ObjBitmaps++; } else { ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture; } Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS); return NULL; } else { ObjBitmaps[N_ObjBitmaps] = bm_load_sub(skip, name); if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64) Error("Bitmap <%s> is not 64x64",name); ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; N_ObjBitmaps++; Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS); return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index]; } } #define MAX_MODEL_VARIANTS 4 // ------------------------------------------------------------------------------ void bm_read_robot(int skip) { char *model_name[MAX_MODEL_VARIANTS]; int n_models,i; int first_bitmap_num[MAX_MODEL_VARIANTS]; char *equal_ptr; int exp1_vclip_num=-1; int exp1_sound_num=-1; int exp2_vclip_num=-1; int exp2_sound_num=-1; fix lighting = F1_0/2; // Default fix strength = F1_0*10; // Default strength fix mass = f1_0*4; fix drag = f1_0/2; short weapon_type = 0, weapon_type2 = -1; int g,s; char name[ROBOT_NAME_LENGTH]; int contains_count=0, contains_id=0, contains_prob=0, contains_type=0, behavior=AIB_NORMAL; int companion = 0, smart_blobs=0, energy_blobs=0, badass=0, energy_drain=0, kamikaze=0, thief=0, pursuit=0, lightcast=0, death_roll=0; fix glow=0, aim=F1_0; int deathroll_sound = SOUND_BOSS_SHARE_DIE; //default int score_value=1000; int cloak_type=0; // Default = this robot does not cloak int attack_type=0; // Default = this robot attacks by firing (1=lunge) int boss_flag=0; // Default = robot is not a boss. int see_sound = ROBOT_SEE_SOUND_DEFAULT; int attack_sound = ROBOT_ATTACK_SOUND_DEFAULT; int claw_sound = ROBOT_CLAW_SOUND_DEFAULT; int taunt_sound = ROBOT_SEE_SOUND_DEFAULT; ubyte flags=0; Assert(N_robot_types < MAX_ROBOT_TYPES); if (skip) { Robot_info[N_robot_types].model_num = -1; N_robot_types++; Assert(N_robot_types < MAX_ROBOT_TYPES); clear_to_end_of_line(); return; } model_name[0] = strtok( NULL, space ); first_bitmap_num[0] = N_ObjBitmapPtrs; n_models = 1; // Process bitmaps bm_flag=BM_ROBOT; arg = strtok( NULL, space ); while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "exp1_vclip" )) { exp1_vclip_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp2_vclip" )) { exp2_vclip_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp1_sound" )) { exp1_sound_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp2_sound" )) { exp2_sound_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "lighting" )) { lighting = fl2f(atof(equal_ptr)); if ( (lighting < 0) || (lighting > F1_0 )) { Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); } } else if (!d_stricmp( arg, "weapon_type" )) { weapon_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "weapon_type2" )) { weapon_type2 = atoi(equal_ptr); } else if (!d_stricmp( arg, "strength" )) { strength = i2f(atoi(equal_ptr)); } else if (!d_stricmp( arg, "mass" )) { mass = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "drag" )) { drag = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "contains_id" )) { contains_id = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_type" )) { contains_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_count" )) { contains_count = atoi(equal_ptr); } else if (!d_stricmp( arg, "companion" )) { companion = atoi(equal_ptr); } else if (!d_stricmp( arg, "badass" )) { badass = atoi(equal_ptr); } else if (!d_stricmp( arg, "lightcast" )) { lightcast = atoi(equal_ptr); } else if (!d_stricmp( arg, "glow" )) { glow = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "death_roll" )) { death_roll = atoi(equal_ptr); } else if (!d_stricmp( arg, "deathroll_sound" )) { deathroll_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "thief" )) { thief = atoi(equal_ptr); } else if (!d_stricmp( arg, "kamikaze" )) { kamikaze = atoi(equal_ptr); } else if (!d_stricmp( arg, "pursuit" )) { pursuit = atoi(equal_ptr); } else if (!d_stricmp( arg, "smart_blobs" )) { smart_blobs = atoi(equal_ptr); } else if (!d_stricmp( arg, "energy_blobs" )) { energy_blobs = atoi(equal_ptr); } else if (!d_stricmp( arg, "energy_drain" )) { energy_drain = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_prob" )) { contains_prob = atoi(equal_ptr); } else if (!d_stricmp( arg, "cloak_type" )) { cloak_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "attack_type" )) { attack_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "boss" )) { boss_flag = atoi(equal_ptr); } else if (!d_stricmp( arg, "score_value" )) { score_value = atoi(equal_ptr); } else if (!d_stricmp( arg, "see_sound" )) { see_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "attack_sound" )) { attack_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "claw_sound" )) { claw_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "taunt_sound" )) { taunt_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "aim" )) { aim = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "big_radius" )) { if (atoi(equal_ptr)) flags |= RIF_BIG_RADIUS; } else if (!d_stricmp( arg, "behavior" )) { if (!d_stricmp(equal_ptr, "STILL")) behavior = AIB_STILL; else if (!d_stricmp(equal_ptr, "NORMAL")) behavior = AIB_NORMAL; else if (!d_stricmp(equal_ptr, "BEHIND")) behavior = AIB_BEHIND; else if (!d_stricmp(equal_ptr, "RUN_FROM")) behavior = AIB_RUN_FROM; else if (!d_stricmp(equal_ptr, "SNIPE")) behavior = AIB_SNIPE; else if (!d_stricmp(equal_ptr, "STATION")) behavior = AIB_STATION; else if (!d_stricmp(equal_ptr, "FOLLOW")) behavior = AIB_FOLLOW; else Int3(); // Error. Illegal behavior type for current robot. } else if (!d_stricmp( arg, "name" )) { Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH); // Oops, name too long. strcpy(name, &equal_ptr[1]); name[strlen(name)-1] = 0; } else if (!d_stricmp( arg, "simple_model" )) { model_name[n_models] = equal_ptr; first_bitmap_num[n_models] = N_ObjBitmapPtrs; n_models++; Assert(n_models < MAX_MODEL_VARIANTS); } else { Int3(); } } else { // Must be a texture specification... load_polymodel_bitmap(skip, arg); } arg = strtok( NULL, space ); } //clear out anim info for (g=0;g i2f(15)) || (glow < 0) || (glow != 0 && glow < 0x1000)) { Int3(); } Robot_info[N_robot_types].exp1_vclip_num = exp1_vclip_num; Robot_info[N_robot_types].exp2_vclip_num = exp2_vclip_num; Robot_info[N_robot_types].exp1_sound_num = exp1_sound_num; Robot_info[N_robot_types].exp2_sound_num = exp2_sound_num; Robot_info[N_robot_types].lighting = lighting; Robot_info[N_robot_types].weapon_type = weapon_type; Robot_info[N_robot_types].weapon_type2 = weapon_type2; Robot_info[N_robot_types].strength = strength; Robot_info[N_robot_types].mass = mass; Robot_info[N_robot_types].drag = drag; Robot_info[N_robot_types].cloak_type = cloak_type; Robot_info[N_robot_types].attack_type = attack_type; Robot_info[N_robot_types].boss_flag = boss_flag; Robot_info[N_robot_types].contains_id = contains_id; Robot_info[N_robot_types].contains_count = contains_count; Robot_info[N_robot_types].contains_prob = contains_prob; Robot_info[N_robot_types].companion = companion; Robot_info[N_robot_types].badass = badass; Robot_info[N_robot_types].lightcast = lightcast; Robot_info[N_robot_types].glow = (glow>>12); //convert to 4:4 Robot_info[N_robot_types].death_roll = death_roll; Robot_info[N_robot_types].deathroll_sound = deathroll_sound; Robot_info[N_robot_types].thief = thief; Robot_info[N_robot_types].flags = flags; Robot_info[N_robot_types].kamikaze = kamikaze; Robot_info[N_robot_types].pursuit = pursuit; Robot_info[N_robot_types].smart_blobs = smart_blobs; Robot_info[N_robot_types].energy_blobs = energy_blobs; Robot_info[N_robot_types].energy_drain = energy_drain; Robot_info[N_robot_types].score_value = score_value; Robot_info[N_robot_types].see_sound = see_sound; Robot_info[N_robot_types].attack_sound = attack_sound; Robot_info[N_robot_types].claw_sound = claw_sound; Robot_info[N_robot_types].taunt_sound = taunt_sound; Robot_info[N_robot_types].behavior = behavior; // Default behavior for this robot, if coming out of matcen. Robot_info[N_robot_types].aim = min(f2i(aim*255), 255); // how well this robot type can aim. 255=perfect if (contains_type) Robot_info[N_robot_types].contains_type = OBJ_ROBOT; else Robot_info[N_robot_types].contains_type = OBJ_POWERUP; strcpy(Robot_names[N_robot_types], name); N_robot_types++; Assert(N_robot_types < MAX_ROBOT_TYPES); bm_flag = BM_NONE; } //read a reactor model void bm_read_reactor(void) { char *model_name, *model_name_dead=NULL; int first_bitmap_num, first_bitmap_num_dead=0, n_normal_bitmaps; char *equal_ptr; short model_num; fix lighting = F1_0/2; // Default int type=-1; Assert(Num_reactors < MAX_REACTORS); if (0 /*skip*/) { Num_reactors++; clear_to_end_of_line(); return; } model_name = strtok( NULL, space ); // Process bitmaps bm_flag = BM_NONE; arg = strtok( NULL, space ); first_bitmap_num = N_ObjBitmapPtrs; while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "dead_pof" )) { model_name_dead = equal_ptr; first_bitmap_num_dead=N_ObjBitmapPtrs; } else if (!d_stricmp( arg, "lighting" )) { lighting = fl2f(atof(equal_ptr)); if ( (lighting < 0) || (lighting > F1_0 )) { Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); } } else { Int3(); } } else { // Must be a texture specification... load_polymodel_bitmap(0, arg); } arg = strtok( NULL, space ); } if ( model_name_dead ) n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num; else n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); if ( model_name_dead ) Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL); else Dead_modelnums[model_num] = -1; if (type == -1) Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum); Reactors[Num_reactors].model_num = model_num; Reactors[Num_reactors].n_guns = read_model_guns(model_name,Reactors[Num_reactors].gun_points,Reactors[Num_reactors].gun_dirs,NULL); Num_reactors++; } //read the marker object void bm_read_marker() { char *model_name; int first_bitmap_num, n_normal_bitmaps; char *equal_ptr; model_name = strtok( NULL, space ); // Process bitmaps bm_flag = BM_NONE; arg = strtok( NULL, space ); first_bitmap_num = N_ObjBitmapPtrs; while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' Int3(); } else { // Must be a texture specification... load_polymodel_bitmap(0, arg); } arg = strtok( NULL, space ); } n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; Marker_model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); } //read the exit model void bm_read_exitmodel() { char *model_name, *model_name_dead=NULL; int first_bitmap_num=0, first_bitmap_num_dead=0, n_normal_bitmaps; char *equal_ptr; short model_num; model_name = strtok( NULL, space ); // Process bitmaps bm_flag = BM_NONE; arg = strtok( NULL, space ); first_bitmap_num = N_ObjBitmapPtrs; while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "dead_pof" )) { model_name_dead = equal_ptr; first_bitmap_num_dead=N_ObjBitmapPtrs; } else { Int3(); } } else { // Must be a texture specification... load_polymodel_bitmap(0, arg); } arg = strtok( NULL, space ); } if ( model_name_dead ) n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num; else n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); if ( model_name_dead ) Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL); else Dead_modelnums[model_num] = -1; exit_modelnum = model_num; destroyed_exit_modelnum = Dead_modelnums[model_num]; } void bm_read_player_ship(void) { char *model_name_dying=NULL; char *model_name[MAX_MODEL_VARIANTS]; int n_models=0,i; int first_bitmap_num[MAX_MODEL_VARIANTS]; char *equal_ptr; robot_info ri; int last_multi_bitmap_num=-1; // Process bitmaps bm_flag = BM_NONE; arg = strtok( NULL, space ); Player_ship->mass = Player_ship->drag = 0; //stupid defaults Player_ship->expl_vclip_num = -1; while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "model" )) { Assert(n_models==0); model_name[0] = equal_ptr; first_bitmap_num[0] = N_ObjBitmapPtrs; n_models = 1; } else if (!d_stricmp( arg, "simple_model" )) { model_name[n_models] = equal_ptr; first_bitmap_num[n_models] = N_ObjBitmapPtrs; n_models++; Assert(n_models < MAX_MODEL_VARIANTS); if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) last_multi_bitmap_num=N_ObjBitmapPtrs; } else if (!d_stricmp( arg, "mass" )) Player_ship->mass = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "drag" )) Player_ship->drag = fl2f(atof(equal_ptr)); // else if (!d_stricmp( arg, "low_thrust" )) // Player_ship->low_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "max_thrust" )) Player_ship->max_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "reverse_thrust" )) Player_ship->reverse_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "brakes" )) Player_ship->brakes = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "wiggle" )) Player_ship->wiggle = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "max_rotthrust" )) Player_ship->max_rotthrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "dying_pof" )) model_name_dying = equal_ptr; else if (!d_stricmp( arg, "expl_vclip_num" )) Player_ship->expl_vclip_num=atoi(equal_ptr); else { Int3(); } } else if (!d_stricmp( arg, "multi_textures" )) { First_multi_bitmap_num = N_ObjBitmapPtrs; first_bitmap_num[n_models] = N_ObjBitmapPtrs; } else // Must be a texture specification... load_polymodel_bitmap(0, arg); arg = strtok( NULL, space ); } Assert(model_name != NULL); if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) last_multi_bitmap_num=N_ObjBitmapPtrs; if (First_multi_bitmap_num==-1) first_bitmap_num[n_models] = N_ObjBitmapPtrs; #ifdef NETWORK Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_PLAYERS-1)*2); #endif for (i=0;imodel_num = model_num; else Polygon_models[last_model_num].simpler_model = model_num+1; last_model_num = model_num; } if ( model_name_dying ) { Assert(n_models); Dying_modelnums[Player_ship->model_num] = load_polygon_model(model_name_dying,first_bitmap_num[1]-first_bitmap_num[0],first_bitmap_num[0],NULL); } Assert(ri.n_guns == N_PLAYER_GUNS); //calc player gun positions { polymodel *pm; robot_info *r; vms_vector pnt; int mn; //submodel number int gun_num; r = &ri; pm = &Polygon_models[Player_ship->model_num]; for (gun_num=0;gun_numn_guns;gun_num++) { pnt = r->gun_points[gun_num]; mn = r->gun_submodels[gun_num]; //instance up the tree for this gun while (mn != 0) { vm_vec_add2(&pnt,&pm->submodel_offsets[mn]); mn = pm->submodel_parents[mn]; } Player_ship->gun_points[gun_num] = pnt; } } } void bm_read_some_file(int skip) { switch (bm_flag) { case BM_NONE: Error("Trying to read bitmap <%s> with bm_flag==BM_NONE on line %d of BITMAPS.TBL",arg,linenum); break; case BM_COCKPIT: { bitmap_index bitmap; bitmap = bm_load_sub(skip, arg); Assert( Num_cockpits < N_COCKPIT_BITMAPS ); cockpit_bitmap[Num_cockpits++] = bitmap; //bm_flag = BM_NONE; return; } break; case BM_GAUGES: bm_read_gauges(skip); return; break; case BM_GAUGES_HIRES: bm_read_gauges_hires(); return; break; case BM_WEAPON: bm_read_weapon(skip, 0); return; break; case BM_VCLIP: bm_read_vclip(skip); return; break; case BM_ECLIP: bm_read_eclip(skip); return; break; case BM_TEXTURES: { bitmap_index bitmap; bitmap = bm_load_sub(skip, arg); Assert(tmap_count < MAX_TEXTURES); TmapList[tmap_count++] = texture_count; Textures[texture_count] = bitmap; set_texture_name( arg ); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; return; } break; case BM_WCLIP: bm_read_wclip(skip); return; break; } Error("Trying to read bitmap <%s> with unknown bm_flag <%x> on line %d of BITMAPS.TBL",arg,bm_flag,linenum); } // ------------------------------------------------------------------------------ // If unused_flag is set, then this is just a placeholder. Don't actually reference vclips or load bbms. void bm_read_weapon(int skip, int unused_flag) { int i,n; int n_models=0; char *equal_ptr; char *pof_file_inner=NULL; char *model_name[MAX_MODEL_VARIANTS]; int first_bitmap_num[MAX_MODEL_VARIANTS]; int lighted; //flag for whether is a texture is lighted Assert(N_weapon_types < MAX_WEAPON_TYPES); n = N_weapon_types; N_weapon_types++; Assert(N_weapon_types <= MAX_WEAPON_TYPES); if (unused_flag) { clear_to_end_of_line(); return; } if (skip) { clear_to_end_of_line(); return; } // Initialize weapon array Weapon_info[n].render_type = WEAPON_RENDER_NONE; // 0=laser, 1=blob, 2=object Weapon_info[n].bitmap.index = 0; Weapon_info[n].model_num = -1; Weapon_info[n].model_num_inner = -1; Weapon_info[n].blob_size = 0x1000; // size of blob Weapon_info[n].flash_vclip = -1; Weapon_info[n].flash_sound = SOUND_LASER_FIRED; Weapon_info[n].flash_size = 0; Weapon_info[n].robot_hit_vclip = -1; Weapon_info[n].robot_hit_sound = -1; Weapon_info[n].wall_hit_vclip = -1; Weapon_info[n].wall_hit_sound = -1; Weapon_info[n].impact_size = 0; for (i=0; ibm_flags |= BM_FLAG_NO_LIGHTING; lighted = 1; //default for next bitmap is lighted } arg = strtok( NULL, space ); } first_bitmap_num[n_models] = N_ObjBitmapPtrs; for (i=0;ifilename)-sizeof(TmapInfo->pad2), 1 ); PHYSFSX_printf(tfile, "NumTextures = %d, Textures array = %d, TmapInfo array = %d\n", NumTextures, (int) sizeof(bitmap_index)*NumTextures, (int) sizeof(tmap_info)*NumTextures); t = MAX_SOUNDS; PHYSFS_write( fp, &t, sizeof(int), 1 ); PHYSFS_write( fp, Sounds, sizeof(ubyte), t ); PHYSFS_write( fp, AltSounds, sizeof(ubyte), t ); PHYSFSX_printf(tfile,"Num Sounds = %d, Sounds array = %d, AltSounds array = %d\n",t,t,t); PHYSFS_write( fp, &Num_vclips, sizeof(int), 1 ); PHYSFS_write( fp, Vclip, sizeof(vclip), Num_vclips ); PHYSFSX_printf(tfile, "Num_vclips = %d, Vclip array = %d\n", Num_vclips, (int) sizeof(vclip)*Num_vclips); PHYSFS_write( fp, &Num_effects, sizeof(int), 1 ); PHYSFS_write( fp, Effects, sizeof(eclip), Num_effects ); PHYSFSX_printf(tfile, "Num_effects = %d, Effects array = %d\n", Num_effects, (int) sizeof(eclip)*Num_effects); PHYSFS_write( fp, &Num_wall_anims, sizeof(int), 1 ); PHYSFS_write( fp, WallAnims, sizeof(wclip), Num_wall_anims ); PHYSFSX_printf(tfile, "Num_wall_anims = %d, WallAnims array = %d\n", Num_wall_anims, (int) sizeof(wclip)*Num_wall_anims); t = N_D2_ROBOT_TYPES; PHYSFS_write( fp, &t, sizeof(int), 1 ); PHYSFS_write( fp, Robot_info, sizeof(robot_info), t ); PHYSFSX_printf(tfile, "N_robot_types = %d, Robot_info array = %d\n", t, (int) sizeof(robot_info)*N_robot_types); t = N_D2_ROBOT_JOINTS; PHYSFS_write( fp, &t, sizeof(int), 1 ); PHYSFS_write( fp, Robot_joints, sizeof(jointpos), t ); PHYSFSX_printf(tfile, "N_robot_joints = %d, Robot_joints array = %d\n", t, (int) sizeof(jointpos)*N_robot_joints); t = N_D2_WEAPON_TYPES; PHYSFS_write( fp, &t, sizeof(int), 1 ); PHYSFS_write( fp, Weapon_info, sizeof(weapon_info), t ); PHYSFSX_printf(tfile, "N_weapon_types = %d, Weapon_info array = %d\n", N_weapon_types, (int) sizeof(weapon_info)*N_weapon_types); PHYSFS_write( fp, &N_powerup_types, sizeof(int), 1 ); PHYSFS_write( fp, Powerup_info, sizeof(powerup_type_info), N_powerup_types ); PHYSFSX_printf(tfile, "N_powerup_types = %d, Powerup_info array = %d\n", N_powerup_types, (int) sizeof(powerup_info)*N_powerup_types); t = N_D2_POLYGON_MODELS; PHYSFS_write( fp, &t, sizeof(int), 1 ); PHYSFS_write( fp, Polygon_models, sizeof(polymodel), t ); PHYSFSX_printf(tfile, "N_polygon_models = %d, Polygon_models array = %d\n", t, (int) sizeof(polymodel)*t); for (i=0; i #include #if !defined(_WIN32) && !defined(macintosh) #include #endif #include "pstypes.h" #include "dxxerror.h" #include "inferno.h" #include "cntrlcen.h" #include "game.h" #include "laser.h" #include "gameseq.h" #include "ai.h" #ifdef NETWORK #include "multi.h" #endif #include "wall.h" #include "object.h" #include "robot.h" #include "vclip.h" #include "fireball.h" #include "endlevel.h" #include "state.h" #include "byteswap.h" #include "args.h" //@@vms_vector controlcen_gun_points[MAX_CONTROLCEN_GUNS]; //@@vms_vector controlcen_gun_dirs[MAX_CONTROLCEN_GUNS]; reactor Reactors[MAX_REACTORS]; int Num_reactors=0; control_center_triggers ControlCenterTriggers; int Control_center_been_hit; int Control_center_player_been_seen; int Control_center_next_fire_time; int Control_center_present; void do_countdown_frame(); // ----------------------------------------------------------------------------- //return the position & orientation of a gun on the control center object void calc_controlcen_gun_point(reactor *reactor, object *obj,int gun_num) { vms_matrix m; vms_vector *gun_point = &obj->ctype.reactor_info.gun_pos[gun_num]; vms_vector *gun_dir = &obj->ctype.reactor_info.gun_dir[gun_num]; Assert(obj->type == OBJ_CNTRLCEN); Assert(obj->render_type==RT_POLYOBJ); Assert(gun_num < reactor->n_guns); //instance gun position & orientation vm_copy_transpose_matrix(&m,&obj->orient); vm_vec_rotate(gun_point,&reactor->gun_points[gun_num],&m); vm_vec_add2(gun_point,&obj->pos); vm_vec_rotate(gun_dir,&reactor->gun_dirs[gun_num],&m); } // ----------------------------------------------------------------------------- // Look at control center guns, find best one to fire at *objp. // Return best gun number (one whose direction dotted with vector to player is largest). // If best gun has negative dot, return -1, meaning no gun is good. int calc_best_gun(int num_guns, const object *objreactor, const vms_vector *objpos) { int i; fix best_dot; int best_gun; const vms_vector (*const gun_pos)[MAX_CONTROLCEN_GUNS] = &objreactor->ctype.reactor_info.gun_pos; const vms_vector (*const gun_dir)[MAX_CONTROLCEN_GUNS] = &objreactor->ctype.reactor_info.gun_dir; best_dot = -F1_0*2; best_gun = -1; for (i=0; i best_dot) { best_dot = dot; best_gun = i; } } Assert(best_gun != -1); // Contact Mike. This is impossible. Or maybe you're getting an unnormalized vector somewhere. if (best_dot < 0) return -1; else return best_gun; } int Dead_controlcen_object_num=-1; //how long to blow up on insane int Base_control_center_explosion_time=DEFAULT_CONTROL_CENTER_EXPLOSION_TIME; int Control_center_destroyed = 0; fix Countdown_timer=0; int Countdown_seconds_left=0, Total_countdown_time=0; //in whole seconds static const int Alan_pavlish_reactor_times[NDL] = {90, 60, 45, 35, 30}; // ----------------------------------------------------------------------------- // Called every frame. If control center been destroyed, then actually do something. void do_controlcen_dead_frame(void) { if ((Game_mode & GM_MULTI) && (Players[Player_num].connected != CONNECT_PLAYING)) // if out of level already there's no need for this return; if ((Dead_controlcen_object_num != -1) && (Countdown_seconds_left > 0)) if (d_rand() < FrameTime*4) create_small_fireball_on_object(&Objects[Dead_controlcen_object_num], F1_0, 1); if (Control_center_destroyed && !Endlevel_sequence) do_countdown_frame(); } #define COUNTDOWN_VOICE_TIME fl2f(12.75) void do_countdown_frame() { fix old_time; int fc, div_scale; if (!Control_center_destroyed) return; if (!is_D2_OEM && !is_MAC_SHARE && !is_SHAREWARE) // get countdown in OEM and SHAREWARE only { // On last level, we don't want a countdown. if (PLAYING_BUILTIN_MISSION && Current_level_num == Last_level) { if (!(Game_mode & GM_MULTI)) return; if (Game_mode & GM_MULTI_ROBOTS) return; } } // Control center destroyed, rock the player's ship. fc = Countdown_seconds_left; if (fc > 16) fc = 16; // At Trainee, decrease rocking of ship by 4x. div_scale = 1; if (Difficulty_level == 0) div_scale = 4; if (d_tick_step) { ConsoleObject->mtype.phys_info.rotvel.x += (fixmul(d_rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32))/div_scale; ConsoleObject->mtype.phys_info.rotvel.z += (fixmul(d_rand() - 16384, 3*F1_0/16 + (F1_0*(16-fc))/32))/div_scale; } // Hook in the rumble sound effect here. old_time = Countdown_timer; Countdown_timer -= FrameTime; Countdown_seconds_left = f2i(Countdown_timer + F1_0*7/8); if ( (old_time > COUNTDOWN_VOICE_TIME ) && (Countdown_timer <= COUNTDOWN_VOICE_TIME) ) { digi_play_sample( SOUND_COUNTDOWN_13_SECS, F3_0 ); } if ( f2i(old_time + F1_0*7/8) != Countdown_seconds_left ) { if ( (Countdown_seconds_left>=0) && (Countdown_seconds_left<10) ) digi_play_sample( SOUND_COUNTDOWN_0_SECS+Countdown_seconds_left, F3_0 ); if ( Countdown_seconds_left==Total_countdown_time-1) digi_play_sample( SOUND_COUNTDOWN_29_SECS, F3_0 ); } if (Countdown_timer > 0) { fix size,old_size; size = (i2f(Total_countdown_time)-Countdown_timer) / fl2f(0.65); old_size = (i2f(Total_countdown_time)-old_time) / fl2f(0.65); if (size != old_size && (Countdown_seconds_left < (Total_countdown_time-5) )) { // Every 2 seconds! //@@if (Dead_controlcen_object_num != -1) { //@@ vms_vector vp; //,v,c; //@@ compute_segment_center(&vp, &Segments[Objects[Dead_controlcen_object_num].segnum]); //@@ object_create_explosion( Objects[Dead_controlcen_object_num].segnum, &vp, size*10, VCLIP_SMALL_EXPLOSION); //@@} digi_play_sample( SOUND_CONTROL_CENTER_WARNING_SIREN, F3_0 ); } } else { int flash_value; if (old_time > 0) digi_play_sample( SOUND_MINE_BLEW_UP, F1_0 ); flash_value = f2i(-Countdown_timer * (64 / 4)); // 4 seconds to total whiteness PALETTE_FLASH_SET(flash_value,flash_value,flash_value); if (PaletteBlueAdd > 64 ) { gr_set_current_canvas( NULL ); gr_clear_canvas(BM_XRGB(31,31,31)); //make screen all white to match palette effect reset_palette_add(); //restore palette for death message //controlcen->MaxCapacity = Fuelcen_max_amount; //gauge_message( "Control Center Reset" ); DoPlayerDead(); //kill_player(); } } } // ----------------------------------------------------------------------------- // Called when control center gets destroyed. // This code is common to whether control center is implicitly imbedded in a boss, // or is an object of its own. // if objp == NULL that means the boss was the control center and don't set Dead_controlcen_object_num void do_controlcen_destroyed_stuff(object *objp) { int i; if ((Game_mode & GM_MULTI_ROBOTS) && Control_center_destroyed) return; // Don't allow resetting if control center and boss on same level // Must toggle walls whether it is a boss or control center. for (i=0;isegnum]; // This is a hack. Since the control center is not processed by // ai_do_frame, it doesn't know to deal with cloaked dudes. It // seems to work in single-player mode because it is actually using // the value of Believed_player_position that was set by the last // person to go through ai_do_frame. But since a no-robots game // never goes through ai_do_frame, I'm making it so the control // center can spot cloaked dudes. if (Game_mode & GM_MULTI) Believed_player_pos = Objects[Players[Player_num].objnum].pos; // Hack for special control centers which are isolated and not reachable because the // real control center is inside the boss. for (i=0; ichildren[i])) break; if (i == MAX_SIDES_PER_SEGMENT) return; vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos); dist_to_player = vm_vec_normalize_quick(&vec_to_player); if (dist_to_player < F1_0*200) { Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player); Control_center_next_fire_time = 0; } } return; } // Periodically, make the reactor fall asleep if player not visible. if (Control_center_been_hit || Control_center_player_been_seen) { if ((Last_time_cc_vis_check + F1_0*5 < GameTime64) || (Last_time_cc_vis_check > GameTime64)) { vms_vector vec_to_player; fix dist_to_player; vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos); dist_to_player = vm_vec_normalize_quick(&vec_to_player); Last_time_cc_vis_check = GameTime64; if (dist_to_player < F1_0*120) { Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player); if (!Control_center_player_been_seen) Control_center_been_hit = 0; } } } if (Player_is_dead) controlcen_death_silence += FrameTime; else controlcen_death_silence = 0; if ((Control_center_next_fire_time < 0) && !(controlcen_death_silence > F1_0*2)) { reactor *reactor = get_reactor_definition(obj->id); if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) best_gun_num = calc_best_gun(reactor->n_guns, obj, &Believed_player_pos); else best_gun_num = calc_best_gun(reactor->n_guns, obj, &ConsoleObject->pos); if (best_gun_num != -1) { int rand_prob, count; vms_vector vec_to_goal; fix dist_to_player; fix delta_fire_time; if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) { vm_vec_sub(&vec_to_goal, &Believed_player_pos, &obj->ctype.reactor_info.gun_pos[best_gun_num]); dist_to_player = vm_vec_normalize_quick(&vec_to_goal); } else { vm_vec_sub(&vec_to_goal, &ConsoleObject->pos, &obj->ctype.reactor_info.gun_pos[best_gun_num]); dist_to_player = vm_vec_normalize_quick(&vec_to_goal); } if (dist_to_player > F1_0*300) { Control_center_been_hit = 0; Control_center_player_been_seen = 0; return; } #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects); #endif Laser_create_new_easy( &vec_to_goal, &obj->ctype.reactor_info.gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 1); // some of time, based on level, fire another thing, not directly at player, so it might hit him if he's constantly moving. rand_prob = F1_0/(abs(Current_level_num)/4+2); count = 0; while ((d_rand() > rand_prob) && (count < 4)) { vms_vector randvec; make_random_vector(&randvec); vm_vec_scale_add2(&vec_to_goal, &randvec, F1_0/6); vm_vec_normalize_quick(&vec_to_goal); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects); #endif Laser_create_new_easy( &vec_to_goal, &obj->ctype.reactor_info.gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 0); count++; } delta_fire_time = (NDL - Difficulty_level) * F1_0/4; if (Difficulty_level == 0) delta_fire_time += F1_0/2; if (Game_mode & GM_MULTI) // slow down rate of fire in multi player delta_fire_time *= 2; Control_center_next_fire_time = delta_fire_time; } } else Control_center_next_fire_time -= FrameTime; } int Reactor_strength=-1; //-1 mean not set by designer // ----------------------------------------------------------------------------- // This must be called at the start of each level. // If this level contains a boss and mode != multiplayer, don't do control center stuff. (Ghost out control center object.) // If this level contains a boss and mode == multiplayer, do control center stuff. void init_controlcen_for_level(void) { int i; object *objp; int cntrlcen_objnum=-1, boss_objnum=-1; for (i=0; i<=Highest_object_index; i++) { objp = &Objects[i]; if (objp->type == OBJ_CNTRLCEN) { if (cntrlcen_objnum != -1) ; else cntrlcen_objnum = i; } if ((objp->type == OBJ_ROBOT) && (Robot_info[objp->id].boss_flag)) { if (boss_objnum != -1) ; else boss_objnum = i; } } #ifndef NDEBUG if (cntrlcen_objnum == -1) { Dead_controlcen_object_num = -1; return; } #endif if ( (boss_objnum != -1) && !((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_ROBOTS)) ) { if (cntrlcen_objnum != -1) { Objects[cntrlcen_objnum].type = OBJ_GHOST; Objects[cntrlcen_objnum].render_type = RT_NONE; Control_center_present = 0; } } else if (cntrlcen_objnum != -1) { // Compute all gun positions. objp = &Objects[cntrlcen_objnum]; reactor *reactor = get_reactor_definition(objp->id); for (i=0; in_guns; i++) calc_controlcen_gun_point(reactor, objp, i); Control_center_present = 1; if (Reactor_strength == -1) { //use old defaults // Boost control center strength at higher levels. if (Current_level_num >= 0) objp->shields = F1_0*200 + (F1_0*200/4) * Current_level_num; else objp->shields = F1_0*200 - Current_level_num*F1_0*150; } else { objp->shields = i2f(Reactor_strength); } } // Say the control center has not yet been hit. Control_center_been_hit = 0; Control_center_player_been_seen = 0; Control_center_next_fire_time = 0; Dead_controlcen_object_num = -1; } void special_reactor_stuff(void) { if (Control_center_destroyed) { Countdown_timer += i2f(Base_control_center_explosion_time + (NDL-1-Difficulty_level)*Base_control_center_explosion_time/(NDL-1)); Total_countdown_time = f2i(Countdown_timer)+2; // Will prevent "Self destruct sequence activated" message from replaying. } } /* * reads n reactor structs from a PHYSFS_file */ extern int reactor_read_n(reactor *r, int n, PHYSFS_file *fp) { int i, j; for (i = 0; i < n; i++) { r[i].model_num = PHYSFSX_readInt(fp); r[i].n_guns = PHYSFSX_readInt(fp); for (j = 0; j < MAX_CONTROLCEN_GUNS; j++) PHYSFSX_readVector(&(r[i].gun_points[j]), fp); for (j = 0; j < MAX_CONTROLCEN_GUNS; j++) PHYSFSX_readVector(&(r[i].gun_dirs[j]), fp); } return i; } /* * reads a control_center_triggers structure from a PHYSFS_file */ extern int control_center_triggers_read_n(control_center_triggers *cct, int n, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++) { cct->num_links = PHYSFSX_readShort(fp); for (unsigned j = 0; j < MAX_CONTROLCEN_LINKS; j++) cct->seg[j] = PHYSFSX_readShort(fp); for (unsigned j = 0; j < MAX_CONTROLCEN_LINKS; j++) cct->side[j] = PHYSFSX_readShort(fp); } return i; } void control_center_triggers_swap(control_center_triggers *cct, int swap) { int i; if (!swap) return; cct->num_links = SWAPSHORT(cct->num_links); for (i = 0; i < MAX_CONTROLCEN_LINKS; i++) cct->seg[i] = SWAPSHORT(cct->seg[i]); for (i = 0; i < MAX_CONTROLCEN_LINKS; i++) cct->side[i] = SWAPSHORT(cct->side[i]); } /* * reads n control_center_triggers structs from a PHYSFS_file and swaps if specified */ void control_center_triggers_read_n_swap(control_center_triggers *cct, int n, int swap, PHYSFS_file *fp) { int i; PHYSFS_read(fp, cct, sizeof(control_center_triggers), n); if (swap) for (i = 0; i < n; i++) control_center_triggers_swap(&cct[i], swap); } int control_center_triggers_write(control_center_triggers *cct, PHYSFS_file *fp) { int j; PHYSFS_writeSLE16(fp, cct->num_links); for (j = 0; j < MAX_CONTROLCEN_LINKS; j++) PHYSFS_writeSLE16(fp, cct->seg[j]); for (j = 0; j < MAX_CONTROLCEN_LINKS; j++) PHYSFS_writeSLE16(fp, cct->side[j]); return 1; } dxx-rebirth-0.58.1-d2x/main/cntrlcen.h000066400000000000000000000066661217717237500174770ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for cntrlcen.c * */ #ifndef _CNTRLCEN_H #define _CNTRLCEN_H #include "vecmat.h" #include "object.h" #include "wall.h" //#include "switch.h" #define CONTROLCEN_WEAPON_NUM 6 #define MAX_CONTROLCEN_LINKS 10 typedef struct control_center_triggers { short num_links; short seg[MAX_CONTROLCEN_LINKS]; short side[MAX_CONTROLCEN_LINKS]; } __pack__ control_center_triggers; extern control_center_triggers ControlCenterTriggers; typedef struct reactor { int model_num; int n_guns; /* Location of the gun on the reactor model */ vms_vector gun_points[MAX_CONTROLCEN_GUNS]; /* Orientation of the gun on the reactor model */ vms_vector gun_dirs[MAX_CONTROLCEN_GUNS]; } __pack__ reactor; #define MAX_REACTORS 7 extern int Num_reactors; extern reactor Reactors[MAX_REACTORS]; static inline int get_num_reactor_models() { return Num_reactors; } static inline int get_reactor_model_number(int id) { return Reactors[id].model_num; } static inline reactor *get_reactor_definition(int id) { return &Reactors[id]; } //@@extern int N_controlcen_guns; extern int Control_center_been_hit; extern int Control_center_player_been_seen; extern int Control_center_next_fire_time; extern int Control_center_present; extern int Dead_controlcen_object_num; //@@extern vms_vector controlcen_gun_points[MAX_CONTROLCEN_GUNS]; //@@extern vms_vector controlcen_gun_dirs[MAX_CONTROLCEN_GUNS]; // do whatever this thing does in a frame extern void do_controlcen_frame(object *obj); // Initialize control center for a level. // Call when a new level is started. extern void init_controlcen_for_level(void); extern void calc_controlcen_gun_point(reactor *reactor, object *obj,int gun_num); extern void do_controlcen_destroyed_stuff(object *objp); extern void do_controlcen_dead_frame(void); #define DEFAULT_CONTROL_CENTER_EXPLOSION_TIME 30 // Note: Usually uses Alan_pavlish_reactor_times, but can be overridden in editor. extern fix Countdown_timer; extern int Control_center_destroyed, Countdown_seconds_left, Total_countdown_time; extern int Base_control_center_explosion_time; // how long to blow up on insane extern int Reactor_strength; /* * reads n reactor structs from a PHYSFS_file */ extern int reactor_read_n(reactor *r, int n, PHYSFS_file *fp); /* * reads n control_center_triggers structs from a PHYSFS_file */ extern int control_center_triggers_read_n(control_center_triggers *cct, int n, PHYSFS_file *fp); /* * reads n control_center_triggers structs from a PHYSFS_file and swaps if specified */ extern void control_center_triggers_read_n_swap(control_center_triggers *cct, int n, int swap, PHYSFS_file *fp); extern int control_center_triggers_write(control_center_triggers *cct, PHYSFS_file *fp); #endif /* _CNTRLCEN_H */ dxx-rebirth-0.58.1-d2x/main/collide.c000066400000000000000000002574331217717237500172750ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to handle collisions * */ #include #include #include "rle.h" #include "inferno.h" #include "game.h" #include "gr.h" #include "stdlib.h" #include "bm.h" #include "3d.h" #include "segment.h" #include "texmap.h" #include "laser.h" #include "key.h" #include "gameseg.h" #include "object.h" #include "physics.h" #include "slew.h" #include "render.h" #include "wall.h" #include "vclip.h" #include "polyobj.h" #include "fireball.h" #include "laser.h" #include "dxxerror.h" #include "ai.h" #include "hostage.h" #include "fuelcen.h" #include "sounds.h" #include "robot.h" #include "weapon.h" #include "player.h" #include "gauges.h" #include "powerup.h" #include "newmenu.h" #include "scores.h" #include "effects.h" #include "textures.h" #ifdef NETWORK #include "multi.h" #endif #include "cntrlcen.h" #include "newdemo.h" #include "endlevel.h" #include "multibot.h" #include "piggy.h" #include "text.h" #include "automap.h" #include "switch.h" #include "palette.h" #include "gameseq.h" #ifdef EDITOR #include "editor/editor.h" #endif #include "collide.h" #include "escort.h" #define WALL_DAMAGE_SCALE (128) // Was 32 before 8:55 am on Thursday, September 15, changed by MK, walls were hurting me more than robots! #define WALL_DAMAGE_THRESHOLD (F1_0/3) #define WALL_LOUDNESS_SCALE (20) #define FORCE_DAMAGE_THRESHOLD (F1_0/3) #define STANDARD_EXPL_DELAY (F1_0/4) int check_collision_delayfunc_exec() { static fix64 last_play_time=0; if (last_play_time + (F1_0/3) < GameTime64 || last_play_time > GameTime64) { last_play_time = GameTime64; last_play_time -= (d_rand()/2); // add some randomness return 1; } return 0; } // ------------------------------------------------------------------------------------------------------------- // The only reason this routine is called (as of 10/12/94) is so Brain guys can open doors. void collide_robot_and_wall( object * robot, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { ai_local *ailp = &Ai_local_info[robot-Objects]; if ((robot->id == ROBOT_BRAIN) || (robot->ctype.ai_info.behavior == AIB_RUN_FROM) || (Robot_info[robot->id].companion == 1) || (robot->ctype.ai_info.behavior == AIB_SNIPE)) { int wall_num = Segments[hitseg].sides[hitwall].wall_num; if (wall_num != -1) { if ((Walls[wall_num].type == WALL_DOOR) && (Walls[wall_num].keys == KEY_NONE) && (Walls[wall_num].state == WALL_DOOR_CLOSED) && !(Walls[wall_num].flags & WALL_DOOR_LOCKED)) { wall_open_door(&Segments[hitseg], hitwall); // -- Changed from this, 10/19/95, MK: Don't want buddy getting stranded from player //-- } else if ((Robot_info[robot->id].companion == 1) && (Walls[wall_num].type == WALL_DOOR) && (Walls[wall_num].keys != KEY_NONE) && (Walls[wall_num].state == WALL_DOOR_CLOSED) && !(Walls[wall_num].flags & WALL_DOOR_LOCKED)) { } else if ((Robot_info[robot->id].companion == 1) && (Walls[wall_num].type == WALL_DOOR)) { if ((ailp->mode == AIM_GOTO_PLAYER) || (Escort_special_goal == ESCORT_GOAL_SCRAM)) { if (Walls[wall_num].keys != KEY_NONE) { if (Walls[wall_num].keys & Players[Player_num].flags) wall_open_door(&Segments[hitseg], hitwall); } else if (!(Walls[wall_num].flags & WALL_DOOR_LOCKED)) wall_open_door(&Segments[hitseg], hitwall); } } else if (Robot_info[robot->id].thief) { // Thief allowed to go through doors to which player has key. if (Walls[wall_num].keys != KEY_NONE) if (Walls[wall_num].keys & Players[Player_num].flags) wall_open_door(&Segments[hitseg], hitwall); } } } return; } //##void collide_hostage_and_wall( object * hostage, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { //## return; //##} // ------------------------------------------------------------------------------------------------------------- int apply_damage_to_clutter(object *clutter, fix damage) { if ( clutter->flags&OF_EXPLODING) return 0; if (clutter->shields < 0 ) return 0; //clutter already dead... clutter->shields -= damage; if (clutter->shields < 0) { explode_object(clutter,0); return 1; } else return 0; } //given the specified force, apply damage from that force to an object void apply_force_damage(object *obj,fix force,object *other_obj) { int result; fix damage; if (obj->flags & (OF_EXPLODING|OF_SHOULD_BE_DEAD)) return; //already exploding or dead damage = fixdiv(force,obj->mtype.phys_info.mass) / 8; if ((other_obj->type == OBJ_PLAYER) && cheats.monsterdamage) damage = 0x7fffffff; if (damage < FORCE_DAMAGE_THRESHOLD) return; switch (obj->type) { case OBJ_ROBOT: if (Robot_info[obj->id].attack_type == 1) { if (other_obj->type == OBJ_WEAPON) result = apply_damage_to_robot(obj,damage/4, other_obj->ctype.laser_info.parent_num); else result = apply_damage_to_robot(obj,damage/4, other_obj-Objects); } else { if (other_obj->type == OBJ_WEAPON) result = apply_damage_to_robot(obj,damage/2, other_obj->ctype.laser_info.parent_num); else result = apply_damage_to_robot(obj,damage/2, other_obj-Objects); } if (result && (other_obj->ctype.laser_info.parent_signature == ConsoleObject->signature)) add_points_to_score(Robot_info[obj->id].score_value); break; case OBJ_PLAYER: // If colliding with a claw type robot, do damage proportional to FrameTime because you can collide with those // bots every frame since they don't move. if ( (other_obj->type == OBJ_ROBOT) && (Robot_info[other_obj->id].attack_type) ) damage = fixmul(damage, FrameTime*2); // Make trainee easier. if (Difficulty_level == 0) damage /= 2; apply_damage_to_player(obj,other_obj,damage, 0); break; case OBJ_CLUTTER: apply_damage_to_clutter(obj,damage); break; case OBJ_CNTRLCEN: // Never hits! Reactor does not have MT_PHYSICS - it's stationary! So no force damage here. apply_damage_to_controlcen(obj,damage, other_obj-Objects); break; case OBJ_WEAPON: break; //weapons don't take damage default: Int3(); } } // ----------------------------------------------------------------------------- void bump_this_object(object *objp, object *other_objp, vms_vector *force, int damage_flag) { fix force_mag; if (! (objp->mtype.phys_info.flags & PF_PERSISTENT)) { if (objp->type == OBJ_PLAYER) { vms_vector force2; force2.x = force->x/4; force2.y = force->y/4; force2.z = force->z/4; phys_apply_force(objp,&force2); if (damage_flag && ((other_objp->type != OBJ_ROBOT) || !Robot_info[other_objp->id].companion)) { force_mag = vm_vec_mag_quick(&force2); apply_force_damage(objp, force_mag, other_objp); } } else if ((objp->type == OBJ_ROBOT) || (objp->type == OBJ_CLUTTER) || (objp->type == OBJ_CNTRLCEN)) { if (!Robot_info[objp->id].boss_flag) { vms_vector force2; force2.x = force->x/(4 + Difficulty_level); force2.y = force->y/(4 + Difficulty_level); force2.z = force->z/(4 + Difficulty_level); phys_apply_force(objp, force); phys_apply_rot(objp, &force2); if (damage_flag) { force_mag = vm_vec_mag_quick(force); apply_force_damage(objp, force_mag, other_objp); } } } } } // ----------------------------------------------------------------------------- //deal with two objects bumping into each other. Apply force from collision //to each robot. The flags tells whether the objects should take damage from //the collision. void bump_two_objects(object *obj0,object *obj1,int damage_flag) { vms_vector force; object *t=NULL; vm_vec_zero(&force); if (obj0->movement_type != MT_PHYSICS) t=obj1; else if (obj1->movement_type != MT_PHYSICS) t=obj0; if (t) { Assert(t->movement_type == MT_PHYSICS); vm_vec_copy_scale(&force,&t->mtype.phys_info.velocity,-t->mtype.phys_info.mass); phys_apply_force(t,&force); return; } vm_vec_sub(&force,&obj0->mtype.phys_info.velocity,&obj1->mtype.phys_info.velocity); vm_vec_scale2(&force,2*fixmul(obj0->mtype.phys_info.mass,obj1->mtype.phys_info.mass),(obj0->mtype.phys_info.mass+obj1->mtype.phys_info.mass)); bump_this_object(obj1, obj0, &force, damage_flag); vm_vec_negate(&force); bump_this_object(obj0, obj1, &force, damage_flag); } void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage) { vms_vector hit_vec; hit_vec = *hit_dir; vm_vec_scale(&hit_vec, damage); phys_apply_force(obj0,&hit_vec); } void collide_player_and_wall( object * playerobj, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { fix damage; char ForceFieldHit=0; int tmap_num,tmap_num2; if (playerobj->id != Player_num) // Execute only for local player return; tmap_num = Segments[hitseg].sides[hitwall].tmap_num; // If this wall does damage, don't make *BONK* sound, we'll be making another sound. if (TmapInfo[tmap_num].damage > 0) return; if (TmapInfo[tmap_num].flags & TMI_FORCE_FIELD) { vms_vector force; PALETTE_FLASH_ADD(0, 0, 60); //flash blue //knock player around force.x = 40*(d_rand() - 16384); force.y = 40*(d_rand() - 16384); force.z = 40*(d_rand() - 16384); phys_apply_rot(playerobj, &force); //make sound digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_PLAYER, hitseg, 0, hitpt, 0, f1_0 ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_PLAYER, f1_0); #endif ForceFieldHit=1; } else { wall_hit_process( &Segments[hitseg], hitwall, 20, playerobj->id, playerobj ); } // ** Damage from hitting wall ** // If the player has less than 10% shields, don't take damage from bump // Note: Does quad damage if hit a force field - JL damage = (hitspeed / WALL_DAMAGE_SCALE) * (ForceFieldHit*8 + 1); tmap_num2 = Segments[hitseg].sides[hitwall].tmap_num2; //don't do wall damage and sound if hit lava or water if ((TmapInfo[tmap_num].flags & (TMI_WATER|TMI_VOLATILE)) || (tmap_num2 && (TmapInfo[tmap_num2&0x3fff].flags & (TMI_WATER|TMI_VOLATILE)))) damage = 0; if (damage >= WALL_DAMAGE_THRESHOLD) { int volume; volume = (hitspeed-(WALL_DAMAGE_SCALE*WALL_DAMAGE_THRESHOLD)) / WALL_LOUDNESS_SCALE ; create_awareness_event(playerobj, PA_WEAPON_WALL_COLLISION); if ( volume > F1_0 ) volume = F1_0; if (volume > 0 && !ForceFieldHit) { // uhhhgly hack digi_link_sound_to_pos( SOUND_PLAYER_HIT_WALL, hitseg, 0, hitpt, 0, volume ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(SOUND_PLAYER_HIT_WALL, volume); #endif } if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) if ( Players[Player_num].shields > f1_0*10 || ForceFieldHit) apply_damage_to_player( playerobj, playerobj, damage, 0 ); // -- No point in doing this unless we compute a reasonable hitpt. Currently it is just the player's position. --MK, 01/18/96 // -- if (!(TmapInfo[Segments[hitseg].sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD)) { // -- vms_vector hitpt1; // -- int hitseg1; // -- // -- vm_vec_avg(&hitpt1, hitpt, &Objects[Players[Player_num].objnum].pos); // -- hitseg1 = find_point_seg(&hitpt1, Objects[Players[Player_num].objnum].segnum); // -- if (hitseg1 != -1) // -- object_create_explosion( hitseg, hitpt, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip ); // -- } } return; } fix64 Last_volatile_scrape_sound_time = 0; void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt); void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt); //see if wall is volatile or water //if volatile, cause damage to player //returns 1=lava, 2=water int check_volatile_wall(object *obj,int segnum,int sidenum,vms_vector *hitpt) { fix tmap_num,d,water; Assert(obj->type==OBJ_PLAYER); tmap_num = Segments[segnum].sides[sidenum].tmap_num; d = TmapInfo[tmap_num].damage; water = (TmapInfo[tmap_num].flags & TMI_WATER); if (d > 0 || water) { if (obj->id == Player_num) { if (d > 0) { fix damage = fixmul(d,FrameTime); if (Difficulty_level == 0) damage /= 2; if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) apply_damage_to_player( obj, obj, damage, 0 ); PALETTE_FLASH_ADD(f2i(damage*4), 0, 0); //flash red } obj->mtype.phys_info.rotvel.x = (d_rand() - 16384)/2; obj->mtype.phys_info.rotvel.z = (d_rand() - 16384)/2; } return (d>0)?1:2; } else { return 0; } } //this gets called when an object is scraping along the wall void scrape_player_on_wall(object *obj, short hitseg, short hitside, vms_vector * hitpt ) { int type; if (obj->type != OBJ_PLAYER || obj->id != Player_num) return; if ((type=check_volatile_wall(obj,hitseg,hitside,hitpt))!=0) { vms_vector hit_dir, rand_vec; if ((GameTime64 > Last_volatile_scrape_sound_time + F1_0/4) || (GameTime64 < Last_volatile_scrape_sound_time)) { int sound = (type==1)?SOUND_VOLATILE_WALL_HISS:SOUND_SHIP_IN_WATER; Last_volatile_scrape_sound_time = GameTime64; digi_link_sound_to_pos( sound, hitseg, 0, hitpt, 0, F1_0 ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(sound, F1_0); #endif } #ifdef COMPACT_SEGS get_side_normal(&Segments[hitseg], higside, 0, &hit_dir ); #else hit_dir = Segments[hitseg].sides[hitside].normals[0]; #endif make_random_vector(&rand_vec); vm_vec_scale_add2(&hit_dir, &rand_vec, F1_0/8); vm_vec_normalize_quick(&hit_dir); bump_one_object(obj, &hit_dir, F1_0*8); } } //if an effect is hit, and it can blow up, then blow it up //returns true if it blew up int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag) { int tm,tmf,ec,db; db=0; // If this wall has a trigger and the blower-upper is not the player or the buddy, abort! { int ok_to_blow = 0; if (blower->ctype.laser_info.parent_type == OBJ_ROBOT) if (Robot_info[Objects[blower->ctype.laser_info.parent_num].id].companion) ok_to_blow = 1; if (!(ok_to_blow || (blower->ctype.laser_info.parent_type == OBJ_PLAYER))) { int trigger_num, wall_num; wall_num = seg->sides[side].wall_num; if ( wall_num != -1 ) { trigger_num = Walls[wall_num].trigger; if (trigger_num != -1) return 0; } } } if ((tm=seg->sides[side].tmap_num2) != 0) { tmf = tm&0xc000; //tm flags tm &= 0x3fff; //tm without flags //check if it's an animation (monitor) or casts light if ((((ec=TmapInfo[tm].eclip_num)!=-1) && ((db=Effects[ec].dest_bm_num)!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) || (ec==-1 && (TmapInfo[tm].destroyed!=-1))) { fix u,v; grs_bitmap *bm = &GameBitmaps[Textures[tm].index]; int x=0,y=0,t; PIGGY_PAGE_IN(Textures[tm]); //this can be blown up...did we hit it? if (!force_blowup_flag) { find_hitpoint_uv(&u,&v,NULL,pnt,seg,side,0); //evil: always say face zero x = ((unsigned) f2i(u*bm->bm_w)) % bm->bm_w; y = ((unsigned) f2i(v*bm->bm_h)) % bm->bm_h; switch (tmf) { //adjust for orientation of paste-on case 0x0000: break; case 0x4000: t=y; y=x; x=bm->bm_w-t-1; break; case 0x8000: y=bm->bm_h-y-1; x=bm->bm_w-x-1; break; case 0xc000: t=x; x=y; y=bm->bm_h-t-1; break; } if (bm->bm_flags & BM_FLAG_RLE) bm = rle_expand_texture(bm); } if (force_blowup_flag || (bm->bm_data[y*bm->bm_w+x] != TRANSPARENCY_COLOR)) { //not trans, thus on effect int vc,sound_num; fix dest_size; #ifdef NETWORK if ((Game_mode & GM_MULTI) && Netgame.AlwaysLighting) if (!(ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) return(0); #endif //note: this must get called before the texture changes, //because we use the light value of the texture to change //the static light in the segment subtract_light(seg-Segments,side); if (Newdemo_state == ND_STATE_RECORDING) newdemo_record_effect_blowup( seg-Segments, side, pnt); if (ec!=-1) { dest_size = Effects[ec].dest_size; vc = Effects[ec].dest_vclip; } else { dest_size = i2f(20); vc = 3; } object_create_explosion( seg-Segments, pnt, dest_size, vc ); if (ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT)) { if ((sound_num = Vclip[vc].sound_num) != -1) digi_link_sound_to_pos( sound_num, seg-Segments, 0, pnt, 0, F1_0 ); if ((sound_num=Effects[ec].sound_num)!=-1) //kill sound digi_kill_sound_linked_to_segment(seg-Segments,side,sound_num); if (Effects[ec].dest_eclip!=-1 && Effects[Effects[ec].dest_eclip].segnum==-1) { int bm_num; eclip *new_ec; new_ec = &Effects[Effects[ec].dest_eclip]; bm_num = new_ec->changing_wall_texture; new_ec->time_left = new_ec->vc.frame_time; new_ec->frame_count = 0; new_ec->segnum = seg-Segments; new_ec->sidenum = side; new_ec->flags |= EF_ONE_SHOT; new_ec->dest_bm_num = Effects[ec].dest_bm_num; Assert(bm_num!=0 && seg->sides[side].tmap_num2!=0); seg->sides[side].tmap_num2 = bm_num | tmf; //replace with destoyed } else { Assert(db!=0 && seg->sides[side].tmap_num2!=0); seg->sides[side].tmap_num2 = db | tmf; //replace with destoyed } } else { seg->sides[side].tmap_num2 = TmapInfo[tm].destroyed | tmf; //assume this is a light, and play light sound digi_link_sound_to_pos( SOUND_LIGHT_BLOWNUP, seg-Segments, 0, pnt, 0, F1_0 ); } return 1; //blew up! } } } return 0; //didn't blow up } //these gets added to the weapon's values when the weapon hits a volitle wall #define VOLATILE_WALL_EXPL_STRENGTH i2f(10) #define VOLATILE_WALL_IMPACT_SIZE i2f(3) #define VOLATILE_WALL_DAMAGE_FORCE i2f(5) #define VOLATILE_WALL_DAMAGE_RADIUS i2f(30) // int Show_seg_and_side = 0; void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { segment *seg = &Segments[hitseg]; int blew_up; int wall_type; int playernum; int robot_escort; if (weapon->id == OMEGA_ID) if (!ok_to_do_omega_damage(weapon)) // see comment in laser.c return; // If this is a guided missile and it strikes fairly directly, clear bounce flag. if (weapon->id == GUIDEDMISS_ID) { fix dot; dot = vm_vec_dot(&weapon->orient.fvec, &Segments[hitseg].sides[hitwall].normals[0]); if (dot < -F1_0/6) { weapon->mtype.phys_info.flags &= ~PF_BOUNCE; } } //if an energy weapon hits a forcefield, let it bounce if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD) && !(weapon->type == OBJ_WEAPON && Weapon_info[weapon->id].energy_usage==0)) { //make sound digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_WEAPON, hitseg, 0, hitpt, 0, f1_0 ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_WEAPON, f1_0); #endif return; //bail here. physics code will bounce this object } #ifndef NDEBUG if (keyd_pressed[KEY_LAPOSTRO]) if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) { // MK: Real pain when you need to know a seg:side and you've got quad lasers. HUD_init_message(HM_DEFAULT, "Hit at segment = %i, side = %i", hitseg, hitwall); if (weapon->id < 4) subtract_light(hitseg, hitwall); else if (weapon->id == FLARE_ID) add_light(hitseg, hitwall); } //@@#ifdef EDITOR //@@Cursegp = &Segments[hitseg]; //@@Curside = hitwall; //@@#endif #endif if ((weapon->mtype.phys_info.velocity.x == 0) && (weapon->mtype.phys_info.velocity.y == 0) && (weapon->mtype.phys_info.velocity.z == 0)) { Int3(); // Contact Matt: This is impossible. A weapon with 0 velocity hit a wall, which doesn't move. return; } blew_up = check_effect_blowup(seg,hitwall,hitpt, weapon, 0); //if ((seg->sides[hitwall].tmap_num2==0) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE)) { if ((weapon->ctype.laser_info.parent_type == OBJ_ROBOT) && (Robot_info[Objects[weapon->ctype.laser_info.parent_num].id].companion==1)) { robot_escort = 1; if (Game_mode & GM_MULTI) { Int3(); // Get Jason! return; } playernum = Player_num; //if single player, he's the player's buddy } else { robot_escort = 0; if (Objects[weapon->ctype.laser_info.parent_num].type == OBJ_PLAYER) playernum = Objects[weapon->ctype.laser_info.parent_num].id; else playernum = -1; //not a player (thus a robot) } if (blew_up) { //could be a wall switch //for wall triggers, always say that the player shot it out. This is //because robots can shoot out wall triggers, and so the trigger better //take effect // NO -- Changed by MK, 10/18/95. We don't want robots blowing puzzles. Only player or buddy can open! check_trigger(seg,hitwall,weapon->ctype.laser_info.parent_num,1); } if (weapon->id == EARTHSHAKER_ID) smega_rock_stuff(); wall_type = wall_hit_process( seg, hitwall, weapon->shields, playernum, weapon ); // Wall is volatile if either tmap 1 or 2 is volatile if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_VOLATILE))) { weapon_info *wi = &Weapon_info[weapon->id]; int vclip; //we've hit a volatile wall digi_link_sound_to_pos( SOUND_VOLATILE_WALL_HIT,hitseg, 0, hitpt, 0, F1_0 ); //for most weapons, use volatile wall hit. For mega, use its special vclip vclip = (weapon->id == MEGA_ID)?Weapon_info[weapon->id].robot_hit_vclip:VCLIP_VOLATILE_WALL_HIT; // New by MK: If powerful badass, explode as badass, not due to lava, fixes megas being wimpy in lava. if (wi->damage_radius >= VOLATILE_WALL_DAMAGE_RADIUS/2) { explode_badass_weapon(weapon,hitpt); } else { object_create_badass_explosion( weapon, hitseg, hitpt, wi->impact_size + VOLATILE_WALL_IMPACT_SIZE, vclip, wi->strength[Difficulty_level]/4+VOLATILE_WALL_EXPL_STRENGTH, // diminished by mk on 12/08/94, i was doing 70 damage hitting lava on lvl 1. wi->damage_radius+VOLATILE_WALL_DAMAGE_RADIUS, wi->strength[Difficulty_level]/2+VOLATILE_WALL_DAMAGE_FORCE, weapon->ctype.laser_info.parent_num ); } weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in lava } else if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_WATER) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_WATER))) { weapon_info *wi = &Weapon_info[weapon->id]; //we've hit water // MK: 09/13/95: Badass in water is 1/2 normal intensity. if ( Weapon_info[weapon->id].matter ) { digi_link_sound_to_pos( SOUND_MISSILE_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 ); if ( Weapon_info[weapon->id].damage_radius ) { digi_link_sound_to_object(SOUND_BADASS_EXPLOSION, weapon-Objects, 0, F1_0); // MK: 09/13/95: Badass in water is 1/2 normal intensity. object_create_badass_explosion( weapon, hitseg, hitpt, wi->impact_size/2, wi->robot_hit_vclip, wi->strength[Difficulty_level]/4, wi->damage_radius, wi->strength[Difficulty_level]/2, weapon->ctype.laser_info.parent_num ); } else object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip ); } else { digi_link_sound_to_pos( SOUND_LASER_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 ); object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, VCLIP_WATER_HIT ); } weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in water } else { if (weapon->mtype.phys_info.flags & PF_BOUNCE) { //do special bound sound & effect } else { //if it's not the player's weapon, or it is the player's and there //is no wall, and no blowing up monitor, then play sound if ((weapon->ctype.laser_info.parent_type != OBJ_PLAYER) || ((seg->sides[hitwall].wall_num == -1 || wall_type==WHP_NOT_SPECIAL) && !blew_up)) if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT))) digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound,weapon->segnum, 0, &weapon->pos, 0, F1_0 ); if ( Weapon_info[weapon->id].wall_hit_vclip > -1 ) { if ( Weapon_info[weapon->id].damage_radius ) explode_badass_weapon(weapon,hitpt); else object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip ); } } } // If weapon fired by player or companion... if (( weapon->ctype.laser_info.parent_type== OBJ_PLAYER ) || robot_escort) { if (!(weapon->flags & OF_SILENT) && (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum)) create_awareness_event(weapon, PA_WEAPON_WALL_COLLISION); // object "weapon" can attract attention to player // if (weapon->id != FLARE_ID) { // We now allow flares to open doors. { if (((weapon->id != FLARE_ID) || (weapon->ctype.laser_info.parent_type != OBJ_PLAYER)) && !(weapon->mtype.phys_info.flags & PF_BOUNCE)) weapon->flags |= OF_SHOULD_BE_DEAD; //don't let flares stick in force fields if ((weapon->id == FLARE_ID) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD)) weapon->flags |= OF_SHOULD_BE_DEAD; if (!(weapon->flags & OF_SILENT)) { switch (wall_type) { case WHP_NOT_SPECIAL: //should be handled above //digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); break; case WHP_NO_KEY: //play special hit door sound (if/when we get it) digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound( SOUND_WEAPON_HIT_DOOR, F1_0 ); #endif break; case WHP_BLASTABLE: //play special blastable wall sound (if/when we get it) if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT))) digi_link_sound_to_pos( SOUND_WEAPON_HIT_BLASTABLE, weapon->segnum, 0, &weapon->pos, 0, F1_0 ); break; case WHP_DOOR: //don't play anything, since door open sound will play break; } } // else } // else { // if (weapon->lifeleft <= 0) // weapon->flags |= OF_SHOULD_BE_DEAD; // } } else { // This is a robot's laser if (!(weapon->mtype.phys_info.flags & PF_BOUNCE)) weapon->flags |= OF_SHOULD_BE_DEAD; } return; } //##void collide_camera_and_wall( object * camera, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { //## return; //##} //##void collide_powerup_and_wall( object * powerup, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { //## return; //##} void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) { if (!PERSISTENT_DEBRIS || TmapInfo[Segments[hitseg].sides[hitwall].tmap_num].damage) explode_object(debris,0); return; } //##void collide_fireball_and_fireball( object * fireball1, object * fireball2, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_robot( object * fireball, object * robot, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_hostage( object * fireball, object * hostage, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_player( object * fireball, object * player, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_weapon( object * fireball, object * weapon, vms_vector *collision_point ) { //## //weapon->flags |= OF_SHOULD_BE_DEAD; //## return; //##} //##void collide_fireball_and_camera( object * fireball, object * camera, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_powerup( object * fireball, object * powerup, vms_vector *collision_point ) { //## return; //##} //##void collide_fireball_and_debris( object * fireball, object * debris, vms_vector *collision_point ) { //## return; //##} // ------------------------------------------------------------------------------------------------------------------- void collide_robot_and_robot( object * robot1, object * robot2, vms_vector *collision_point ) { bump_two_objects(robot1, robot2, 1); return; } void collide_robot_and_controlcen( object * obj1, object * obj2, vms_vector *collision_point ) { if (obj1->type == OBJ_ROBOT) { vms_vector hitvec; vm_vec_normalize(vm_vec_sub(&hitvec, &obj2->pos, &obj1->pos)); bump_one_object(obj1, &hitvec, 0); } else { vms_vector hitvec; vm_vec_normalize(vm_vec_sub(&hitvec, &obj1->pos, &obj2->pos)); bump_one_object(obj2, &hitvec, 0); } } //##void collide_robot_and_hostage( object * robot, object * hostage, vms_vector *collision_point ) { //## return; //##} fix64 Last_thief_hit_time; void collide_robot_and_player( object * robot, object * playerobj, vms_vector *collision_point ) { int steal_attempt = 0; if (robot->flags&OF_EXPLODING) return; if (playerobj->id == Player_num) { if (Robot_info[robot->id].companion) // Player and companion don't collide. return; if (Robot_info[robot->id].kamikaze) { apply_damage_to_robot(robot, robot->shields+1, playerobj-Objects); if (playerobj == ConsoleObject) add_points_to_score(Robot_info[robot->id].score_value); } if (Robot_info[robot->id].thief) { if (Ai_local_info[robot-Objects].mode == AIM_THIEF_ATTACK) { Last_thief_hit_time = GameTime64; attempt_to_steal_item(robot, playerobj->id); steal_attempt = 1; } else if (GameTime64 - Last_thief_hit_time < F1_0*2) return; // ZOUNDS! BRILLIANT! Thief not collide with player if not stealing! // NO! VERY DUMB! makes thief look very stupid if player hits him while cloaked! -AP else Last_thief_hit_time = GameTime64; } create_awareness_event(playerobj, PA_PLAYER_COLLISION); // object robot can attract attention to player do_ai_robot_hit_attack(robot, playerobj, collision_point); do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION); } #ifdef NETWORK else { multi_robot_request_change(robot, playerobj->id); return; // only controlling player should make damage otherwise we might juggle robot back and forth, killing it instantly } #endif if (check_collision_delayfunc_exec()) { int collision_seg = find_point_seg(collision_point, playerobj->segnum);; // added this if to remove the bump sound if it's the thief. // A "steal" sound was added and it was getting obscured by the bump. -AP 10/3/95 // Changed by MK to make this sound unless the robot stole. if ((!steal_attempt) && !Robot_info[robot->id].energy_drain) digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); if (collision_seg != -1) object_create_explosion( collision_seg, collision_point, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip ); } bump_two_objects(robot, playerobj, 1); return; } // Provide a way for network message to instantly destroy the control center // without awarding points or anything. // if controlcen == NULL, that means don't do the explosion because the control center // was actually in another object. void net_destroy_controlcen(object *controlcen) { if (Control_center_destroyed != 1) { do_controlcen_destroyed_stuff(controlcen); if ((controlcen != NULL) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED))) { digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 ); explode_object(controlcen,0); } } } // ----------------------------------------------------------------------------- void apply_damage_to_controlcen(object *controlcen, fix damage, short who) { int whotype; // Only allow a player to damage the control center. if ((who < 0) || (who > Highest_object_index)) return; whotype = Objects[who].type; if (whotype != OBJ_PLAYER) { return; } #ifdef NETWORK if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && ((i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level) < Netgame.control_invul_time)) { if (Objects[who].id == Player_num) { int secs = f2i(Netgame.control_invul_time-(i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level)) % 60; int mins = f2i(Netgame.control_invul_time-(i2f(Players[Player_num].hours_level*3600)+Players[Player_num].time_level)) / 60; HUD_init_message(HM_DEFAULT, "%s %d:%02d.", TXT_CNTRLCEN_INVUL, mins, secs); } return; } #endif if (Objects[who].id == Player_num) { Control_center_been_hit = 1; ai_do_cloak_stuff(); } if ( controlcen->shields >= 0 ) controlcen->shields -= damage; if ( (controlcen->shields < 0) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED)) ) { do_controlcen_destroyed_stuff(controlcen); #ifdef NETWORK if (Game_mode & GM_MULTI) { if (who == Players[Player_num].objnum) add_points_to_score(CONTROL_CEN_SCORE); multi_send_destroy_controlcen((ushort)(controlcen-Objects), Objects[who].id ); } #endif if (!(Game_mode & GM_MULTI)) add_points_to_score(CONTROL_CEN_SCORE); digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 ); explode_object(controlcen,0); } } void collide_player_and_controlcen( object * controlcen, object * playerobj, vms_vector *collision_point ) { if (playerobj->id == Player_num) { Control_center_been_hit = 1; ai_do_cloak_stuff(); // In case player cloaked, make control center know where he is. } if (check_collision_delayfunc_exec()) digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); bump_two_objects(controlcen, playerobj, 1); return; } void collide_player_and_marker( object * marker, object * playerobj, vms_vector *collision_point ) { if (playerobj->id==Player_num) { int drawn; if (Game_mode & GM_MULTI) { drawn = HUD_init_message(HM_DEFAULT|HM_MAYDUPL, "MARKER %s: %s",Players[marker->id/2].callsign,MarkerMessage[marker->id]); } else { if (MarkerMessage[marker->id][0]) drawn = HUD_init_message(HM_DEFAULT|HM_MAYDUPL, "MARKER %d: %s", marker->id+1,MarkerMessage[marker->id]); else drawn = HUD_init_message(HM_DEFAULT|HM_MAYDUPL, "MARKER %d", marker->id+1); } if (drawn) digi_play_sample( SOUND_MARKER_HIT, F1_0 ); detect_escort_goal_accomplished(marker-Objects); } } // If a persistent weapon and other object is not a weapon, weaken it, else kill it. // If both objects are weapons, weaken the weapon. void maybe_kill_weapon(object *weapon, object *other_obj) { if (is_proximity_bomb_or_smart_mine_or_placed_mine(weapon->id)) { weapon->flags |= OF_SHOULD_BE_DEAD; return; } // Changed, 10/12/95, MK: Make weapon-weapon collisions always kill both weapons if not persistent. // Reason: Otherwise you can't use proxbombs to detonate incoming homing missiles (or mega missiles). if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { // Weapons do a lot of damage to weapons, other objects do much less. if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) { if (other_obj->type == OBJ_WEAPON) weapon->shields -= other_obj->shields/2; else weapon->shields -= other_obj->shields/4; if (weapon->shields <= 0) { weapon->shields = 0; weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1; } } } else weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1; // -- if ((weapon->mtype.phys_info.flags & PF_PERSISTENT) || (other_obj->type == OBJ_WEAPON)) { // -- // Weapons do a lot of damage to weapons, other objects do much less. // -- if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) { // -- if (other_obj->type == OBJ_WEAPON) // -- weapon->shields -= other_obj->shields/2; // -- else // -- weapon->shields -= other_obj->shields/4; // -- // -- if (weapon->shields <= 0) { // -- weapon->shields = 0; // -- weapon->flags |= OF_SHOULD_BE_DEAD; // -- } // -- } // -- } else // -- weapon->flags |= OF_SHOULD_BE_DEAD; } void collide_weapon_and_controlcen( object * weapon, object *controlcen, vms_vector *collision_point ) { if (weapon->id == OMEGA_ID) if (!ok_to_do_omega_damage(weapon)) // see comment in laser.c return; if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) { fix damage = weapon->shields; /* * Check if persistent weapon already hit this object. If yes, abort. * If no, add this object to hitobj_list and do it's damage. */ if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { damage = weapon->shields*2; // to not alter Gameplay too much, multiply damage by 2. if (!weapon->ctype.laser_info.hitobj_list[controlcen-Objects]) { weapon->ctype.laser_info.hitobj_list[controlcen-Objects] = 1; weapon->ctype.laser_info.last_hitobj = controlcen-Objects; } else { return; } } if (Objects[weapon->ctype.laser_info.parent_num].id == Player_num) Control_center_been_hit = 1; if ( Weapon_info[weapon->id].damage_radius ) explode_badass_weapon(weapon,collision_point); else object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION ); digi_link_sound_to_pos( SOUND_CONTROL_CENTER_HIT, controlcen->segnum, 0, collision_point, 0, F1_0 ); damage = fixmul(damage, weapon->ctype.laser_info.multiplier); apply_damage_to_controlcen(controlcen, damage, weapon->ctype.laser_info.parent_num); maybe_kill_weapon(weapon,controlcen); } else { // If robot weapon hits control center, blow it up, make it go away, but do no damage to control center. object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION ); maybe_kill_weapon(weapon,controlcen); } } void collide_weapon_and_clutter( object * weapon, object *clutter, vms_vector *collision_point ) { short exp_vclip = VCLIP_SMALL_EXPLOSION; if ( clutter->shields >= 0 ) clutter->shields -= weapon->shields; digi_link_sound_to_pos( SOUND_LASER_HIT_CLUTTER, weapon->segnum, 0, collision_point, 0, F1_0 ); object_create_explosion( clutter->segnum, collision_point, ((clutter->size/3)*3)/4, exp_vclip ); if ( (clutter->shields < 0) && !(clutter->flags&(OF_EXPLODING|OF_DESTROYED))) explode_object(clutter,STANDARD_EXPL_DELAY); maybe_kill_weapon(weapon,clutter); } //--mk, 121094 -- extern void spin_robot(object *robot, vms_vector *collision_point); extern object *explode_badass_object(object *objp, fix damage, fix distance, fix force); int Final_boss_is_dead = 0; fix Final_boss_countdown_time = 0; // ------------------------------------------------------------------------------------------------------ void do_final_boss_frame(void) { if (!Final_boss_is_dead) return; if (!Control_center_destroyed) return; if (Final_boss_countdown_time == 0) Final_boss_countdown_time = F1_0*2; Final_boss_countdown_time -= FrameTime; if (Final_boss_countdown_time > 0) return; start_endlevel_sequence(); //pretend we hit the exit trigger } // ------------------------------------------------------------------------------------------------------ // This is all the ugly stuff we do when you kill the final boss so that you don't die or something // which would ruin the logic of the cut sequence. void do_final_boss_hacks(void) { if (Player_is_dead) { Int3(); // Uh-oh, player is dead. Try to rescue him. Player_is_dead = 0; } if (Players[Player_num].shields <= 0) Players[Player_num].shields = 1; // If you're not invulnerable, get invulnerable! if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) { Players[Player_num].invulnerable_time = GameTime64; Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE; } if (!(Game_mode & GM_MULTI)) buddy_message("Nice job, %s!", Players[Player_num].callsign); Final_boss_is_dead = 1; } extern int multi_all_players_alive(); void multi_send_finish_game (); // ------------------------------------------------------------------------------------------------------ // Return 1 if robot died, else return 0 int apply_damage_to_robot(object *robot, fix damage, int killer_objnum) { #ifdef NETWORK char isthief; char i,temp_stolen[MAX_STOLEN_ITEMS]; #endif if ( robot->flags&OF_EXPLODING) return 0; if (robot->shields < 0 ) return 0; //robot already dead... if (Robot_info[robot->id].boss_flag) Boss_hit_time = GameTime64; // Buddy invulnerable on level 24 so he can give you his important messages. Bah. // Also invulnerable if his cheat for firing weapons is in effect. if (Robot_info[robot->id].companion) { #ifdef NETWORK if (PLAYING_BUILTIN_MISSION && Current_level_num == Last_level) return 0; #endif } // if (robot->control_type == CT_REMOTE) // return 0; // Can't damange a robot controlled by another player // -- MK, 10/21/95, unused! -- if (Robot_info[robot->id].boss_flag) // Boss_been_hit = 1; robot->shields -= damage; // Do unspeakable hacks to make sure player doesn't die after killing boss. Or before, sort of. if (Robot_info[robot->id].boss_flag) if (PLAYING_BUILTIN_MISSION && Current_level_num == Last_level) if (robot->shields < 0) { #ifdef NETWORK if (Game_mode & GM_MULTI) { if (!multi_all_players_alive()) // everyones gotta be alive robot->shields=1; else { multi_send_finish_game(); do_final_boss_hacks(); } } else #endif { // NOTE LINK TO ABOVE!!! if ((Players[Player_num].shields < 0) || Player_is_dead) robot->shields = 1; // Sorry, we can't allow you to kill the final boss after you've died. Rough luck. else do_final_boss_hacks(); } } if (robot->shields < 0) { #ifdef NETWORK if (Game_mode & GM_MULTI) { if (Robot_info[robot->id].thief) isthief=1; else isthief=0; if (isthief) for (i=0;iid].thief)) { if (isthief) for (i=0;iid].thief); if (isthief) for (i=0;iid].boss_flag) { start_boss_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL); } else if (Robot_info[robot->id].death_roll) { start_robot_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL); } else { if (robot->id == SPECIAL_REACTOR_ROBOT) special_reactor_stuff(); //if (Robot_info[robot->id].smart_blobs) // create_smart_children(robot, Robot_info[robot->id].smart_blobs); //if (Robot_info[robot->id].badass) // explode_badass_object(robot, F1_0*Robot_info[robot->id].badass, F1_0*40, F1_0*150); if (Robot_info[robot->id].kamikaze) explode_object(robot,1); // Kamikaze, explode right away, IN YOUR FACE! else explode_object(robot,STANDARD_EXPL_DELAY); } return 1; } else return 0; } extern int boss_spew_robot(object *objp, vms_vector *pos); //--ubyte Boss_teleports[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can teleport //--ubyte Boss_cloaks[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can cloak //--ubyte Boss_spews_bots_energy[NUM_D2_BOSSES] = {1,1,0,0,1,1}; // Set byte if boss spews bots when hit by energy weapon. //--ubyte Boss_spews_bots_matter[NUM_D2_BOSSES] = {0,0,1,0,1,1}; // Set byte if boss spews bots when hit by matter weapon. //--ubyte Boss_invulnerable_energy[NUM_D2_BOSSES] = {0,0,1,1,0,0}; // Set byte if boss is invulnerable to energy weapons. //--ubyte Boss_invulnerable_matter[NUM_D2_BOSSES] = {0,0,0,1,0,0}; // Set byte if boss is invulnerable to matter weapons. //--ubyte Boss_invulnerable_spot[NUM_D2_BOSSES] = {0,0,0,0,1,1}; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) //#define BOSS_INVULNERABLE_DOT 0 // If a boss is invulnerable over most of his body, fvec(dot)vec_to_collision must be less than this for damage to occur. int Boss_invulnerable_dot = 0; int Buddy_gave_hint_count = 5; fix64 Last_time_buddy_gave_hint = 0; // ------------------------------------------------------------------------------------------------------ // Return true if damage done to boss, else return false. int do_boss_weapon_collision(object *robot, object *weapon, vms_vector *collision_point) { int d2_boss_index; int damage_flag; damage_flag = 1; d2_boss_index = Robot_info[robot->id].boss_flag - BOSS_D2; Assert((d2_boss_index >= 0) && (d2_boss_index < NUM_D2_BOSSES)); // See if should spew a bot. if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) if ((Weapon_info[weapon->id].matter && Boss_spews_bots_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_spews_bots_energy[d2_boss_index])) { if (Boss_spew_more[d2_boss_index]) if (d_rand() > 16384) { if (boss_spew_robot(robot, collision_point) != -1) Last_gate_time = GameTime64 - Gate_interval - 1; // Force allowing spew of another bot. } boss_spew_robot(robot, collision_point); } if (Boss_invulnerable_spot[d2_boss_index]) { fix dot; vms_vector tvec1; // Boss only vulnerable in back. See if hit there. vm_vec_sub(&tvec1, collision_point, &robot->pos); vm_vec_normalize_quick(&tvec1); // Note, if BOSS_INVULNERABLE_DOT is close to F1_0 (in magnitude), then should probably use non-quick version. dot = vm_vec_dot(&tvec1, &robot->orient.fvec); if (dot > Boss_invulnerable_dot) { int new_obj; int segnum; segnum = find_point_seg(collision_point, robot->segnum); digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0); damage_flag = 0; if (Buddy_objnum != -1) { if (Last_time_buddy_gave_hint == 0) Last_time_buddy_gave_hint = d_rand()*32 + F1_0*16; if (Buddy_gave_hint_count) { if (Last_time_buddy_gave_hint + F1_0*20 < GameTime64) { int sval; Buddy_gave_hint_count--; Last_time_buddy_gave_hint = GameTime64; sval = (d_rand()*4) >> 15; switch (sval) { case 0: buddy_message("Hit him in the back!"); break; case 1: buddy_message("He's invulnerable there!"); break; case 2: buddy_message("Get behind him and fire!"); break; case 3: default: buddy_message("Hit the glowing spot!"); break; } } } } // Cause weapon to bounce. // Make a copy of this weapon, because the physics wants to destroy it. if (!Weapon_info[weapon->id].matter) { new_obj = obj_create(weapon->type, weapon->id, weapon->segnum, &weapon->pos, &weapon->orient, weapon->size, weapon->control_type, weapon->movement_type, weapon->render_type); if (new_obj != -1) { vms_vector vec_to_point; vms_vector weap_vec; fix speed; if (weapon->render_type == RT_POLYOBJ) { Objects[new_obj].rtype.pobj_info.model_num = Weapon_info[Objects[new_obj].id].model_num; Objects[new_obj].size = fixdiv(Polygon_models[Objects[new_obj].rtype.pobj_info.model_num].rad,Weapon_info[Objects[new_obj].id].po_len_to_width_ratio); } Objects[new_obj].mtype.phys_info.mass = Weapon_info[weapon->id].mass; Objects[new_obj].mtype.phys_info.drag = Weapon_info[weapon->id].drag; vm_vec_zero(&Objects[new_obj].mtype.phys_info.thrust); vm_vec_sub(&vec_to_point, collision_point, &robot->pos); vm_vec_normalize_quick(&vec_to_point); weap_vec = weapon->mtype.phys_info.velocity; speed = vm_vec_normalize_quick(&weap_vec); vm_vec_scale_add2(&vec_to_point, &weap_vec, -F1_0*2); vm_vec_scale(&vec_to_point, speed/4); Objects[new_obj].mtype.phys_info.velocity = vec_to_point; } } } } else if ((Weapon_info[weapon->id].matter && Boss_invulnerable_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_invulnerable_energy[d2_boss_index])) { int segnum; segnum = find_point_seg(collision_point, robot->segnum); digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0); damage_flag = 0; } return damage_flag; } // ------------------------------------------------------------------------------------------------------ void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *collision_point ) { int damage_flag=1; int boss_invul_flag=0; if (weapon->id == OMEGA_ID) if (!ok_to_do_omega_damage(weapon)) // see comment in laser.c return; if (Robot_info[robot->id].boss_flag) { Boss_hit_time = GameTime64; if (Robot_info[robot->id].boss_flag >= BOSS_D2) { damage_flag = do_boss_weapon_collision(robot, weapon, collision_point); boss_invul_flag = !damage_flag; } } // Put in at request of Jasen (and Adam) because the Buddy-Bot gets in their way. // MK has so much fun whacking his butt around the mine he never cared... if ((Robot_info[robot->id].companion) && ((weapon->ctype.laser_info.parent_type != OBJ_ROBOT) && !cheats.robotskillrobots)) return; if (weapon->id == EARTHSHAKER_ID) smega_rock_stuff(); #if 1 /* * Check if persistent weapon already hit this object. If yes, abort. * If no, add this object to hitobj_list and do it's damage. */ if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { if (!weapon->ctype.laser_info.hitobj_list[robot-Objects]) { weapon->ctype.laser_info.hitobj_list[robot-Objects] = 1; weapon->ctype.laser_info.last_hitobj = robot-Objects; } else { return; } } #else // If a persistent weapon hit robot most recently, quick abort, else we cream the same robot many times, // depending on frame rate. if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { if (weapon->ctype.laser_info.last_hitobj == robot-Objects) return; else weapon->ctype.laser_info.last_hitobj = robot-Objects; } #endif if (weapon->ctype.laser_info.parent_signature == robot->signature) return; // Changed, 10/04/95, put out blobs based on skill level and power of weapon doing damage. // Also, only a weapon hit from a player weapon causes smart blobs. if ((weapon->ctype.laser_info.parent_type == OBJ_PLAYER) && (Robot_info[robot->id].energy_blobs)) if ((robot->shields > 0) && Weapon_is_energy[weapon->id]) { fix probval; int num_blobs; probval = (Difficulty_level+2) * min(weapon->shields, robot->shields); probval = Robot_info[robot->id].energy_blobs * probval/(NDL*32); num_blobs = probval >> 16; if (2*d_rand() < (probval & 0xffff)) num_blobs++; if (num_blobs) create_smart_children(robot, num_blobs); } // Note: If weapon hits an invulnerable boss, it will still do badass damage, including to the boss, // unless this is trapped elsewhere. if ( Weapon_info[weapon->id].damage_radius ) { if (boss_invul_flag) { //don't make badass sound weapon_info *wi = &Weapon_info[weapon->id]; //this code copied from explode_badass_weapon() object_create_badass_explosion( weapon, weapon->segnum, collision_point, wi->impact_size, wi->robot_hit_vclip, wi->strength[Difficulty_level], wi->damage_radius,wi->strength[Difficulty_level], weapon->ctype.laser_info.parent_num ); } else //normal badass explosion explode_badass_weapon(weapon,collision_point); } if ( ((weapon->ctype.laser_info.parent_type==OBJ_PLAYER) || cheats.robotskillrobots) && !(robot->flags & OF_EXPLODING) ) { object *expl_obj=NULL; if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) { create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION); } #ifdef NETWORK else multi_robot_request_change(robot, Objects[weapon->ctype.laser_info.parent_num].id); #endif if ( Robot_info[robot->id].exp1_vclip_num > -1 ) expl_obj = object_create_explosion( weapon->segnum, collision_point, (robot->size/2*3)/4, Robot_info[robot->id].exp1_vclip_num ); else if ( Weapon_info[weapon->id].robot_hit_vclip > -1 ) expl_obj = object_create_explosion( weapon->segnum, collision_point, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].robot_hit_vclip ); if (expl_obj) obj_attach(robot,expl_obj); if ( damage_flag && (Robot_info[robot->id].exp1_sound_num > -1 )) digi_link_sound_to_pos( Robot_info[robot->id].exp1_sound_num, robot->segnum, 0, collision_point, 0, F1_0 ); if (!(weapon->flags & OF_HARMLESS)) { fix damage = weapon->shields; if (damage_flag) damage = fixmul(damage, weapon->ctype.laser_info.multiplier); else damage = 0; // Cut Gauss damage on bosses because it just breaks the game. Bosses are so easy to // hit, and missing a robot is what prevents the Gauss from being game-breaking. if (weapon->id == GAUSS_ID) if (Robot_info[robot->id].boss_flag) damage = damage * (2*NDL-Difficulty_level)/(2*NDL); if (! apply_damage_to_robot(robot, damage, weapon->ctype.laser_info.parent_num)) bump_two_objects(robot, weapon, 0); //only bump if not dead. no damage from bump else if (weapon->ctype.laser_info.parent_signature == ConsoleObject->signature) { add_points_to_score(Robot_info[robot->id].score_value); detect_escort_goal_accomplished(robot-Objects); } } // If Gauss Cannon, spin robot. if ((robot != NULL) && (!Robot_info[robot->id].companion) && (!Robot_info[robot->id].boss_flag) && (weapon->id == GAUSS_ID)) { ai_static *aip = &robot->ctype.ai_info; if (aip->SKIP_AI_COUNT * FrameTime < F1_0) { aip->SKIP_AI_COUNT++; robot->mtype.phys_info.rotthrust.x = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); robot->mtype.phys_info.rotthrust.y = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); robot->mtype.phys_info.rotthrust.z = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT); robot->mtype.phys_info.flags |= PF_USES_THRUST; } } } maybe_kill_weapon(weapon,robot); return; } //##void collide_robot_and_camera( object * robot, object * camera, vms_vector *collision_point ) { //## return; //##} //##void collide_robot_and_powerup( object * robot, object * powerup, vms_vector *collision_point ) { //## return; //##} //##void collide_robot_and_debris( object * robot, object * debris, vms_vector *collision_point ) { //## return; //##} //##void collide_hostage_and_hostage( object * hostage1, object * hostage2, vms_vector *collision_point ) { //## return; //##} void collide_hostage_and_player( object * hostage, object * player, vms_vector *collision_point ) { // Give player points, etc. if ( player == ConsoleObject ) { detect_escort_goal_accomplished(hostage-Objects); add_points_to_score(HOSTAGE_SCORE); // Do effect hostage_rescue(hostage->id); // Remove the hostage object. hostage->flags |= OF_SHOULD_BE_DEAD; #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_remobj(hostage-Objects); #endif } return; } //--unused-- void collide_hostage_and_weapon( object * hostage, object * weapon, vms_vector *collision_point ) //--unused-- { //--unused-- // Cannot kill hostages, as per Matt's edict! //--unused-- // (A fine edict, but in contradiction to the milestone: "Robots attack hostages.") //--unused-- hostage->shields -= weapon->shields/2; //--unused-- //--unused-- create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player //--unused-- //--unused-- //PLAY_SOUND_3D( SOUND_HOSTAGE_KILLED, collision_point, hostage->segnum ); //--unused-- digi_link_sound_to_pos( SOUND_HOSTAGE_KILLED, hostage->segnum , 0, collision_point, 0, F1_0 ); //--unused-- //--unused-- //--unused-- if (hostage->shields <= 0) { //--unused-- explode_object(hostage,0); //--unused-- hostage->flags |= OF_SHOULD_BE_DEAD; //--unused-- } //--unused-- //--unused-- if ( Weapon_info[weapon->id].damage_radius ) //--unused-- explode_badass_weapon(weapon); //--unused-- //--unused-- maybe_kill_weapon(weapon,hostage); //--unused-- //--unused-- } //##void collide_hostage_and_camera( object * hostage, object * camera, vms_vector *collision_point ) { //## return; //##} //##void collide_hostage_and_powerup( object * hostage, object * powerup, vms_vector *collision_point ) { //## return; //##} //##void collide_hostage_and_debris( object * hostage, object * debris, vms_vector *collision_point ) { //## return; //##} void collide_player_and_player( object * player1, object * player2, vms_vector *collision_point ) { static fix64 last_player_bump[MAX_PLAYERS] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int damage_flag = 1, otherpl = -1; if (check_collision_delayfunc_exec()) digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player1->segnum, 0, collision_point, 0, F1_0 ); // Multi is special - as always. Clients do the bump damage locally but the remote players do their collision result (change velocity) on their own. So after our initial collision, ignore further collision damage till remote players (hopefully) react. if (Game_mode & GM_MULTI) { damage_flag = 0; if (!(player1->id == Player_num || player2->id == Player_num)) return; if (player1->id > MAX_PLAYERS || player2->id > MAX_PLAYERS) return; otherpl = (player1->id==Player_num)?player2->id:player1->id; if (last_player_bump[otherpl] + (F1_0/Netgame.PacketsPerSec) < GameTime64 || last_player_bump[otherpl] > GameTime64) { last_player_bump[otherpl] = GameTime64; damage_flag = 1; } } bump_two_objects(player1, player2, damage_flag); return; } int maybe_drop_primary_weapon_egg(object *playerobj, int weapon_index) { int weapon_flag = HAS_FLAG(weapon_index); int powerup_num; powerup_num = Primary_weapon_to_powerup[weapon_index]; if (Players[playerobj->id].primary_weapon_flags & weapon_flag) return call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num); else return -1; } void maybe_drop_secondary_weapon_egg(object *playerobj, int weapon_index, int count) { int weapon_flag = HAS_FLAG(weapon_index); int powerup_num; powerup_num = Secondary_weapon_to_powerup[weapon_index]; if (Players[playerobj->id].secondary_weapon_flags & weapon_flag) { int i, max_count; max_count = min(count, 3); for (i=0; iid].secondary_ammo[missile_index]; powerup_id = Secondary_weapon_to_powerup[missile_index]; if (num_missiles > 10) num_missiles = 10; call_object_create_egg(playerobj, num_missiles/4, OBJ_POWERUP, powerup_id+1); call_object_create_egg(playerobj, num_missiles%4, OBJ_POWERUP, powerup_id); } // -- int Items_destroyed = 0; void drop_player_eggs(object *playerobj) { if ((playerobj->type == OBJ_PLAYER) || (playerobj->type == OBJ_GHOST)) { int rthresh; int pnum = playerobj->id; int objnum; int vulcan_ammo=0; vms_vector randvec; // -- Items_destroyed = 0; // Seed the random number generator so in net play the eggs will always // drop the same way #ifdef NETWORK if (Game_mode & GM_MULTI) { Net_create_loc = 0; d_srand(5483L); } #endif // If the player had smart mines, maybe arm one of them. rthresh = 30000; while ((Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX]%4==1) && (d_rand() < rthresh)) { int newseg; vms_vector tvec; make_random_vector(&randvec); rthresh /= 2; vm_vec_add(&tvec, &playerobj->pos, &randvec); newseg = find_point_seg(&tvec, playerobj->segnum); if (newseg != -1) Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, SUPERPROX_ID, 0); } // If the player had proximity bombs, maybe arm one of them. if ((Game_mode & GM_MULTI) && !(Game_mode & GM_HOARD)) { rthresh = 30000; while ((Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX]%4==1) && (d_rand() < rthresh)) { int newseg; vms_vector tvec; make_random_vector(&randvec); rthresh /= 2; vm_vec_add(&tvec, &playerobj->pos, &randvec); newseg = find_point_seg(&tvec, playerobj->segnum); if (newseg != -1) Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, PROXIMITY_ID, 0); } } // If the player dies and he has powerful lasers, create the powerups here. if (Players[pnum].laser_level > MAX_LASER_LEVEL) call_object_create_egg(playerobj, Players[pnum].laser_level-MAX_LASER_LEVEL, OBJ_POWERUP, POW_SUPER_LASER); else if (Players[pnum].laser_level >= 1) call_object_create_egg(playerobj, Players[pnum].laser_level, OBJ_POWERUP, POW_LASER); // Note: laser_level = 0 for laser level 1. // Drop quad laser if appropos if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_QUAD_FIRE); if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CLOAK); if (Players[pnum].flags & PLAYER_FLAGS_MAP_ALL) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FULL_MAP); if (Players[pnum].flags & PLAYER_FLAGS_AFTERBURNER) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AFTERBURNER); if (Players[pnum].flags & PLAYER_FLAGS_AMMO_RACK) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AMMO_RACK); if (Players[pnum].flags & PLAYER_FLAGS_CONVERTER) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CONVERTER); if (Players[pnum].flags & PLAYER_FLAGS_HEADLIGHT) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_HEADLIGHT); // drop the other enemies flag if you have it #ifdef NETWORK if ((Game_mode & GM_CAPTURE) && (Players[pnum].flags & PLAYER_FLAGS_FLAG)) { if ((get_team (pnum)==TEAM_RED)) call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_BLUE); else call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_RED); } if (Game_mode & GM_HOARD) { // Drop hoard orbs int max_count,i; max_count = min(Players[pnum].secondary_ammo[PROXIMITY_INDEX], 12); for (i=0; iid==Player_num)?Omega_charge:MAX_OMEGA_CHARGE; // Drop the secondary weapons // Note, proximity weapon only comes in packets of 4. So drop n/2, but a max of 3 (handled inside maybe_drop..) Make sense? if (!(Game_mode & GM_HOARD)) maybe_drop_secondary_weapon_egg(playerobj, PROXIMITY_INDEX, (Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX])/4); maybe_drop_secondary_weapon_egg(playerobj, SMART_INDEX, Players[playerobj->id].secondary_ammo[SMART_INDEX]); maybe_drop_secondary_weapon_egg(playerobj, MEGA_INDEX, Players[playerobj->id].secondary_ammo[MEGA_INDEX]); maybe_drop_secondary_weapon_egg(playerobj, SMART_MINE_INDEX,(Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX])/4); maybe_drop_secondary_weapon_egg(playerobj, SMISSILE5_INDEX, Players[playerobj->id].secondary_ammo[SMISSILE5_INDEX]); // Drop the player's missiles in packs of 1 and/or 4 drop_missile_1_or_4(playerobj,HOMING_INDEX); drop_missile_1_or_4(playerobj,GUIDED_INDEX); drop_missile_1_or_4(playerobj,CONCUSSION_INDEX); drop_missile_1_or_4(playerobj,SMISSILE1_INDEX); drop_missile_1_or_4(playerobj,SMISSILE4_INDEX); // If player has vulcan ammo, but no vulcan cannon, drop the ammo. if (!(Players[playerobj->id].primary_weapon_flags & HAS_VULCAN_FLAG)) { int amount = Players[playerobj->id].primary_ammo[VULCAN_INDEX]; if (amount > 200) { amount = 200; } while (amount > 0) { call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_VULCAN_AMMO); amount -= VULCAN_AMMO_AMOUNT; } } // Always drop a shield and energy powerup. if (Game_mode & GM_MULTI) { call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_SHIELD_BOOST); call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_ENERGY); } //-- // Drop all the keys. //-- if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) { //-- playerobj->contains_count = 1; //-- playerobj->contains_type = OBJ_POWERUP; //-- playerobj->contains_id = POW_KEY_BLUE; //-- object_create_egg(playerobj); //-- } //-- if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) { //-- playerobj->contains_count = 1; //-- playerobj->contains_type = OBJ_POWERUP; //-- playerobj->contains_id = POW_KEY_RED; //-- object_create_egg(playerobj); //-- } //-- if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) { //-- playerobj->contains_count = 1; //-- playerobj->contains_type = OBJ_POWERUP; //-- playerobj->contains_id = POW_KEY_GOLD; //-- object_create_egg(playerobj); //-- } // -- if (Items_destroyed) { // -- if (Items_destroyed == 1) // -- HUD_init_message(HM_DEFAULT, "%i item was destroyed.", Items_destroyed); // -- else // -- HUD_init_message(HM_DEFAULT, "%i items were destroyed.", Items_destroyed); // -- Items_destroyed = 0; // -- } } } // -- removed, 09/06/95, MK -- void destroy_primary_weapon(int weapon_index) // -- removed, 09/06/95, MK -- { // -- removed, 09/06/95, MK -- if (weapon_index == MAX_PRIMARY_WEAPONS) { // -- removed, 09/06/95, MK -- HUD_init_message(HM_DEFAULT, "Quad lasers destroyed!"); // -- removed, 09/06/95, MK -- Players[Player_num].flags &= ~PLAYER_FLAGS_QUAD_LASERS; // -- removed, 09/06/95, MK -- update_laser_weapon_info(); // -- removed, 09/06/95, MK -- } else if (weapon_index == 0) { // -- removed, 09/06/95, MK -- Assert(Players[Player_num].laser_level > 0); // -- removed, 09/06/95, MK -- HUD_init_message(HM_DEFAULT, "%s degraded!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger! // -- removed, 09/06/95, MK -- Players[Player_num].laser_level--; // -- removed, 09/06/95, MK -- update_laser_weapon_info(); // -- removed, 09/06/95, MK -- } else { // -- removed, 09/06/95, MK -- HUD_init_message(HM_DEFAULT, "%s destroyed!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger! // -- removed, 09/06/95, MK -- Players[Player_num].primary_weapon_flags &= ~(1 << weapon_index); // -- removed, 09/06/95, MK -- auto_select_weapon(0); // -- removed, 09/06/95, MK -- } // -- removed, 09/06/95, MK -- // -- removed, 09/06/95, MK -- } // -- removed, 09/06/95, MK -- // -- removed, 09/06/95, MK -- void destroy_secondary_weapon(int weapon_index) // -- removed, 09/06/95, MK -- { // -- removed, 09/06/95, MK -- if (Players[Player_num].secondary_ammo <= 0) // -- removed, 09/06/95, MK -- return; // -- removed, 09/06/95, MK -- // -- removed, 09/06/95, MK -- HUD_init_message(HM_DEFAULT, "%s destroyed!", Text_string[114+weapon_index]); // Danger! Danger! Use of literal! Danger! // -- removed, 09/06/95, MK -- if (--Players[Player_num].secondary_ammo[weapon_index] == 0) // -- removed, 09/06/95, MK -- auto_select_weapon(1); // -- removed, 09/06/95, MK -- // -- removed, 09/06/95, MK -- } // -- removed, 09/06/95, MK -- // -- removed, 09/06/95, MK -- #define LOSE_WEAPON_THRESHOLD (F1_0*30) extern fix64 Buddy_sorry_time; void apply_damage_to_player(object *playerobj, object *killer, fix damage, ubyte possibly_friendly) { if (Player_is_dead) return; if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) return; if (multi_maybe_disable_friendly_fire(killer) && possibly_friendly) return; if (Endlevel_sequence) return; //for the player, the 'real' shields are maintained in the Players[] //array. The shields value in the player's object are, I think, not //used anywhere. This routine, however, sets the objects shields to //be a mirror of the value in the Player structure. if (playerobj->id == Player_num) { //is this the local player? Players[Player_num].shields -= damage; PALETTE_FLASH_ADD(f2i(damage)*4,-f2i(damage/2),-f2i(damage/2)); //flash red if (Players[Player_num].shields < 0) { Players[Player_num].killer_objnum = killer-Objects; // if ( killer && (killer->type == OBJ_PLAYER)) // Players[Player_num].killer_objnum = killer-Objects; playerobj->flags |= OF_SHOULD_BE_DEAD; if (Buddy_objnum != -1) if (killer && (killer->type == OBJ_ROBOT) && (Robot_info[killer->id].companion)) Buddy_sorry_time = GameTime64; } playerobj->shields = Players[Player_num].shields; //mirror } } void collide_player_and_weapon( object * playerobj, object * weapon, vms_vector *collision_point ) { fix damage = weapon->shields; object * killer=NULL; if (weapon->id == OMEGA_ID) if (!ok_to_do_omega_damage(weapon)) // see comment in laser.c return; // Don't collide own smart mines unless direct hit. if (weapon->id == SUPERPROX_ID) if (playerobj-Objects == weapon->ctype.laser_info.parent_num) if (vm_vec_dist_quick(collision_point, &playerobj->pos) > playerobj->size) return; if (weapon->id == EARTHSHAKER_ID) smega_rock_stuff(); damage = fixmul(damage, weapon->ctype.laser_info.multiplier); #ifndef SHAREWARE if (Game_mode & GM_MULTI) damage = fixmul(damage, Weapon_info[weapon->id].multi_damage_scale); #endif #if 1 /* * Check if persistent weapon already hit this object. If yes, abort. * If no, add this object to hitobj_list and do it's damage. */ if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { if (!weapon->ctype.laser_info.hitobj_list[playerobj-Objects]) { weapon->ctype.laser_info.hitobj_list[playerobj-Objects] = 1; weapon->ctype.laser_info.last_hitobj = playerobj-Objects; } else { return; } } #else if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { if (weapon->ctype.laser_info.last_hitobj == playerobj-Objects) return; else weapon->ctype.laser_info.last_hitobj = playerobj-Objects; } #endif if (playerobj->id == Player_num) { if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) { digi_link_sound_to_pos( SOUND_PLAYER_GOT_HIT, playerobj->segnum, 0, collision_point, 0, F1_0 ); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(SOUND_PLAYER_GOT_HIT, F1_0); #endif } else { digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, playerobj->segnum, 0, collision_point, 0, F1_0); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_play_sound(SOUND_WEAPON_HIT_DOOR, F1_0); #endif } } object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT ); if ( Weapon_info[weapon->id].damage_radius ) explode_badass_weapon(weapon,collision_point); maybe_kill_weapon(weapon,playerobj); bump_two_objects(playerobj, weapon, 0); //no damage from bump if ( !Weapon_info[weapon->id].damage_radius ) { if ( weapon->ctype.laser_info.parent_num > -1 ) killer = &Objects[weapon->ctype.laser_info.parent_num]; // if (weapon->id == SMART_HOMING_ID) // damage /= 4; if (!(weapon->flags & OF_HARMLESS)) apply_damage_to_player( playerobj, killer, damage, 1); } // Robots become aware of you if you get hit. ai_do_cloak_stuff(); return; } // Nasty robots are the ones that attack you by running into you and doing lots of damage. void collide_player_and_nasty_robot( object * playerobj, object * robot, vms_vector *collision_point ) { // if (!(Robot_info[robot->id].energy_drain && Players[playerobj->id].energy)) digi_link_sound_to_pos( Robot_info[robot->id].claw_sound, playerobj->segnum, 0, collision_point, 0, F1_0 ); object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT ); bump_two_objects(playerobj, robot, 0); //no damage from bump apply_damage_to_player( playerobj, robot, F1_0*(Difficulty_level+1), 0); return; } void collide_player_and_materialization_center(object *objp) { int side; vms_vector exit_dir; segment *segp = &Segments[objp->segnum]; digi_link_sound_to_pos(SOUND_PLAYER_GOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0); // digi_play_sample( SOUND_PLAYER_GOT_HIT, F1_0 ); object_create_explosion( objp->segnum, &objp->pos, i2f(10)/2, VCLIP_PLAYER_HIT ); if (objp->id != Player_num) return; for (side=0; sidepos); vm_vec_normalize_quick(&exit_dir); make_random_vector(&rand_vec); rand_vec.x /= 4; rand_vec.y /= 4; rand_vec.z /= 4; vm_vec_add2(&exit_dir, &rand_vec); vm_vec_normalize_quick(&exit_dir); } bump_one_object(objp, &exit_dir, 64*F1_0); apply_damage_to_player( objp, objp, 4*F1_0, 0); // Changed, MK, 2/19/96, make killer the player, so if you die in matcen, will say you killed yourself return; } void collide_robot_and_materialization_center(object *objp) { int side; vms_vector exit_dir; segment *segp=&Segments[objp->segnum]; vm_vec_zero(&exit_dir); digi_link_sound_to_pos(SOUND_ROBOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0); if ( Robot_info[objp->id].exp1_vclip_num > -1 ) object_create_explosion( objp->segnum, &objp->pos, (objp->size/2*3)/4, Robot_info[objp->id].exp1_vclip_num ); for (side=0; sidepos); vm_vec_normalize_quick(&exit_dir); } bump_one_object(objp, &exit_dir, 8*F1_0); apply_damage_to_robot( objp, F1_0, -1); return; } //##void collide_player_and_camera( object * playerobj, object * camera, vms_vector *collision_point ) { //## return; //##} extern int Network_got_powerup; // HACK!!! void collide_player_and_powerup( object * playerobj, object * powerup, vms_vector *collision_point ) { if (!Endlevel_sequence && !Player_is_dead && (playerobj->id == Player_num )) { int powerup_used; powerup_used = do_powerup(powerup); if (powerup_used) { powerup->flags |= OF_SHOULD_BE_DEAD; #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_remobj(powerup-Objects); #endif } } #ifndef SHAREWARE else if ((Game_mode & GM_MULTI_COOP) && (playerobj->id != Player_num)) { switch (powerup->id) { case POW_KEY_BLUE: Players[playerobj->id].flags |= PLAYER_FLAGS_BLUE_KEY; break; case POW_KEY_RED: Players[playerobj->id].flags |= PLAYER_FLAGS_RED_KEY; break; case POW_KEY_GOLD: Players[playerobj->id].flags |= PLAYER_FLAGS_GOLD_KEY; break; default: break; } } #endif return; } //##void collide_player_and_debris( object * playerobj, object * debris, vms_vector *collision_point ) { //## return; //##} void collide_player_and_clutter( object * playerobj, object * clutter, vms_vector *collision_point ) { if (check_collision_delayfunc_exec()) digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 ); bump_two_objects(clutter, playerobj, 1); return; } // See if weapon1 creates a badass explosion. If so, create the explosion // Return true if weapon does proximity (as opposed to only contact) damage when it explodes. int maybe_detonate_weapon(object *weapon1, object *weapon2, vms_vector *collision_point) { if ( Weapon_info[weapon1->id].damage_radius ) { fix dist; dist = vm_vec_dist_quick(&weapon1->pos, &weapon2->pos); if (dist < F1_0*5) { maybe_kill_weapon(weapon1,weapon2); if (weapon1->flags & OF_SHOULD_BE_DEAD) { explode_badass_weapon(weapon1,collision_point); digi_link_sound_to_pos( Weapon_info[weapon1->id].robot_hit_sound, weapon1->segnum , 0, collision_point, 0, F1_0 ); } return 1; } else { weapon1->lifeleft = min(dist/64, F1_0); return 1; } } else return 0; } void collide_weapon_and_weapon( object * weapon1, object * weapon2, vms_vector *collision_point ) { // -- Does this look buggy??: if (weapon1->id == PMINE_ID && weapon1->id == PMINE_ID) if (weapon1->id == PMINE_ID && weapon2->id == PMINE_ID) return; //these can't blow each other up if (weapon1->id == OMEGA_ID) { if (!ok_to_do_omega_damage(weapon1)) // see comment in laser.c return; } else if (weapon2->id == OMEGA_ID) { if (!ok_to_do_omega_damage(weapon2)) // see comment in laser.c return; } if ((Weapon_info[weapon1->id].destroyable) || (Weapon_info[weapon2->id].destroyable)) { // shooting Plasma will make bombs explode one drops at the same time since hitboxes overlap. Small HACK to get around this issue. if the player moves away from the bomb at least... if ((GameTime64 < weapon1->ctype.laser_info.creation_time + (F1_0/5)) && (GameTime64 < weapon2->ctype.laser_info.creation_time + (F1_0/5)) && (weapon1->ctype.laser_info.parent_num == weapon2->ctype.laser_info.parent_num)) return; // Bug reported by Adam Q. Pletcher on September 9, 1994, smart bomb homing missiles were toasting each other. if ((weapon1->id == weapon2->id) && (weapon1->ctype.laser_info.parent_num == weapon2->ctype.laser_info.parent_num)) return; if (Weapon_info[weapon1->id].destroyable) if (maybe_detonate_weapon(weapon1, weapon2, collision_point)) maybe_detonate_weapon(weapon2,weapon1, collision_point); if (Weapon_info[weapon2->id].destroyable) if (maybe_detonate_weapon(weapon2, weapon1, collision_point)) maybe_detonate_weapon(weapon1,weapon2, collision_point); } } //##void collide_weapon_and_camera( object * weapon, object * camera, vms_vector *collision_point ) { //## return; //##} //##void collide_weapon_and_powerup( object * weapon, object * powerup, vms_vector *collision_point ) { //## return; //##} void collide_weapon_and_debris( object * weapon, object * debris, vms_vector *collision_point ) { // Hack! Prevent debris from causing bombs spewed at player death to detonate! if ((weapon->id == PROXIMITY_ID) || (weapon->id == SUPERPROX_ID)) { if (weapon->ctype.laser_info.creation_time + F1_0/2 > GameTime64) return; } if ( (weapon->ctype.laser_info.parent_type==OBJ_PLAYER) && !(debris->flags & OF_EXPLODING) ) { digi_link_sound_to_pos( SOUND_ROBOT_HIT, weapon->segnum , 0, collision_point, 0, F1_0 ); explode_object(debris,0); if ( Weapon_info[weapon->id].damage_radius ) explode_badass_weapon(weapon,collision_point); maybe_kill_weapon(weapon,debris); if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) weapon->flags |= OF_SHOULD_BE_DEAD; } return; } //##void collide_camera_and_camera( object * camera1, object * camera2, vms_vector *collision_point ) { //## return; //##} //##void collide_camera_and_powerup( object * camera, object * powerup, vms_vector *collision_point ) { //## return; //##} //##void collide_camera_and_debris( object * camera, object * debris, vms_vector *collision_point ) { //## return; //##} //##void collide_powerup_and_powerup( object * powerup1, object * powerup2, vms_vector *collision_point ) { //## return; //##} //##void collide_powerup_and_debris( object * powerup, object * debris, vms_vector *collision_point ) { //## return; //##} //##void collide_debris_and_debris( object * debris1, object * debris2, vms_vector *collision_point ) { //## return; //##} /* DPH: Put these macros on one long line to avoid CR/LF problems on linux */ #define COLLISION_OF(a,b) (((a)<<8) + (b)) #define DO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): (collision_function)( (A), (B), collision_point ); break; case COLLISION_OF( (type2), (type1) ): (collision_function)( (B), (A), collision_point ); break; #define DO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): (collision_function)( (A), (B), collision_point ); break; //these next two macros define a case that does nothing #define NO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): break; case COLLISION_OF( (type2), (type1) ): break; #define NO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): break; /* DPH: These ones are never used so I'm not going to bother */ #ifndef __GNUC__ #define IGNORE_COLLISION(type1,type2,collision_function) \ case COLLISION_OF( (type1), (type2) ): \ break; \ case COLLISION_OF( (type2), (type1) ): \ break; #define ERROR_COLLISION(type1,type2,collision_function) \ case COLLISION_OF( (type1), (type2) ): \ Error( "Error in collision type!" ); \ break; \ case COLLISION_OF( (type2), (type1) ): \ Error( "Error in collision type!" ); \ break; #endif void collide_two_objects( object * A, object * B, vms_vector *collision_point ) { int collision_type; collision_type = COLLISION_OF(A->type,B->type); switch( collision_type ) { NO_SAME_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL, collide_fireball_and_fireball ) DO_SAME_COLLISION( OBJ_ROBOT, OBJ_ROBOT, collide_robot_and_robot ) NO_SAME_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE, collide_hostage_and_hostage ) DO_SAME_COLLISION( OBJ_PLAYER, OBJ_PLAYER, collide_player_and_player ) DO_SAME_COLLISION( OBJ_WEAPON, OBJ_WEAPON, collide_weapon_and_weapon ) NO_SAME_COLLISION( OBJ_CAMERA, OBJ_CAMERA, collide_camera_and_camera ) NO_SAME_COLLISION( OBJ_POWERUP, OBJ_POWERUP, collide_powerup_and_powerup ) NO_SAME_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS, collide_debris_and_debris ) NO_SAME_COLLISION( OBJ_MARKER, OBJ_MARKER, NULL ) NO_COLLISION( OBJ_FIREBALL, OBJ_ROBOT, collide_fireball_and_robot ) NO_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE, collide_fireball_and_hostage ) NO_COLLISION( OBJ_FIREBALL, OBJ_PLAYER, collide_fireball_and_player ) NO_COLLISION( OBJ_FIREBALL, OBJ_WEAPON, collide_fireball_and_weapon ) NO_COLLISION( OBJ_FIREBALL, OBJ_CAMERA, collide_fireball_and_camera ) NO_COLLISION( OBJ_FIREBALL, OBJ_POWERUP, collide_fireball_and_powerup ) NO_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS, collide_fireball_and_debris ) NO_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE, collide_robot_and_hostage ) DO_COLLISION( OBJ_ROBOT, OBJ_PLAYER, collide_robot_and_player ) DO_COLLISION( OBJ_ROBOT, OBJ_WEAPON, collide_robot_and_weapon ) NO_COLLISION( OBJ_ROBOT, OBJ_CAMERA, collide_robot_and_camera ) NO_COLLISION( OBJ_ROBOT, OBJ_POWERUP, collide_robot_and_powerup ) NO_COLLISION( OBJ_ROBOT, OBJ_DEBRIS, collide_robot_and_debris ) DO_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER, collide_hostage_and_player ) NO_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON, collide_hostage_and_weapon ) NO_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA, collide_hostage_and_camera ) NO_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP, collide_hostage_and_powerup ) NO_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS, collide_hostage_and_debris ) DO_COLLISION( OBJ_PLAYER, OBJ_WEAPON, collide_player_and_weapon ) NO_COLLISION( OBJ_PLAYER, OBJ_CAMERA, collide_player_and_camera ) DO_COLLISION( OBJ_PLAYER, OBJ_POWERUP, collide_player_and_powerup ) NO_COLLISION( OBJ_PLAYER, OBJ_DEBRIS, collide_player_and_debris ) DO_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN, collide_player_and_controlcen ) DO_COLLISION( OBJ_PLAYER, OBJ_CLUTTER, collide_player_and_clutter ) NO_COLLISION( OBJ_WEAPON, OBJ_CAMERA, collide_weapon_and_camera ) NO_COLLISION( OBJ_WEAPON, OBJ_POWERUP, collide_weapon_and_powerup ) DO_COLLISION( OBJ_WEAPON, OBJ_DEBRIS, collide_weapon_and_debris ) NO_COLLISION( OBJ_CAMERA, OBJ_POWERUP, collide_camera_and_powerup ) NO_COLLISION( OBJ_CAMERA, OBJ_DEBRIS, collide_camera_and_debris ) NO_COLLISION( OBJ_POWERUP, OBJ_DEBRIS, collide_powerup_and_debris ) DO_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN, collide_weapon_and_controlcen ) DO_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN, collide_robot_and_controlcen ) DO_COLLISION( OBJ_WEAPON, OBJ_CLUTTER, collide_weapon_and_clutter ) DO_COLLISION( OBJ_MARKER, OBJ_PLAYER, collide_player_and_marker) NO_COLLISION( OBJ_MARKER, OBJ_ROBOT, NULL) NO_COLLISION( OBJ_MARKER, OBJ_HOSTAGE, NULL) NO_COLLISION( OBJ_MARKER, OBJ_WEAPON, NULL) NO_COLLISION( OBJ_MARKER, OBJ_CAMERA, NULL) NO_COLLISION( OBJ_MARKER, OBJ_POWERUP, NULL) NO_COLLISION( OBJ_MARKER, OBJ_DEBRIS, NULL) default: Int3(); //Error( "Unhandled collision_type in collide.c!\n" ); } } #define ENABLE_COLLISION(type1,type2) \ CollisionResult[type1][type2] = RESULT_CHECK; \ CollisionResult[type2][type1] = RESULT_CHECK; #define DISABLE_COLLISION(type1,type2) \ CollisionResult[type1][type2] = RESULT_NOTHING; \ CollisionResult[type2][type1] = RESULT_NOTHING; void collide_init() { int i, j; for (i=0; i < MAX_OBJECT_TYPES; i++ ) for (j=0; j < MAX_OBJECT_TYPES; j++ ) CollisionResult[i][j] = RESULT_NOTHING; ENABLE_COLLISION( OBJ_WALL, OBJ_ROBOT ); ENABLE_COLLISION( OBJ_WALL, OBJ_WEAPON ); ENABLE_COLLISION( OBJ_WALL, OBJ_PLAYER ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL ); ENABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT ); // DISABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT ); // ALERT: WARNING: HACK: MK = RESPONSIBLE! TESTING!! DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE ); ENABLE_COLLISION( OBJ_PLAYER, OBJ_PLAYER ); ENABLE_COLLISION( OBJ_WEAPON, OBJ_WEAPON ); DISABLE_COLLISION( OBJ_CAMERA, OBJ_CAMERA ); DISABLE_COLLISION( OBJ_POWERUP, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_ROBOT ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_PLAYER ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_WEAPON ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_CAMERA ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS ); DISABLE_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE ); ENABLE_COLLISION( OBJ_ROBOT, OBJ_PLAYER ); ENABLE_COLLISION( OBJ_ROBOT, OBJ_WEAPON ); DISABLE_COLLISION( OBJ_ROBOT, OBJ_CAMERA ); DISABLE_COLLISION( OBJ_ROBOT, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_ROBOT, OBJ_DEBRIS ); ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER ); ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON ); DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA ); DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS ); ENABLE_COLLISION( OBJ_PLAYER, OBJ_WEAPON ); DISABLE_COLLISION( OBJ_PLAYER, OBJ_CAMERA ); ENABLE_COLLISION( OBJ_PLAYER, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_PLAYER, OBJ_DEBRIS ); DISABLE_COLLISION( OBJ_WEAPON, OBJ_CAMERA ); DISABLE_COLLISION( OBJ_WEAPON, OBJ_POWERUP ); ENABLE_COLLISION( OBJ_WEAPON, OBJ_DEBRIS ); DISABLE_COLLISION( OBJ_CAMERA, OBJ_POWERUP ); DISABLE_COLLISION( OBJ_CAMERA, OBJ_DEBRIS ); DISABLE_COLLISION( OBJ_POWERUP, OBJ_DEBRIS ); ENABLE_COLLISION( OBJ_POWERUP, OBJ_WALL ); ENABLE_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN ) ENABLE_COLLISION( OBJ_WEAPON, OBJ_CLUTTER ) ENABLE_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN ) ENABLE_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN ) ENABLE_COLLISION( OBJ_PLAYER, OBJ_CLUTTER ) ENABLE_COLLISION( OBJ_PLAYER, OBJ_MARKER ); ENABLE_COLLISION( OBJ_DEBRIS, OBJ_WALL ); } void collide_object_with_wall( object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt ) { switch( A->type ) { case OBJ_NONE: Error( "A object of type NONE hit a wall!\n"); break; case OBJ_PLAYER: collide_player_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; case OBJ_WEAPON: collide_weapon_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; case OBJ_DEBRIS: collide_debris_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; case OBJ_FIREBALL: break; //collide_fireball_and_wall(A,hitspeed,hitseg,hitwall,hitpt); case OBJ_ROBOT: collide_robot_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break; case OBJ_HOSTAGE: break; //collide_hostage_and_wall(A,hitspeed,hitseg,hitwall,hitpt); case OBJ_CAMERA: break; //collide_camera_and_wall(A,hitspeed,hitseg,hitwall,hitpt); case OBJ_POWERUP: break; //collide_powerup_and_wall(A,hitspeed,hitseg,hitwall,hitpt); case OBJ_GHOST: break; //do nothing default: Error( "Unhandled object type hit wall in collide.c\n" ); } } dxx-rebirth-0.58.1-d2x/main/collide.h000066400000000000000000000045151217717237500172710ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for collide.c * */ #ifndef _COLLIDE_H #define _COLLIDE_H #include "playsave.h" void collide_init(); void collide_two_objects(object * A, object * B, vms_vector *collision_point); void collide_object_with_wall(object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt); extern void apply_damage_to_player(object *player, object *killer, fix damage, ubyte possibly_friendly); // Returns 1 if robot died, else 0. extern int apply_damage_to_robot(object *robot, fix damage, int killer_objnum); extern int Immaterial; #define PERSISTENT_DEBRIS (PlayerCfg.PersistentDebris && !(Game_mode & GM_MULTI)) // no persistent debris in multi extern void collide_player_and_weapon(object * player, object * weapon, vms_vector *collision_point); extern void collide_player_and_materialization_center(object *objp); extern void collide_robot_and_materialization_center(object *objp); extern void scrape_player_on_wall(object *obj, short hitseg, short hitwall, vms_vector * hitpt); extern int maybe_detonate_weapon(object *obj0p, object *obj, vms_vector *pos); extern void collide_player_and_nasty_robot(object * player, object * robot, vms_vector *collision_point); extern void net_destroy_controlcen(object *controlcen); extern void collide_player_and_powerup(object * player, object * powerup, vms_vector *collision_point); extern int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag); extern void apply_damage_to_controlcen(object *controlcen, fix damage, short who); extern void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage); #endif /* _COLLIDE_H */ dxx-rebirth-0.58.1-d2x/main/config.c000066400000000000000000000270611217717237500171170ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * contains routine(s) to read in the configuration file which contains * game configuration stuff like detail level, sound card, etc * */ #include #include #include #include #include "config.h" #include "pstypes.h" #include "game.h" #include "songs.h" #include "kconfig.h" #include "palette.h" #include "args.h" #include "player.h" #include "mission.h" #include "physfsx.h" struct Cfg GameCfg; static const char DigiVolumeStr[] = "DigiVolume"; static const char MusicVolumeStr[] = "MusicVolume"; static const char ReverseStereoStr[] = "ReverseStereo"; static const char OrigTrackOrderStr[] = "OrigTrackOrder"; static const char MusicTypeStr[] = "MusicType"; static const char CMLevelMusicPlayOrderStr[] = "CMLevelMusicPlayOrder"; static const char CMLevelMusicTrack0Str[] = "CMLevelMusicTrack0"; static const char CMLevelMusicTrack1Str[] = "CMLevelMusicTrack1"; static const char CMLevelMusicPathStr[] = "CMLevelMusicPath"; static const char CMMiscMusic0Str[] = "CMMiscMusic0"; static const char CMMiscMusic1Str[] = "CMMiscMusic1"; static const char CMMiscMusic2Str[] ="CMMiscMusic2"; static const char CMMiscMusic3Str[] = "CMMiscMusic3"; static const char CMMiscMusic4Str[] = "CMMiscMusic4"; static const char GammaLevelStr[] = "GammaLevel"; static const char LastPlayerStr[] = "LastPlayer"; static const char LastMissionStr[] = "LastMission"; static const char ResolutionXStr[] ="ResolutionX"; static const char ResolutionYStr[] ="ResolutionY"; static const char AspectXStr[] ="AspectX"; static const char AspectYStr[] ="AspectY"; static const char WindowModeStr[] ="WindowMode"; static const char TexFiltStr[] ="TexFilt"; static const char MovieTexFiltStr[] ="MovieTexFilt"; static const char MovieSubtitlesStr[] ="MovieSubtitles"; static const char VSyncStr[] ="VSync"; static const char MultisampleStr[] ="Multisample"; static const char FPSIndicatorStr[] ="FPSIndicator"; static const char GrabinputStr[] ="GrabInput"; int ReadConfigFile() { PHYSFS_file *infile; char *line, *token, *value, *ptr; // set defaults GameCfg.DigiVolume = 8; GameCfg.MusicVolume = 8; GameCfg.ReverseStereo = 0; GameCfg.OrigTrackOrder = 0; #if defined(__APPLE__) && defined(__MACH__) GameCfg.MusicType = MUSIC_TYPE_REDBOOK; #else GameCfg.MusicType = MUSIC_TYPE_BUILTIN; #endif GameCfg.CMLevelMusicPlayOrder = MUSIC_CM_PLAYORDER_CONT; GameCfg.CMLevelMusicTrack[0] = -1; GameCfg.CMLevelMusicTrack[1] = -1; memset(GameCfg.CMLevelMusicPath,0,PATH_MAX+1); memset(GameCfg.CMMiscMusic[SONG_TITLE],0,PATH_MAX+1); memset(GameCfg.CMMiscMusic[SONG_BRIEFING],0,PATH_MAX+1); memset(GameCfg.CMMiscMusic[SONG_ENDLEVEL],0,PATH_MAX+1); memset(GameCfg.CMMiscMusic[SONG_ENDGAME],0,PATH_MAX+1); memset(GameCfg.CMMiscMusic[SONG_CREDITS],0,PATH_MAX+1); #if defined(__APPLE__) && defined(__MACH__) GameCfg.OrigTrackOrder = 1; snprintf(GameCfg.CMLevelMusicPath, PATH_MAX, "%s", "descent2.m3u"); snprintf(GameCfg.CMMiscMusic[SONG_TITLE], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Redbook Soundtrack/Descent II, Macintosh CD-ROM/02 Title.mp3"); snprintf(GameCfg.CMMiscMusic[SONG_BRIEFING], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/03 Outerlimits.mp3"); snprintf(GameCfg.CMMiscMusic[SONG_ENDLEVEL], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/04 Close Call.mp3"); snprintf(GameCfg.CMMiscMusic[SONG_ENDGAME], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Insanity/Descent/14 Insanity.mp3"); snprintf(GameCfg.CMMiscMusic[SONG_CREDITS], PATH_MAX, "%s%s", PHYSFS_getUserDir(), "Music/iTunes/iTunes Music/Redbook Soundtrack/Descent II, Macintosh CD-ROM/03 Crawl.mp3"); #endif GameCfg.GammaLevel = 0; memset(GameCfg.LastPlayer,0,CALLSIGN_LEN+1); memset(GameCfg.LastMission,0,MISSION_NAME_LEN+1); GameCfg.ResolutionX = 640; GameCfg.ResolutionY = 480; GameCfg.AspectX = 3; GameCfg.AspectY = 4; GameCfg.WindowMode = 0; GameCfg.TexFilt = 0; GameCfg.MovieTexFilt = 0; GameCfg.MovieSubtitles = 0; GameCfg.VSync = 0; GameCfg.Multisample = 0; GameCfg.FPSIndicator = 0; GameCfg.Grabinput = 1; infile = PHYSFSX_openReadBuffered("descent.cfg"); if (infile == NULL) { return 1; } while (!PHYSFS_eof(infile)) { int max_len = PHYSFS_fileLength(infile); // to be fully safe, assume the whole cfg consists of one big line CALLOC(line, char, max_len); PHYSFSX_gets(infile, line); ptr = &(line[0]); while (isspace(*ptr)) ptr++; if (*ptr != '\0') { token = strtok(ptr, "="); value = strtok(NULL, "="); if (!value) value = ""; if (!strcmp(token, DigiVolumeStr)) GameCfg.DigiVolume = strtol(value, NULL, 10); else if (!strcmp(token, MusicVolumeStr)) GameCfg.MusicVolume = strtol(value, NULL, 10); else if (!strcmp(token, ReverseStereoStr)) GameCfg.ReverseStereo = strtol(value, NULL, 10); else if (!strcmp(token, OrigTrackOrderStr)) GameCfg.OrigTrackOrder = strtol(value, NULL, 10); else if (!strcmp(token, MusicTypeStr)) GameCfg.MusicType = strtol(value, NULL, 10); else if (!strcmp(token, CMLevelMusicPlayOrderStr)) GameCfg.CMLevelMusicPlayOrder = strtol(value, NULL, 10); else if (!strcmp(token, CMLevelMusicTrack0Str)) GameCfg.CMLevelMusicTrack[0] = strtol(value, NULL, 10); else if (!strcmp(token, CMLevelMusicTrack1Str)) GameCfg.CMLevelMusicTrack[1] = strtol(value, NULL, 10); else if (!strcmp(token, CMLevelMusicPathStr)) { char * p; strncpy( GameCfg.CMLevelMusicPath, value, PATH_MAX ); p = strchr( GameCfg.CMLevelMusicPath, '\n'); if ( p ) *p = 0; } else if (!strcmp(token, CMMiscMusic0Str)) { char * p; strncpy( GameCfg.CMMiscMusic[SONG_TITLE], value, PATH_MAX ); p = strchr( GameCfg.CMMiscMusic[SONG_TITLE], '\n'); if ( p ) *p = 0; } else if (!strcmp(token, CMMiscMusic1Str)) { char * p; strncpy( GameCfg.CMMiscMusic[SONG_BRIEFING], value, PATH_MAX ); p = strchr( GameCfg.CMMiscMusic[SONG_BRIEFING], '\n'); if ( p ) *p = 0; } else if (!strcmp(token, CMMiscMusic2Str)) { char * p; strncpy( GameCfg.CMMiscMusic[SONG_ENDLEVEL], value, PATH_MAX ); p = strchr( GameCfg.CMMiscMusic[SONG_ENDLEVEL], '\n'); if ( p ) *p = 0; } else if (!strcmp(token, CMMiscMusic3Str)) { char * p; strncpy( GameCfg.CMMiscMusic[SONG_ENDGAME], value, PATH_MAX ); p = strchr( GameCfg.CMMiscMusic[SONG_ENDGAME], '\n'); if ( p ) *p = 0; } else if (!strcmp(token, CMMiscMusic4Str)) { char * p; strncpy( GameCfg.CMMiscMusic[SONG_CREDITS], value, PATH_MAX ); p = strchr( GameCfg.CMMiscMusic[SONG_CREDITS], '\n'); if ( p ) *p = 0; } else if (!strcmp(token, GammaLevelStr)) { GameCfg.GammaLevel = strtol(value, NULL, 10); gr_palette_set_gamma( GameCfg.GammaLevel ); } else if (!strcmp(token, LastPlayerStr)) { char * p; strncpy( GameCfg.LastPlayer, value, CALLSIGN_LEN ); p = strchr( GameCfg.LastPlayer, '\n'); if ( p ) *p = 0; } else if (!strcmp(token, LastMissionStr)) { char * p; strncpy( GameCfg.LastMission, value, MISSION_NAME_LEN ); p = strchr( GameCfg.LastMission, '\n'); if ( p ) *p = 0; } else if (!strcmp(token, ResolutionXStr)) GameCfg.ResolutionX = strtol(value, NULL, 10); else if (!strcmp(token, ResolutionYStr)) GameCfg.ResolutionY = strtol(value, NULL, 10); else if (!strcmp(token, AspectXStr)) GameCfg.AspectX = strtol(value, NULL, 10); else if (!strcmp(token, AspectYStr)) GameCfg.AspectY = strtol(value, NULL, 10); else if (!strcmp(token, WindowModeStr)) GameCfg.WindowMode = strtol(value, NULL, 10); else if (!strcmp(token, TexFiltStr)) GameCfg.TexFilt = strtol(value, NULL, 10); else if (!strcmp(token, MovieTexFiltStr)) GameCfg.MovieTexFilt = strtol(value, NULL, 10); else if (!strcmp(token, MovieSubtitlesStr)) GameCfg.MovieSubtitles = strtol(value, NULL, 10); else if (!strcmp(token, VSyncStr)) GameCfg.VSync = strtol(value, NULL, 10); else if (!strcmp(token, MultisampleStr)) GameCfg.Multisample = strtol(value, NULL, 10); else if (!strcmp(token, FPSIndicatorStr)) GameCfg.FPSIndicator = strtol(value, NULL, 10); else if (!strcmp(token, GrabinputStr)) GameCfg.Grabinput = strtol(value, NULL, 10); } d_free(line); } PHYSFS_close(infile); if ( GameCfg.DigiVolume > 8 ) GameCfg.DigiVolume = 8; if ( GameCfg.MusicVolume > 8 ) GameCfg.MusicVolume = 8; if (GameCfg.ResolutionX >= 320 && GameCfg.ResolutionY >= 200) Game_screen_mode = SM(GameCfg.ResolutionX,GameCfg.ResolutionY); return 0; } int WriteConfigFile() { PHYSFS_file *infile; GameCfg.GammaLevel = gr_palette_get_gamma(); infile = PHYSFSX_openWriteBuffered("descent.cfg"); if (infile == NULL) { return 1; } PHYSFSX_printf(infile, "%s=%d\n", DigiVolumeStr, GameCfg.DigiVolume); PHYSFSX_printf(infile, "%s=%d\n", MusicVolumeStr, GameCfg.MusicVolume); PHYSFSX_printf(infile, "%s=%d\n", ReverseStereoStr, GameCfg.ReverseStereo); PHYSFSX_printf(infile, "%s=%d\n", OrigTrackOrderStr, GameCfg.OrigTrackOrder); PHYSFSX_printf(infile, "%s=%d\n", MusicTypeStr, GameCfg.MusicType); PHYSFSX_printf(infile, "%s=%d\n", CMLevelMusicPlayOrderStr, GameCfg.CMLevelMusicPlayOrder); PHYSFSX_printf(infile, "%s=%d\n", CMLevelMusicTrack0Str, GameCfg.CMLevelMusicTrack[0]); PHYSFSX_printf(infile, "%s=%d\n", CMLevelMusicTrack1Str, GameCfg.CMLevelMusicTrack[1]); PHYSFSX_printf(infile, "%s=%s\n", CMLevelMusicPathStr, GameCfg.CMLevelMusicPath); PHYSFSX_printf(infile, "%s=%s\n", CMMiscMusic0Str, GameCfg.CMMiscMusic[SONG_TITLE]); PHYSFSX_printf(infile, "%s=%s\n", CMMiscMusic1Str, GameCfg.CMMiscMusic[SONG_BRIEFING]); PHYSFSX_printf(infile, "%s=%s\n", CMMiscMusic2Str, GameCfg.CMMiscMusic[SONG_ENDLEVEL]); PHYSFSX_printf(infile, "%s=%s\n", CMMiscMusic3Str, GameCfg.CMMiscMusic[SONG_ENDGAME]); PHYSFSX_printf(infile, "%s=%s\n", CMMiscMusic4Str, GameCfg.CMMiscMusic[SONG_CREDITS]); PHYSFSX_printf(infile, "%s=%d\n", GammaLevelStr, GameCfg.GammaLevel); PHYSFSX_printf(infile, "%s=%s\n", LastPlayerStr, Players[Player_num].callsign); PHYSFSX_printf(infile, "%s=%s\n", LastMissionStr, GameCfg.LastMission); PHYSFSX_printf(infile, "%s=%i\n", ResolutionXStr, SM_W(Game_screen_mode)); PHYSFSX_printf(infile, "%s=%i\n", ResolutionYStr, SM_H(Game_screen_mode)); PHYSFSX_printf(infile, "%s=%i\n", AspectXStr, GameCfg.AspectX); PHYSFSX_printf(infile, "%s=%i\n", AspectYStr, GameCfg.AspectY); PHYSFSX_printf(infile, "%s=%i\n", WindowModeStr, GameCfg.WindowMode); PHYSFSX_printf(infile, "%s=%i\n", TexFiltStr, GameCfg.TexFilt); PHYSFSX_printf(infile, "%s=%i\n", MovieTexFiltStr, GameCfg.MovieTexFilt); PHYSFSX_printf(infile, "%s=%i\n", MovieSubtitlesStr, GameCfg.MovieSubtitles); PHYSFSX_printf(infile, "%s=%i\n", VSyncStr, GameCfg.VSync); PHYSFSX_printf(infile, "%s=%i\n", MultisampleStr, GameCfg.Multisample); PHYSFSX_printf(infile, "%s=%i\n", FPSIndicatorStr, GameCfg.FPSIndicator); PHYSFSX_printf(infile, "%s=%i\n", GrabinputStr, GameCfg.Grabinput); PHYSFS_close(infile); return 0; } dxx-rebirth-0.58.1-d2x/main/config.h000066400000000000000000000033331217717237500171200ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * prototype definitions for descent.cfg reading/writing * */ #ifndef _CONFIG_H #define _CONFIG_H #include "player.h" #include "mission.h" typedef struct Cfg { ubyte DigiVolume; ubyte MusicVolume; int ReverseStereo; int OrigTrackOrder; int MusicType; int CMLevelMusicPlayOrder; int CMLevelMusicTrack[2]; char CMLevelMusicPath[PATH_MAX+1]; char CMMiscMusic[5][PATH_MAX+1]; int GammaLevel; char LastPlayer[CALLSIGN_LEN+1]; char LastMission[MISSION_NAME_LEN+1]; int ResolutionX; int ResolutionY; int AspectX; int AspectY; int WindowMode; int TexFilt; int MovieTexFilt; int MovieSubtitles; int VSync; int Multisample; int FPSIndicator; int Grabinput; } __pack__ Cfg; extern struct Cfg GameCfg; //#ifdef USE_SDLMIXER //#define EXT_MUSIC_ON (GameCfg.SndEnableRedbook || GameCfg.JukeboxOn) //#else //#define EXT_MUSIC_ON (GameCfg.SndEnableRedbook) // JukeboxOn shouldn't do anything if it's not supported //#endif extern int ReadConfigFile(void); extern int WriteConfigFile(void); #endif dxx-rebirth-0.58.1-d2x/main/console.c000066400000000000000000000140431217717237500173100ustar00rootroot00000000000000/* * * Game console * */ #include #include #include #include #include #include #include "window.h" #include "console.h" #include "args.h" #include "gr.h" #include "physfsx.h" #include "gamefont.h" #include "key.h" #include "vers_id.h" #include "timer.h" static PHYSFS_file *gamelog_fp=NULL; static struct console_buffer con_buffer[CON_LINES_MAX]; static int con_state = CON_STATE_CLOSED, con_scroll_offset = 0, con_size = 0; extern void game_flush_inputs(); static void con_add_buffer_line(int priority, char *buffer) { int i=0; /* shift con_buffer for one line */ for (i=1; itm_hour,lt->tm_min,lt->tm_sec); #ifdef _WIN32 // stupid hack to force DOS-style newlines if (buffer[strlen(buffer)-1] == '\n' && strlen(buffer) <= CON_LINE_LENGTH) { buffer[strlen(buffer)-1]='\r'; buffer[strlen(buffer)]='\n'; } #endif PHYSFSX_printf(gamelog_fp,"%s",buffer); } } } static void con_draw(void) { int i = 0, y = 0, done = 0; if (con_size <= 0) return; gr_set_current_canvas(NULL); gr_set_curfont(GAME_FONT); gr_setcolor(BM_XRGB(0,0,0)); gr_settransblend(7, GR_BLEND_NORMAL); gr_rect(0,0,SWIDTH,(LINE_SPACING*(con_size))+FSPACY(1)); gr_settransblend(GR_FADE_OFF, GR_BLEND_NORMAL); y=FSPACY(1)+(LINE_SPACING*con_size); i+=con_scroll_offset; while (!done) { int w,h,aw; switch (con_buffer[CON_LINES_MAX-1-i].priority) { case CON_CRITICAL: gr_set_fontcolor(BM_XRGB(28,0,0),-1); break; case CON_URGENT: gr_set_fontcolor(BM_XRGB(54,54,0),-1); break; case CON_DEBUG: case CON_VERBOSE: gr_set_fontcolor(BM_XRGB(14,14,14),-1); break; case CON_HUD: gr_set_fontcolor(BM_XRGB(0,28,0),-1); break; default: gr_set_fontcolor(BM_XRGB(255,255,255),-1); break; } gr_get_string_size(con_buffer[CON_LINES_MAX-1-i].line,&w,&h,&aw); y-=h+FSPACY(1); gr_printf(FSPACX(1),y,"%s",con_buffer[CON_LINES_MAX-1-i].line); i++; if (y<=0 || CON_LINES_MAX-1-i <= 0 || i < 0) done=1; } gr_setcolor(BM_XRGB(0,0,0)); gr_rect(0,0,SWIDTH,LINE_SPACING); gr_set_fontcolor(BM_XRGB(255,255,255),-1); gr_printf(FSPACX(1),FSPACY(1),"%s LOG", DESCENT_VERSION); gr_printf(SWIDTH-FSPACX(110),FSPACY(1),"PAGE-UP/DOWN TO SCROLL"); } static int con_handler(window *wind, d_event *event) { int key; static fix64 last_scroll_time = 0; switch (event->type) { case EVENT_WINDOW_ACTIVATED: break; case EVENT_WINDOW_DEACTIVATED: con_size = 0; con_state = CON_STATE_CLOSED; break; case EVENT_KEY_COMMAND: key = event_key_get(event); switch (key) { case KEY_SHIFTED + KEY_ESC: switch (con_state) { case CON_STATE_OPEN: case CON_STATE_OPENING: con_state = CON_STATE_CLOSING; break; case CON_STATE_CLOSED: case CON_STATE_CLOSING: con_state = CON_STATE_OPENING; default: break; } break; case KEY_PAGEUP: con_scroll_offset+=CON_SCROLL_OFFSET; if (con_scroll_offset >= CON_LINES_MAX-1) con_scroll_offset = CON_LINES_MAX-1; while (con_buffer[CON_LINES_MAX-1-con_scroll_offset].line[0]=='\0') con_scroll_offset--; break; case KEY_PAGEDOWN: con_scroll_offset-=CON_SCROLL_OFFSET; if (con_scroll_offset<0) con_scroll_offset=0; break; default: break; } return 1; case EVENT_WINDOW_DRAW: timer_delay2(50); if (con_state == CON_STATE_OPENING) { if (con_size < CON_LINES_ONSCREEN && timer_query() >= last_scroll_time+(F1_0/30)) { last_scroll_time = timer_query(); con_size++; } } else if (con_state == CON_STATE_CLOSING) { if (con_size > 0 && timer_query() >= last_scroll_time+(F1_0/30)) { last_scroll_time = timer_query(); con_size--; } } if (con_size >= CON_LINES_ONSCREEN) con_state = CON_STATE_OPEN; else if (con_size <= 0) con_state = CON_STATE_CLOSED; if (con_state == CON_STATE_CLOSED && wind) window_close(wind); con_draw(); break; case EVENT_WINDOW_CLOSE: break; default: break; } return 0; } void con_showup(void) { window *wind; game_flush_inputs(); con_state = CON_STATE_OPENING; wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *))con_handler, NULL); if (!wind) { d_event event = { EVENT_WINDOW_CLOSE }; con_handler(NULL, &event); return; } } static void con_close(void) { if (gamelog_fp) PHYSFS_close(gamelog_fp); gamelog_fp = NULL; } void con_init(void) { memset(con_buffer,0,sizeof(con_buffer)); if (GameArg.DbgSafelog) gamelog_fp = PHYSFS_openWrite("gamelog.txt"); else gamelog_fp = PHYSFSX_openWriteBuffered("gamelog.txt"); atexit(con_close); } dxx-rebirth-0.58.1-d2x/main/controls.c000066400000000000000000000150521217717237500175120ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Code for controlling player movement * */ #include #include #include "pstypes.h" #include "key.h" #include "joy.h" #include "timer.h" #include "dxxerror.h" #include "inferno.h" #include "game.h" #include "object.h" #include "player.h" #include "controls.h" #include "render.h" #include "args.h" #include "palette.h" #include "mouse.h" #include "kconfig.h" #include "laser.h" #ifdef NETWORK #include "multi.h" #endif #include "vclip.h" #include "fireball.h" //look at keyboard, mouse, joystick, CyberMan, whatever, and set //physics vars rotvel, velocity fix Afterburner_charge=f1_0; #define AFTERBURNER_USE_SECS 3 //use up in 3 seconds #define DROP_DELTA_TIME (f1_0/15) //drop 3 per second extern int Drop_afterburner_blob_flag; //ugly hack extern fix Seismic_tremor_magnitude; void read_flying_controls( object * obj ) { fix forward_thrust_time; Assert(FrameTime > 0); //Get MATT if hit this! // this section commented and moved to the bottom by WraithX // if (Player_is_dead) { // vm_vec_zero(&obj->mtype.phys_info.rotthrust); // vm_vec_zero(&obj->mtype.phys_info.thrust); // return; // } // end of section to be moved. if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return; //references to player_ship require that this obj be the player if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) { vms_angvec rotangs; vms_matrix rotmat,tempm; fix speed; //this is a horrible hack. guided missile stuff should not be //handled in the middle of a routine that is dealing with the player vm_vec_zero(&obj->mtype.phys_info.rotthrust); rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64; rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16; rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64; vm_angles_2_matrix(&rotmat,&rotangs); vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat); Guided_missile[Player_num]->orient = tempm; speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level]; vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed); #ifdef NETWORK if (Game_mode & GM_MULTI) multi_send_guided_info (Guided_missile[Player_num],0); #endif } else { obj->mtype.phys_info.rotthrust.x = Controls.pitch_time; obj->mtype.phys_info.rotthrust.y = Controls.heading_time; obj->mtype.phys_info.rotthrust.z = Controls.bank_time; } forward_thrust_time = Controls.forward_thrust_time; if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER) { if (Controls.afterburner_state) { //player has key down //if (forward_thrust_time >= 0) { //..and isn't moving backward { fix afterburner_scale; int old_count,new_count; //add in value from 0..1 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2; forward_thrust_time = fixmul(FrameTime,afterburner_scale); //based on full thrust old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS; if (Afterburner_charge < 0) Afterburner_charge = 0; new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); if (old_count != new_count) Drop_afterburner_blob_flag = 1; //drop blob (after physics called) } } else { fix cur_energy,charge_up; //charge up to full charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10 //maybe limit charge up by energy charge_up = min(charge_up,cur_energy/10); Afterburner_charge += charge_up; Players[Player_num].energy -= charge_up * 100 / 10; //full charge uses 10% of energy } } // Set object's thrust vector for forward/backward vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->orient.fvec, forward_thrust_time ); // slide left/right vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time ); // slide up/down vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time ); if (obj->mtype.phys_info.flags & PF_WIGGLE) { fix swiggle; fix_fastsincos(((fix)GameTime64), &swiggle, NULL); if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem. swiggle = fixmul(swiggle*30, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at 30 FPS) vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&obj->orient.uvec,fixmul(swiggle,Player_ship->wiggle)); } // As of now, obj->mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are // in units of time... In other words, if thrust==FrameTime, that // means that the user was holding down the Max_thrust key for the // whole frame. So we just scale them up by the max, and divide by // FrameTime to make them independant of framerate // Prevent divide overflows on high frame rates. // In a signed divide, you get an overflow if num >= div<<15 { fix ft = FrameTime; // Note, you must check for ft < F1_0/2, else you can get an overflow on the << 15. if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) { ft = (Player_ship->max_thrust >> 15) + 1; } vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) ); if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) { ft = (Player_ship->max_thrust >> 15) + 1; } vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) ); } // moved here by WraithX if (Player_is_dead) { //vm_vec_zero(&obj->mtype.phys_info.rotthrust); // let dead players rotate, changed by WraithX vm_vec_zero(&obj->mtype.phys_info.thrust); // don't let dead players move, changed by WraithX return; }// end if } dxx-rebirth-0.58.1-d2x/main/controls.h000066400000000000000000000017731217717237500175240ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for controls.c * */ #ifndef _CONTROLS_H #define _CONTROLS_H extern int Cyberman_installed; //SWIFT device present void read_flying_controls( object * obj ); extern ubyte Controls_stopped; extern ubyte Controls_always_move; extern fix Afterburner_charge; #endif dxx-rebirth-0.58.1-d2x/main/credits.c000066400000000000000000000144261217717237500173100ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to display the credits. * */ #include #include #include #include #include #include "dxxerror.h" #include "pstypes.h" #include "gr.h" #include "window.h" #include "key.h" #include "mouse.h" #include "palette.h" #include "game.h" #include "gamepal.h" #include "timer.h" #include "gamefont.h" #include "pcx.h" #include "u_mem.h" #include "screens.h" #include "digi.h" #include "rbaudio.h" #include "text.h" #include "songs.h" #include "menu.h" #include "mission.h" #include "config.h" #include "args.h" #define ROW_SPACING (SHEIGHT / 17) #define NUM_LINES 20 //14 #define CREDITS_FILE (PHYSFSX_exists("mcredits.tex",1)?"mcredits.tex":PHYSFSX_exists("ocredits.tex",1)?"ocredits.tex":"credits.tex") #define ALLOWED_CHAR ( Current_mission==NULL ? 'R' : (is_SHAREWARE ? 'S' : 'R')) typedef struct credits { PHYSFS_file * file; int have_bin_file; char buffer[NUM_LINES][80]; int buffer_line; int first_line_offset; int extra_inc; int done; int row; grs_bitmap backdrop; } credits; int credits_handler(window *wind, d_event *event, credits *cr) { int j, l, y; char * tempp; switch (event->type) { case EVENT_KEY_COMMAND: if (!call_default_handler(event)) // if not print screen, debug etc window_close(wind); return 1; case EVENT_MOUSE_BUTTON_DOWN: case EVENT_MOUSE_BUTTON_UP: if (event_mouse_get_button(event) == MBTN_LEFT || event_mouse_get_button(event) == MBTN_RIGHT) { window_close(wind); return 1; } break; case EVENT_IDLE: if (cr->done>NUM_LINES) { window_close(wind); return 0; } break; case EVENT_WINDOW_DRAW: timer_delay(F1_0/28); if (cr->row == 0) { do { cr->buffer_line = (cr->buffer_line+1) % NUM_LINES; get_line:; if (PHYSFSX_fgets( cr->buffer[cr->buffer_line], 80, cr->file )) { char *p; if (cr->have_bin_file) // is this a binary tbl file decode_text_line (cr->buffer[cr->buffer_line]); p = cr->buffer[cr->buffer_line]; if (p[0] == ';') goto get_line; if (p[0] == '%') { if (p[1] == ALLOWED_CHAR) { int i = 0, len = strlen(p); for (i = 0; i < len; i++) p[i] = p[i+2]; } else goto get_line; } } else { //fseek( file, 0, SEEK_SET); cr->buffer[cr->buffer_line][0] = 0; cr->done++; } } while (cr->extra_inc--); cr->extra_inc = 0; } // cheap but effective: towards end of credits sequence, fade out the music volume if (cr->done >= NUM_LINES-16) { static int curvol = -10; if (curvol == -10) curvol = GameCfg.MusicVolume; if (curvol > (NUM_LINES-cr->done)/2) { curvol = (NUM_LINES-cr->done)/2; songs_set_volume(curvol); } } y = cr->first_line_offset - cr->row; show_fullscr(&cr->backdrop); for (j=0; jbuffer_line + j + 1 ) % NUM_LINES; s = cr->buffer[l]; if ( s[0] == '!' ) { s++; } else if ( s[0] == '$' ) { gr_set_curfont( HUGE_FONT ); s++; } else if ( s[0] == '*' ) { gr_set_curfont( MEDIUM3_FONT ); s++; } else gr_set_curfont( MEDIUM2_FONT ); tempp = strchr( s, '\t' ); if ( !tempp ) { // Wacky Fast Credits thing int w, h, aw; gr_get_string_size( s, &w, &h, &aw); gr_string( 0x8000, y, s ); } y += ROW_SPACING; } cr->row += SHEIGHT/200; if (cr->row >= ROW_SPACING) cr->row = 0; break; case EVENT_WINDOW_CLOSE: gr_free_bitmap_data (&cr->backdrop); PHYSFS_close(cr->file); songs_set_volume(GameCfg.MusicVolume); songs_play_song( SONG_TITLE, 1 ); d_free(cr); break; default: break; } return 0; } //if filename passed is NULL, show normal credits void credits_show(char *credits_filename) { credits *cr; window *wind; int i; int pcx_error; char * tempp; char filename[32]; ubyte backdrop_palette[768]; MALLOC(cr, credits, 1); if (!cr) return; cr->have_bin_file = 0; cr->buffer_line = 0; cr->first_line_offset = 0; cr->extra_inc = 0; cr->done = 0; cr->row = 0; // Clear out all tex buffer lines. for (i=0; ibuffer[i][0] = 0; sprintf(filename, "%s", CREDITS_FILE); cr->have_bin_file = 0; if (credits_filename) { strcpy(filename,credits_filename); cr->have_bin_file = 1; } cr->file = PHYSFSX_openReadBuffered( filename ); if (cr->file == NULL) { char nfile[32]; if (credits_filename) { d_free(cr); return; //ok to not find special filename } tempp = strchr(filename, '.'); *tempp = '\0'; sprintf(nfile, "%s.txb", filename); cr->file = PHYSFSX_openReadBuffered(nfile); if (cr->file == NULL) Error("Missing CREDITS.TEX and CREDITS.TXB file\n"); cr->have_bin_file = 1; } set_screen_mode(SCREEN_MENU); gr_use_palette_table( "credits.256" ); cr->backdrop.bm_data=NULL; pcx_error = pcx_read_bitmap(STARS_BACKGROUND,&cr->backdrop, BM_LINEAR,backdrop_palette); if (pcx_error != PCX_ERROR_NONE) { PHYSFS_close(cr->file); d_free(cr); return; } songs_play_song( SONG_CREDITS, 1 ); gr_remap_bitmap_good( &cr->backdrop,backdrop_palette, -1, -1 ); gr_set_current_canvas(NULL); show_fullscr(&cr->backdrop); gr_palette_load( gr_palette ); key_flush(); wind = window_create(&grd_curscreen->sc_canvas, 0, 0, SWIDTH, SHEIGHT, (int (*)(window *, d_event *, void *))credits_handler, cr); if (!wind) { d_event event = { EVENT_WINDOW_CLOSE }; credits_handler(NULL, &event, cr); return; } while (window_exists(wind)) event_process(); } dxx-rebirth-0.58.1-d2x/main/credits.h000066400000000000000000000015531217717237500173120ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Prototypes for the credit sequence. * */ #ifndef _CREDITS_H #define _CREDITS_H void credits_show(char *credits_filename); #endif dxx-rebirth-0.58.1-d2x/main/descent.cfg000077500000000000000000000003611217717237500176110ustar00rootroot00000000000000DigiVolume=8 MidiVolume=8 RedbookEnabled=1 RedbookVolume=8 StereoReverse=0 GammaLevel=0 DetailLevel=4 JoystickMin=0,0,0,0 JoystickCen=0,0,0,0 JoystickMax=0,0,0,0 LastPlayer=i LastMission= VR_type=0 VR_resolution=0 VR_tracking=0 MovieHires=1 dxx-rebirth-0.58.1-d2x/main/digi.h000066400000000000000000000103471217717237500165720ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Include file for sound hardware. * */ #ifndef _DIGI_H #define _DIGI_H #include "pstypes.h" #include "vecmat.h" typedef struct digi_sound { int bits; int freq; int length; ubyte * data; } digi_sound; extern int digi_get_settings(); extern int digi_init(); extern void digi_reset(); extern void digi_close(); // Volume is max at F1_0. extern void digi_play_sample( int sndnum, fix max_volume ); extern void digi_play_sample_once( int sndnum, fix max_volume ); extern int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ); extern int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ); // Same as above, but you pass the max distance sound can be heard. The old way uses f1_0*256 for max_distance. extern int digi_link_sound_to_object2( int soundnum, short objnum, int forever, fix max_volume, fix max_distance ); extern int digi_link_sound_to_pos2( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ); extern int digi_link_sound_to_object3( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance, int loop_start, int loop_end ); extern void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ); // Volume from 0-0x7fff extern void digi_init_sounds(); extern void digi_sync_sounds(); extern void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ); extern void digi_kill_sound_linked_to_object( int objnum ); extern void digi_set_digi_volume( int dvolume ); extern void digi_set_volume( int dvolume ); extern int digi_is_sound_playing(int soundno); extern void digi_pause_digi_sounds(); extern void digi_resume_digi_sounds(); extern void digi_set_max_channels(int n); extern int digi_get_max_channels(); extern int digi_xlat_sound(int soundno); extern void digi_stop_sound( int channel ); // Volume 0-F1_0 extern int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj); // Stops all sounds that are playing void digi_stop_all_channels(); void digi_stop_digi_sounds(); extern void digi_end_sound( int channel ); extern void digi_set_channel_pan( int channel, int pan ); extern void digi_set_channel_volume( int channel, int volume ); extern int digi_is_channel_playing(int channel); extern void digi_debug(); extern void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int loop_end ); extern void digi_change_looping_volume( fix volume ); extern void digi_stop_looping_sound(); // Plays a queued voice sound. extern void digi_start_sound_queued( short soundnum, fix volume ); // Following declarations are for the runtime switching system #define SAMPLE_RATE_11K 11025 #define SAMPLE_RATE_22K 22050 #define SAMPLE_RATE_44K 44100 #define SDLMIXER_SYSTEM 1 #define SDLAUDIO_SYSTEM 2 #define MUSIC_TYPE_NONE 0 #define MUSIC_TYPE_BUILTIN 1 #define MUSIC_TYPE_REDBOOK 2 #define MUSIC_TYPE_CUSTOM 3 // play-order definitions for custom music #define MUSIC_CM_PLAYORDER_CONT 0 #define MUSIC_CM_PLAYORDER_LEVEL 1 #define MUSIC_CM_PLAYORDER_RAND 2 #define SOUND_MAX_VOLUME F1_0 / 2 extern int digi_volume; extern int digi_sample_rate; void digi_select_system(int); #ifdef _WIN32 // Windows native-MIDI stuff. void digi_win32_set_midi_volume( int mvolume ); int digi_win32_play_midi_song( char * filename, int loop ); void digi_win32_pause_midi_song(); void digi_win32_resume_midi_song(); void digi_win32_stop_midi_song(); #endif #endif dxx-rebirth-0.58.1-d2x/main/digiobj.c000066400000000000000000000552371217717237500172670ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ #include #include #include #include #include #include "fix.h" #include "object.h" #include "timer.h" #include "joy.h" #include "digi.h" #include "sounds.h" #include "args.h" #include "key.h" #include "newdemo.h" #include "game.h" #include "dxxerror.h" #include "wall.h" #include "piggy.h" #include "text.h" #include "kconfig.h" #include "config.h" #define SOF_USED 1 // Set if this sample is used #define SOF_PLAYING 2 // Set if this sample is playing on a channel #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits. #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once #define SOF_PERMANENT 32 // Part of the level, like a waterfall or fan typedef struct sound_object { short signature; // A unique signature to this sound ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long. ubyte pad; // Keep alignment fix max_volume; // Max volume that this sound is playing at fix max_distance; // The max distance that this sound can be heard at... int volume; // Volume that this sound is playing at int pan; // Pan value that this sound is playing at int channel; // What channel this is playing on, -1 if not playing short soundnum; // The sound number that is playing int loop_start; // The start point of the loop. -1 means no loop int loop_end; // The end point of the loop union { struct { short segnum; // Used if SOF_LINK_TO_POS field is used short sidenum; vms_vector position; } pos; struct { short objnum; // Used if SOF_LINK_TO_OBJ field is used short objsignature; } obj; } link_type; } sound_object; #define MAX_SOUND_OBJECTS 150 sound_object SoundObjects[MAX_SOUND_OBJECTS]; short next_signature=0; int N_active_sound_objects=0; int digi_sounds_initialized=0; /* Find the sound which actually equates to a sound number */ int digi_xlat_sound(int soundno) { if (soundno < 0) return -1; if (GameArg.SysLowMem) { soundno = AltSounds[soundno]; if (soundno == 255) return -1; } //Assert(Sounds[soundno] != 255); //if hit this, probably using undefined sound if (Sounds[soundno] == 255) return -1; return Sounds[soundno]; } int digi_unxlat_sound(int soundno) { int i; ubyte *table = (GameArg.SysLowMem?AltSounds:Sounds); if ( soundno < 0 ) return -1; for (i=0;i -1 ) { *volume = max_volume - fixdiv(path_distance,max_distance); if (*volume > 0 ) { angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec); fix_sincos(angle_from_ear,&sinang,&cosang); if (GameCfg.ReverseStereo) cosang *= -1; *pan = (cosang + F1_0)/2; } else { *volume = 0; } } } } void digi_play_sample_once( int soundno, fix max_volume ) { if ( Newdemo_state == ND_STATE_RECORDING ) newdemo_record_sound( soundno ); soundno = digi_xlat_sound(soundno); if (soundno < 0 ) return; // start the sample playing digi_start_sound( soundno, max_volume, 0xffff/2, 0, -1, -1, -1 ); } void digi_play_sample( int soundno, fix max_volume ) { if ( Newdemo_state == ND_STATE_RECORDING ) newdemo_record_sound( soundno ); soundno = digi_xlat_sound(soundno); if (soundno < 0 ) return; // start the sample playing digi_start_sound( soundno, max_volume, 0xffff/2, 0, -1, -1, -1 ); } void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) { no_dups = 1; if ( Newdemo_state == ND_STATE_RECORDING ) { if ( no_dups ) newdemo_record_sound_3d_once( soundno, angle, volume ); else newdemo_record_sound_3d( soundno, angle, volume ); } soundno = digi_xlat_sound(soundno); if (soundno < 0 ) return; if (volume < 10 ) return; // start the sample playing digi_start_sound( soundno, volume, angle, 0, -1, -1, -1 ); } void SoundQ_init(); void SoundQ_process(); void SoundQ_pause(); void digi_init_sounds() { int i; SoundQ_init(); digi_stop_all_channels(); digi_stop_looping_sound(); for (i=0; i -1 ) digi_looping_channel = digi_start_sound( digi_looping_sound, digi_looping_volume, 0xFFFF/2, 1, digi_looping_start, digi_looping_end, -1 ); } void digi_play_sample_looping( int soundno, fix max_volume,int loop_start, int loop_end ) { soundno = digi_xlat_sound(soundno); if (soundno < 0 ) return; if (digi_looping_channel>-1) digi_stop_sound( digi_looping_channel ); digi_looping_sound = soundno; digi_looping_volume = max_volume; digi_looping_start = loop_start; digi_looping_end = loop_end; digi_play_sample_looping_sub(); } void digi_change_looping_volume( fix volume ) { if ( digi_looping_channel > -1 ) digi_set_channel_volume( digi_looping_channel, volume ); digi_looping_volume = volume; } void digi_stop_looping_sound() { if ( digi_looping_channel > -1 ) digi_stop_sound( digi_looping_channel ); digi_looping_channel = -1; digi_looping_sound = -1; } void digi_pause_looping_sound() { if ( digi_looping_channel > -1 ) digi_stop_sound( digi_looping_channel ); digi_looping_channel = -1; } void digi_unpause_looping_sound() { digi_play_sample_looping_sub(); } //hack to not start object when loading level int Dont_start_sound_objects = 0; void digi_start_sound_object(int i) { // start sample structures SoundObjects[i].channel = -1; if ( SoundObjects[i].volume <= 0 ) return; if ( Dont_start_sound_objects ) return; // -- MK, 2/22/96 -- if ( Newdemo_state == ND_STATE_RECORDING ) // -- MK, 2/22/96 -- newdemo_record_sound_3d_once( digi_unxlat_sound(SoundObjects[i].soundnum), SoundObjects[i].pan, SoundObjects[i].volume ); // only use up to half the sound channels for "permanent" sounts if ((SoundObjects[i].flags & SOF_PERMANENT) && (N_active_sound_objects >= max(1, digi_max_channels / 4))) return; // start the sample playing SoundObjects[i].channel = digi_start_sound( SoundObjects[i].soundnum, SoundObjects[i].volume, SoundObjects[i].pan, SoundObjects[i].flags & SOF_PLAY_FOREVER, SoundObjects[i].loop_start, SoundObjects[i].loop_end, i ); if (SoundObjects[i].channel > -1 ) N_active_sound_objects++; } //sounds longer than this get their 3d aspects updated #define SOUND_3D_THRESHHOLD (GameArg.SndDigiSampleRate * 3 / 2) //1.5 seconds int digi_link_sound_to_object3( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance, int loop_start, int loop_end ) { int i,volume,pan; object * objp; int soundnum; soundnum = digi_xlat_sound(org_soundnum); if ( max_volume < 0 ) return -1; // if ( max_volume > F1_0 ) max_volume = F1_0; if (soundnum < 0 ) return -1; if (GameSounds[soundnum].data==NULL) { Int3(); return -1; } if ((objnum<0)||(objnum>Highest_object_index)) return -1; if ( !forever ) { // && GameSounds[soundnum - SOUND_OFFSET].length < SOUND_3D_THRESHHOLD) { // Hack to keep sounds from building up... digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance ); digi_play_sample_3d( org_soundnum, pan, volume, 0 ); return -1; } if ( Newdemo_state == ND_STATE_RECORDING ) { newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end ); } for (i=0; iorient, &Viewer->pos, Viewer->segnum, &objp->pos, objp->segnum, SoundObjects[i].max_volume, &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); digi_start_sound_object(i); // If it's a one-shot sound effect, and it can't start right away, then // just cancel it and be done with it. if ( (SoundObjects[i].channel < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) { SoundObjects[i].flags = 0; return -1; } } return SoundObjects[i].signature; } int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance ) { return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 ); } int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0 ); } int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) { int i, volume, pan; int soundnum; soundnum = digi_xlat_sound(org_soundnum); if ( max_volume < 0 ) return -1; // if ( max_volume > F1_0 ) max_volume = F1_0; if (soundnum < 0 ) return -1; if (GameSounds[soundnum].data==NULL) { Int3(); return -1; } if ((segnum<0)||(segnum>Highest_segment_index)) return -1; if ( !forever ) { //&& GameSounds[soundnum - SOUND_OFFSET].length < SOUND_3D_THRESHHOLD) { // Hack to keep sounds from building up... digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance ); digi_play_sample_3d( org_soundnum, pan, volume, 0 ); return -1; } for (i=0; iorient, &Viewer->pos, Viewer->segnum, &SoundObjects[i].link_type.pos.position, SoundObjects[i].link_type.pos.segnum, SoundObjects[i].max_volume, &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); digi_start_sound_object(i); // If it's a one-shot sound effect, and it can't start right away, then // just cancel it and be done with it. if ( (SoundObjects[i].channel < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) { SoundObjects[i].flags = 0; return -1; } } return SoundObjects[i].signature; } int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) { return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 ); } //if soundnum==-1, kill any sound void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) { int i,killed; if (soundnum != -1) soundnum = digi_xlat_sound(soundnum); killed = 0; for (i=0; i -1 ) { digi_stop_sound( SoundObjects[i].channel ); N_active_sound_objects--; } SoundObjects[i].channel = -1; SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound killed++; } } } } void digi_kill_sound_linked_to_object( int objnum ) { int i,killed; killed = 0; if ( Newdemo_state == ND_STATE_RECORDING ) { newdemo_record_kill_sound_linked_to_object( objnum ); } for (i=0; i -1 ) { digi_stop_sound( SoundObjects[i].channel ); N_active_sound_objects--; } SoundObjects[i].channel = -1; SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound killed++; } } } } // John's new function, 2/22/96. void digi_record_sound_objects() { int i; for (i=0; i -1 ) { if ( !digi_is_channel_playing(SoundObjects[i].channel) ) { digi_end_sound( SoundObjects[i].channel ); SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound N_active_sound_objects--; continue; // Go on to next sound... } } } if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) { digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &SoundObjects[i].link_type.pos.position, SoundObjects[i].link_type.pos.segnum, SoundObjects[i].max_volume, &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) { object * objp; if ( Newdemo_state == ND_STATE_PLAYBACK ) { int objnum; objnum = newdemo_find_object( SoundObjects[i].link_type.obj.objsignature ); if ( objnum > -1 ) { objp = &Objects[objnum]; } else { objp = &Objects[0]; } } else { objp = &Objects[SoundObjects[i].link_type.obj.objnum]; } if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].link_type.obj.objsignature)) { // The object that this is linked to is dead, so just end this sound if it is looping. if ( SoundObjects[i].channel>-1 ) { if (SoundObjects[i].flags & SOF_PLAY_FOREVER) digi_stop_sound( SoundObjects[i].channel ); else digi_end_sound( SoundObjects[i].channel ); N_active_sound_objects--; } SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound continue; // Go on to next sound... } else { digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &objp->pos, objp->segnum, SoundObjects[i].max_volume, &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance ); } } if (oldvolume != SoundObjects[i].volume) { if ( SoundObjects[i].volume < 1 ) { // Sound is too far away, so stop it from playing. if ( SoundObjects[i].channel>-1 ) { if (SoundObjects[i].flags & SOF_PLAY_FOREVER) digi_stop_sound( SoundObjects[i].channel ); else digi_end_sound( SoundObjects[i].channel ); N_active_sound_objects--; SoundObjects[i].channel = -1; } if (! (SoundObjects[i].flags & SOF_PLAY_FOREVER)) { SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound continue; } } else { if (SoundObjects[i].channel<0) { digi_start_sound_object(i); } else { digi_set_channel_volume( SoundObjects[i].channel, SoundObjects[i].volume ); } } } if (oldpan != SoundObjects[i].pan) { if (SoundObjects[i].channel>-1) digi_set_channel_pan( SoundObjects[i].channel, SoundObjects[i].pan ); } } } #ifndef NDEBUG // digi_sound_debug(); #endif } void digi_pause_digi_sounds() { int i; digi_pause_looping_sound(); for (i=0; i-1) ) { digi_stop_sound( SoundObjects[i].channel ); if (! (SoundObjects[i].flags & SOF_PLAY_FOREVER)) SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound N_active_sound_objects--; SoundObjects[i].channel = -1; } } digi_stop_all_channels(); SoundQ_pause(); } void digi_resume_digi_sounds() { digi_sync_sounds(); //don't think we really need to do this, but can't hurt digi_unpause_looping_sound(); } // Called by the code in digi.c when another sound takes this sound object's // slot because the sound was done playing. void digi_end_soundobj(int i) { Assert( SoundObjects[i].flags & SOF_USED ); Assert( SoundObjects[i].channel > -1 ); N_active_sound_objects--; SoundObjects[i].channel = -1; } void digi_stop_digi_sounds() { int i; digi_stop_looping_sound(); for (i=0; i -1 ) { digi_stop_sound( SoundObjects[i].channel ); N_active_sound_objects--; } SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound } } digi_stop_all_channels(); SoundQ_init(); } #ifndef NDEBUG int verify_sound_channel_free( int channel ) { int i; for (i=0; i -1 ) n_active_sound_objs++; } } digi_debug(); } #endif typedef struct sound_q { fix64 time_added; int soundnum; } sound_q; #define MAX_Q 32 #define MAX_LIFE F1_0*30 // After being queued for 30 seconds, don't play it sound_q SoundQ[MAX_Q]; int SoundQ_head, SoundQ_tail, SoundQ_num; int SoundQ_channel; void SoundQ_init() { SoundQ_head = SoundQ_tail = 0; SoundQ_num = 0; SoundQ_channel = -1; } void SoundQ_pause() { SoundQ_channel = -1; } void SoundQ_end() { // Current playing sound is stopped, so take it off the Queue SoundQ_head = (SoundQ_head+1); if ( SoundQ_head >= MAX_Q ) SoundQ_head = 0; SoundQ_num--; SoundQ_channel = -1; } void SoundQ_process() { if ( SoundQ_channel > -1 ) { if ( digi_is_channel_playing(SoundQ_channel) ) return; SoundQ_end(); } while ( SoundQ_head != SoundQ_tail ) { sound_q * q = &SoundQ[SoundQ_head]; if ( q->time_added+MAX_LIFE > timer_query() ) { SoundQ_channel = digi_start_sound(q->soundnum, F1_0+1, 0xFFFF/2, 0, -1, -1, -1 ); return; } else { // expired; remove from Queue SoundQ_end(); } } } void digi_start_sound_queued( short soundnum, fix volume ) { int i; soundnum = digi_xlat_sound(soundnum); if (soundnum < 0 ) return; i = SoundQ_tail+1; if ( i>=MAX_Q ) i = 0; // Make sure its loud so it doesn't get cancelled! if ( volume < F1_0+1 ) volume = F1_0 + 1; if ( i != SoundQ_head ) { SoundQ[SoundQ_tail].time_added = timer_query(); SoundQ[SoundQ_tail].soundnum = soundnum; SoundQ_num++; SoundQ_tail = i; } // Try to start it! SoundQ_process(); } dxx-rebirth-0.58.1-d2x/main/dumpmine.c000066400000000000000000001033531217717237500174670ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Functions to dump text description of mine. * An editor-only function, called at mine load time. * To be read by a human to verify the correctness and completeness of a mine. * */ #include #include #include #include #include "pstypes.h" #include "console.h" #include "key.h" #include "gr.h" #include "palette.h" #include "inferno.h" #ifdef EDITOR #include "editor/editor.h" #endif #include "dxxerror.h" #include "object.h" #include "wall.h" #include "gamemine.h" #include "robot.h" #include "player.h" #include "newmenu.h" #include "textures.h" #include "bm.h" #include "menu.h" #include "switch.h" #include "fuelcen.h" #include "powerup.h" #include "gameseq.h" #include "polyobj.h" #include "gamesave.h" #ifdef EDITOR extern ubyte bogus_data[64*64]; void dump_used_textures_level(PHYSFS_file *my_file, int level_num); static void say_totals(PHYSFS_file *my_file, const char *level_name); // ---------------------------------------------------------------------------- char *object_types(int objnum) { int type = Objects[objnum].type; Assert((type == OBJ_NONE) || ((type >= 0) && (type < MAX_OBJECT_TYPES))); return Object_type_names[type]; } // ---------------------------------------------------------------------------- char *object_ids(int objnum) { int type = Objects[objnum].type; int id = Objects[objnum].id; switch (type) { case OBJ_ROBOT: return Robot_names[id]; break; case OBJ_POWERUP: return Powerup_names[id]; break; } return NULL; } void err_printf(PHYSFS_file *my_file, char * format, ... ) { va_list args; char message[256]; va_start(args, format ); vsprintf(message,format,args); va_end(args); con_printf(CON_CRITICAL, "%s", message); PHYSFSX_printf(my_file, "%s", message); Errors_in_mine++; } void warning_printf(PHYSFS_file *my_file, char * format, ... ) { va_list args; char message[256]; va_start(args, format ); vsprintf(message,format,args); va_end(args); con_printf(CON_URGENT, "%s", message); PHYSFSX_printf(my_file, "%s", message); } // ---------------------------------------------------------------------------- void write_exit_text(PHYSFS_file *my_file) { int i, j, count; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Exit stuff\n"); // ---------- Find exit triggers ---------- count=0; for (i=0; i 1) err_printf(my_file, "Error: Trigger %i is bound to %i walls.\n", i, count2); } if (count == 0) err_printf(my_file, "Error: No exit trigger in this mine.\n"); else if (count != 1) err_printf(my_file, "Error: More than one exit trigger in this mine.\n"); else PHYSFSX_printf(my_file, "\n"); // ---------- Find exit doors ---------- count = 0; for (i=0; i<=Highest_segment_index; i++) for (j=0; j 1) warning_printf(my_file, "Warning: %i doors are keyed to the blue key.\n", blue_count); if (red_count > 1) warning_printf(my_file, "Warning: %i doors are keyed to the red key.\n", red_count); if (gold_count > 1) warning_printf(my_file, "Warning: %i doors are keyed to the gold key.\n", gold_count); red_count2 = 0; blue_count2 = 0; gold_count2 = 0; for (i=0; i<=Highest_object_index; i++) { if (Objects[i].type == OBJ_POWERUP) if (Objects[i].id == POW_KEY_BLUE) { PHYSFSX_printf(my_file, "The BLUE key is object %i in segment %i\n", i, Objects[i].segnum); blue_count2++; } if (Objects[i].type == OBJ_POWERUP) if (Objects[i].id == POW_KEY_RED) { PHYSFSX_printf(my_file, "The RED key is object %i in segment %i\n", i, Objects[i].segnum); red_count2++; } if (Objects[i].type == OBJ_POWERUP) if (Objects[i].id == POW_KEY_GOLD) { PHYSFSX_printf(my_file, "The GOLD key is object %i in segment %i\n", i, Objects[i].segnum); gold_count2++; } if (Objects[i].contains_count) { if (Objects[i].contains_type == OBJ_POWERUP) { switch (Objects[i].contains_id) { case POW_KEY_BLUE: PHYSFSX_printf(my_file, "The BLUE key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); blue_count2 += Objects[i].contains_count; break; case POW_KEY_GOLD: PHYSFSX_printf(my_file, "The GOLD key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); gold_count2 += Objects[i].contains_count; break; case POW_KEY_RED: PHYSFSX_printf(my_file, "The RED key is contained in object %i (a %s %s) in segment %i\n", i, Object_type_names[Objects[i].type], Robot_names[Objects[i].id], Objects[i].segnum); red_count2 += Objects[i].contains_count; break; default: break; } } } } if (blue_count) if (blue_count2 == 0) err_printf(my_file, "Error: There is a door keyed to the blue key, but no blue key!\n"); if (red_count) if (red_count2 == 0) err_printf(my_file, "Error: There is a door keyed to the red key, but no red key!\n"); if (gold_count) if (gold_count2 == 0) err_printf(my_file, "Error: There is a door keyed to the gold key, but no gold key!\n"); if (blue_count2 > 1) err_printf(my_file, "Error: There are %i blue keys!\n", blue_count2); if (red_count2 > 1) err_printf(my_file, "Error: There are %i red keys!\n", red_count2); if (gold_count2 > 1) err_printf(my_file, "Error: There are %i gold keys!\n", gold_count2); } // ---------------------------------------------------------------------------- void write_control_center_text(PHYSFS_file *my_file) { int i, count, objnum, count2; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Control Center stuff:\n"); count = 0; for (i=0; i<=Highest_segment_index; i++) if (Segment2s[i].special == SEGMENT_IS_CONTROLCEN) { count++; PHYSFSX_printf(my_file, "Segment %3i is a control center.\n", i); objnum = Segments[i].objects; count2 = 0; while (objnum != -1) { if (Objects[objnum].type == OBJ_CNTRLCEN) count2++; objnum = Objects[objnum].next; } if (count2 == 0) PHYSFSX_printf(my_file, "No control center object in control center segment.\n"); else if (count2 != 1) PHYSFSX_printf(my_file, "%i control center objects in control center segment.\n", count2); } if (count == 0) err_printf(my_file, "Error: No control center in this mine.\n"); else if (count != 1) err_printf(my_file, "Error: More than one control center in this mine.\n"); } // ---------------------------------------------------------------------------- void write_fuelcen_text(PHYSFS_file *my_file) { int i; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Fuel Center stuff: (Note: This means fuel, repair, materialize, control centers!)\n"); for (i=0; i 30) { PHYSFSX_printf(my_file, "\nAborted after %i links\n", depth); break; } } } PHYSFSX_printf(my_file, "\n"); } } // ---------------------------------------------------------------------------- // This routine is bogus. It assumes that all centers are matcens, // which is not true. The setting of segnum is bogus. void write_matcen_text(PHYSFS_file *my_file) { int i, j, k; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Materialization centers:\n"); for (i=0; i> 16, Walls[i].trigger, Walls[i].clip_num, Walls[i].keys, Walls[i].state); if (Walls[i].trigger >= Num_triggers) PHYSFSX_printf(my_file, "Wall %03d points to invalid trigger %d\n",i,Walls[i].trigger); segnum = Walls[i].segnum; sidenum = Walls[i].sidenum; if (Segments[segnum].sides[sidenum].wall_num != i) err_printf(my_file, "Error: Wall %i points at segment %i, side %i, but that segment doesn't point back (it's wall_num = %i)\n", i, segnum, sidenum, Segments[segnum].sides[sidenum].wall_num); } for (i=0; isides[j]; if (sidep->wall_num != -1) { if (wall_flags[sidep->wall_num]) err_printf(my_file, "Error: Wall %i appears in two or more segments, including segment %i, side %i.\n", sidep->wall_num, i, j); else wall_flags[sidep->wall_num] = 1; } } } } //typedef struct trigger { // sbyte type; // short flags; // fix value; // fix time; // sbyte link_num; // short num_links; // short seg[MAX_WALLS_PER_LINK]; // short side[MAX_WALLS_PER_LINK]; // } trigger; // ---------------------------------------------------------------------------- void write_player_text(PHYSFS_file *my_file) { int i, num_players=0; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Players:\n"); for (i=0; i<=Highest_object_index; i++) { if (Objects[i].type == OBJ_PLAYER) { num_players++; PHYSFSX_printf(my_file, "Player %2i is object #%3i in segment #%3i.\n", Objects[i].id, i, Objects[i].segnum); } } if (num_players != MAX_PLAYERS) err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS); if (num_players > MAX_MULTI_PLAYERS) err_printf(my_file, "Error: %i player objects. %i are required.\n", num_players, MAX_PLAYERS); } // ---------------------------------------------------------------------------- void write_trigger_text(PHYSFS_file *my_file) { int i, j, w; PHYSFSX_printf(my_file, "-----------------------------------------------------------------------------\n"); PHYSFSX_printf(my_file, "Triggers:\n"); for (i=0; i 4); Assert (filename[namelen-4] == '.'); strcpy(my_filename, filename); strcpy( &my_filename[namelen-4], ".txm"); my_file = PHYSFSX_openWriteBuffered( my_filename ); if (!my_file) { char ErrorMessage[200]; sprintf(ErrorMessage, "ERROR: Unable to open %s\nErrno = %i", my_filename, errno); gr_palette_load(gr_palette); nm_messagebox( NULL, 1, "Ok", ErrorMessage ); return; } dump_used_textures_level(my_file, 0); say_totals(my_file, Gamesave_current_filename); PHYSFSX_printf(my_file, "\nNumber of segments: %4i\n", Highest_segment_index+1); PHYSFSX_printf(my_file, "Number of objects: %4i\n", Highest_object_index+1); PHYSFSX_printf(my_file, "Number of walls: %4i\n", Num_walls); PHYSFSX_printf(my_file, "Number of open doors: %4i\n", Num_open_doors); PHYSFSX_printf(my_file, "Number of triggers: %4i\n", Num_triggers); PHYSFSX_printf(my_file, "Number of matcens: %4i\n", Num_robot_centers); PHYSFSX_printf(my_file, "\n"); write_segment_text(my_file); write_fuelcen_text(my_file); write_matcen_text(my_file); write_player_text(my_file); write_wall_text(my_file); write_trigger_text(my_file); write_exit_text(my_file); // ---------- Find control center segment ---------- write_control_center_text(my_file); // ---------- Show keyed walls ---------- write_key_text(my_file); { int r; r = PHYSFS_close(my_file); if (!r) Int3(); } } // -- // --------------- // -- // Note: This only works for a loaded level because the objects array must be valid. // -- void determine_used_textures_robots(int *tmap_buf) // -- { // -- int i, objnum; // -- polymodel *po; // -- // -- Assert(N_polygon_models); // -- // -- for (objnum=0; objnum <= Highest_object_index; objnum++) { // -- int model_num; // -- // -- if (Objects[objnum].render_type == RT_POLYOBJ) { // -- model_num = Objects[objnum].rtype.pobj_info.model_num; // -- // -- po=&Polygon_models[model_num]; // -- // -- for (i=0;in_textures;i++) { // -- int tli; // -- // -- tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]]; // -- Assert((tli>=0) && (tli<= Num_tmaps)); // -- tmap_buf[tli]++; // -- } // -- } // -- } // -- // -- } // --05/17/95--// ----------------------------------------------------------------------------- // --05/17/95--void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, sbyte *level_tmap_buf, int max_tmap) // --05/17/95--{ // --05/17/95-- int segnum, sidenum; // --05/17/95-- int i, j; // --05/17/95-- // --05/17/95-- for (i=0; isides[sidenum]; // --05/17/95-- // --05/17/95-- if (sidep->wall_num != -1) { // --05/17/95-- int clip_num = Walls[sidep->wall_num].clip_num; // --05/17/95-- if (clip_num != -1) { // --05/17/95-- // --05/17/95-- int num_frames = WallAnims[clip_num].num_frames; // --05/17/95-- // --05/17/95-- wall_buf[clip_num] = 1; // --05/17/95-- // --05/17/95-- for (j=0; jtmap_num >= 0) // --05/17/95-- if (sidep->tmap_num < max_tmap) { // --05/17/95-- tmap_buf[sidep->tmap_num]++; // --05/17/95-- if (level_tmap_buf[sidep->tmap_num] == -1) // --05/17/95-- level_tmap_buf[sidep->tmap_num] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS; // --05/17/95-- } else // --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap. // --05/17/95-- // --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) != 0) // --05/17/95-- if ((sidep->tmap_num2 & 0x3fff) < max_tmap) { // --05/17/95-- tmap_buf[sidep->tmap_num2 & 0x3fff]++; // --05/17/95-- if (level_tmap_buf[sidep->tmap_num2 & 0x3fff] == -1) // --05/17/95-- level_tmap_buf[sidep->tmap_num2 & 0x3fff] = level_num + (!shareware_flag) * NUM_SHAREWARE_LEVELS; // --05/17/95-- } else // --05/17/95-- Int3(); // Error, bogus texture map. Should not be greater than max_tmap. // --05/17/95-- } // --05/17/95-- } // --05/17/95--} // Adam: Change NUM_ADAM_LEVELS to the number of levels. #define NUM_ADAM_LEVELS 30 // Adam: Stick the names here. static const char *const Adam_level_names[NUM_ADAM_LEVELS] = { "D2LEVA-1.LVL", "D2LEVA-2.LVL", "D2LEVA-3.LVL", "D2LEVA-4.LVL", "D2LEVA-S.LVL", "D2LEVB-1.LVL", "D2LEVB-2.LVL", "D2LEVB-3.LVL", "D2LEVB-4.LVL", "D2LEVB-S.LVL", "D2LEVC-1.LVL", "D2LEVC-2.LVL", "D2LEVC-3.LVL", "D2LEVC-4.LVL", "D2LEVC-S.LVL", "D2LEVD-1.LVL", "D2LEVD-2.LVL", "D2LEVD-3.LVL", "D2LEVD-4.LVL", "D2LEVD-S.LVL", "D2LEVE-1.LVL", "D2LEVE-2.LVL", "D2LEVE-3.LVL", "D2LEVE-4.LVL", "D2LEVE-S.LVL", "D2LEVF-1.LVL", "D2LEVF-2.LVL", "D2LEVF-3.LVL", "D2LEVF-4.LVL", "D2LEVF-S.LVL", }; typedef struct BitmapFile { char name[15]; } BitmapFile; extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ]; int Ignore_tmap_num2_error; // ---------------------------------------------------------------------------- void determine_used_textures_level(int load_level_flag, int shareware_flag, int level_num, int *tmap_buf, int *wall_buf, sbyte *level_tmap_buf, int max_tmap) { int segnum, sidenum, objnum=max_tmap; int i, j; Assert(shareware_flag != -17); for (i=0; irender_type == RT_POLYOBJ) { polymodel *po = &Polygon_models[objp->rtype.pobj_info.model_num]; for (i=0; in_textures; i++) { int tli = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index; if ((tli < MAX_BITMAP_FILES) && (tli >= 0)) { tmap_buf[tli]++; if (level_tmap_buf[tli] == -1) level_tmap_buf[tli] = level_num; } else Int3(); // Hmm, It seems this texture is bogus! } } } Ignore_tmap_num2_error = 0; // Process walls and segment sides. for (segnum=0; segnum<=Highest_segment_index; segnum++) { segment *segp = &Segments[segnum]; for (sidenum=0; sidenumsides[sidenum]; if (sidep->wall_num != -1) { int clip_num = Walls[sidep->wall_num].clip_num; if (clip_num != -1) { // -- int num_frames = WallAnims[clip_num].num_frames; wall_buf[clip_num] = 1; for (j=0; j<1; j++) { // Used to do through num_frames, but don't really want all the door01#3 stuff. int tmap_num; tmap_num = Textures[WallAnims[clip_num].frames[j]].index; Assert((tmap_num >= 0) && (tmap_num < MAX_BITMAP_FILES)); tmap_buf[tmap_num]++; if (level_tmap_buf[tmap_num] == -1) level_tmap_buf[tmap_num] = level_num; } } } else if (segp->children[sidenum] == -1) { if (sidep->tmap_num >= 0) { if (sidep->tmap_num < MAX_BITMAP_FILES) { Assert(Textures[sidep->tmap_num].index < MAX_BITMAP_FILES); tmap_buf[Textures[sidep->tmap_num].index]++; if (level_tmap_buf[Textures[sidep->tmap_num].index] == -1) level_tmap_buf[Textures[sidep->tmap_num].index] = level_num; } else Int3(); // Error, bogus texture map. Should not be greater than max_tmap. } if ((sidep->tmap_num2 & 0x3fff) != 0) { if ((sidep->tmap_num2 & 0x3fff) < MAX_BITMAP_FILES) { Assert(Textures[sidep->tmap_num2 & 0x3fff].index < MAX_BITMAP_FILES); tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index]++; if (level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] == -1) level_tmap_buf[Textures[sidep->tmap_num2 & 0x3fff].index] = level_num; } else { if (!Ignore_tmap_num2_error) Int3(); // Error, bogus texture map. Should not be greater than max_tmap. Ignore_tmap_num2_error = 1; sidep->tmap_num2 = 0; } } } } } } // ---------------------------------------------------------------------------- void merge_buffers(int *dest, int *src, int num) { int i; for (i=0; i= 4) { // -- mk, 08/14/95 -- PHYSFSX_printf(my_file, "\n"); // -- mk, 08/14/95 -- count = 0; // -- mk, 08/14/95 -- } } } // --05/17/95--// ----------------------------------------------------------------------------- // --05/17/95--void say_used_once_tmaps(PHYSFS_file *my_file, int *tb, sbyte *tb_lnum) // --05/17/95--{ // --05/17/95-- int i; // --05/17/95-- char *level_name; // --05/17/95-- // --05/17/95-- for (i=0; i= NUM_SHAREWARE_LEVELS) { // --05/17/95-- Assert((level_num - NUM_SHAREWARE_LEVELS >= 0) && (level_num - NUM_SHAREWARE_LEVELS < NUM_REGISTERED_LEVELS)); // --05/17/95-- level_name = Registered_level_names[level_num - NUM_SHAREWARE_LEVELS]; // --05/17/95-- } else { // --05/17/95-- Assert((level_num >= 0) && (level_num < NUM_SHAREWARE_LEVELS)); // --05/17/95-- level_name = Shareware_level_names[level_num]; // --05/17/95-- } // --05/17/95-- // --05/17/95-- PHYSFSX_printf(my_file, "Texture %3i %8s used only once on level %s\n", i, TmapInfo[i].filename, level_name); // --05/17/95-- } // --05/17/95--} // ---------------------------------------------------------------------------- void say_used_once_tmaps(PHYSFS_file *my_file, int *tb, sbyte *tb_lnum) { int i; const char *level_name; for (i=0; i= 4) { PHYSFSX_printf(my_file, "\n"); count = 0; } } } // ---------------------------------------------------------------------------- void say_unused_walls(PHYSFS_file *my_file, int *tb) { int i; for (i=0; i #include #include #include #include "gr.h" #include "inferno.h" #include "game.h" #include "vclip.h" #include "effects.h" #include "bm.h" #include "u_mem.h" #include "textures.h" #include "cntrlcen.h" #include "dxxerror.h" int Num_effects; eclip Effects[MAX_EFFECTS]; void init_special_effects() { int i; for (i=0;iflags & EF_STOPPED) continue; ec->time_left -= FrameTime; while (ec->time_left < 0) { ec->time_left += ec->vc.frame_time; ec->frame_count++; if (ec->frame_count >= ec->vc.num_frames) { if (ec->flags & EF_ONE_SHOT) { Assert(ec->segnum!=-1); Assert(ec->sidenum>=0 && ec->sidenum<6); Assert(ec->dest_bm_num!=0 && Segments[ec->segnum].sides[ec->sidenum].tmap_num2!=0); Segments[ec->segnum].sides[ec->sidenum].tmap_num2 = ec->dest_bm_num | (Segments[ec->segnum].sides[ec->sidenum].tmap_num2&0xc000); //replace with destoyed ec->flags &= ~EF_ONE_SHOT; ec->segnum = -1; //done with this } ec->frame_count = 0; } } if (ec->flags & EF_CRITICAL) continue; if (ec->crit_clip!=-1 && Control_center_destroyed) { int n = ec->crit_clip; //*ec->bm_ptr = &GameBitmaps[Effects[n].vc.frames[Effects[n].frame_count].index]; if (ec->changing_wall_texture != -1) Textures[ec->changing_wall_texture] = Effects[n].vc.frames[Effects[n].frame_count]; if (ec->changing_object_texture != -1) ObjBitmaps[ec->changing_object_texture] = Effects[n].vc.frames[Effects[n].frame_count]; } else { // *ec->bm_ptr = &GameBitmaps[ec->vc.frames[ec->frame_count].index]; if (ec->changing_wall_texture != -1) Textures[ec->changing_wall_texture] = ec->vc.frames[ec->frame_count]; if (ec->changing_object_texture != -1) ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[ec->frame_count]; } } } void restore_effect_bitmap_icons() { int i; for (i=0;ibm_ptr != -1); ec->flags |= EF_STOPPED; ec->frame_count = 0; //*ec->bm_ptr = &GameBitmaps[ec->vc.frames[0].index]; if (ec->changing_wall_texture != -1) Textures[ec->changing_wall_texture] = ec->vc.frames[0]; if (ec->changing_object_texture != -1) ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[0]; } //restart a stopped effect void restart_effect(int effect_num) { Effects[effect_num].flags &= ~EF_STOPPED; //Assert(Effects[effect_num].bm_ptr != -1); } /* * reads n eclip structs from a PHYSFS_file */ int eclip_read_n(eclip *ec, int n, PHYSFS_file *fp) { int i; for (i = 0; i < n; i++) { vclip_read_n(&ec[i].vc, 1, fp); ec[i].time_left = PHYSFSX_readFix(fp); ec[i].frame_count = PHYSFSX_readInt(fp); ec[i].changing_wall_texture = PHYSFSX_readShort(fp); ec[i].changing_object_texture = PHYSFSX_readShort(fp); ec[i].flags = PHYSFSX_readInt(fp); ec[i].crit_clip = PHYSFSX_readInt(fp); ec[i].dest_bm_num = PHYSFSX_readInt(fp); ec[i].dest_vclip = PHYSFSX_readInt(fp); ec[i].dest_eclip = PHYSFSX_readInt(fp); ec[i].dest_size = PHYSFSX_readFix(fp); ec[i].sound_num = PHYSFSX_readInt(fp); ec[i].segnum = PHYSFSX_readInt(fp); ec[i].sidenum = PHYSFSX_readInt(fp); } return i; } dxx-rebirth-0.58.1-d2x/main/effects.h000066400000000000000000000051151217717237500172720ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Headerfile for effects.c * */ #ifndef _EFFECTS_H #define _EFFECTS_H #include "vclip.h" #define MAX_EFFECTS 110 //flags for eclips. If no flags are set, always plays #define EF_CRITICAL 1 //this doesn't get played directly (only when mine critical) #define EF_ONE_SHOT 2 //this is a special that gets played once #define EF_STOPPED 4 //this has been stopped #define ECLIP_NUM_FUELCEN 2 #define ECLIP_NUM_BOSS 53 #define ECLIP_NUM_FORCE_FIELD 78 typedef struct eclip { vclip vc; //imbedded vclip fix time_left; //for sequencing int frame_count; //for sequencing short changing_wall_texture; //Which element of Textures array to replace. short changing_object_texture; //Which element of ObjBitmapPtrs array to replace. int flags; //see above int crit_clip; //use this clip instead of above one when mine critical int dest_bm_num; //use this bitmap when monitor destroyed int dest_vclip; //what vclip to play when exploding int dest_eclip; //what eclip to play when exploding fix dest_size; //3d size of explosion int sound_num; //what sound this makes int segnum,sidenum; //what seg & side, for one-shot clips } __pack__ eclip; extern int Num_effects; extern eclip Effects[MAX_EFFECTS]; // Set up special effects. extern void init_special_effects(); // Clear any active one-shots void reset_special_effects(); // Function called in game loop to do effects. extern void do_special_effects(); // Restore bitmap extern void restore_effect_bitmap_icons(); //stop an effect from animating. Show first frame. void stop_effect(int effect_num); //restart a stopped effect void restart_effect(int effect_num); /* * reads n eclip structs from a PHYSFS_file */ extern int eclip_read_n(eclip *ec, int n, PHYSFS_file *fp); #endif /* _EFFECTS_H */ dxx-rebirth-0.58.1-d2x/main/endlevel.c000066400000000000000000001201451217717237500174450ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Code for rendering external scenes * */ //#define SLEW_ON 1 //#define _MARK_ON #include #include #include #include // for isspace #include "fix.h" #include "vecmat.h" #include "gr.h" #include "3d.h" #include "dxxerror.h" #include "palette.h" #include "iff.h" #include "console.h" #include "texmap.h" #include "fvi.h" #include "u_mem.h" #include "sounds.h" #include "playsave.h" #include "inferno.h" #include "endlevel.h" #include "object.h" #include "game.h" #include "gamepal.h" #include "screens.h" #include "gauges.h" #include "wall.h" #include "terrain.h" #include "polyobj.h" #include "bm.h" #include "gameseq.h" #include "newdemo.h" #include "gamepal.h" #include "multi.h" #include "vclip.h" #include "fireball.h" #include "text.h" #include "digi.h" #include "songs.h" #include "movie.h" #include "render.h" #include "titles.h" #ifdef OGL #include "ogl_init.h" #endif #ifdef EDITOR #include "editor/editor.h" #endif typedef struct flythrough_data { object *obj; vms_angvec angles; //orientation in angles vms_vector step; //how far in a second vms_vector angstep; //rotation per second fix speed; //how fast object is moving vms_vector headvec; //where we want to be pointing int first_time; //flag for if first time through fix offset_frac; //how far off-center as portion of way fix offset_dist; //how far currently off-center } flythrough_data; //endlevel sequence states #define EL_OFF 0 //not in endlevel #define EL_FLYTHROUGH 1 //auto-flythrough in tunnel #define EL_LOOKBACK 2 //looking back at player #define EL_OUTSIDE 3 //flying outside for a while #define EL_STOPPED 4 //stopped, watching explosion #define EL_PANNING 5 //panning around, watching player #define EL_CHASING 6 //chasing player to station #define SHORT_SEQUENCE 1 //if defined, end sequnce when panning starts //#define STATION_ENABLED 1 //if defined, load & use space station model int Endlevel_sequence = 0; extern fix player_speed; int transition_segnum,exit_segnum; object *endlevel_camera; #define FLY_SPEED i2f(50) void do_endlevel_flythrough(int n); void draw_stars(); int find_exit_side(object *obj); void generate_starfield(); void start_endlevel_flythrough(int n,object *obj,fix speed); void start_rendered_endlevel_sequence(); #ifdef D2_OEM static const char movie_table[] = { 'a','a','a','a','d','d','d','d' }; #else static const char movie_table[] = { 'a','b','c', #ifndef SHAREWARE 'a', 'd','f','d','f', 'g','h','i','g', 'j','k','l','j', 'm','o','m','o', 'p','q','p','q' #endif }; #endif #define N_MOVIES (sizeof(movie_table) / sizeof(*movie_table)) #ifndef SHAREWARE #ifdef D2_OEM static const char movie_table_secret[] = {'a','d'}; #else static const char movie_table_secret[] = {'a','d','g','j','m','p'}; #endif #define N_MOVIES_SECRET (sizeof(movie_table_secret) / sizeof(*movie_table_secret)) #else #define N_MOVIES_SECRET 0 #endif #define FLY_ACCEL i2f(5) fix cur_fly_speed,desired_fly_speed; extern int matt_find_connect_side(int seg0,int seg1); grs_bitmap *satellite_bitmap,*station_bitmap,*terrain_bitmap; //!!*exit_bitmap, vms_vector satellite_pos,satellite_upvec; //!!grs_bitmap **exit_bitmap_list[1]; int station_modelnum,exit_modelnum,destroyed_exit_modelnum; vms_vector station_pos = {0xf8c4<<10,0x3c1c<<12,0x372<<10}; #ifdef STATION_ENABLED grs_bitmap *station_bitmap; grs_bitmap **station_bitmap_list[1]; int station_modelnum; #endif vms_vector mine_exit_point; vms_vector mine_ground_exit_point; vms_vector mine_side_exit_point; vms_matrix mine_exit_orient; int outside_mine; grs_bitmap terrain_bm_instance; grs_bitmap satellite_bm_instance; //find delta between two angles fixang delta_ang(fixang a,fixang b) { fixang delta0,delta1; return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1; } //return though which side of seg0 is seg1 int matt_find_connect_side(int seg0,int seg1) { segment *Seg=&Segments[seg0]; int i; for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i; return -1; } extern int Kmatrix_nomovie_message; #if defined(D2_OEM) || defined(COMPILATION) #define MOVIE_REQUIRED 0 #else #define MOVIE_REQUIRED 1 #endif //returns movie played status. see movie.h int start_endlevel_movie() { char movie_name[] = "esa.mve"; int r; ubyte save_pal[768]; //Assert(PLAYING_BUILTIN_MISSION); //only play movie for built-in mission //Assert(N_MOVIES >= Last_level); //Assert(N_MOVIES_SECRET >= -Last_secret_level); if (is_SHAREWARE) return 0; if (!is_D2_OEM) if (Current_level_num == Last_level) return 1; //don't play movie if (Current_level_num > 0) movie_name[2] = movie_table[Current_level_num-1]; else { return 0; //no escapes for secret level } memcpy(save_pal,gr_palette,768); r=PlayMovie(movie_name,(Game_mode & GM_MULTI)?0:MOVIE_REQUIRED); if (Newdemo_state == ND_STATE_PLAYBACK) { set_screen_mode(SCREEN_GAME); memcpy(gr_palette,save_pal,768); } return (r); } void free_endlevel_data() { if (terrain_bm_instance.bm_data) d_free(terrain_bm_instance.bm_data); if (satellite_bm_instance.bm_data) d_free(satellite_bm_instance.bm_data); free_light_table(); free_height_array(); } void init_endlevel() { //##satellite_bitmap = bm_load("earth.bbm"); //##terrain_bitmap = bm_load("moon.bbm"); //## //##load_terrain("matt5b.bbm"); //load bitmap as height array //##//load_terrain("ttest2.bbm"); //load bitmap as height array #ifdef STATION_ENABLED station_bitmap = bm_load("steel3.bbm"); station_bitmap_list[0] = &station_bitmap; station_modelnum = load_polygon_model("station.pof",1,station_bitmap_list,NULL); #endif //!! exit_bitmap = bm_load("steel1.bbm"); //!! exit_bitmap_list[0] = &exit_bitmap; //!! exit_modelnum = load_polygon_model("exit01.pof",1,exit_bitmap_list,NULL); //!! destroyed_exit_modelnum = load_polygon_model("exit01d.pof",1,exit_bitmap_list,NULL); generate_starfield(); terrain_bm_instance.bm_data = satellite_bm_instance.bm_data = NULL; } object external_explosion; int ext_expl_playing,mine_destroyed; extern fix flash_scale; vms_angvec exit_angles={-0xa00,0,0}; vms_matrix surface_orient; int endlevel_data_loaded=0; int endlevel_movie_played = MOVIE_NOT_PLAYED; void start_endlevel_sequence() { int i; reset_rear_view(); //turn off rear view if set - NOTE: make sure this happens before we pause demo recording!! if (Newdemo_state == ND_STATE_RECORDING) // stop demo recording Newdemo_state = ND_STATE_PAUSED; if (Newdemo_state == ND_STATE_PLAYBACK) { // don't do this if in playback mode if (PLAYING_BUILTIN_MISSION) // only play movie for built-in mission { window_set_visible(Game_wind, 0); // suspend the game, including drawing start_endlevel_movie(); window_set_visible(Game_wind, 1); } strcpy(last_palette_loaded,""); //force palette load next time return; } if (Player_is_dead || ConsoleObject->flags&OF_SHOULD_BE_DEAD) return; //don't start if dead! // Dematerialize Buddy! for (i=0; i<=Highest_object_index; i++) if (Objects[i].type == OBJ_ROBOT) if (Robot_info[Objects[i].id].companion) { object_create_explosion(Objects[i].segnum, &Objects[i].pos, F1_0*7/2, VCLIP_POWERUP_DISAPPEARANCE ); Objects[i].flags |= OF_SHOULD_BE_DEAD; } Players[Player_num].homing_object_dist = -F1_0; // Turn off homing sound. #ifdef NETWORK if (Game_mode & GM_MULTI) { multi_send_endlevel_start(0); multi_do_protocol_frame(1, 1); } #endif window_set_visible(Game_wind, 0); // suspend the game, including drawing if (PLAYING_BUILTIN_MISSION) // only play movie for built-in mission if (!(Game_mode & GM_MULTI)) endlevel_movie_played = start_endlevel_movie(); window_set_visible(Game_wind, 1); if (!(Game_mode & GM_MULTI) && (endlevel_movie_played == MOVIE_NOT_PLAYED) && endlevel_data_loaded) { //don't have movie. Do rendered sequence, if available int exit_models_loaded = 0; if (Piggy_hamfile_version < 3) exit_models_loaded = 1; // built-in for PC shareware else exit_models_loaded = load_exit_models(); if (exit_models_loaded) { start_rendered_endlevel_sequence(); return; } } PlayerFinishedLevel(0); //done with level } void start_rendered_endlevel_sequence() { #ifndef NDEBUG int last_segnum; #endif int exit_side,tunnel_length; { int segnum,old_segnum,entry_side,i; //count segments in exit tunnel old_segnum = ConsoleObject->segnum; exit_side = find_exit_side(ConsoleObject); segnum = Segments[old_segnum].children[exit_side]; tunnel_length = 0; do { entry_side = matt_find_connect_side(segnum,old_segnum); exit_side = Side_opposite[entry_side]; old_segnum = segnum; segnum = Segments[segnum].children[exit_side]; tunnel_length++; } while (segnum >= 0); if (segnum != -2) { PlayerFinishedLevel(0); //don't do special sequence return; } #ifndef NDEBUG last_segnum = old_segnum; #endif //now pick transition segnum 1/3 of the way in old_segnum = ConsoleObject->segnum; exit_side = find_exit_side(ConsoleObject); segnum = Segments[old_segnum].children[exit_side]; i=tunnel_length/3; while (i--) { entry_side = matt_find_connect_side(segnum,old_segnum); exit_side = Side_opposite[entry_side]; old_segnum = segnum; segnum = Segments[segnum].children[exit_side]; } transition_segnum = segnum; } #ifdef NETWORK if (Game_mode & GM_MULTI) { multi_send_endlevel_start(0); multi_do_protocol_frame(1, 1); } #endif #ifndef NDEBUG Assert(last_segnum == exit_segnum); #endif songs_play_song( SONG_ENDLEVEL, 0 ); Endlevel_sequence = EL_FLYTHROUGH; ConsoleObject->movement_type = MT_NONE; //movement handled by flythrough ConsoleObject->control_type = CT_NONE; Game_suspended |= SUSP_ROBOTS; //robots don't move cur_fly_speed = desired_fly_speed = FLY_SPEED; start_endlevel_flythrough(0,ConsoleObject,cur_fly_speed); //initialize HUD_init_message_literal(HM_DEFAULT, TXT_EXIT_SEQUENCE ); outside_mine = ext_expl_playing = 0; flash_scale = f1_0; //init_endlevel(); mine_destroyed=0; } extern flythrough_data fly_objects[]; extern object *slew_obj; vms_angvec player_angles,player_dest_angles; vms_angvec camera_desired_angles,camera_cur_angles; #define CHASE_TURN_RATE (0x4000/4) //max turn per second //returns bitmask of which angles are at dest. bits 0,1,2 = p,b,h int chase_angles(vms_angvec *cur_angles,vms_angvec *desired_angles) { vms_angvec delta_angs,alt_angles,alt_delta_angs; fix total_delta,alt_total_delta; fix frame_turn; int mask=0; delta_angs.p = desired_angles->p - cur_angles->p; delta_angs.h = desired_angles->h - cur_angles->h; delta_angs.b = desired_angles->b - cur_angles->b; total_delta = abs(delta_angs.p) + abs(delta_angs.b) + abs(delta_angs.h); alt_angles.p = f1_0/2 - cur_angles->p; alt_angles.b = cur_angles->b + f1_0/2; alt_angles.h = cur_angles->h + f1_0/2; alt_delta_angs.p = desired_angles->p - alt_angles.p; alt_delta_angs.h = desired_angles->h - alt_angles.h; alt_delta_angs.b = desired_angles->b - alt_angles.b; alt_total_delta = abs(alt_delta_angs.p) + abs(alt_delta_angs.b) + abs(alt_delta_angs.h); if (alt_total_delta < total_delta) { *cur_angles = alt_angles; delta_angs = alt_delta_angs; } frame_turn = fixmul(FrameTime,CHASE_TURN_RATE); if (abs(delta_angs.p) < frame_turn) { cur_angles->p = desired_angles->p; mask |= 1; } else if (delta_angs.p > 0) cur_angles->p += frame_turn; else cur_angles->p -= frame_turn; if (abs(delta_angs.b) < frame_turn) { cur_angles->b = desired_angles->b; mask |= 2; } else if (delta_angs.b > 0) cur_angles->b += frame_turn; else cur_angles->b -= frame_turn; //cur_angles->b = 0; if (abs(delta_angs.h) < frame_turn) { cur_angles->h = desired_angles->h; mask |= 4; } else if (delta_angs.h > 0) cur_angles->h += frame_turn; else cur_angles->h -= frame_turn; return mask; } void stop_endlevel_sequence() { Interpolation_method = 0; select_cockpit(PlayerCfg.CockpitMode[0]); Endlevel_sequence = EL_OFF; PlayerFinishedLevel(0); } #define VCLIP_BIG_PLAYER_EXPLOSION 58 //--unused-- vms_vector upvec = {0,f1_0,0}; //find the angle between the player's heading & the station void get_angs_to_object(vms_angvec *av,vms_vector *targ_pos,vms_vector *cur_pos) { vms_vector tv; vm_vec_sub(&tv,targ_pos,cur_pos); vm_extract_angles_vector(av,&tv); } void do_endlevel_frame() { static fix timer; static fix bank_rate; vms_vector save_last_pos; static fix explosion_wait1=0; static fix explosion_wait2=0; static fix ext_expl_halflife; save_last_pos = ConsoleObject->last_pos; //don't let move code change this object_move_all(); ConsoleObject->last_pos = save_last_pos; if (ext_expl_playing) { external_explosion.lifeleft -= FrameTime; do_explosion_sequence(&external_explosion); if (external_explosion.lifeleft < ext_expl_halflife) mine_destroyed = 1; if (external_explosion.flags & OF_SHOULD_BE_DEAD) ext_expl_playing = 0; } if (cur_fly_speed != desired_fly_speed) { fix delta = desired_fly_speed - cur_fly_speed; fix frame_accel = fixmul(FrameTime,FLY_ACCEL); if (abs(delta) < frame_accel) cur_fly_speed = desired_fly_speed; else if (delta > 0) cur_fly_speed += frame_accel; else cur_fly_speed -= frame_accel; } //do big explosions if (!outside_mine) { if (Endlevel_sequence==EL_OUTSIDE) { vms_vector tvec; vm_vec_sub(&tvec,&ConsoleObject->pos,&mine_side_exit_point); if (vm_vec_dot(&tvec,&mine_exit_orient.fvec) > 0) { object *tobj; vms_vector mov_vec; outside_mine = 1; tobj = object_create_explosion(exit_segnum,&mine_side_exit_point,i2f(50),VCLIP_BIG_PLAYER_EXPLOSION); // Move explosion to Viewer to draw it in front of mine exit model vm_vec_normalized_dir_quick(&mov_vec,&Viewer->pos,&tobj->pos); vm_vec_scale_add2(&tobj->pos,&mov_vec,i2f(30)); if (tobj) { external_explosion = *tobj; tobj->flags |= OF_SHOULD_BE_DEAD; flash_scale = 0; //kill lights in mine ext_expl_halflife = tobj->lifeleft; ext_expl_playing = 1; } digi_link_sound_to_pos( SOUND_BIG_ENDLEVEL_EXPLOSION, exit_segnum, 0, &mine_side_exit_point, 0, i2f(3)/4 ); } } //do explosions chasing player if ((explosion_wait1-=FrameTime) < 0) { vms_vector tpnt; int segnum; static int sound_count; vm_vec_scale_add(&tpnt,&ConsoleObject->pos,&ConsoleObject->orient.fvec,-ConsoleObject->size*5); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.rvec,(d_rand()-D_RAND_MAX/2)*15); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(d_rand()-D_RAND_MAX/2)*15); segnum = find_point_seg(&tpnt,ConsoleObject->segnum); if (segnum != -1) { object_create_explosion(segnum,&tpnt,i2f(20),VCLIP_BIG_PLAYER_EXPLOSION); if (d_rand()<10000 || ++sound_count==7) { //pseudo-random digi_link_sound_to_pos( SOUND_TUNNEL_EXPLOSION, segnum, 0, &tpnt, 0, F1_0 ); sound_count=0; } } explosion_wait1 = 0x2000 + d_rand()/4; } } //do little explosions on walls if (Endlevel_sequence >= EL_FLYTHROUGH && Endlevel_sequence < EL_OUTSIDE) if ((explosion_wait2-=FrameTime) < 0) { vms_vector tpnt; fvi_query fq; fvi_info hit_data; //create little explosion on wall vm_vec_copy_scale(&tpnt,&ConsoleObject->orient.rvec,(d_rand()-RAND_MAX/2)*100); vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(d_rand()-RAND_MAX/2)*100); vm_vec_add2(&tpnt,&ConsoleObject->pos); if (Endlevel_sequence == EL_FLYTHROUGH) vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,d_rand()*200); else vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,d_rand()*60); //find hit point on wall fq.p0 = &ConsoleObject->pos; fq.p1 = &tpnt; fq.startseg = ConsoleObject->segnum; fq.rad = 0; fq.thisobjnum = 0; fq.ignore_obj_list = NULL; fq.flags = 0; find_vector_intersection(&fq,&hit_data); if (hit_data.hit_type==HIT_WALL && hit_data.hit_seg!=-1) object_create_explosion(hit_data.hit_seg,&hit_data.hit_pnt,i2f(3)+d_rand()*6,VCLIP_SMALL_EXPLOSION); explosion_wait2 = (0xa00 + d_rand()/8)/2; } switch (Endlevel_sequence) { case EL_OFF: return; case EL_FLYTHROUGH: { do_endlevel_flythrough(0); if (ConsoleObject->segnum == transition_segnum) { if (PLAYING_BUILTIN_MISSION && endlevel_movie_played != MOVIE_NOT_PLAYED) stop_endlevel_sequence(); else { int objnum; //songs_play_song( SONG_ENDLEVEL, 0 ); Endlevel_sequence = EL_LOOKBACK; objnum = obj_create(OBJ_CAMERA, 0, ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0, CT_NONE,MT_NONE,RT_NONE); if (objnum == -1) { //can't get object, so abort stop_endlevel_sequence(); return; } Viewer = endlevel_camera = &Objects[objnum]; select_cockpit(CM_LETTERBOX); fly_objects[1] = fly_objects[0]; fly_objects[1].obj = endlevel_camera; fly_objects[1].speed = (5*cur_fly_speed)/4; fly_objects[1].offset_frac = 0x4000; vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,i2f(7)); timer=0x20000; } } break; } case EL_LOOKBACK: { do_endlevel_flythrough(0); do_endlevel_flythrough(1); if (timer>0) { timer -= FrameTime; if (timer < 0) //reduce speed fly_objects[1].speed = fly_objects[0].speed; } if (endlevel_camera->segnum == exit_segnum) { vms_angvec cam_angles,exit_seg_angles; Endlevel_sequence = EL_OUTSIDE; timer = i2f(2); vm_vec_negate(&endlevel_camera->orient.fvec); vm_vec_negate(&endlevel_camera->orient.rvec); vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); vm_extract_angles_matrix(&exit_seg_angles,&mine_exit_orient); bank_rate = (-exit_seg_angles.b - cam_angles.b)/2; ConsoleObject->control_type = endlevel_camera->control_type = CT_NONE; #ifdef SLEW_ON slew_obj = endlevel_camera; #endif } break; } case EL_OUTSIDE: { #ifndef SLEW_ON vms_angvec cam_angles; #endif vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifndef SLEW_ON vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,-2*cur_fly_speed)); vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.uvec,fixmul(FrameTime,-cur_fly_speed/10)); vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient); cam_angles.b += fixmul(bank_rate,FrameTime); vm_angles_2_matrix(&endlevel_camera->orient,&cam_angles); #endif timer -= FrameTime; if (timer < 0) { Endlevel_sequence = EL_STOPPED; vm_extract_angles_matrix(&player_angles,&ConsoleObject->orient); timer = i2f(3); } break; } case EL_STOPPED: { get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); timer -= FrameTime; if (timer < 0) { #ifdef SLEW_ON slew_obj = endlevel_camera; _do_slew_movement(endlevel_camera,1); timer += FrameTime; //make time stop break; #else #ifdef SHORT_SEQUENCE stop_endlevel_sequence(); #else Endlevel_sequence = EL_PANNING; vm_extract_angles_matrix(&camera_cur_angles,&endlevel_camera->orient); timer = i2f(3); if (Game_mode & GM_MULTI) { // try to skip part of the seq if multiplayer stop_endlevel_sequence(); return; } #endif //SHORT_SEQUENCE #endif //SLEW_ON } break; } #ifndef SHORT_SEQUENCE case EL_PANNING: { #ifndef SLEW_ON int mask; #endif get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifdef SLEW_ON _do_slew_movement(endlevel_camera,1); #else get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); mask = chase_angles(&camera_cur_angles,&camera_desired_angles); vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); if ((mask&5) == 5) { vms_vector tvec; Endlevel_sequence = EL_CHASING; vm_vec_normalized_dir_quick(&tvec,&station_pos,&ConsoleObject->pos); vm_vector_2_matrix(&ConsoleObject->orient,&tvec,&surface_orient.uvec,NULL); desired_fly_speed *= 2; } #endif break; } case EL_CHASING: { fix d,speed_scale; #ifdef SLEW_ON _do_slew_movement(endlevel_camera,1); #endif get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos); chase_angles(&camera_cur_angles,&camera_desired_angles); #ifndef SLEW_ON vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles); #endif d = vm_vec_dist_quick(&ConsoleObject->pos,&endlevel_camera->pos); speed_scale = fixdiv(d,i2f(0x20)); if (dpos); chase_angles(&player_angles,&player_dest_angles); vm_angles_2_matrix(&ConsoleObject->orient,&player_angles); vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed)); #ifndef SLEW_ON vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,fixmul(speed_scale,cur_fly_speed))); if (vm_vec_dist(&ConsoleObject->pos,&station_pos) < i2f(10)) stop_endlevel_sequence(); #endif break; } #endif //ifdef SHORT_SEQUENCE } } #define MIN_D 0x100 //find which side to fly out of int find_exit_side(object *obj) { int i; vms_vector prefvec,segcenter,sidevec; fix best_val=-f2_0; int best_side; segment *pseg = &Segments[obj->segnum]; //find exit side vm_vec_normalized_dir_quick(&prefvec,&obj->pos,&obj->last_pos); compute_segment_center(&segcenter,pseg); best_side=-1; for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) { fix d; if (pseg->children[i]!=-1) { compute_center_point_on_side(&sidevec,pseg,i); vm_vec_normalized_dir_quick(&sidevec,&sidevec,&segcenter); d = vm_vec_dotprod(&sidevec,&prefvec); if (labs(d) < MIN_D) d=0; if (d > best_val) {best_val=d; best_side=i;} } } Assert(best_side!=-1); return best_side; } extern fix Render_zoom; //the player's zoom factor extern vms_vector Viewer_eye; //valid during render void draw_exit_model() { vms_vector model_pos; int f=15,u=0; //21; g3s_lrgb lrgb = { f1_0, f1_0, f1_0 }; vm_vec_scale_add(&model_pos,&mine_exit_point,&mine_exit_orient.fvec,i2f(f)); vm_vec_scale_add2(&model_pos,&mine_exit_orient.uvec,i2f(u)); draw_polygon_model(&model_pos,&mine_exit_orient,NULL,(mine_destroyed)?destroyed_exit_modelnum:exit_modelnum,0,lrgb,NULL,NULL); } int exit_point_bmx,exit_point_bmy; fix satellite_size = i2f(400); #define SATELLITE_DIST i2f(1024) #define SATELLITE_WIDTH satellite_size #define SATELLITE_HEIGHT ((satellite_size*9)/4) //((satellite_size*5)/2) void render_external_scene(fix eye_offset) { #ifdef OGL int orig_Render_depth = Render_depth; #endif g3s_lrgb lrgb = { f1_0, f1_0, f1_0 }; Viewer_eye = Viewer->pos; if (eye_offset) vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.rvec,eye_offset); g3_set_view_matrix(&Viewer->pos,&Viewer->orient,Render_zoom); //g3_draw_horizon(BM_XRGB(0,0,0),BM_XRGB(16,16,16)); //,-1); gr_clear_canvas(BM_XRGB(0,0,0)); g3_start_instance_matrix(&vmd_zero_vector,&surface_orient); draw_stars(); g3_done_instance(); { //draw satellite vms_vector delta; g3s_point p,top_pnt; g3_rotate_point(&p,&satellite_pos); g3_rotate_delta_vec(&delta,&satellite_upvec); g3_add_delta_vec(&top_pnt,&p,&delta); if (! (p.p3_codes & CC_BEHIND)) { int save_im = Interpolation_method; //p.p3_flags &= ~PF_PROJECTED; //g3_project_point(&p); if (! (p.p3_flags & PF_OVERFLOW)) { Interpolation_method = 0; //gr_bitmapm(f2i(p.p3_sx)-32,f2i(p.p3_sy)-32,satellite_bitmap); g3_draw_rod_tmap(satellite_bitmap,&p,SATELLITE_WIDTH,&top_pnt,SATELLITE_WIDTH,lrgb); Interpolation_method = save_im; } } } #ifdef STATION_ENABLED draw_polygon_model(&station_pos,&vmd_identity_matrix,NULL,station_modelnum,0,lrgb,NULL,NULL); #endif #ifdef OGL ogl_toggle_depth_test(0); Render_depth = (200-(vm_vec_dist_quick(&mine_ground_exit_point, &Viewer_eye)/F1_0))/36; #endif render_terrain(&mine_ground_exit_point,exit_point_bmx,exit_point_bmy); #ifdef OGL Render_depth = orig_Render_depth; ogl_toggle_depth_test(1); #endif draw_exit_model(); if (ext_expl_playing) { if ( PlayerCfg.AlphaEffects ) // set nice transparency/blending for the big explosion gr_settransblend( GR_FADE_OFF, GR_BLEND_ADDITIVE_C ); draw_fireball(&external_explosion); gr_settransblend( GR_FADE_OFF, GR_BLEND_NORMAL ); // revert any transparency/blending setting back to normal } Lighting_on=0; render_object(ConsoleObject); Lighting_on=1; } #define MAX_STARS 500 vms_vector stars[MAX_STARS]; void generate_starfield() { int i; for (i=0;ipos; if (Viewer->type == OBJ_PLAYER ) vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.fvec,(Viewer->size*3)/4); if (eye_offset) vm_vec_scale_add2(&Viewer_eye,&Viewer->orient.rvec,eye_offset); #ifdef EDITOR if (EditorWindow) Viewer_eye = Viewer->pos; #endif if (Endlevel_sequence >= EL_OUTSIDE) { start_seg_num = exit_segnum; } else { start_seg_num = find_point_seg(&Viewer_eye,Viewer->segnum); if (start_seg_num==-1) start_seg_num = Viewer->segnum; } if (Endlevel_sequence == EL_LOOKBACK) { vms_matrix headm,viewm; vms_angvec angles = {0,0,0x7fff}; vm_angles_2_matrix(&headm,&angles); vm_matrix_x_matrix(&viewm,&Viewer->orient,&headm); g3_set_view_matrix(&Viewer_eye,&viewm,Render_zoom); } else g3_set_view_matrix(&Viewer_eye,&Viewer->orient,Render_zoom); render_mine(start_seg_num,eye_offset, 0); } void render_endlevel_frame(fix eye_offset) { g3_start_frame(); if (Endlevel_sequence < EL_OUTSIDE) endlevel_render_mine(eye_offset); else render_external_scene(eye_offset); g3_end_frame(); } ///////////////////////// copy of flythrough code for endlevel #define MAX_FLY_OBJECTS 2 flythrough_data fly_objects[MAX_FLY_OBJECTS]; flythrough_data *flydata; int matt_find_connect_side(int seg0,int seg1); void compute_segment_center(vms_vector *vp,segment *sp); fixang delta_ang(fixang a,fixang b); fixang interp_angle(fixang dest,fixang src,fixang step); #define DEFAULT_SPEED i2f(16) #define MIN_D 0x100 //if speed is zero, use default speed void start_endlevel_flythrough(int n,object *obj,fix speed) { flydata = &fly_objects[n]; flydata->obj = obj; flydata->first_time = 1; flydata->speed = speed?speed:DEFAULT_SPEED; flydata->offset_frac = 0; } static vms_angvec *angvec_add2_scale(vms_angvec *dest,vms_vector *src,fix s) { dest->p += fixmul(src->x,s); dest->b += fixmul(src->z,s); dest->h += fixmul(src->y,s); return dest; } #define MAX_ANGSTEP 0x4000 //max turn per second #define MAX_SLIDE_PER_SEGMENT 0x10000 void do_endlevel_flythrough(int n) { object *obj; segment *pseg; int old_player_seg; flydata = &fly_objects[n]; obj = flydata->obj; old_player_seg = obj->segnum; //move the player for this frame if (!flydata->first_time) { vm_vec_scale_add2(&obj->pos,&flydata->step,FrameTime); angvec_add2_scale(&flydata->angles,&flydata->angstep,FrameTime); vm_angles_2_matrix(&obj->orient,&flydata->angles); } //check new player seg update_object_seg(obj); pseg = &Segments[obj->segnum]; if (flydata->first_time || obj->segnum != old_player_seg) { //moved into new seg vms_vector curcenter,nextcenter; fix step_size,seg_time; short entry_side,exit_side = -1;//what sides we entry and leave through vms_vector dest_point; //where we are heading (center of exit_side) vms_angvec dest_angles; //where we want to be pointing vms_matrix dest_orient; int up_side=0; entry_side=0; //find new exit side if (!flydata->first_time) { entry_side = matt_find_connect_side(obj->segnum,old_player_seg); exit_side = Side_opposite[entry_side]; } if (flydata->first_time || entry_side==-1 || pseg->children[exit_side]==-1) exit_side = find_exit_side(obj); { //find closest side to align to fix d,largest_d=-f1_0; int i; for (i=0;i<6;i++) { #ifdef COMPACT_SEGS vms_vector v1; get_side_normal(pseg, i, 0, &v1 ); d = vm_vec_dot(&v1,&flydata->obj->orient.uvec); #else d = vm_vec_dot(&pseg->sides[i].normals[0],&flydata->obj->orient.uvec); #endif if (d > largest_d) {largest_d = d; up_side=i;} } } //update target point & angles compute_center_point_on_side(&dest_point,pseg,exit_side); if (pseg->children[exit_side] == -2) nextcenter = dest_point; else compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]); //update target point and movement points //offset object sideways if (flydata->offset_frac) { int s0=-1,s1=0,i; vms_vector s0p,s1p; fix dist; for (i=0;i<6;i++) if (i!=entry_side && i!=exit_side && i!=up_side && i!=Side_opposite[up_side]) { if (s0==-1) s0 = i; else s1 = i; } compute_center_point_on_side(&s0p,pseg,s0); compute_center_point_on_side(&s1p,pseg,s1); dist = fixmul(vm_vec_dist(&s0p,&s1p),flydata->offset_frac); if (dist-flydata->offset_dist > MAX_SLIDE_PER_SEGMENT) dist = flydata->offset_dist + MAX_SLIDE_PER_SEGMENT; flydata->offset_dist = dist; vm_vec_scale_add2(&dest_point,&obj->orient.rvec,dist); } vm_vec_sub(&flydata->step,&dest_point,&obj->pos); step_size = vm_vec_normalize_quick(&flydata->step); vm_vec_scale(&flydata->step,flydata->speed); compute_segment_center(&curcenter,pseg); vm_vec_sub(&flydata->headvec,&nextcenter,&curcenter); #ifdef COMPACT_SEGS { vms_vector _v1; get_side_normal(pseg, up_side, 0, &_v1 ); vm_vector_2_matrix(&dest_orient,&flydata->headvec,&_v1,NULL); } #else vm_vector_2_matrix(&dest_orient,&flydata->headvec,&pseg->sides[up_side].normals[0],NULL); #endif vm_extract_angles_matrix(&dest_angles,&dest_orient); if (flydata->first_time) vm_extract_angles_matrix(&flydata->angles,&obj->orient); seg_time = fixdiv(step_size,flydata->speed); //how long through seg if (seg_time) { flydata->angstep.x = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.p,dest_angles.p),seg_time))); flydata->angstep.z = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.b,dest_angles.b),seg_time))); flydata->angstep.y = max(-MAX_ANGSTEP,min(MAX_ANGSTEP,fixdiv(delta_ang(flydata->angles.h,dest_angles.h),seg_time))); } else { flydata->angles = dest_angles; flydata->angstep.x = flydata->angstep.y = flydata->angstep.z = 0; } } flydata->first_time=0; } #define JOY_NULL 15 #define ROT_SPEED 8 //rate of rotation while key held down #define VEL_SPEED (15) //rate of acceleration while key held down extern short old_joy_x,old_joy_y; //position last time around #include "key.h" #include "joy.h" #ifdef SLEW_ON //this is a special routine for slewing around external scene int _do_slew_movement(object *obj, int check_keys ) { int moved = 0; vms_vector svel, movement; //scaled velocity (per this frame) vms_matrix rotmat,new_pm; vms_angvec rotang; if (keyd_pressed[KEY_PAD5]) vm_vec_zero(&obj->phys_info.velocity); if (check_keys) { obj->phys_info.velocity.x += VEL_SPEED * keyd_pressed[KEY_PAD9] * FrameTime; obj->phys_info.velocity.x -= VEL_SPEED * keyd_pressed[KEY_PAD7] * FrameTime; obj->phys_info.velocity.y += VEL_SPEED * keyd_pressed[KEY_PADMINUS] * FrameTime; obj->phys_info.velocity.y -= VEL_SPEED * keyd_pressed[KEY_PADPLUS] * FrameTime; obj->phys_info.velocity.z += VEL_SPEED * keyd_pressed[KEY_PAD8] * FrameTime; obj->phys_info.velocity.z -= VEL_SPEED * keyd_pressed[KEY_PAD2] * FrameTime; rotang.pitch = rotang.bank = rotang.head = 0; rotang.pitch += keyd_pressed[KEY_LBRACKET] * FrameTime / ROT_SPEED; rotang.pitch -= keyd_pressed[KEY_RBRACKET] * FrameTime / ROT_SPEED; rotang.bank += keyd_pressed[KEY_PAD1] * FrameTime / ROT_SPEED; rotang.bank -= keyd_pressed[KEY_PAD3] * FrameTime / ROT_SPEED; rotang.head += keyd_pressed[KEY_PAD6] * FrameTime / ROT_SPEED; rotang.head -= keyd_pressed[KEY_PAD4] * FrameTime / ROT_SPEED; } else rotang.pitch = rotang.bank = rotang.head = 0; moved = rotang.pitch | rotang.bank | rotang.head; vm_angles_2_matrix(&rotmat,&rotang); vm_matrix_x_matrix(&new_pm,&obj->orient,&rotmat); obj->orient = new_pm; vm_transpose_matrix(&new_pm); //make those columns rows moved |= obj->phys_info.velocity.x | obj->phys_info.velocity.y | obj->phys_info.velocity.z; svel = obj->phys_info.velocity; vm_vec_scale(&svel,FrameTime); //movement in this frame vm_vec_rotate(&movement,&svel,&new_pm); vm_vec_add2(&obj->pos,&movement); moved |= (movement.x || movement.y || movement.z); return moved; } #endif #define LINE_LEN 80 #define NUM_VARS 8 #define STATION_DIST i2f(1024) int convert_ext( char *dest, char *ext ) { char *t; t = strchr(dest,'.'); if (t && (t-dest <= 8)) { t[1] = ext[0]; t[2] = ext[1]; t[3] = ext[2]; return 1; } else return 0; } //called for each level to load & setup the exit sequence void load_endlevel_data(int level_num) { char filename[13]; char line[LINE_LEN],*p; PHYSFS_file *ifile; int var,segnum,sidenum; int exit_side = 0; int have_binary = 0; endlevel_data_loaded = 0; //not loaded yet try_again: ; if (level_num<0) //secret level strcpy(filename,Secret_level_names[-level_num-1]); else //normal level strcpy(filename,Level_names[level_num-1]); if (!convert_ext(filename,"END")) Error("Error converting filename <%s> for endlevel data\n",filename); ifile = PHYSFSX_openReadBuffered(filename); if (!ifile) { convert_ext(filename,"txb"); if (!strcmp(filename, Briefing_text_filename) || !strcmp(filename, Ending_text_filename)) return; // Don't want to interpret the briefing as an end level sequence! ifile = PHYSFSX_openReadBuffered(filename); if (!ifile) { if (level_num==1) { con_printf(CON_DEBUG, "Cannot load file text of binary version of <%s>\n",filename); endlevel_data_loaded = 0; // won't be able to play endlevel sequence return; } else { level_num = 1; goto try_again; } } have_binary = 1; } //ok...this parser is pretty simple. It ignores comments, but //everything else must be in the right place var = 0; while (PHYSFSX_fgets(line,LINE_LEN,ifile)) { if (have_binary) decode_text_line (line); if ((p=strchr(line,';'))!=NULL) *p = 0; //cut off comment for (p=line+strlen(line);p>line && isspace(*p);*p--=0); for (p=line;isspace(*p);p++); if (!*p) //empty line continue; switch (var) { case 0: { //ground terrain int iff_error; ubyte pal[768]; if (terrain_bm_instance.bm_data) d_free(terrain_bm_instance.bm_data); Assert(terrain_bm_instance.bm_data == NULL); iff_error = iff_read_bitmap(p,&terrain_bm_instance,BM_LINEAR,pal); if (iff_error != IFF_NO_ERROR) { con_printf(CON_DEBUG, "Can't load exit terrain from file %s: IFF error: %s\n", p, iff_errormsg(iff_error)); endlevel_data_loaded = 0; // won't be able to play endlevel sequence PHYSFS_close(ifile); return; } terrain_bitmap = &terrain_bm_instance; gr_remap_bitmap_good( terrain_bitmap, pal, iff_transparent_color, -1); break; } case 1: //height map load_terrain(p); break; case 2: sscanf(p,"%d,%d",&exit_point_bmx,&exit_point_bmy); break; case 3: //exit heading exit_angles.h = i2f(atoi(p))/360; break; case 4: { //planet bitmap int iff_error; ubyte pal[768]; if (satellite_bm_instance.bm_data) d_free(satellite_bm_instance.bm_data); iff_error = iff_read_bitmap(p,&satellite_bm_instance,BM_LINEAR,pal); if (iff_error != IFF_NO_ERROR) { con_printf(CON_DEBUG, "Can't load exit satellite from file %s: IFF error: %s\n", p, iff_errormsg(iff_error)); endlevel_data_loaded = 0; // won't be able to play endlevel sequence PHYSFS_close(ifile); return; } satellite_bitmap = &satellite_bm_instance; gr_remap_bitmap_good( satellite_bitmap, pal, iff_transparent_color, -1); break; } case 5: //earth pos case 7: { //station pos vms_matrix tm; vms_angvec ta; int pitch,head; sscanf(p,"%d,%d",&head,&pitch); ta.h = i2f(head)/360; ta.p = -i2f(pitch)/360; ta.b = 0; vm_angles_2_matrix(&tm,&ta); if (var==5) satellite_pos = tm.fvec; //vm_vec_copy_scale(&satellite_pos,&tm.fvec,SATELLITE_DIST); else station_pos = tm.fvec; break; } case 6: //planet size satellite_size = i2f(atoi(p)); break; } var++; } Assert(var == NUM_VARS); // OK, now the data is loaded. Initialize everything //find the exit sequence by searching all segments for a side with //children == -2 for (segnum=0,exit_segnum=-1;exit_segnum==-1 && segnum<=Highest_segment_index;segnum++) for (sidenum=0;sidenum<6;sidenum++) if (Segments[segnum].children[sidenum] == -2) { exit_segnum = segnum; exit_side = sidenum; break; } Assert(exit_segnum!=-1); compute_segment_center(&mine_exit_point,&Segments[exit_segnum]); extract_orient_from_segment(&mine_exit_orient,&Segments[exit_segnum]); compute_center_point_on_side(&mine_side_exit_point,&Segments[exit_segnum],exit_side); vm_vec_scale_add(&mine_ground_exit_point,&mine_exit_point,&mine_exit_orient.uvec,-i2f(20)); //compute orientation of surface { vms_vector tv; vms_matrix exit_orient,tm; vm_angles_2_matrix(&exit_orient,&exit_angles); vm_transpose_matrix(&exit_orient); vm_matrix_x_matrix(&surface_orient,&mine_exit_orient,&exit_orient); vm_copy_transpose_matrix(&tm,&surface_orient); vm_vec_rotate(&tv,&station_pos,&tm); vm_vec_scale_add(&station_pos,&mine_exit_point,&tv,STATION_DIST); vm_vec_rotate(&tv,&satellite_pos,&tm); vm_vec_scale_add(&satellite_pos,&mine_exit_point,&tv,SATELLITE_DIST); vm_vector_2_matrix(&tm,&tv,&surface_orient.uvec,NULL); vm_vec_copy_scale(&satellite_upvec,&tm.uvec,SATELLITE_HEIGHT); } PHYSFS_close(ifile); endlevel_data_loaded = 1; } dxx-rebirth-0.58.1-d2x/main/endlevel.h000066400000000000000000000027141217717237500174530ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header for endlevel.c * */ #ifndef _OUTSIDE_H #define _OUTSIDE_H #include "object.h" extern int Endlevel_sequence; void do_endlevel_frame(); void stop_endlevel_sequence(); void start_endlevel_sequence(); void render_endlevel_frame(fix eye_offset); void render_external_scene(); void draw_exit_model(); void free_endlevel_data(); void init_endlevel(); extern grs_bitmap *terrain_bitmap; //*satellite_bitmap,*station_bitmap, extern int exit_segnum; //@@extern vms_vector mine_exit_point; //@@extern object external_explosion; //@@extern int ext_expl_playing; //called for each level to load & setup the exit sequence void load_endlevel_data(int level_num); extern int exit_modelnum, destroyed_exit_modelnum; #endif /* _OUTSIDE_H */ dxx-rebirth-0.58.1-d2x/main/escort.c000066400000000000000000001570371217717237500171600ustar00rootroot00000000000000/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Escort robot behavior. * */ #include // for printf() #include // for rand() and qsort() #include // for memset() #include "window.h" #include "inferno.h" #include "console.h" #include "fix.h" #include "vecmat.h" #include "gr.h" #include "3d.h" #include "palette.h" #include "timer.h" #include "object.h" #include "dxxerror.h" #include "ai.h" #include "robot.h" #include "fvi.h" #include "physics.h" #include "wall.h" #include "player.h" #include "fireball.h" #include "game.h" #include "powerup.h" #include "cntrlcen.h" #include "gauges.h" #include "key.h" #include "fuelcen.h" #include "sounds.h" #include "screens.h" #include "text.h" #include "gamefont.h" #include "newmenu.h" #include "playsave.h" #include "gameseq.h" #include "automap.h" #include "laser.h" #include "escort.h" #ifdef EDITOR #include "editor/editor.h" #endif extern void multi_send_stolen_items(); void say_escort_goal(int goal_num); void show_escort_menu(char *msg); static const char *const Escort_goal_text[MAX_ESCORT_GOALS] = { "BLUE KEY", "YELLOW KEY", "RED KEY", "REACTOR", "EXIT", "ENERGY", "ENERGYCEN", "SHIELD", "POWERUP", "ROBOT", "HOSTAGES", "SPEW", "SCRAM", "EXIT", "BOSS", "MARKER 1", "MARKER 2", "MARKER 3", "MARKER 4", "MARKER 5", "MARKER 6", "MARKER 7", "MARKER 8", "MARKER 9", // -- too much work -- "KAMIKAZE " }; int Max_escort_length = 200; int Escort_kill_object = -1; ubyte Stolen_items[MAX_STOLEN_ITEMS]; int Stolen_item_index; fix64 Escort_last_path_created = 0; int Escort_goal_object = ESCORT_GOAL_UNSPECIFIED, Escort_special_goal = -1, Escort_goal_index = -1, Buddy_messages_suppressed = 0; fix64 Buddy_sorry_time; int Buddy_objnum, Buddy_allowed_to_talk; int Looking_for_marker; int Last_buddy_key; fix64 Last_buddy_message_time; void init_buddy_for_level(void) { int i; Buddy_allowed_to_talk = 0; Buddy_objnum = -1; Escort_goal_object = ESCORT_GOAL_UNSPECIFIED; Escort_special_goal = -1; Escort_goal_index = -1; Buddy_messages_suppressed = 0; for (i=0; i<=Highest_object_index; i++) if (Robot_info[Objects[i].id].companion) break; if (i <= Highest_object_index) Buddy_objnum = i; Buddy_sorry_time = -F1_0; Looking_for_marker = -1; Last_buddy_key = -1; } // ----------------------------------------------------------------------------- // See if segment from curseg through sidenum is reachable. // Return true if it is reachable, else return false. int segment_is_reachable(int curseg, int sidenum) { int wall_num, rval; segment *segp = &Segments[curseg]; if (!IS_CHILD(segp->children[sidenum])) return 0; wall_num = segp->sides[sidenum].wall_num; // If no wall, then it is reachable if (wall_num == -1) return 1; rval = ai_door_is_openable(NULL, segp, sidenum); return rval; // -- MK, 10/17/95 -- // -- MK, 10/17/95 -- // Hmm, a closed wall. I think this mean not reachable. // -- MK, 10/17/95 -- if (Walls[wall_num].type == WALL_CLOSED) // -- MK, 10/17/95 -- return 0; // -- MK, 10/17/95 -- // -- MK, 10/17/95 -- if (Walls[wall_num].type == WALL_DOOR) { // -- MK, 10/17/95 -- if (Walls[wall_num].keys == KEY_NONE) { // -- MK, 10/17/95 -- return 1; // @MK, 10/17/95: Be consistent with ai_door_is_openable // -- MK, 10/17/95 -- // -- if (Walls[wall_num].flags & WALL_DOOR_LOCKED) // -- MK, 10/17/95 -- // -- return 0; // -- MK, 10/17/95 -- // -- else // -- MK, 10/17/95 -- // -- return 1; // -- MK, 10/17/95 -- } else if (Walls[wall_num].keys == KEY_BLUE) // -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY); // -- MK, 10/17/95 -- else if (Walls[wall_num].keys == KEY_GOLD) // -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY); // -- MK, 10/17/95 -- else if (Walls[wall_num].keys == KEY_RED) // -- MK, 10/17/95 -- return (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY); // -- MK, 10/17/95 -- else // -- MK, 10/17/95 -- Int3(); // Impossible! Doesn't have no key, but doesn't have any key! // -- MK, 10/17/95 -- } else // -- MK, 10/17/95 -- return 1; // -- MK, 10/17/95 -- // -- MK, 10/17/95 -- Int3(); // Hmm, thought 'if' above had to return! // -- MK, 10/17/95 -- return 0; } // ----------------------------------------------------------------------------- // Create a breadth-first list of segments reachable from current segment. // max_segs is maximum number of segments to search. Use MAX_SEGMENTS to search all. // On exit, *length <= max_segs. // Input: // start_seg // Output: // bfs_list: array of shorts, each reachable segment. Includes start segment. // length: number of elements in bfs_list void create_bfs_list(int start_seg, short bfs_list[], int *length, int max_segs) { int head, tail; sbyte visited[MAX_SEGMENTS]; for (unsigned s=0; schildren[i]; if (IS_CHILD(connected_seg) && (visited[connected_seg] == 0)) { if (segment_is_reachable(curseg, i)) { bfs_list[head++] = connected_seg; if (head >= max_segs) break; visited[connected_seg] = 1; Assert(head < MAX_SEGMENTS); } } } } *length = head; } // ----------------------------------------------------------------------------- // Return true if ok for buddy to talk, else return false. // Buddy is allowed to talk if the segment he is in does not contain a blastable wall that has not been blasted // AND he has never yet, since being initialized for level, been allowed to talk. int ok_for_buddy_to_talk(void) { int i; segment *segp; if (Buddy_objnum == -1) return 0; if (Objects[Buddy_objnum].type != OBJ_ROBOT) { Buddy_allowed_to_talk = 0; return 0; } if (Buddy_allowed_to_talk) return 1; if ((Objects[Buddy_objnum].type == OBJ_ROBOT) && (Buddy_objnum <= Highest_object_index) && !Robot_info[Objects[Buddy_objnum].id].companion) { for (i=0; i<=Highest_object_index; i++) if (Robot_info[Objects[i].id].companion) break; if (i > Highest_object_index) return 0; else Buddy_objnum = i; } segp = &Segments[Objects[Buddy_objnum].segnum]; for (i=0; isides[i].wall_num; if (wall_num != -1) { if ((Walls[wall_num].type == WALL_BLASTABLE) && !(Walls[wall_num].flags & WALL_BLASTED)) return 0; } // Check one level deeper. if (IS_CHILD(segp->children[i])) { int j; segment *csegp = &Segments[segp->children[i]]; for (j=0; jsides[j].wall_num; if (wall2 != -1) { if ((Walls[wall2].type == WALL_BLASTABLE) && !(Walls[wall2].flags & WALL_BLASTED)) return 0; } } } } Buddy_allowed_to_talk = 1; return 1; } // -------------------------------------------------------------------------------------------- void detect_escort_goal_accomplished(int index) { int i,j; int detected = 0; if (!Buddy_allowed_to_talk) return; // If goal is to go away, how can it be achieved? if (Escort_special_goal == ESCORT_GOAL_SCRAM) return; // See if goal found was a key. Need to handle default goals differently. // Note, no buddy_met_goal sound when blow up reactor or exit. Not great, but ok // since for reactor, noisy, for exit, buddy is disappearing. if ((Escort_special_goal == -1) && (Escort_goal_index == index)) { detected = 1; goto dega_ok; } if ((Escort_goal_index <= ESCORT_GOAL_RED_KEY) && (index >= 0)) { if (Objects[index].type == OBJ_POWERUP) { if (Objects[index].id == POW_KEY_BLUE) { if (Escort_goal_index == ESCORT_GOAL_BLUE_KEY) { detected = 1; goto dega_ok; } } else if (Objects[index].id == POW_KEY_GOLD) { if (Escort_goal_index == ESCORT_GOAL_GOLD_KEY) { detected = 1; goto dega_ok; } } else if (Objects[index].id == POW_KEY_RED) { if (Escort_goal_index == ESCORT_GOAL_RED_KEY) { detected = 1; goto dega_ok; } } } } if (Escort_special_goal != -1) { if (Escort_special_goal == ESCORT_GOAL_ENERGYCEN) { if (index == -4) detected = 1; else { for (i=0; iflags & OF_PLAYER_DROPPED) return objnum; } if (curobjp->type == objtype) { // Don't find escort robots if looking for robot! if ((curobjp->type == OBJ_ROBOT) && (Robot_info[curobjp->id].companion)) ; else if (objid == -1) { if ((objtype == OBJ_POWERUP) && (curobjp->id != POW_KEY_BLUE) && (curobjp->id != POW_KEY_GOLD) && (curobjp->id != POW_KEY_RED)) return objnum; else return objnum; } else if (curobjp->id == objid) return objnum; } if (objtype == OBJ_POWERUP) if (curobjp->contains_count) if (curobjp->contains_type == OBJ_POWERUP) if (curobjp->contains_id == objid) return objnum; objnum = curobjp->next; } } return -1; } // ----------------------------------------------------------------------------- // Return nearest object of interest. // If special == ESCORT_GOAL_PLAYER_SPEW, then looking for any object spewed by player. // -1 means object does not exist in mine. // -2 means object does exist in mine, but buddy-bot can't reach it (eg, behind triggered wall) int exists_in_mine(int start_seg, int objtype, int objid, int special) { int segindex, segnum; short bfs_list[MAX_SEGMENTS]; int length; create_bfs_list(start_seg, bfs_list, &length, MAX_SEGMENTS); if (objtype == FUELCEN_CHECK) { for (segindex=0; segindex