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