]> icculus.org git repositories - btb/d2x.git/blob - main/old/3dfx.c
This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / main / old / 3dfx.c
1 /*
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.
12 */
13
14 char _3dfx_rcsid[] = "$Id: 3dfx.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include "mono.h"
21 #include "bm.h"
22 #include "gr.h"
23 #include "3d.h"
24 #include "segment.h"
25 #include "piggy.h"
26 #include "3dfx_des.h"
27 #include "game.h"
28
29 #ifdef _3DFX
30
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;
44 float              _3dfx_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;
51 float              _3dfx_stencil;
52 int                _3dfx_no_bilinear;
53 int                _3dfx_available;
54
55 typedef struct BitmapFile       {
56         char                    name[15];
57 } BitmapFile;
58 extern BitmapFile AllBitmaps[ MAX_BITMAP_FILES ];
59
60 _3dfxTextureInfo   _3dfx_texture_info[MAX_BITMAP_FILES];
61
62 void MyErrorHandler( const char *s, FxBool fatal )
63 {
64    mprintf( ( 0, "3Dfx err_handler - %s\n", s ) );
65    if ( fatal )
66    {
67       exit( 2 );
68    }
69 }
70
71 int _3dfx_Init( void )
72 {
73    int         i;
74
75    mprintf( ( 0, "Initializing 3Dfx Interactive Voodoo Graphics hardware\n" ) );
76    grGlideInit();
77    grErrorSetCallback( MyErrorHandler );
78
79    if ( !grSstQueryHardware( &hwconfig ) )
80    {
81       mprintf( ( 0, "3Dfx Interactive Voodoo Graphics not found!" ) );
82       return 0;
83    }
84    grSstSelect( 0 );
85    if ( !grSstOpen( GR_RESOLUTION_640x480,
86                     GR_REFRESH_60Hz,
87                     GR_COLORFORMAT_ARGB,
88                     GR_ORIGIN_UPPER_LEFT,
89                     GR_SMOOTHING_ENABLE,
90                     2 ) )
91    {
92       mprintf( ( 0, "3Dfx Interactive Voodoo Graphics not opened!" ) );
93       return 0;
94    }
95
96    if ( getenv( "GLIDE_OFF" ) != 0 )
97    {
98       mprintf( ( 0, "3Dfx Interactive Voodoo Graphics disabled!" ) );
99       return 0;
100    }
101
102    grDepthBufferMode( GR_DEPTHBUFFER_DISABLE );
103    grBufferClear( 0x00000000, 0, 0 );
104    grCullMode( GR_CULL_DISABLE );
105
106    /*
107    ** configure environment variable controlled options
108    */
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;
117    else
118       _3dfx_allow_transparency = 1;
119    if ( getenv( "GLIDE_NO_SYNC" ) )
120       _3dfx_should_sync = 0;
121    else
122       _3dfx_should_sync = 1;
123
124    /*
125    ** allocate texture memory
126    */
127    for ( i = 0; i < MAX_BITMAP_FILES; i++ )
128    {
129       _3dfx_texture_info[i].handle = GR_NULL_MIPMAP_HANDLE;
130    }
131
132    _3dfx_current_handle = 0;
133    for ( i = 0; i < _3DFX_MAX_HANDLES; i++ )
134    {
135       GrMipMapId_t id;
136
137       id = grTexAllocateMemory( GR_TMU0,
138                                 GR_MIPMAPLEVELMASK_BOTH,
139                                 64, 64,
140                                 GR_TEXFMT_ARGB_1555,
141                                 GR_MIPMAP_NEAREST,
142                                 GR_LOD_1, GR_LOD_64,
143                                 GR_ASPECT_1x1,
144                                 GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
145                                 GR_TEXTUREFILTER_BILINEAR, _3dfx_no_bilinear ? GR_TEXTUREFILTER_POINT_SAMPLED : GR_TEXTUREFILTER_BILINEAR,
146                                 1.0F,
147                                 FXFALSE );
148
149       if ( id == GR_NULL_MIPMAP_HANDLE )
150       {
151          mprintf( ( 0, "            - unexpected null mmid returned\n" ) );
152          exit( 1 );
153       }
154    }
155
156    return 1;
157 }
158
159 void _3dfx_DownloadTexture( int index )
160 {
161    GrMipMapId_t      id   = _3dfx_current_handle;
162    _3dfxTextureInfo *info = &_3dfx_texture_info[index];
163    int               texture_being_replaced;
164    GrTextureFormat_t fmt;
165
166    /*
167    ** make sure the texture is in main memory
168    */
169    _3dfx_download_requests_made++;
170
171    if ( !( info->flags & _3DFX_TF_IN_MEMORY ) )
172    {
173       _3dfx_LoadTexture( index, AllBitmaps[index].name );
174
175       if ( !( info->flags & _3DFX_TF_IN_MEMORY ) )
176          return;
177    }
178
179    /*
180    ** if it's already in memory then we're cool
181    */
182    if ( info->flags & _3DFX_TF_DOWNLOADED )
183    {
184       return;
185    }
186
187    /*
188    ** otherwise we gotta do a swaperoo.  So, find the old texture and
189    ** give it the bad news.
190    */
191    texture_being_replaced = _3dfx_handle_to_index[id];
192
193    _3dfx_texture_info[texture_being_replaced].flags &= ~_3DFX_TF_DOWNLOADED;
194
195    /*
196    ** update the new texture
197    */
198    _3dfx_handle_to_index[id] = index;
199    info->handle              = id;
200    info->flags              |= _3DFX_TF_DOWNLOADED;
201
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;
206    else
207       fmt = GR_TEXFMT_RGB_565;
208
209    grTexChangeAttributes( id,
210                           64, 64,
211                           fmt,
212                           GR_MIPMAP_NEAREST,
213                           GR_LOD_1, GR_LOD_64,
214                           GR_ASPECT_1x1,
215                           GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
216                           -1, -1 );
217
218    grTexDownloadMipMap( id, info->data, 0 );
219
220    if ( ++_3dfx_current_handle >= _3DFX_MAX_HANDLES )
221       _3dfx_current_handle = 0;
222
223    _3dfx_bytes_downloaded_this_frame += SIZEOF_64x64_16BIT_TEXTURE;
224
225    _3dfx_download_requests_granted++;
226 }
227
228 int _3dfx_LoadTextureFromDisk( const char *name, int index )
229 {
230    Gu3dfInfo info;
231    int       success_or_fail = 0;
232
233    if ( gu3dfGetInfo( name, &info ) )
234    {
235       _3dfx_texture_info[index].flags = 0;
236
237       if ( info.header.large_lod != GR_LOD_64 )
238       {
239          goto done;
240       }
241
242       if ( info.header.aspect_ratio != GR_ASPECT_1x1 )
243       {
244          goto done;
245       }
246
247       #ifdef malloc
248       #  undef malloc
249       #endif
250       info.data = ( void * ) malloc( info.mem_required );
251
252       if ( info.data == 0 )
253       {
254          mprintf( ( 0, "info.data == 0\n" ) );
255          goto done;
256       }
257
258       if ( !gu3dfLoad( name, &info ) )
259       {
260          mprintf( ( 0, "couldn't gu3dfLoad() '%s'\n", name ) );
261          free( info.data );
262          goto done;
263       }
264
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;
268
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 );
273    }
274
275    success_or_fail = 1;
276 done:
277    return success_or_fail;
278 }
279
280 /*
281 ** _3dfx_LoadTexture
282 */
283 void _3dfx_LoadTexture( int index, const char *_name )
284 {
285    /*
286    ** load a non-ABM file
287    */
288    if ( !strchr( _name, '#' ) )
289    {
290       char name[256];
291
292       strcpy( name, _name );
293       sprintf( name, "3DF\\%s.3df", _name );
294
295       _3dfx_LoadTextureFromDisk( name, index );
296    }
297    /*
298    ** handle ABM files
299    */
300    else
301    {
302       char _3dfx_filename[256], _3dfx_name[256], _3dfx_extension[256];
303
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 );
308
309       _3dfx_LoadTextureFromDisk( _3dfx_filename, index );
310    }
311 }
312
313 /*
314 ** _3dfx_BufferSwap
315 */
316 void _3dfx_BufferSwap( void )
317 {
318    if ( _3dfx_available )
319    {
320       while ( ( ( grSstStatus() >> 28 ) & 7 ) > 0 )
321          ;
322
323       grBufferSwap( _3dfx_should_sync );
324       grBufferClear( 0xFFFF0000, 0, 0 );
325    }
326
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;
332 }
333
334 /*
335 ** _3dfx_DrawFlatShadedPoly
336 */
337 #define SNAP( a ) ( ( fix ) ( (a) & ( 0xFFFFF000L ) ) )
338
339 void _3dfx_DrawFlatShadedPoly( g3ds_tmap *Tmap1, unsigned long argb )
340 {
341    GrVertex a, b, c;
342    int      i;
343    float    lowest_y = 10000, highest_y = 0;
344    float    lowest_x = 10000, highest_x = 0;
345
346    for ( i = 0; i < Tmap1->nv; i++ )
347    {
348       float x = SNAP( Tmap1->verts[i].x2d ) * fix_to_float;
349       float y = SNAP( Tmap1->verts[i].y2d ) * fix_to_float;
350
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;
355    }
356
357    if ( highest_x < 0 || highest_y < 0 || lowest_x > 639 || lowest_y > 479 )
358    {
359       mprintf( ( 0, "3dfx - rejecting fspoly way off screen\n" ) );
360       return;
361    }
362
363    guColorCombineFunction( GR_COLORCOMBINE_CCRGB );
364    grConstantColorValue( argb );
365
366    a.x = SNAP( Tmap1->verts[0].x2d ) * fix_to_float;
367    a.y = SNAP( Tmap1->verts[0].y2d ) * fix_to_float;
368
369    for ( i = 1; i < Tmap1->nv - 1; i++ )
370    {
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;
375
376       grDrawTriangle( &a, &b, &c );
377    }
378 }
379
380 /*
381 ** _3dfx_DownloadAndUseTexture
382 */
383 void _3dfx_DownloadAndUseTexture( unsigned long index )
384 {
385    _3dfx_DownloadTexture( index );
386    if ( _3dfx_texture_info[index].handle != GR_NULL_MIPMAP_HANDLE )
387       grTexSource( _3dfx_texture_info[index].handle );
388 }
389
390 /*
391 ** _3dfx_decompose_tmap_and_draw
392 */
393 void _3dfx_decompose_tmap_and_draw( int nv, g3s_point **pointlist, uvl *uvl_copy, grs_bitmap *bm )
394 {
395    int        i;
396    uvl        uvl_copy_3dfx[8];
397    g3s_point *pointlist2[8];
398
399    pointlist2[0]    = pointlist[0];
400    uvl_copy_3dfx[0] = uvl_copy[0];
401
402    _3dfx_DownloadAndUseTexture( bm->bm_handle );
403
404    for ( i = 0; i < nv - 2; i++ )
405    {
406       int j;
407
408       for ( j = 1; j < 3; j++ )
409       {
410          pointlist2[j]    = pointlist[i+j];
411          uvl_copy_3dfx[j] = uvl_copy[i+j];
412       }
413
414       if ( _3dfx_available )
415       {
416          g3_draw_tmap( 3, pointlist2, (g3s_uvl *) uvl_copy_3dfx, bm );
417       }
418       _3dfx_triangles_rendered_pre_clip++;
419    }
420 }
421
422 /*
423 ** _3dfx_PaletteToARGB
424 */
425 unsigned long _3dfx_PaletteToARGB( int pindex )
426 {
427    unsigned long result = 0;
428
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;
432
433    return result;
434 }
435
436 /*
437 ** _3dfx_BlitScale
438 */
439 #define _3DFX_FB_WIDTH 1024
440
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 )
444 {
445    if ( _3dfx_available )
446    {
447       if ( source_bmp->bm_flags & BM_FLAG_RLE )
448       {
449          fix u, v, du, dv;
450          int x, y;
451          ubyte * sbits;
452          unsigned long * dbits;
453          unsigned long * fb;
454
455          du = (u1-u0) / (x1-x0);
456          dv = (v1-v0) / (y1-y0);
457
458          v = v0;
459
460          grLfbBegin();
461
462          grLfbBypassMode( GR_LFBBYPASS_ENABLE );
463
464          fb = ( unsigned long * ) grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
465          grLfbWriteMode( GR_LFBWRITEMODE_8888 );
466
467          guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
468
469          for ( y = y0; y <= y1; y++, v += dv )
470          {
471             extern ubyte scale_rle_data[];
472
473             decode_row( source_bmp, f2i( v ) );
474
475             sbits = scale_rle_data + f2i( u0 );
476             dbits = fb + _3DFX_FB_WIDTH * y + x0;
477
478             u = u0;
479
480             for ( x = x0; x <= x1; x++ )
481             {
482                int pindex = sbits[ u >> 16 ];
483
484                if ( pindex != 255 )
485                   *dbits = _3dfx_PaletteToARGB( pindex );
486
487                dbits++;
488                u += du;
489             }
490          }
491          grLfbBypassMode( GR_LFBBYPASS_DISABLE );
492
493          grLfbEnd();
494       }
495       else
496       {
497          mprintf( ( 0, "_3dfx_BlitScale() - non RLE not implemented yet\n" ) );
498       }
499    }
500 }
501
502 /*
503 ** _3dfx_Blit
504 */
505 #define _3DFX_FB_WIDTH 1024
506
507 void _3dfx_Blit( int x, int y, grs_bitmap *bm )
508 {
509    if ( _3dfx_available )
510    {
511       if ( bm->bm_flags & BM_FLAG_RLE )
512       {
513          ubyte * sbits;
514          unsigned long * dbits;
515          unsigned long * fb;
516          int             v;
517
518          grLfbBegin();
519
520          grLfbBypassMode( GR_LFBBYPASS_ENABLE );
521
522          fb = ( unsigned long * ) grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
523          grLfbWriteMode( GR_LFBWRITEMODE_8888 );
524
525          guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );
526
527          for ( v = 0; v < bm->bm_h; v++ )
528          {
529             extern ubyte scale_rle_data[];
530             int          u;
531
532             decode_row( bm, v );
533
534             sbits = scale_rle_data;
535             dbits = fb + _3DFX_FB_WIDTH * ( y + v ) + x;
536
537             for ( u = 0; u < bm->bm_w; u++ )
538             {
539                int pindex = sbits[ u ];
540
541                if ( pindex != 255 )
542                   *dbits = _3dfx_PaletteToARGB( pindex );
543                dbits++;
544             }
545          }
546          grLfbBypassMode( GR_LFBBYPASS_DISABLE );
547
548          grLfbEnd();
549       }
550       else
551       {
552          mprintf( ( 0, "_3dfx_Blit() - non RLE not implemented yet\n" ) );
553       }
554    }
555 }
556
557 /*
558 ** _3dfx_InitFogForPaletteTricks
559 */
560 void _3dfx_InitFogForPaletteTricks( void )
561 {
562    GrFog_t _3dfx_fog_table[GR_FOG_TABLE_SIZE];
563
564    if ( PaletteRedAdd + PaletteGreenAdd + PaletteBlueAdd )
565    {
566       int i;
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;
571
572       if ( PaletteGreenAdd > max_palette_add ) max_palette_add = PaletteGreenAdd;
573       if ( PaletteBlueAdd > max_palette_add )  max_palette_add = PaletteBlueAdd;
574
575       palette_add_intensity = max_palette_add / 31.0;
576
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 ) ) );
580
581       grFogMode( GR_FOG_WITH_TABLE );
582       grFogColorValue( fog_color_value );
583
584       for ( i = 0; i < GR_FOG_TABLE_SIZE; i++ )
585       {
586          _3dfx_fog_table[i] = 256 * palette_add_intensity;
587       }
588       grFogTable( _3dfx_fog_table );
589    }
590    else
591    {
592       grFogMode( GR_FOG_DISABLE );
593    }
594 }
595
596
597 #endif
598