2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
14 char _3dfx_rcsid[] = "$Id: 3dfx.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
31 GrHwConfiguration hwconfig;
32 int _3dfx_triangles_rendered_pre_clip;
33 int _3dfx_triangles_rendered_post_clip;
34 int _3dfx_tex_combine, _3dfx_tex_combine_top, _3dfx_tex_combine_bottom;
35 int _3dfx_current_handle;
36 int _3dfx_handle_to_index[_3DFX_MAX_HANDLES];
37 int _3dfx_bytes_downloaded_this_frame;
38 int _3dfx_download_requests_made;
39 int _3dfx_download_requests_granted;
40 int _3dfx_drawing_polygon_model;
41 int _3dfx_current_bitmap_index;
42 int _3dfx_skip_ddraw, _3dfx_no_texture, _3dfx_allow_transparency;
43 float _3dfx_oo_stencil;
45 int _3dfx_should_sync;
46 int _3dfx_rendering_poly_obj;
47 int _3dfx_tex_combine_orientation;
48 int _3dfx_tex_combine_superx;
49 int _3dfx_tex_combine_top_flags,
50 _3dfx_tex_combine_bottom_flags;
52 int _3dfx_no_bilinear;
55 typedef struct BitmapFile {
58 extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
60 _3dfxTextureInfo _3dfx_texture_info[MAX_BITMAP_FILES];
62 void MyErrorHandler( const char *s, FxBool fatal )
64 mprintf( ( 0, "3Dfx err_handler - %s\n", s ) );
71 int _3dfx_Init( void )
75 mprintf( ( 0, "Initializing 3Dfx Interactive Voodoo Graphics hardware\n" ) );
77 grErrorSetCallback( MyErrorHandler );
79 if ( !grSstQueryHardware( &hwconfig ) )
81 mprintf( ( 0, "3Dfx Interactive Voodoo Graphics not found!" ) );
85 if ( !grSstOpen( GR_RESOLUTION_640x480,
92 mprintf( ( 0, "3Dfx Interactive Voodoo Graphics not opened!" ) );
96 if ( getenv( "GLIDE_OFF" ) != 0 )
98 mprintf( ( 0, "3Dfx Interactive Voodoo Graphics disabled!" ) );
102 grDepthBufferMode( GR_DEPTHBUFFER_DISABLE );
103 grBufferClear( 0x00000000, 0, 0 );
104 grCullMode( GR_CULL_DISABLE );
107 ** configure environment variable controlled options
109 if ( getenv( "GLIDE_NO_BILINEAR" ) )
110 _3dfx_no_bilinear = 1;
111 if ( getenv( "GLIDE_NO_DDRAW" ) )
112 _3dfx_skip_ddraw = 1;
113 if ( getenv( "GLIDE_NO_TEXTURE" ) )
114 _3dfx_no_texture = 1;
115 if ( getenv( "GLIDE_NO_TRANSPARENCY" ) )
116 _3dfx_allow_transparency = 0;
118 _3dfx_allow_transparency = 1;
119 if ( getenv( "GLIDE_NO_SYNC" ) )
120 _3dfx_should_sync = 0;
122 _3dfx_should_sync = 1;
125 ** allocate texture memory
127 for ( i = 0; i < MAX_BITMAP_FILES; i++ )
129 _3dfx_texture_info[i].handle = GR_NULL_MIPMAP_HANDLE;
132 _3dfx_current_handle = 0;
133 for ( i = 0; i < _3DFX_MAX_HANDLES; i++ )
137 id = grTexAllocateMemory( GR_TMU0,
138 GR_MIPMAPLEVELMASK_BOTH,
144 GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
145 GR_TEXTUREFILTER_BILINEAR, _3dfx_no_bilinear ? GR_TEXTUREFILTER_POINT_SAMPLED : GR_TEXTUREFILTER_BILINEAR,
149 if ( id == GR_NULL_MIPMAP_HANDLE )
151 mprintf( ( 0, " - unexpected null mmid returned\n" ) );
159 void _3dfx_DownloadTexture( int index )
161 GrMipMapId_t id = _3dfx_current_handle;
162 _3dfxTextureInfo *info = &_3dfx_texture_info[index];
163 int texture_being_replaced;
164 GrTextureFormat_t fmt;
167 ** make sure the texture is in main memory
169 _3dfx_download_requests_made++;
171 if ( !( info->flags & _3DFX_TF_IN_MEMORY ) )
173 _3dfx_LoadTexture( index, AllBitmaps[index].name );
175 if ( !( info->flags & _3DFX_TF_IN_MEMORY ) )
180 ** if it's already in memory then we're cool
182 if ( info->flags & _3DFX_TF_DOWNLOADED )
188 ** otherwise we gotta do a swaperoo. So, find the old texture and
189 ** give it the bad news.
191 texture_being_replaced = _3dfx_handle_to_index[id];
193 _3dfx_texture_info[texture_being_replaced].flags &= ~_3DFX_TF_DOWNLOADED;
196 ** update the new texture
198 _3dfx_handle_to_index[id] = index;
200 info->flags |= _3DFX_TF_DOWNLOADED;
202 if ( info->flags & _3DFX_TF_SUPERX )
203 fmt = GR_TEXFMT_ARGB_4444;
204 else if ( info->flags & _3DFX_TF_TRANSPARENT )
205 fmt = GR_TEXFMT_ARGB_1555;
207 fmt = GR_TEXFMT_RGB_565;
209 grTexChangeAttributes( id,
215 GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
218 grTexDownloadMipMap( id, info->data, 0 );
220 if ( ++_3dfx_current_handle >= _3DFX_MAX_HANDLES )
221 _3dfx_current_handle = 0;
223 _3dfx_bytes_downloaded_this_frame += SIZEOF_64x64_16BIT_TEXTURE;
225 _3dfx_download_requests_granted++;
228 int _3dfx_LoadTextureFromDisk( const char *name, int index )
231 int success_or_fail = 0;
233 if ( gu3dfGetInfo( name, &info ) )
235 _3dfx_texture_info[index].flags = 0;
237 if ( info.header.large_lod != GR_LOD_64 )
242 if ( info.header.aspect_ratio != GR_ASPECT_1x1 )
250 info.data = ( void * ) malloc( info.mem_required );
252 if ( info.data == 0 )
254 mprintf( ( 0, "info.data == 0\n" ) );
258 if ( !gu3dfLoad( name, &info ) )
260 mprintf( ( 0, "couldn't gu3dfLoad() '%s'\n", name ) );
265 _3dfx_texture_info[index].data = info.data;
266 _3dfx_texture_info[index].flags = _3DFX_TF_IN_MEMORY;
267 _3dfx_texture_info[index].mem_required = info.mem_required;
269 if ( info.header.format == GR_TEXFMT_ARGB_1555 )
270 _3dfx_texture_info[index].flags |= _3DFX_TF_TRANSPARENT;
271 else if ( info.header.format == GR_TEXFMT_ARGB_4444 )
272 _3dfx_texture_info[index].flags |= ( _3DFX_TF_SUPERX | _3DFX_TF_TRANSPARENT );
277 return success_or_fail;
283 void _3dfx_LoadTexture( int index, const char *_name )
286 ** load a non-ABM file
288 if ( !strchr( _name, '#' ) )
292 strcpy( name, _name );
293 sprintf( name, "3DF\\%s.3df", _name );
295 _3dfx_LoadTextureFromDisk( name, index );
302 char _3dfx_filename[256], _3dfx_name[256], _3dfx_extension[256];
304 strcpy( _3dfx_name, _name );
305 *strchr( _3dfx_name, '#' ) = 0;
306 strcpy( _3dfx_extension, strchr( _name, '#' ) + 1 );
307 sprintf( _3dfx_filename, "ABM\\%s.%03s", _3dfx_name, _3dfx_extension );
309 _3dfx_LoadTextureFromDisk( _3dfx_filename, index );
316 void _3dfx_BufferSwap( void )
318 if ( _3dfx_available )
320 while ( ( ( grSstStatus() >> 28 ) & 7 ) > 0 )
323 grBufferSwap( _3dfx_should_sync );
324 grBufferClear( 0xFFFF0000, 0, 0 );
327 _3dfx_bytes_downloaded_this_frame = 0;
328 _3dfx_download_requests_made = 0;
329 _3dfx_download_requests_granted = 0;
330 _3dfx_triangles_rendered_pre_clip = 0;
331 _3dfx_triangles_rendered_post_clip = 0;
335 ** _3dfx_DrawFlatShadedPoly
337 #define SNAP( a ) ( ( fix ) ( (a) & ( 0xFFFFF000L ) ) )
339 void _3dfx_DrawFlatShadedPoly( g3ds_tmap *Tmap1, unsigned long argb )
343 float lowest_y = 10000, highest_y = 0;
344 float lowest_x = 10000, highest_x = 0;
346 for ( i = 0; i < Tmap1->nv; i++ )
348 float x = SNAP( Tmap1->verts[i].x2d ) * fix_to_float;
349 float y = SNAP( Tmap1->verts[i].y2d ) * fix_to_float;
351 if ( x < lowest_x ) lowest_x = x;
352 if ( x > highest_x ) highest_x = x;
353 if ( y < lowest_y ) lowest_y = y;
354 if ( y > highest_y ) highest_y = y;
357 if ( highest_x < 0 || highest_y < 0 || lowest_x > 639 || lowest_y > 479 )
359 mprintf( ( 0, "3dfx - rejecting fspoly way off screen\n" ) );
363 guColorCombineFunction( GR_COLORCOMBINE_CCRGB );
364 grConstantColorValue( argb );
366 a.x = SNAP( Tmap1->verts[0].x2d ) * fix_to_float;
367 a.y = SNAP( Tmap1->verts[0].y2d ) * fix_to_float;
369 for ( i = 1; i < Tmap1->nv - 1; i++ )
371 b.x = SNAP( Tmap1->verts[i].x2d ) * fix_to_float;
372 b.y = SNAP( Tmap1->verts[i].y2d ) * fix_to_float;
373 c.x = SNAP( Tmap1->verts[i+1].x2d ) * fix_to_float;
374 c.y = SNAP( Tmap1->verts[i+1].y2d ) * fix_to_float;
376 grDrawTriangle( &a, &b, &c );
381 ** _3dfx_DownloadAndUseTexture
383 void _3dfx_DownloadAndUseTexture( unsigned long index )
385 _3dfx_DownloadTexture( index );
386 if ( _3dfx_texture_info[index].handle != GR_NULL_MIPMAP_HANDLE )
387 grTexSource( _3dfx_texture_info[index].handle );
391 ** _3dfx_decompose_tmap_and_draw
393 void _3dfx_decompose_tmap_and_draw( int nv, g3s_point **pointlist, uvl *uvl_copy, grs_bitmap *bm )
396 uvl uvl_copy_3dfx[8];
397 g3s_point *pointlist2[8];
399 pointlist2[0] = pointlist[0];
400 uvl_copy_3dfx[0] = uvl_copy[0];
402 _3dfx_DownloadAndUseTexture( bm->bm_handle );
404 for ( i = 0; i < nv - 2; i++ )
408 for ( j = 1; j < 3; j++ )
410 pointlist2[j] = pointlist[i+j];
411 uvl_copy_3dfx[j] = uvl_copy[i+j];
414 if ( _3dfx_available )
416 g3_draw_tmap( 3, pointlist2, (g3s_uvl *) uvl_copy_3dfx, bm );
418 _3dfx_triangles_rendered_pre_clip++;
423 ** _3dfx_PaletteToARGB
425 unsigned long _3dfx_PaletteToARGB( int pindex )
427 unsigned long result = 0;
429 result |= ( ( unsigned long ) gr_palette[pindex*3+0] ) << 18;
430 result |= ( ( unsigned long ) gr_palette[pindex*3+1] ) << 10;
431 result |= ( ( unsigned long ) gr_palette[pindex*3+2] ) << 2;
439 #define _3DFX_FB_WIDTH 1024
441 void _3dfx_BlitScale( grs_bitmap *source_bmp, grs_bitmap *dest_bmp,
442 int x0, int y0, int x1, int y1,
443 fix u0, fix v0, fix u1, fix v1, int orient )
445 if ( _3dfx_available )
447 if ( source_bmp->bm_flags & BM_FLAG_RLE )
452 unsigned long * dbits;
455 du = (u1-u0) / (x1-x0);
456 dv = (v1-v0) / (y1-y0);
462 grLfbBypassMode( GR_LFBBYPASS_ENABLE );
464 fb = ( unsigned long * ) grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
465 grLfbWriteMode( GR_LFBWRITEMODE_8888 );
467 guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
469 for ( y = y0; y <= y1; y++, v += dv )
471 extern ubyte scale_rle_data[];
473 decode_row( source_bmp, f2i( v ) );
475 sbits = scale_rle_data + f2i( u0 );
476 dbits = fb + _3DFX_FB_WIDTH * y + x0;
480 for ( x = x0; x <= x1; x++ )
482 int pindex = sbits[ u >> 16 ];
485 *dbits = _3dfx_PaletteToARGB( pindex );
491 grLfbBypassMode( GR_LFBBYPASS_DISABLE );
497 mprintf( ( 0, "_3dfx_BlitScale() - non RLE not implemented yet\n" ) );
505 #define _3DFX_FB_WIDTH 1024
507 void _3dfx_Blit( int x, int y, grs_bitmap *bm )
509 if ( _3dfx_available )
511 if ( bm->bm_flags & BM_FLAG_RLE )
514 unsigned long * dbits;
520 grLfbBypassMode( GR_LFBBYPASS_ENABLE );
522 fb = ( unsigned long * ) grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
523 grLfbWriteMode( GR_LFBWRITEMODE_8888 );
525 guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
527 for ( v = 0; v < bm->bm_h; v++ )
529 extern ubyte scale_rle_data[];
534 sbits = scale_rle_data;
535 dbits = fb + _3DFX_FB_WIDTH * ( y + v ) + x;
537 for ( u = 0; u < bm->bm_w; u++ )
539 int pindex = sbits[ u ];
542 *dbits = _3dfx_PaletteToARGB( pindex );
546 grLfbBypassMode( GR_LFBBYPASS_DISABLE );
552 mprintf( ( 0, "_3dfx_Blit() - non RLE not implemented yet\n" ) );
558 ** _3dfx_InitFogForPaletteTricks
560 void _3dfx_InitFogForPaletteTricks( void )
562 GrFog_t _3dfx_fog_table[GR_FOG_TABLE_SIZE];
564 if ( PaletteRedAdd + PaletteGreenAdd + PaletteBlueAdd )
567 unsigned long fog_color_value;
568 unsigned long max_palette_add = PaletteRedAdd;
569 float palette_add_intensity;
570 float palette_to_255 = 255.0 / 31.0;
572 if ( PaletteGreenAdd > max_palette_add ) max_palette_add = PaletteGreenAdd;
573 if ( PaletteBlueAdd > max_palette_add ) max_palette_add = PaletteBlueAdd;
575 palette_add_intensity = max_palette_add / 31.0;
577 fog_color_value = ( ( ( unsigned long ) ( palette_to_255 * PaletteRedAdd ) << 16 ) |
578 ( ( unsigned long ) ( palette_to_255 * PaletteGreenAdd ) << 8 ) |
579 ( ( unsigned long ) ( palette_to_255 * PaletteBlueAdd ) ) );
581 grFogMode( GR_FOG_WITH_TABLE );
582 grFogColorValue( fog_color_value );
584 for ( i = 0; i < GR_FOG_TABLE_SIZE; i++ )
586 _3dfx_fog_table[i] = 256 * palette_add_intensity;
588 grFogTable( _3dfx_fog_table );
592 grFogMode( GR_FOG_DISABLE );