~ubuntu-branches/ubuntu/karmic/xmame/karmic

« back to all changes in this revision

Viewing changes to src/vidhrdw/hng64.c

  • Committer: Bazaar Package Importer
  • Author(s): Bruno Barrera C.
  • Date: 2007-02-16 10:06:54 UTC
  • mfrom: (2.1.5 edgy)
  • Revision ID: james.westby@ubuntu.com-20070216100654-iztas2cl47k5j039
Tags: 0.106-2
* Added Italian debconf templates translation. (closes: #382672)
* Added German debconf templates translation. (closes: #396610)
* Added Japanese debconf templates translation. (closes: #400011)
* Added Portuguese debconf templates translation. (closes: #409960)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "driver.h"
 
2
 
 
3
#include <math.h>
 
4
 
 
5
 
 
6
/* !!! I'm sure this isn't right !!! */
 
7
UINT32 hng64_dls[2][0x81] ;
 
8
 
 
9
static int frameCount = 0 ;
 
10
 
 
11
UINT32* hng64_videoram;
 
12
tilemap *hng64_tilemap0;
 
13
tilemap *hng64_tilemap1;
 
14
tilemap *hng64_tilemap2;
 
15
tilemap *hng64_tilemap3;
 
16
 
 
17
UINT32 *hng64_spriteram;
 
18
UINT32 *hng64_videoregs;
 
19
 
 
20
UINT32 *hng64_tcram ;
 
21
 
 
22
/* HAAAACK to make the floor 'work' */
 
23
UINT32 hackTilemap3, hackTm3Count, rowScrollOffset ;
 
24
 
 
25
 
 
26
static void  matmul4( float *product, const float *a, const float *b ) ;
 
27
static void  vecmatmul4( float *product, const float *a, const float *b) ;
 
28
static float vecDotProduct( const float *a, const float *b) ;
 
29
static void normalize(float* x) ;
 
30
 
 
31
/* 3d helpers */
 
32
static float uToF(UINT16 input) ;
 
33
static void SetIdentity(float *matrix) ;
 
34
 
 
35
 
 
36
static void plot(INT32 x, INT32 y, INT32 color, mame_bitmap *bitmap) ;
 
37
static void drawline2d(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, mame_bitmap *bitmap) ;
 
38
 
 
39
static float *depthBuffer ;
 
40
static struct polygon *polys ;
 
41
 
 
42
/*static int tilemap2Offset = 0x10000 ; */
 
43
 
 
44
 
 
45
#define WORD_AT(BUFFER,OFFSET) ( (BUFFER[OFFSET] << 8) | BUFFER[OFFSET+1] )
 
46
 
 
47
 
 
48
/*
 
49
 * Sprite Format
 
50
 * ------------------
 
51
 *
 
52
 * UINT32 | Bytes    | Use
 
53
 * -------+-76543210-+----------------
 
54
 *   0    | xxxx---- | y position
 
55
 *   0    | ----xxxx | x position
 
56
 *   1    | xxxx---- | y zoom
 
57
 *   1    | ----xxxx | x zoom
 
58
 *   2    | ------x- | x chain
 
59
 *   2    | -------x | y chain
 
60
 *   2    | xxxx---- | end of sprite list - though it surely contains more info !
 
61
 *   2    | ----oo-- | not used ??
 
62
 *   3    | --xx---- | palette entry
 
63
 *   3    | --x----- | (bit 0x8) - maybe a graphics bank selector
 
64
 *   3    | oo--oooo | not used  ?
 
65
 *   4    | --xxxxxx | tile number
 
66
 *   4    | --x----- | (bit 0x2) - x flip
 
67
 *   4    | --x----- | (bit 0x1) - y flip
 
68
 *   4    | oo------ | not used ??
 
69
 *   5    | oooooooo | not used ??
 
70
 *   6    | oooooooo | not used ??
 
71
 *   7    | oooooooo | not used ??
 
72
 */
 
73
 
 
74
/* xxxx---- | I think this part of UINT32 2 is interesting as more than just a list end marker (AJG)
 
75
 */
 
76
 
 
77
static void hng64_drawsprites( mame_bitmap *bitmap, const rectangle *cliprect )
 
78
{
 
79
        const gfx_element *gfx;
 
80
        UINT32 *source = hng64_spriteram;
 
81
        UINT32 *finish = hng64_spriteram + 0xb000/4;
 
82
 
 
83
        /* find end of list? */
 
84
        while( source<finish)
 
85
        {
 
86
                int endlist;
 
87
 
 
88
                endlist=(source[2]&0xffff0000)>>16;
 
89
                if (endlist == 0x07ff) break;
 
90
                source+=8;
 
91
        }
 
92
 
 
93
/*  for (int iii = 0; iii < 0x0f; iii++) */
 
94
/*      printf("%.8x ", hng64_videoregs[iii]) ; */
 
95
 
 
96
/*  printf("\n") ; */
 
97
 
 
98
        finish = hng64_spriteram;
 
99
 
 
100
        /* draw backwards .. */
 
101
        while( source>finish )
 
102
        {
 
103
                int xpos, ypos, tileno,chainx,chainy,xflip;
 
104
                int xdrw,ydrw,pal,xinc,yinc,yflip;
 
105
                UINT32 zoomx,zoomy;
 
106
                float foomX, foomY;
 
107
                source-=8;
 
108
 
 
109
                ypos = (source[0]&0xffff0000)>>16;
 
110
                xpos = (source[0]&0x0000ffff)>>0;
 
111
                tileno=(source[4]&0x00ffffff);
 
112
                chainx=(source[2]&0x000000f0)>>4;
 
113
                chainy=(source[2]&0x0000000f);
 
114
 
 
115
                zoomy = (source[1]&0xffff0000)>>16;
 
116
                zoomx = (source[1]&0x0000ffff)>>0;
 
117
 
 
118
                pal =(source[3]&0x00ff0000)>>16;
 
119
                xflip=(source[4]&0x02000000)>>25;
 
120
                yflip=(source[4]&0x01000000)>>24;
 
121
 
 
122
                if(xpos&0x8000) xpos -=0x10000;
 
123
                if(ypos&0x8000) ypos -=0x10000;
 
124
 
 
125
 
 
126
/*      if (!(source[4] == 0x00000000 || source[4] == 0x000000aa)) */
 
127
/*          printf("unknown : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n", source[0], source[1], source[2], source[3], */
 
128
/*                                                                         source[4], source[5], source[6], source[7]) ; */
 
129
 
 
130
                /* Calculate the zoom */
 
131
                /* First, prevent any possible divide by zero errors */
 
132
                if(!zoomx) zoomx=0x1000;
 
133
                if(!zoomy) zoomy=0x1000;
 
134
 
 
135
                foomX = (float)(0x1000) / (float)zoomx ;
 
136
                foomY = (float)(0x1000) / (float)zoomy ;
 
137
 
 
138
                zoomx = ((int)foomX) << 16 ;
 
139
                zoomy = ((int)foomY) << 16 ;
 
140
 
 
141
                zoomx += (int)((foomX - floor(foomX)) * (float)0x10000) ;
 
142
                zoomy += (int)((foomY - floor(foomY)) * (float)0x10000) ;
 
143
 
 
144
 
 
145
                if (source[3]&0x00800000) /* maybe .. */
 
146
                {
 
147
                        gfx= Machine->gfx[4];
 
148
                }
 
149
                else
 
150
                {
 
151
                        gfx= Machine->gfx[5];
 
152
                        tileno>>=1;
 
153
 
 
154
                        /* Just a big hack to make the top and bottom tiles in the intro not crash (a pal value of 0x70 is bad) */
 
155
                        /* Is there a problem with drawsprites?  Doubtful... */
 
156
                        if (source[2] == 0x00080000)
 
157
                                pal >>=4;
 
158
                }
 
159
 
 
160
                /* Accomodate for chaining and flipping */
 
161
                if(xflip)
 
162
                {
 
163
                        xinc=-(int)(16.0f*foomX);
 
164
                        xpos-=xinc*chainx;
 
165
                }
 
166
                else
 
167
                {
 
168
                        xinc=(int)(16.0f*foomX);
 
169
                }
 
170
 
 
171
                if(yflip)
 
172
                {
 
173
                        yinc=-(int)(16.0f*foomY);
 
174
                        ypos-=yinc*chainy;
 
175
                }
 
176
                else
 
177
                {
 
178
                        yinc=(int)(16.0f*foomY);
 
179
                }
 
180
 
 
181
 
 
182
/*      if (((source[2] & 0xffff0000) >> 16) == 0x0001) */
 
183
/*      { */
 
184
/*          usrintf_showmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]) ; */
 
185
/*          // usrintf_showmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]) ; */
 
186
/*      } */
 
187
 
 
188
                for(ydrw=0;ydrw<=chainy;ydrw++)
 
189
                {
 
190
                        for(xdrw=0;xdrw<=chainx;xdrw++)
 
191
                        {
 
192
                                drawgfxzoom(bitmap,gfx,tileno,pal,xflip,yflip,xpos+(xinc*xdrw),ypos+(yinc*ydrw),cliprect,TRANSPARENCY_PEN,0,zoomx,zoomy/*0x10000*/);
 
193
                                tileno++;
 
194
                        }
 
195
                }
 
196
        }
 
197
}
 
198
 
 
199
 
 
200
/* Transition_Control Memory Region Map
 
201
 * ------------------------------
 
202
 *
 
203
 *  UINT32 | Bytes    | Use
 
204
 *  -------+-76543210-+----------
 
205
 *       0 |          |
 
206
 *       1 |          |
 
207
 *       2 |          |
 
208
 *       3 |          |
 
209
 *       4 |          |
 
210
 *       5 |          |
 
211
 *       6 | --xxxxxx | I popped into Buriki and saw some of these values changing to the same as 7.  hmmmm...
 
212
 *       7 | --xxxxxx | Almost certainly RGB darkening
 
213
 *       8 |          |
 
214
 *       9 |          |
 
215
 *      10 | --xxxxxx | Almost certainly RGB brightening
 
216
 *      11 | xxxxxxxx | Unknown - looks like an ARGB value - it seems to change when the scene changes
 
217
 *      12 |          |
 
218
 *      13 |          |
 
219
 *      14 |          |
 
220
 *      15 |          |
 
221
 *
 
222
 *  Various bits change depending on what is happening in the scene.
 
223
 *  These bits may set which 'layer' is affected by the blending.
 
224
 *  Or maybe they adjust the scale of the lightening and darkening...
 
225
 *  Or maybe it switches from fading by scaling to fading using absolute addition and subtraction...
 
226
 *  Or maybe they set transition type (there seems to be a cute scaling-squares transition in there somewhere)...
 
227
 */
 
228
static void hng64_transition_control(mame_bitmap *bitmap)
 
229
{
 
230
        int i, j ;
 
231
 
 
232
/*  float colorScaleR, colorScaleG, colorScaleB ; */
 
233
/*  float finR, finG, finB ; */
 
234
        INT32 finR, finG, finB ;
 
235
 
 
236
        INT32 darkR, darkG, darkB ;
 
237
        INT32 brigR, brigG, brigB ;
 
238
 
 
239
        /* If either of the fading memory regions is non-zero... */
 
240
        if (hng64_tcram[0x00000007] != 0x00000000 || hng64_tcram[0x0000000a] != 0x00000000)
 
241
        {
 
242
                darkR = (INT32)( hng64_tcram[0x00000007]        & 0xff) ;
 
243
                darkG = (INT32)((hng64_tcram[0x00000007] >> 8)  & 0xff) ;
 
244
                darkB = (INT32)((hng64_tcram[0x00000007] >> 16) & 0xff) ;
 
245
 
 
246
                brigR = (INT32)( hng64_tcram[0x0000000a]        & 0xff) ;
 
247
                brigG = (INT32)((hng64_tcram[0x0000000a] >> 8)  & 0xff) ;
 
248
                brigB = (INT32)((hng64_tcram[0x0000000a] >> 16) & 0xff) ;
 
249
 
 
250
                for (i = Machine->visible_area.min_x; i < Machine->visible_area.max_x; i++)
 
251
                {
 
252
                        for (j = Machine->visible_area.min_y; j < Machine->visible_area.max_y; j++)
 
253
                        {
 
254
                                UINT32* thePixel = &((UINT32 *)(bitmap->line[j]))[i] ;
 
255
 
 
256
                                finR = (INT32)RGB_RED(*thePixel) ;
 
257
                                finG = (INT32)RGB_GREEN(*thePixel) ;
 
258
                                finB = (INT32)RGB_BLUE(*thePixel) ;
 
259
 
 
260
                                /*
 
261
                // Apply the darkening pass (0x07)...
 
262
                colorScaleR = 1.0f - (float)( hng64_tcram[0x00000007] & 0xff)        / 255.0f ;
 
263
                colorScaleG = 1.0f - (float)((hng64_tcram[0x00000007] >> 8)  & 0xff) / 255.0f ;
 
264
                colorScaleB = 1.0f - (float)((hng64_tcram[0x00000007] >> 16) & 0xff) / 255.0f ;
 
265
 
 
266
                finR = ((float)RGB_RED(*thePixel)   * colorScaleR) ;
 
267
                finG = ((float)RGB_GREEN(*thePixel) * colorScaleG) ;
 
268
                finB = ((float)RGB_BLUE(*thePixel)  * colorScaleB) ;
 
269
 
 
270
 
 
271
                // Apply the lightening pass (0x0a)...
 
272
                colorScaleR = 1.0f + (float)( hng64_tcram[0x0000000a] & 0xff)        / 255.0f ;
 
273
                colorScaleG = 1.0f + (float)((hng64_tcram[0x0000000a] >> 8)  & 0xff) / 255.0f ;
 
274
                colorScaleB = 1.0f + (float)((hng64_tcram[0x0000000a] >> 16) & 0xff) / 255.0f ;
 
275
 
 
276
                finR *= colorScaleR ;
 
277
                finG *= colorScaleG ;
 
278
                finB *= colorScaleB ;
 
279
 
 
280
 
 
281
                // Clamp
 
282
                if (finR > 255.0f) finR = 255.0f ;
 
283
                if (finG > 255.0f) finG = 255.0f ;
 
284
                if (finB > 255.0f) finB = 255.0f ;
 
285
                */
 
286
 
 
287
 
 
288
                                /* Subtractive fading */
 
289
                                if (hng64_tcram[0x00000007] != 0x00000000)
 
290
                                {
 
291
                                        finR -= darkR ;
 
292
                                        finG -= darkG ;
 
293
                                        finB -= darkB ;
 
294
                                }
 
295
 
 
296
                                /* Additive fading */
 
297
                                if (hng64_tcram[0x0000000a] != 0x00000000)
 
298
                                {
 
299
                                        finR += brigR ;
 
300
                                        finG += brigG ;
 
301
                                        finB += brigB ;
 
302
                                }
 
303
 
 
304
                                /* Clamp the high end */
 
305
                                if (finR > 255) finR = 255 ;
 
306
                                if (finG > 255) finG = 255 ;
 
307
                                if (finB > 255) finB = 255 ;
 
308
 
 
309
                                /* Clamp the low end */
 
310
                                if (finR < 0) finR = 0 ;
 
311
                                if (finG < 0) finG = 0 ;
 
312
                                if (finB < 0) finB = 0 ;
 
313
 
 
314
                                *thePixel = MAKE_ARGB(255, (UINT8)finR, (UINT8)finG, (UINT8)finB) ;
 
315
                        }
 
316
                }
 
317
        }
 
318
}
 
319
 
 
320
 
 
321
/*
 
322
 * 3d 'Sprite' Format
 
323
 * ------------------
 
324
 *
 
325
 * (documented below)
 
326
 *
 
327
 */
 
328
 
 
329
#define MAX_ONSCREEN_POLYS (10000)
 
330
 
 
331
struct polyVert
 
332
{
 
333
        float worldCoords[4] ;          /* World space coordinates (X Y Z 1.0) */
 
334
 
 
335
        float texCoords[4] ;            /* Texture coordinates (U V 0 1.0) -> OpenGL style... */
 
336
 
 
337
        float normal[4] ;                       /* Normal (X Y Z 1.0) */
 
338
        float clipCoords[4] ;           /* Homogeneous screen space coordinates (X Y Z W) */
 
339
 
 
340
        float light[3] ;                        /* The intensity of the illumination at this point */
 
341
} ;
 
342
 
 
343
struct polygon
 
344
{
 
345
        int n ;                                                 /* Number of sides */
 
346
        struct polyVert vert[10] ;              /* Vertices (maximum number per polygon is 10 -> 3+6) */
 
347
 
 
348
        float faceNormal[4] ;                   /* Normal of the face overall - for calculating visibility and flat-shading... */
 
349
        int visible ;                                   /* Polygon visibility in scene */
 
350
 
 
351
        INT8 texIndex ;                                 /* Which texture to draw from (0x00-0x0f) */
 
352
        INT8 texType ;                                  /* How to index into the texture */
 
353
        UINT8 palIndex ;                                /* Which palette to use when rasterizing */
 
354
} ;
 
355
 
 
356
 
 
357
static void PerformFrustumClip(struct polygon *p) ;
 
358
 
 
359
static void DrawWireframe(struct polygon *p, mame_bitmap *bitmap) ;
 
360
static void DrawShaded(struct polygon *p, mame_bitmap *bitmap) ;
 
361
 
 
362
 
 
363
static void hng64_draw3d( mame_bitmap *bitmap, const rectangle *cliprect )
 
364
{
 
365
        int i,j,k,l,m ;
 
366
 
 
367
        float projectionMatrix[16] ;
 
368
        float modelViewMatrix[16] ;
 
369
        float cameraMatrix[16] ;
 
370
        float objectMatrix[16] ;
 
371
 
 
372
        int paletteState = 0x00 ;
 
373
 
 
374
        UINT32 numPolys = 0 ;
 
375
 
 
376
        struct polygon lastPoly = { 0 } ;
 
377
 
 
378
        /* Set some matrices to the identity... */
 
379
        SetIdentity(projectionMatrix) ;
 
380
        SetIdentity(modelViewMatrix) ;
 
381
        SetIdentity(cameraMatrix) ;
 
382
        SetIdentity(objectMatrix) ;
 
383
 
 
384
        /* Display list 2 comes after display list 1.  Go figure. */
 
385
        for (j = 1; j >= 0; j--)
 
386
        {
 
387
                UINT32 *workingList = hng64_dls[j] ;
 
388
 
 
389
                for (i = 0; i < 0x80; i += 0x08)
 
390
                {
 
391
                        float left, right, top, bottom, near_, far_ ;
 
392
                        UINT8 *threeDRoms ;
 
393
                        UINT8 *threeDPointer ;
 
394
                        UINT32 threeDOffset ;
 
395
                        UINT32 size[4] ;
 
396
                        UINT32 address[4] ;
 
397
                        UINT32 megaOffset ;
 
398
                        float eyeCoords[4] ;                    /* objectCoords transformed by the modelViewMatrix */
 
399
                        /* float clipCoords[4] ;        // eyeCoords transformed by the projectionMatrix */
 
400
                        float ndCoords[4] ;                             /* normalized device coordinates/clipCoordinates (x/w, y/w, z/w) */
 
401
                        float windowCoords[4] ;                 /* mapped ndCoordinates to screen space */
 
402
                        float cullRay[4] ;
 
403
 
 
404
                        /* Debug... */
 
405
/*          printf("Element %.2d (%d) : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", i/0x08, j, */
 
406
/*                                     (UINT32)hng64_dls[j][i+0], (UINT32)hng64_dls[j][i+1], (UINT32)hng64_dls[j][i+2], (UINT32)hng64_dls[j][i+3], */
 
407
/*                                     (UINT32)hng64_dls[j][i+4], (UINT32)hng64_dls[j][i+5], (UINT32)hng64_dls[j][i+6], (UINT32)hng64_dls[j][i+7]) ; */
 
408
 
 
409
                        /* Depending on what the initial flags are, do sumthin'... */
 
410
                        switch((workingList[i+0] & 0xffff0000) >> 16)
 
411
                        {
 
412
                        case 0x0012:
 
413
                                /* UNKNOWN - seems an awful lot parameters for a projection matrix though... */
 
414
 
 
415
                                ;
 
416
 
 
417
                                /* It changes when 'How to play' is on the screen...  not too much, but if this is right, the aspect */
 
418
                                /* ratio is different... */
 
419
 
 
420
                                /* Heisted from GLFrustum - 6 parameters... */
 
421
                                left   = uToF( workingList[i+5] & 0x0000ffff) ;
 
422
                                right  = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
 
423
                                top    = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
 
424
                                bottom = uToF( workingList[i+6] & 0x0000ffff) ;
 
425
                                near_   = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
 
426
                                far_    = uToF( workingList[i+3] & 0x0000ffff) ;
 
427
 
 
428
                                /* It's almost .always. these values in fatfurwa... */
 
429
                                /* 0.070313    0.000000 [0]     (scaled by 128) */
 
430
                                /* 0.000000   10.000000 [1] */
 
431
                                /* 0.000000    0.500000 [2] */
 
432
                                /* 2.000000   11.062500 [3] */
 
433
                                /* 10.000000  11.000000 [4] */
 
434
                                /* 1.000000   -1.000000 [5] */
 
435
                                /* 0.875000   -0.875000 [6] */
 
436
                                /* 0.000000    0.000000 [7] */
 
437
 
 
438
                                projectionMatrix[0]  = (2.0f*near_)/(right-left) ;
 
439
                                projectionMatrix[1]  = 0.0f ;
 
440
                                projectionMatrix[2]  = 0.0f ;
 
441
                                projectionMatrix[3]  = 0.0f ;
 
442
 
 
443
                                projectionMatrix[4]  = 0.0f ;
 
444
                                projectionMatrix[5]  = (2.0f*near_)/(top-bottom) ;
 
445
                                projectionMatrix[6]  = 0.0f ;
 
446
                                projectionMatrix[7]  = 0.0f ;
 
447
 
 
448
                                projectionMatrix[8]  = (right+left)/(right-left) ;
 
449
                                projectionMatrix[9]  = (top+bottom)/(top-bottom) ;
 
450
                                projectionMatrix[10] = -((far_+near_)/(far_-near_)) ;
 
451
                                projectionMatrix[11] = -1.0f ;
 
452
 
 
453
                                projectionMatrix[12] = 0.0f ;
 
454
                                projectionMatrix[13] = 0.0f ;
 
455
                                projectionMatrix[14] = -((2.0f*far_*near_)/(far_-near_)) ;
 
456
                                projectionMatrix[15] = 0.0f ;
 
457
 
 
458
                                /*
 
459
                int xxx ;
 
460
                for (xxx = 0; xxx < 16; xxx++)
 
461
                    printf("%f ", projectionMatrix[xxx]) ;
 
462
                printf("\n") ;
 
463
 
 
464
                printf("Vars   : %f %f %f %f %f %f\n", left, right, top, bottom, near, far) ;
 
465
                printf("Camera : %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
 
466
                                 uToF((workingList[i+0] & 0xffff0000) >> 16)*128, uToF( workingList[i+0] & 0x0000ffff)*128,
 
467
                                 uToF((workingList[i+1] & 0xffff0000) >> 16)*128, uToF( workingList[i+1] & 0x0000ffff)*128,
 
468
 
 
469
                                 uToF((workingList[i+2] & 0xffff0000) >> 16)*128, uToF( workingList[i+2] & 0x0000ffff)*128,
 
470
                                 uToF((workingList[i+3] & 0xffff0000) >> 16)*128, uToF( workingList[i+3] & 0x0000ffff)*128,
 
471
 
 
472
                                 uToF((workingList[i+4] & 0xffff0000) >> 16)*128, uToF( workingList[i+4] & 0x0000ffff)*128,
 
473
                                 uToF((workingList[i+5] & 0xffff0000) >> 16)*128, uToF( workingList[i+5] & 0x0000ffff)*128,
 
474
 
 
475
                                 uToF((workingList[i+6] & 0xffff0000) >> 16)*128, uToF( workingList[i+6] & 0x0000ffff)*128,
 
476
                                 uToF((workingList[i+7] & 0xffff0000) >> 16)*128, uToF( workingList[i+7] & 0x0000ffff)*128) ;
 
477
                */
 
478
 
 
479
                                break ;
 
480
 
 
481
                        case 0x0001:
 
482
                                /* CAMERA TRANSFORMATION MATRIX */
 
483
                                cameraMatrix[0]  = uToF( workingList[i+0] & 0x0000ffff) ;
 
484
                                cameraMatrix[4]  = uToF((workingList[i+1] & 0xffff0000) >> 16) ;
 
485
                                cameraMatrix[8]  = uToF( workingList[i+1] & 0x0000ffff) ;
 
486
                                cameraMatrix[3]  = 0.0f ;
 
487
 
 
488
                                cameraMatrix[1]  = uToF((workingList[i+2] & 0xffff0000) >> 16) ;
 
489
                                cameraMatrix[5]  = uToF( workingList[i+2] & 0x0000ffff) ;
 
490
                                cameraMatrix[9]  = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
 
491
                                cameraMatrix[7]  = 0.0f ;
 
492
 
 
493
                                cameraMatrix[2]  = uToF( workingList[i+3] & 0x0000ffff) ;
 
494
                                cameraMatrix[6]  = uToF((workingList[i+4] & 0xffff0000) >> 16) ;
 
495
                                cameraMatrix[10] = uToF( workingList[i+4] & 0x0000ffff) ;
 
496
                                cameraMatrix[11] = 0.0f ;
 
497
 
 
498
                                cameraMatrix[12] = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
 
499
                                cameraMatrix[13] = uToF( workingList[i+5] & 0x0000ffff) ;
 
500
                                cameraMatrix[14] = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
 
501
                                cameraMatrix[15] = 1.0f ;
 
502
                                break ;
 
503
 
 
504
                        case 0x0010:
 
505
                                /* UNKNOWN - light maybe */
 
506
                                break ;
 
507
 
 
508
                        case 0x0011:
 
509
                                /* Model Flags? */
 
510
                                /* 00110000 00000000 00000100 01000100 0400-0000 00007fff 00000000 00000020 */
 
511
                                /* ----                                pal  ---- -------- -------- -------- not used (known) */
 
512
                                paletteState = (workingList[i+4] & 0xff000000) >> 24 ;
 
513
 
 
514
                                break ;
 
515
 
 
516
                        case 0x0100:
 
517
                                /* GEOMETRY */
 
518
                                ;
 
519
 
 
520
                                threeDRoms = memory_region(REGION_GFX4) ;
 
521
 
 
522
                                /*/////////////////////// */
 
523
                                /* GET THE HEADER INFO // */
 
524
                                /*/////////////////////// */
 
525
 
 
526
                                /* 3d ROM Offset */
 
527
                                /* !!! This might be more than just 20 bits... */
 
528
                                threeDOffset = workingList[i+1] & 0x000fffff ;
 
529
                                threeDOffset = (threeDOffset<<1) * 3 ;
 
530
 
 
531
                                threeDPointer = &threeDRoms[threeDOffset] ;
 
532
 
 
533
 
 
534
                                /* 66 byte versus 48 byte chunk flag */
 
535
                                /*    WRONG !  I think it's something to do with lighting... */
 
536
                                /*    it's 0 for the 66-byte lit globe in the character select and 0 for something in terry's hand... */
 
537
                                /* if (workingList[i+0] & 0x00000010) */
 
538
 
 
539
 
 
540
                                /*//////////////////////////////////////// */
 
541
                                /* GET THE OBJECT TRANSFORMATION MATRIX // */
 
542
                                /*//////////////////////////////////////// */
 
543
 
 
544
                                objectMatrix[8 ] = uToF( workingList[i+3] & 0x0000ffff) ;
 
545
                                objectMatrix[4 ] = uToF((workingList[i+4] & 0xffff0000) >> 16) ;
 
546
                                objectMatrix[0 ] = uToF( workingList[i+4] & 0x0000ffff) ;
 
547
                                objectMatrix[3]  = 0.0f ;
 
548
 
 
549
                                objectMatrix[9 ] = uToF((workingList[i+5] & 0xffff0000) >> 16) ;
 
550
                                objectMatrix[5 ] = uToF( workingList[i+5] & 0x0000ffff) ;
 
551
                                objectMatrix[1 ] = uToF((workingList[i+6] & 0xffff0000) >> 16) ;
 
552
                                objectMatrix[7]  = 0.0f ;
 
553
 
 
554
                                objectMatrix[10] = uToF( workingList[i+6] & 0x0000ffff) ;
 
555
                                objectMatrix[6 ] = uToF((workingList[i+7] & 0xffff0000) >> 16) ;
 
556
                                objectMatrix[2 ] = uToF( workingList[i+7] & 0x0000ffff) ;
 
557
                                objectMatrix[11] = 0.0f ;
 
558
 
 
559
                                objectMatrix[12] = uToF((workingList[i+2] & 0xffff0000) >> 16) ;
 
560
                                objectMatrix[13] = uToF( workingList[i+2] & 0x0000ffff) ;
 
561
                                objectMatrix[14] = uToF((workingList[i+3] & 0xffff0000) >> 16) ;
 
562
                                objectMatrix[15] = 1.0f ;
 
563
 
 
564
 
 
565
 
 
566
                                /*//////////////////////////////////////////////////////// */
 
567
                                /* EXTRACT DATA FROM THE ADDRESS POINTED TO IN THE FILE // */
 
568
                                /*//////////////////////////////////////////////////////// */
 
569
 
 
570
                                /* Okay, there are 4 hunks per address.  They all seem good too... */
 
571
 
 
572
                                /* First tell me how many 'chunks' are at each address... */
 
573
                                size[0] = WORD_AT( threeDPointer, ( 6<<1) ) ;
 
574
                                size[1] = WORD_AT( threeDPointer, ( 7<<1) ) ;
 
575
                                size[2] = WORD_AT( threeDPointer, ( 9<<1) ) ;
 
576
                                size[3] = WORD_AT( threeDPointer, (10<<1) ) ;
 
577
 
 
578
                                megaOffset = ( WORD_AT(threeDRoms, (threeDOffset + 4)) ) << 16 ;
 
579
                                address[0] = megaOffset | WORD_AT(threeDPointer, (0<<1)) ;
 
580
                                address[1] = megaOffset | WORD_AT(threeDPointer, (1<<1)) ;
 
581
                                address[2] = megaOffset | WORD_AT(threeDPointer, (3<<1)) ;
 
582
                                address[3] = megaOffset | WORD_AT(threeDPointer, (4<<1)) ;
 
583
 
 
584
                                /* DEBUG */
 
585
                                /* printf("%.5x %.3x %.5x %.3x %.5x %.3x %.5x %.3x\n", address[0], size[0], address[1], size[1], address[2], size[2], address[3], size[3]) ; */
 
586
                                /* !! END DEBUG !! */
 
587
 
 
588
 
 
589
 
 
590
                                /*////////////////////////////////// */
 
591
                                /* A FEW 'GLOBAL' TRANSFORMATIONS // */
 
592
                                /*////////////////////////////////// */
 
593
 
 
594
                                /* Now perform the world transformations... */
 
595
                                /* !! Can eliminate this step with a matrix stack (maybe necessary?) !! */
 
596
                                SetIdentity(modelViewMatrix) ;
 
597
                                matmul4(modelViewMatrix, modelViewMatrix, cameraMatrix) ;
 
598
                                matmul4(modelViewMatrix, modelViewMatrix, objectMatrix) ;
 
599
 
 
600
                                for (k = 0; k < 4; k++)                                                                         /* For all 4 chunks */
 
601
                                {
 
602
                                        threeDPointer = &threeDRoms[(address[k]<<1) * 3] ;
 
603
 
 
604
                                        for (l = 0; l < size[k]; l++)
 
605
                                        {
 
606
                                                /*////////////////////////////////////////// */
 
607
                                                /* GATHER A SINGLE TRIANGLE'S INFORMATION // */
 
608
                                                /*////////////////////////////////////////// */
 
609
 
 
610
                                                UINT8 triangleType = threeDPointer[1] ;
 
611
 
 
612
                                                UINT8 numVertices = 3 ;
 
613
                                                UINT8 chunkLength = 0 ;
 
614
 
 
615
                                                /* Some chunks only have 1 vertex (they act as a vertex fan) */
 
616
                                                if (triangleType == 0x97 ||
 
617
                                                        triangleType == 0x87 ||
 
618
                                                        triangleType == 0xd7 ||
 
619
                                                        triangleType == 0x96)
 
620
                                                        numVertices = 1 ;
 
621
 
 
622
                                                /* Get which texture this polygon refers to... */
 
623
                                                /* In fatfur it's 0xc for the smooth-shaded earth       - maybe this is for all things with alpha - check the hair at some point... */
 
624
                                                /*                0x9 for the untextured buildings */
 
625
                                                /*                0xd for the 'explosion' of the HNG64 */
 
626
                                                /*            and 0x8 everywhere else... */
 
627
                                                /*        they're 0x8 in the buriki intro too (those are 66-byte chunks!) */
 
628
                                                polys[numPolys].texType = ((threeDPointer[2] & 0xf0) >> 4);
 
629
 
 
630
                                                if (polys[numPolys].texType == 0x8 || polys[numPolys].texType == 0xc)           /*  || polys[numPolys].texType == 0x9 */
 
631
                                                        polys[numPolys].texIndex = threeDPointer[3] & 0x0f ;
 
632
                                                else
 
633
                                                        polys[numPolys].texIndex = -1 ;
 
634
 
 
635
                                                /* Set the polygon's palette */
 
636
                                                polys[numPolys].palIndex = paletteState ;
 
637
 
 
638
                                                for (m = 0; m < numVertices; m++)                                                               /* For all vertices of the chunk */
 
639
                                                {
 
640
                                                        switch(triangleType)
 
641
                                                        {
 
642
                                                        /* 42 byte chunk */
 
643
                                                        case 0x04:
 
644
                                                        case 0x0e:
 
645
                                                                polys[numPolys].vert[m].worldCoords[0] = uToF(WORD_AT(threeDPointer, ((3<<1) + (6<<1)*m)) ) ;
 
646
                                                                polys[numPolys].vert[m].worldCoords[1] = uToF(WORD_AT(threeDPointer, ((4<<1) + (6<<1)*m)) ) ;
 
647
                                                                polys[numPolys].vert[m].worldCoords[2] = uToF(WORD_AT(threeDPointer, ((5<<1) + (6<<1)*m)) ) ;
 
648
                                                                polys[numPolys].vert[m].worldCoords[3] = 1.0f ;
 
649
                                                                polys[numPolys].n = 3 ;
 
650
 
 
651
                                                                /* !! What is the first coordinate here (6) - maybe denotes size of chunk? !! */
 
652
                                                                polys[numPolys].vert[m].texCoords[0] = uToF(WORD_AT(threeDPointer, ((7<<1) + (6<<1)*m)) ) ;
 
653
                                                                polys[numPolys].vert[m].texCoords[1] = uToF(WORD_AT(threeDPointer, ((8<<1) + (6<<1)*m)) ) ;
 
654
                                                                polys[numPolys].vert[m].texCoords[2] = 0.0f ;
 
655
                                                                polys[numPolys].vert[m].texCoords[3] = 1.0f ;
 
656
 
 
657
                                                                polys[numPolys].vert[m].normal[0] = uToF(WORD_AT(threeDPointer, (21<<1) )) ;
 
658
                                                                polys[numPolys].vert[m].normal[1] = uToF(WORD_AT(threeDPointer, (22<<1) )) ;
 
659
                                                                polys[numPolys].vert[m].normal[2] = uToF(WORD_AT(threeDPointer, (23<<1) )) ;
 
660
                                                                polys[numPolys].vert[m].normal[3] = 0.0f ;
 
661
 
 
662
                                                                /* !!! DUMB !!! */
 
663
                                                                polys[numPolys].vert[m].light[0] = polys[numPolys].vert[m].texCoords[0] * 255.0f ;
 
664
                                                                polys[numPolys].vert[m].light[1] = polys[numPolys].vert[m].texCoords[1] * 255.0f ;
 
665
                                                                polys[numPolys].vert[m].light[2] = polys[numPolys].vert[m].texCoords[2] * 255.0f ;
 
666
 
 
667
                                                                /* Redundantly called, but it works... */
 
668
                                                                polys[numPolys].faceNormal[0] = polys[numPolys].vert[m].normal[0] ;
 
669
                                                                polys[numPolys].faceNormal[1] = polys[numPolys].vert[m].normal[1] ;
 
670
                                                                polys[numPolys].faceNormal[2] = polys[numPolys].vert[m].normal[2] ;
 
671
                                                                polys[numPolys].faceNormal[3] = 0.0f ;
 
672
 
 
673
                                                                chunkLength = (24<<1) ;
 
674
                                                                break ;
 
675
 
 
676
                                                        /* 66 byte chunk */
 
677
                                                        case 0x05:
 
678
                                                        case 0x0f:
 
679
                                                                polys[numPolys].vert[m].worldCoords[0] = uToF(WORD_AT(threeDPointer, ((3<<1) + (9<<1)*m)) ) ;
 
680
                                                                polys[numPolys].vert[m].worldCoords[1] = uToF(WORD_AT(threeDPointer, ((4<<1) + (9<<1)*m)) ) ;
 
681
                                                                polys[numPolys].vert[m].worldCoords[2] = uToF(WORD_AT(threeDPointer, ((5<<1) + (9<<1)*m)) ) ;
 
682
                                                                polys[numPolys].vert[m].worldCoords[3] = 1.0f ;
 
683
                                                                polys[numPolys].n = 3 ;
 
684
 
 
685
                                                                /* !! See above - (6) - why? !! */
 
686
                                                                polys[numPolys].vert[m].texCoords[0] = uToF(WORD_AT(threeDPointer, ((7<<1) + (9<<1)*m)) ) ;
 
687
                                                                polys[numPolys].vert[m].texCoords[1] = uToF(WORD_AT(threeDPointer, ((8<<1) + (9<<1)*m)) ) ;
 
688
                                                                polys[numPolys].vert[m].texCoords[2] = 0.0f ;
 
689
                                                                polys[numPolys].vert[m].texCoords[3] = 1.0f ;
 
690
 
 
691
                                                                polys[numPolys].vert[m].normal[0] = uToF(WORD_AT(threeDPointer, ((9<<1) + (9<<1)*m)) ) ;
 
692
                                                                polys[numPolys].vert[m].normal[1] = uToF(WORD_AT(threeDPointer, ((10<<1) + (9<<1)*m)) ) ;
 
693
                                                                polys[numPolys].vert[m].normal[2] = uToF(WORD_AT(threeDPointer, ((11<<1) + (9<<1)*m)) ) ;
 
694
                                                                polys[numPolys].vert[m].normal[3] = 0.0f ;
 
695
 
 
696
                                                                /* !!! DUMB !!! */
 
697
                                                                polys[numPolys].vert[m].light[0] = polys[numPolys].vert[m].texCoords[0] * 255.0f ;
 
698
                                                                polys[numPolys].vert[m].light[1] = polys[numPolys].vert[m].texCoords[1] * 255.0f ;
 
699
                                                                polys[numPolys].vert[m].light[2] = polys[numPolys].vert[m].texCoords[2] * 255.0f ;
 
700
 
 
701
                                                                /* Redundantly called, but it works... */
 
702
                                                                polys[numPolys].faceNormal[0] = uToF(WORD_AT(threeDPointer, (30<<1) )) ;
 
703
                                                                polys[numPolys].faceNormal[1] = uToF(WORD_AT(threeDPointer, (31<<1) )) ;
 
704
                                                                polys[numPolys].faceNormal[2] = uToF(WORD_AT(threeDPointer, (32<<1) )) ;
 
705
                                                                polys[numPolys].faceNormal[3] = 0.0f ;
 
706
 
 
707
                                                                chunkLength = (33<<1) ;
 
708
                                                                break ;
 
709
 
 
710
                                                        /* 30 byte chunk */
 
711
                                                        case 0x97:
 
712
                                                        case 0x87:
 
713
                                                        case 0xd7:
 
714
 
 
715
                                                                /* Copy over the proper vertices from the previous triangle... */
 
716
                                                                memcpy(&polys[numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert)) ;
 
717
                                                                memcpy(&polys[numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert)) ;
 
718
 
 
719
                                                                /* Fill in the appropriate data... */
 
720
                                                                polys[numPolys].vert[0].worldCoords[0] = uToF(WORD_AT(threeDPointer, (3<<1) )) ;
 
721
                                                                polys[numPolys].vert[0].worldCoords[1] = uToF(WORD_AT(threeDPointer, (4<<1) )) ;
 
722
                                                                polys[numPolys].vert[0].worldCoords[2] = uToF(WORD_AT(threeDPointer, (5<<1) )) ;
 
723
                                                                polys[numPolys].vert[0].worldCoords[3] = 1.0f ;
 
724
                                                                polys[numPolys].n = 3 ;
 
725
 
 
726
                                                                /* !! See above - (6) - why? !! */
 
727
                                                                polys[numPolys].vert[0].texCoords[0] = uToF(WORD_AT(threeDPointer, (7<<1) )) ;
 
728
                                                                polys[numPolys].vert[0].texCoords[1] = uToF(WORD_AT(threeDPointer, (8<<1) )) ;
 
729
                                                                polys[numPolys].vert[0].texCoords[2] = 0.0f ;
 
730
                                                                polys[numPolys].vert[0].texCoords[3] = 1.0f ;
 
731
 
 
732
                                                                polys[numPolys].vert[0].normal[0] = uToF(WORD_AT(threeDPointer, (9<<1) )) ;
 
733
                                                                polys[numPolys].vert[0].normal[1] = uToF(WORD_AT(threeDPointer, (10<<1) )) ;
 
734
                                                                polys[numPolys].vert[0].normal[2] = uToF(WORD_AT(threeDPointer, (11<<1) )) ;
 
735
                                                                polys[numPolys].vert[0].normal[3] = 0.0f ;
 
736
 
 
737
                                                                polys[numPolys].vert[0].light[0] = polys[numPolys].vert[0].texCoords[0] * 255.0f ;
 
738
                                                                polys[numPolys].vert[0].light[1] = polys[numPolys].vert[0].texCoords[1] * 255.0f ;
 
739
                                                                polys[numPolys].vert[0].light[2] = polys[numPolys].vert[0].texCoords[2] * 255.0f ;
 
740
 
 
741
                                                                polys[numPolys].faceNormal[0] = uToF(WORD_AT(threeDPointer, (12<<1) )) ;
 
742
                                                                polys[numPolys].faceNormal[1] = uToF(WORD_AT(threeDPointer, (13<<1) )) ;
 
743
                                                                polys[numPolys].faceNormal[2] = uToF(WORD_AT(threeDPointer, (14<<1) )) ;
 
744
                                                                polys[numPolys].faceNormal[3] = 0.0f ;
 
745
 
 
746
                                                                chunkLength = (15<<1) ;
 
747
                                                                break ;
 
748
 
 
749
                                                        /* 18 byte chunk */
 
750
                                                        case 0x96:
 
751
 
 
752
                                                                /* Copy over the proper vertices from the previous triangle... */
 
753
                                                                memcpy(&polys[numPolys].vert[1], &lastPoly.vert[0], sizeof(struct polyVert)) ;
 
754
                                                                memcpy(&polys[numPolys].vert[2], &lastPoly.vert[2], sizeof(struct polyVert)) ;
 
755
 
 
756
                                                                /* !!! Too lazy to have finished this yet !!! */
 
757
 
 
758
                                                                polys[numPolys].vert[0].worldCoords[0] = uToF(WORD_AT(threeDPointer, (3<<1))) ;
 
759
                                                                polys[numPolys].vert[0].worldCoords[1] = uToF(WORD_AT(threeDPointer, (4<<1))) ;
 
760
                                                                polys[numPolys].vert[0].worldCoords[2] = uToF(WORD_AT(threeDPointer, (5<<1))) ;
 
761
                                                                polys[numPolys].vert[0].worldCoords[3] = 1.0f ;
 
762
                                                                polys[numPolys].n = 3 ;
 
763
 
 
764
                                                                /* !! See above - (6) - why? !! */
 
765
                                                                polys[numPolys].vert[0].texCoords[0] = uToF(WORD_AT(threeDPointer, (7<<1))) ;
 
766
                                                                polys[numPolys].vert[0].texCoords[1] = uToF(WORD_AT(threeDPointer, (8<<1))) ;
 
767
                                                                polys[numPolys].vert[0].texCoords[2] = 0.0f ;
 
768
                                                                polys[numPolys].vert[0].texCoords[3] = 1.0f ;
 
769
 
 
770
                                                                /* !!! DUMB !!! */
 
771
                                                                polys[numPolys].vert[0].light[0] = polys[numPolys].vert[0].texCoords[0] * 255.0f ;
 
772
                                                                polys[numPolys].vert[0].light[1] = polys[numPolys].vert[0].texCoords[1] * 255.0f ;
 
773
                                                                polys[numPolys].vert[0].light[2] = polys[numPolys].vert[0].texCoords[2] * 255.0f ;
 
774
 
 
775
                                                                /* This normal could be right, but I'm not entirely sure - there is no normal in the 18 bytes! */
 
776
                                                                polys[numPolys].vert[0].normal[0] = lastPoly.faceNormal[0] ;
 
777
                                                                polys[numPolys].vert[0].normal[1] = lastPoly.faceNormal[1] ;
 
778
                                                                polys[numPolys].vert[0].normal[2] = lastPoly.faceNormal[2] ;
 
779
                                                                polys[numPolys].vert[0].normal[3] = lastPoly.faceNormal[3] ;
 
780
 
 
781
                                                                polys[numPolys].faceNormal[0] = lastPoly.faceNormal[0] ;
 
782
                                                                polys[numPolys].faceNormal[1] = lastPoly.faceNormal[1] ;
 
783
                                                                polys[numPolys].faceNormal[2] = lastPoly.faceNormal[2] ;
 
784
                                                                polys[numPolys].faceNormal[3] = lastPoly.faceNormal[3] ;
 
785
 
 
786
                                                                chunkLength = (9<<1) ;
 
787
                                                                break ;
 
788
 
 
789
                                                        default:
 
790
                                                                printf("UNKNOWN geometry CHUNK TYPE : %x\n", triangleType) ;
 
791
                                                                break ;
 
792
                                                        }
 
793
                                                }
 
794
 
 
795
                                                polys[numPolys].visible = 1 ;
 
796
 
 
797
                                                memcpy(&lastPoly, &polys[numPolys], sizeof(struct polygon)) ;
 
798
 
 
799
 
 
800
 
 
801
 
 
802
                                                /* THE HNG64 HARDWARE DOES NOT SEEM TO BACKFACE CULL // */
 
803
 
 
804
                                                /*///////////////// */
 
805
                                                /* BACKFACE CULL // */
 
806
                                                /*///////////////// */
 
807
/*
 
808
                        float cullRay[4] ;
 
809
                        float cullNorm[4] ;
 
810
 
 
811
                        // Cast a ray out of the camera towards the polygon's point in eyespace.
 
812
                        vecmatmul4(cullRay, modelViewMatrix, polys[numPolys].vert[0].worldCoords) ;
 
813
                        normalize(cullRay) ;
 
814
                        // Dot product that with the normal to see if you're negative...
 
815
                        vecmatmul4(cullNorm, modelViewMatrix, polys[numPolys].faceNormal) ;
 
816
 
 
817
                        float result = vecDotProduct(cullRay, cullNorm) ;
 
818
 
 
819
                        if (result < 0.0f)
 
820
                            polys[numPolys].visible = 1 ;
 
821
                        else
 
822
                            polys[numPolys].visible = 0 ;
 
823
*/
 
824
 
 
825
                                                /*////////////////////////// */
 
826
                                                /* BEHIND-THE-CAMERA CULL // */
 
827
                                                /*////////////////////////// */
 
828
                                                vecmatmul4(cullRay, modelViewMatrix, polys[numPolys].vert[0].worldCoords) ;
 
829
 
 
830
                                                if (cullRay[2] > 0.0f)                          /* Camera is pointing down -Z */
 
831
                                                {
 
832
                                                        polys[numPolys].visible = 0 ;
 
833
                                                }
 
834
 
 
835
 
 
836
                                                /*//////////////////////////////////////////////////////// */
 
837
                                                /* TRANSFORM THE TRIANGLE INTO HOMOGENEOUS SCREEN SPACE // */
 
838
                                                /*//////////////////////////////////////////////////////// */
 
839
 
 
840
                                                if (polys[numPolys].visible)
 
841
                                                {
 
842
                                                        for (m = 0; m < polys[numPolys].n; m++)
 
843
                                                        {
 
844
                                                                /* Transform and project the vertex into pre-divided homogeneous coordinates... */
 
845
                                                                vecmatmul4(eyeCoords, modelViewMatrix, polys[numPolys].vert[m].worldCoords) ;
 
846
                                                                vecmatmul4(polys[numPolys].vert[m].clipCoords, projectionMatrix, eyeCoords) ;
 
847
                                                        }
 
848
 
 
849
                                                        if (polys[numPolys].visible)
 
850
                                                        {
 
851
                                                                /* Clip the triangles to the view frustum... */
 
852
                                                                PerformFrustumClip(&polys[numPolys]) ;
 
853
 
 
854
                                                                for (m = 0; m < polys[numPolys].n; m++)
 
855
                                                                {
 
856
                                                                        /* Convert into normalized device coordinates... */
 
857
                                                                        ndCoords[0] = polys[numPolys].vert[m].clipCoords[0] / polys[numPolys].vert[m].clipCoords[3] ;
 
858
                                                                        ndCoords[1] = polys[numPolys].vert[m].clipCoords[1] / polys[numPolys].vert[m].clipCoords[3] ;
 
859
                                                                        ndCoords[2] = polys[numPolys].vert[m].clipCoords[2] / polys[numPolys].vert[m].clipCoords[3] ;
 
860
                                                                        ndCoords[3] = polys[numPolys].vert[m].clipCoords[3] ;
 
861
 
 
862
                                                                        /* Final pixel values are garnered here : */
 
863
                                                                        windowCoords[0] = (ndCoords[0]+1.0f) * ((float)(Machine->visible_area.max_x) / 2.0f) + 0.0f ;
 
864
                                                                        windowCoords[1] = (ndCoords[1]+1.0f) * ((float)(Machine->visible_area.max_y) / 2.0f) + 0.0f ;
 
865
                                                                        windowCoords[2] = (ndCoords[2]+1.0f) * 0.5f ;
 
866
 
 
867
                                                                        windowCoords[1] = (float)Machine->visible_area.max_y - windowCoords[1] ;                /* Flip Y */
 
868
 
 
869
                                                                        /* Store the points in a list for later use... */
 
870
                                                                        polys[numPolys].vert[m].clipCoords[0] = windowCoords[0] ;
 
871
                                                                        polys[numPolys].vert[m].clipCoords[1] = windowCoords[1] ;
 
872
                                                                        polys[numPolys].vert[m].clipCoords[2] = windowCoords[2] ;
 
873
                                                                        polys[numPolys].vert[m].clipCoords[3] = ndCoords[3] ;
 
874
                                                                }
 
875
                                                        }
 
876
                                                }
 
877
 
 
878
 
 
879
/*
 
880
                        // DEBUG
 
881
                        if (chunkLength == (9 << 1))
 
882
                        {
 
883
                            printf("Chunk : ") ;
 
884
                            for (int ajg = 0; ajg < chunkLength; ajg+=2)
 
885
                                printf("%.2x%.2x ", threeDPointer[ajg], threeDPointer[ajg+1]) ;
 
886
                            printf("\n") ;
 
887
                        }
 
888
                        // END DEBUG
 
889
*/
 
890
 
 
891
                                                /* Advance to the next polygon chunk... */
 
892
                                                threeDPointer += chunkLength ;
 
893
 
 
894
                                                numPolys++ ;                            /* Add one more to the display list... */
 
895
                                        }
 
896
                                }
 
897
 
 
898
                                break ;
 
899
 
 
900
                        default:
 
901
                                break ;
 
902
                        }
 
903
                }
 
904
 
 
905
                /* Don't forget about this !!! */
 
906
                /*printf("                 %.8x\n\n", (UINT32)hng64_dls[j][0x80]) ; */
 
907
 
 
908
        }
 
909
 
 
910
 
 
911
        /*/////////////////////////////////////////////// */
 
912
        /* FINALLY RENDER THE TRIANGLES INTO THE FRAME // */
 
913
        /*/////////////////////////////////////////////// */
 
914
 
 
915
        /* Reset the depth buffer... */
 
916
        for (i = 0; i < (Machine->visible_area.max_x)*(Machine->visible_area.max_y); i++)
 
917
                depthBuffer[i] = 100.0f ;
 
918
 
 
919
        for (i = 0; i < numPolys; i++)
 
920
        {
 
921
                if (polys[i].visible)
 
922
                {
 
923
                        /*DrawWireframe(&polys[i], bitmap) ; */
 
924
                        DrawShaded(&polys[i], bitmap) ;
 
925
                }
 
926
        }
 
927
 
 
928
        /* usrintf_showmessage("%d", numPolys) ; */
 
929
 
 
930
        /* Clear each of the display list buffers after drawing... */
 
931
        for (i = 0; i < 0x81; i++)
 
932
        {
 
933
                hng64_dls[0][i] = 0 ;
 
934
                hng64_dls[1][i] = 0 ;
 
935
        }
 
936
}
 
937
 
 
938
 
 
939
/* 8x8 tiles, 4bpp layer */
 
940
static void get_hng64_tile0_info(int tile_index)
 
941
{
 
942
        int tileno,pal;
 
943
        tileno = hng64_videoram[tile_index];
 
944
        pal = hng64_videoram[tile_index]>>24;
 
945
        SET_TILE_INFO((tileno&1)?0:1,(tileno&0x3fffff)>>1,pal,TILE_FLIPYX((tileno&0xc00000)>>22))
 
946
}
 
947
 
 
948
/* 16x16 tiles, 8bpp layer */
 
949
static void get_hng64_tile1_info(int tile_index)
 
950
{
 
951
        int tileno,pal;
 
952
        tileno = hng64_videoram[tile_index+(0x10000/4)];
 
953
        pal = hng64_videoram[tile_index+(0x10000/4)]>>24;
 
954
 
 
955
        SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4,  TILE_FLIPYX((tileno&0xc00000)>>22) )
 
956
}
 
957
 
 
958
/* 16x16 tiles, 8bpp layer */
 
959
static void get_hng64_tile2_info(int tile_index)
 
960
{
 
961
        int tileno,pal;
 
962
        tileno = hng64_videoram[tile_index+(0x20000/4)];
 
963
        pal = hng64_videoram[tile_index+(0x20000/4)]>>24;
 
964
        SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4,TILE_FLIPYX((tileno&0xc00000)>>22))
 
965
}
 
966
 
 
967
/* 16x16 tiles, 8bpp layer */
 
968
static void get_hng64_tile3_info(int tile_index)
 
969
{
 
970
        int tileno,pal;
 
971
        tileno = hng64_videoram[tile_index+(0x30000/4)];
 
972
        pal = hng64_videoram[tile_index+(0x30000/4)]>>24;
 
973
        SET_TILE_INFO(3,(tileno&0x3fffff)>>3,pal>>4,TILE_FLIPYX((tileno&0xc00000)>>22))
 
974
}
 
975
 
 
976
 
 
977
 
 
978
/* Tilemaps zoom, and probably rotate.. they can have linescroll/lineselect,
 
979
looks like the zoom center can move too..
 
980
not sure how these features are enabled up yet */
 
981
 
 
982
static int gatherPixelsForLine(mame_bitmap *tilemapBitmap,
 
983
                                                           INT32 startX, INT32 startY, INT32 endX, INT32 endY,
 
984
                                                           UINT16 *penList)
 
985
{
 
986
        int retVal = 0 ;
 
987
 
 
988
        /* !! BRESENHAM'S AGAIN - I REALLY SHOULD GENERALIZE THIS !! */
 
989
 
 
990
#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
 
991
 
 
992
        INT32 i;
 
993
        INT32 steep = 1;
 
994
        INT32 sx, sy;  /* step positive or negative (1 or -1) */
 
995
        INT32 dx, dy;  /* delta (difference in X and Y between points) */
 
996
        INT32 e;
 
997
 
 
998
        /*
 
999
    * inline swap. On some architectures, the XOR trick may be faster
 
1000
    */
 
1001
        INT32 tmpswap;
 
1002
 
 
1003
        /*
 
1004
    * optimize for vertical and horizontal lines here
 
1005
    */
 
1006
 
 
1007
        dx = abs(endX - startX);
 
1008
        sx = ((endX - startX) > 0) ? 1 : -1;
 
1009
        dy = abs(endY - startY);
 
1010
        sy = ((endY - startY) > 0) ? 1 : -1;
 
1011
 
 
1012
        if (dy > dx)
 
1013
        {
 
1014
                steep = 0;
 
1015
                SWAP(startX, startY);
 
1016
                SWAP(dx, dy);
 
1017
                SWAP(sx, sy);
 
1018
        }
 
1019
 
 
1020
        e = (dy << 1) - dx;
 
1021
 
 
1022
        for (i = 0; i < dx; i++)
 
1023
        {
 
1024
                if (steep)
 
1025
                {
 
1026
                        penList[retVal] = ((UINT16*)tilemapBitmap->line[startY])[startX] ;
 
1027
                        retVal++ ;
 
1028
                }
 
1029
                else
 
1030
                {
 
1031
                        penList[retVal] = ((UINT16*)tilemapBitmap->line[startX])[startY] ;
 
1032
                        retVal++ ;
 
1033
                }
 
1034
                while (e >= 0)
 
1035
                {
 
1036
                        startY += sy;
 
1037
                        e -= (dx << 1);
 
1038
                }
 
1039
 
 
1040
                startX += sx;
 
1041
                e += (dy << 1);
 
1042
        }
 
1043
#undef SWAP
 
1044
 
 
1045
 
 
1046
        return retVal ;
 
1047
}
 
1048
 
 
1049
static void plotTilemap3Line(mame_bitmap *tilemapBitmap,
 
1050
                                                         INT32 startX, INT32 startY, INT32 endX, INT32 endY,
 
1051
                                                         INT32 screenY, mame_bitmap *bitmap)
 
1052
{
 
1053
        int i ;
 
1054
        UINT8 r, g, b ;
 
1055
 
 
1056
        int numPix ;
 
1057
        UINT16 penList[0x1000] ;                        /* 4k of pixels to be safe */
 
1058
 
 
1059
        float pixStride, pixOffset ;
 
1060
 
 
1061
/*  printf("(%d,%d) (%d,%d)\n", startX, startY, endX, endY) ; */
 
1062
 
 
1063
        /* CLAMP - BUT I'M PRETTY SURE THIS ISN'T QUITE RIGHT !!! ??? */
 
1064
        startX += 1024 ; if (startX < 0) startX = 0 ; else if (startX > 2048) startX = 2048 ;
 
1065
        startY += 1024 ; if (startY < 0) startY = 0 ; else if (startY > 2048) startY = 2048 ;
 
1066
        endX += 1024 ; if (endX < 0) endX = 0 ; else if (endX > 2048) endX = 2048 ;
 
1067
        endY += 1024 ; if (endY < 0) endY = 0 ; else if (endY > 2048) endY = 2048 ;
 
1068
 
 
1069
        numPix = gatherPixelsForLine(tilemapBitmap, startX, startY, endX, endY, penList) ;
 
1070
 
 
1071
        pixStride = (float)numPix / (float)(Machine->visible_area.max_x-1) ;
 
1072
        pixOffset = 0 ;
 
1073
 
 
1074
        if (numPix == 0)
 
1075
                penList[0] = ((UINT16*)tilemapBitmap->line[1024])[1024] ;
 
1076
 
 
1077
/*  printf("numpix %d ps %f po %f s(%d,%d) e(%d,%d)\n", numPix, pixStride, pixOffset, startX, startY, endX, endY) ; */
 
1078
 
 
1079
        /* Draw out the screen's line... */
 
1080
        for (i = Machine->visible_area.min_x; i < Machine->visible_area.max_x; i++)
 
1081
        {
 
1082
                /* Nearest-neighbor interpolation for now (but i doubt it does linear) */
 
1083
                UINT16 tmPen = penList[(int)pixOffset] ;
 
1084
                palette_get_color(tmPen, &r, &g, &b);
 
1085
 
 
1086
                ((UINT32 *)(bitmap->line[screenY]))[i] = MAKE_ARGB((UINT8)255, (UINT8)r, (UINT8)g, (UINT8)b) ;
 
1087
 
 
1088
                pixOffset += pixStride ;
 
1089
        }
 
1090
}
 
1091
 
 
1092
static void hng64_drawtilemap3( mame_bitmap *bitmap, const rectangle *cliprect )
 
1093
{
 
1094
        int i ;
 
1095
 
 
1096
        mame_bitmap *srcbitmap = tilemap_get_pixmap( hng64_tilemap3 );
 
1097
 
 
1098
/*  usrintf_showmessage("%d", hackTm3Count) ; */
 
1099
 
 
1100
        if (hackTm3Count/4 < Machine->visible_area.max_y)
 
1101
        {
 
1102
                for (i = 0; i < hackTm3Count/4; i++)
 
1103
                {
 
1104
                        UINT32 address = rowScrollOffset + 0xbf0 ;
 
1105
                        address -= (i * 0x10) ;
 
1106
                        address /= 4 ;
 
1107
                        /*printf("nums : %.4x %.4x %.4x %.4x\n", (INT16)((hng64_videoram[address+0x0]&0xffff0000) >> 16), */
 
1108
                        /*                                     (INT16)((hng64_videoram[address+0x1]&0xffff0000) >> 16), */
 
1109
                        /*                                     (INT16)((hng64_videoram[address+0x2]&0xffff0000) >> 16), */
 
1110
                        /*                                     (INT16)((hng64_videoram[address+0x3]&0xffff0000) >> 16)) ; */
 
1111
 
 
1112
                        plotTilemap3Line(srcbitmap,
 
1113
                                                         (INT16)((hng64_videoram[address+0x0]&0xffff0000) >> 16),
 
1114
                                                         (INT16)((hng64_videoram[address+0x2]&0xffff0000) >> 16),
 
1115
                                                         (INT16)((hng64_videoram[address+0x1]&0xffff0000) >> 16),
 
1116
                                                         (INT16)((hng64_videoram[address+0x3]&0xffff0000) >> 16),
 
1117
                                                         (Machine->visible_area.max_y-1)-i,
 
1118
                                                         bitmap) ;
 
1119
                }
 
1120
        }
 
1121
 
 
1122
        /* Maybe the scrollbase should be used instead of my hacky rowScrollOffset :)? */
 
1123
/*  scrollbase = (hng64_videoregs[0x05]&0x00003fff)>>0; */
 
1124
 
 
1125
/*  xscroll = hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16; */
 
1126
/*  yscroll = hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16; */
 
1127
/*  xzoom   = hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16; */
 
1128
/*  yzoom   = hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16; */
 
1129
/*  xzoom   = xzoom-xscroll; */
 
1130
/*  yzoom   = yzoom-yscroll; */
 
1131
/*  xzoom &=0xffff; */
 
1132
/*  yzoom &=0xffff; */
 
1133
 
 
1134
/*  xscroll <<=16; */
 
1135
/*  yscroll <<=16; */
 
1136
/*  xzoom <<=8; */
 
1137
/*  yzoom <<=8; */
 
1138
 
 
1139
/*  tilemap_set_scrollx(hng64_tilemap3,0, xscroll); */
 
1140
/*  tilemap_set_scrolly(hng64_tilemap3,0, yscroll); */
 
1141
 
 
1142
/*  tilemap_draw(bitmap,cliprect,hng64_tilemap3,0,0); */
 
1143
 
 
1144
/*  tilemap_draw_roz(bitmap,cliprect,hng64_tilemap3,xscroll,yscroll, */
 
1145
/*          xzoom,0,0,yzoom, */
 
1146
/*          1, */
 
1147
/*          0,0); */
 
1148
}
 
1149
 
 
1150
static void hng64_drawtilemap2( mame_bitmap *bitmap, const rectangle *cliprect )
 
1151
{
 
1152
        int scrollbase,xscroll,yscroll,xzoom,yzoom;
 
1153
 
 
1154
        scrollbase = (hng64_videoregs[0x05]&0x3fff0000)>>16;
 
1155
        xscroll = (INT16)(hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16);
 
1156
        /* ???  = (INT16)(hng64_videoram[(0x40004+(scrollbase<<4))/4]>>16); */
 
1157
        yscroll = (INT16)(hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16);
 
1158
        yzoom   = (INT16)(hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16);
 
1159
        xzoom   = (INT16)(hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16);
 
1160
        /* ???  = (INT16)(hng64_videoram[(0x40014+(scrollbase<<4))/4]>>16); */
 
1161
        /* ???  = (INT16)(hng64_videoram[(0x40018+(scrollbase<<4))/4]>>16); */
 
1162
        /* ???  = (INT16)(hng64_videoram[(0x4001c+(scrollbase<<4))/4]>>16); */
 
1163
        xzoom   = xzoom-xscroll;
 
1164
        yzoom   = yzoom-yscroll;
 
1165
        xzoom &=0xffff;
 
1166
        yzoom &=0xffff;
 
1167
 
 
1168
        xscroll <<=16;
 
1169
        yscroll <<=16;
 
1170
        xzoom <<=8;
 
1171
        yzoom <<=8;
 
1172
 
 
1173
        tilemap_draw_roz(bitmap,cliprect,hng64_tilemap2,xscroll,yscroll,
 
1174
                        xzoom,0,0,yzoom,
 
1175
                        1,
 
1176
                        0,0);
 
1177
}
 
1178
 
 
1179
static void hng64_drawtilemap1( mame_bitmap *bitmap, const rectangle *cliprect )
 
1180
{
 
1181
        int scrollbase,xscroll,yscroll,xzoom,yzoom;
 
1182
 
 
1183
        scrollbase = (hng64_videoregs[0x04]&0x00003fff)>>0;
 
1184
        xscroll = (INT16)(hng64_videoram[(0x40000+(scrollbase<<4))/4]>>16);
 
1185
        /* ???  = (INT16)(hng64_videoram[(0x40004+(scrollbase<<4))/4]>>16); */
 
1186
        yscroll = (INT16)(hng64_videoram[(0x40008+(scrollbase<<4))/4]>>16);
 
1187
        xzoom   = (INT16)(hng64_videoram[(0x40010+(scrollbase<<4))/4]>>16);
 
1188
        yzoom   = (INT16)(hng64_videoram[(0x4000c+(scrollbase<<4))/4]>>16);
 
1189
        /* ???  = (INT16)(hng64_videoram[(0x40014+(scrollbase<<4))/4]>>16); */
 
1190
        /* ???  = (INT16)(hng64_videoram[(0x40018+(scrollbase<<4))/4]>>16); */
 
1191
        /* ???  = (INT16)(hng64_videoram[(0x4001c+(scrollbase<<4))/4]>>16); */
 
1192
        xzoom   = xzoom-xscroll;
 
1193
        yzoom   = yzoom-yscroll;
 
1194
        xzoom &=0xffff;
 
1195
        yzoom &=0xffff;
 
1196
 
 
1197
        xscroll <<=16;
 
1198
        yscroll <<=16;
 
1199
        xzoom <<=8;
 
1200
        yzoom <<=8;
 
1201
 
 
1202
        tilemap_draw_roz(bitmap,cliprect,hng64_tilemap1,xscroll,yscroll,
 
1203
                        xzoom,0,0,yzoom,
 
1204
                        1,
 
1205
                        0,0);
 
1206
}
 
1207
 
 
1208
 
 
1209
 
 
1210
/*
 
1211
 * Video Regs Format
 
1212
 * ------------------
 
1213
 *
 
1214
 * UINT32 | Bytes    | Use
 
1215
 * -------+-76543210-+----------------
 
1216
 *   0    | oooooooo | unknown - always seems to be 04060000 (fatfurwa) and 00060000 (buriki)
 
1217
 *   1    | xxxx---- | looks like it's 0001 most (all) of the time - turns off in buriki intro
 
1218
 *   1    | ----oooo | unknown - always seems to be 0000 (fatfurwa)
 
1219
 *   2    | oooooooo | unknown - likes to change sometimes though... (looks like bit-flags)
 
1220
 *   3    | oooooooo | unknown - change a lot - maybe mixer flags?
 
1221
 *   4    | xxxx---- | tilemap0 offset into tilemap RAM?
 
1222
 *   4    | ----xxxx | tilemap1 offset into tilemap RAM
 
1223
 *   5    | xxxx---- | tilemap3 offset into tilemap RAM
 
1224
 *   5    | ----xxxx | tilemap4 offset into tilemap RAM?
 
1225
 *   6    | oooooooo | unknown - always seems to be 000001ff (fatfurwa)
 
1226
 *   7    | oooooooo | unknown - always seems to be 000001ff (fatfurwa)
 
1227
 *   8    | oooooooo | unknown - always seems to be 80008000 (fatfurwa)
 
1228
 *   9    | oooooooo | unknown - always seems to be 00000000 (fatfurwa)
 
1229
 *   a    | oooooooo | unknown - always seems to be 00000000 (fatfurwa)
 
1230
 *   b    | oooooooo | unknown - 00000000 in intro - 00007ff8 when fight is going on (looks like &'ing it with 0x3fff is a good thing to do - tilemap stuff?)
 
1231
 *   c    | xxxxxxxx | I'm almost positive this is some form of offset to produce animations in Tilemap1 - or maybe all tilemaps?
 
1232
 *                     - 00xxx000 are used in fatfurwa during fights
 
1233
 *                     - 00000?xx are used in buriki during the intro
 
1234
 *   d    | oooooooo | not used ??
 
1235
 *   e    | oooooooo | not used ??
 
1236
 */
 
1237
 
 
1238
 
 
1239
VIDEO_UPDATE( hng64 )
 
1240
{
 
1241
        fillbitmap(bitmap, get_black_pen(), 0);
 
1242
 
 
1243
        /* Debug */
 
1244
/*  for (int iii = 0; iii < 0x0f; iii++) */
 
1245
/*      printf("%.8x ", hng64_videoregs[iii]) ; */
 
1246
/*  printf("\n") ; */
 
1247
/*  usrintf_showmessage("%.8x %.8x %.8x %.8x", hng64_videoregs[0x1], hng64_videoregs[0x3], hng64_videoregs[0xb], hng64_videoregs[0xc]) ; */
 
1248
 
 
1249
        /* I think there's something to this, but I'm not doing it right... */
 
1250
        /* Interestingly enough, this turns the bootup screen blue :) */
 
1251
        /*
 
1252
    if (hng64_videoregs[0xc] != tilemap2Offset)
 
1253
    {
 
1254
        tilemap2Offset = hng64_videoregs[0xc] ;
 
1255
 
 
1256
        tilemap_dispose(hng64_tilemap1) ;
 
1257
        hng64_tilemap1 = tilemap_create(get_hng64_tile2_info,tilemap_scan_rows,TILEMAP_TRANSPARENT, 16, 16, 128,128); // 128x128x4 = 0x10000
 
1258
    }
 
1259
    */
 
1260
 
 
1261
        /* Rowscroll variables... */
 
1262
        /* usrintf_showmessage("%.8x %.8x x %.8x %.8x", hng64_videoram[0x00057bf0/4], hng64_videoram[0x00057bf4/4], hng64_videoram[0x00057bf8/4], hng64_videoram[0x00057bfc/4]) ; */
 
1263
 
 
1264
        /* All of this priority stuff is probably done with some funky layer mixing chip - */
 
1265
        /*   (there are neato alpha effects on a real board, etc) */
 
1266
        hng64_drawtilemap2(bitmap,cliprect);
 
1267
        hng64_drawtilemap1(bitmap,cliprect);
 
1268
        hng64_drawtilemap3(bitmap,cliprect);                                            /* Draw the ground last... */
 
1269
 
 
1270
        /* !!! This tilemap has the same flags as the 'previous' three, but they're not used in fatfurwa !!! */
 
1271
        /*     (in other words, we should make a similar hng64_drawtilemap0() function for this tilemap) */
 
1272
        tilemap_draw(bitmap,cliprect,hng64_tilemap0,0,0);
 
1273
 
 
1274
        hng64_drawsprites(bitmap,cliprect);
 
1275
 
 
1276
        /* 3d really shouldn't be last, but you don't see some cool stuff right now if it's put before sprites :)... */
 
1277
        hng64_draw3d(bitmap, cliprect);
 
1278
 
 
1279
        /* hack to enable 2nd cpu when key is pressed */
 
1280
        if ( code_pressed_memory(KEYCODE_L) )
 
1281
        {
 
1282
                cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
 
1283
                cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
 
1284
        }
 
1285
 
 
1286
        /* AJG */
 
1287
        /* if(code_pressed(KEYCODE_D)) */
 
1288
 
 
1289
        hng64_transition_control(bitmap) ;
 
1290
 
 
1291
/*  printf("FRAME DONE %d\n", frameCount) ; */
 
1292
        frameCount++ ;
 
1293
 
 
1294
        hackTilemap3 = rowScrollOffset = hackTm3Count = 0 ;
 
1295
}
 
1296
 
 
1297
VIDEO_START( hng64 )
 
1298
{
 
1299
        hng64_tilemap0 = tilemap_create(get_hng64_tile0_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8,   8, 128,128); /* 128x128x4 = 0x10000 */
 
1300
        hng64_tilemap1 = tilemap_create(get_hng64_tile1_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
 
1301
        hng64_tilemap2 = tilemap_create(get_hng64_tile2_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
 
1302
        hng64_tilemap3 = tilemap_create(get_hng64_tile3_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 16, 16, 128,128); /* 128x128x4 = 0x10000 */
 
1303
        tilemap_set_transparent_pen(hng64_tilemap0,0);
 
1304
        tilemap_set_transparent_pen(hng64_tilemap1,0);
 
1305
        tilemap_set_transparent_pen(hng64_tilemap2,0);
 
1306
        tilemap_set_transparent_pen(hng64_tilemap3,0);
 
1307
 
 
1308
        /* 3d Buffer Allocation */
 
1309
        depthBuffer = (float*)auto_malloc((Machine->visible_area.max_x)*(Machine->visible_area.max_y)*sizeof(float)) ;
 
1310
 
 
1311
        /* The general display list of polygons in the scene... */
 
1312
        /* !! This really should be a dynamic array !! */
 
1313
        polys = auto_malloc(MAX_ONSCREEN_POLYS * sizeof(struct polygon))  ;
 
1314
 
 
1315
        return 0;
 
1316
}
 
1317
 
 
1318
/*///////////// */
 
1319
/* UTILITIES // */
 
1320
/*///////////// */
 
1321
 
 
1322
/* 4x4 matrix multiplication */
 
1323
static void matmul4( float *product, const float *a, const float *b )
 
1324
{
 
1325
   int i;
 
1326
   for (i = 0; i < 4; i++)
 
1327
   {
 
1328
      const float ai0 = a[0  + i] ;
 
1329
          const float ai1 = a[4  + i] ;
 
1330
          const float ai2 = a[8  + i] ;
 
1331
          const float ai3 = a[12 + i] ;
 
1332
 
 
1333
          product[0  + i] = ai0 * b[0 ] + ai1 * b[1 ] + ai2 * b[2 ] + ai3 * b[3 ] ;
 
1334
          product[4  + i] = ai0 * b[4 ] + ai1 * b[5 ] + ai2 * b[6 ] + ai3 * b[7 ] ;
 
1335
          product[8  + i] = ai0 * b[8 ] + ai1 * b[9 ] + ai2 * b[10] + ai3 * b[11] ;
 
1336
          product[12 + i] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15] ;
 
1337
   }
 
1338
}
 
1339
 
 
1340
/* vector by 4x4 matrix multiply */
 
1341
static void vecmatmul4( float *product, const float *a, const float *b)
 
1342
{
 
1343
        const float bi0 = b[0] ;
 
1344
        const float bi1 = b[1] ;
 
1345
        const float bi2 = b[2] ;
 
1346
        const float bi3 = b[3] ;
 
1347
 
 
1348
        product[0] = bi0 * a[0] + bi1 * a[4] + bi2 * a[8 ] + bi3 * a[12];
 
1349
        product[1] = bi0 * a[1] + bi1 * a[5] + bi2 * a[9 ] + bi3 * a[13];
 
1350
        product[2] = bi0 * a[2] + bi1 * a[6] + bi2 * a[10] + bi3 * a[14];
 
1351
        product[3] = bi0 * a[3] + bi1 * a[7] + bi2 * a[11] + bi3 * a[15];
 
1352
}
 
1353
 
 
1354
static float vecDotProduct( const float *a, const float *b)
 
1355
{
 
1356
        return ((a[0]*b[0]) + (a[1]*b[1]) + (a[2]*b[2])) ;
 
1357
}
 
1358
 
 
1359
static void SetIdentity(float *matrix)
 
1360
{
 
1361
        int i ;
 
1362
 
 
1363
        for (i = 0; i < 16; i++)
 
1364
        {
 
1365
                matrix[i] = 0.0f ;
 
1366
        }
 
1367
 
 
1368
        matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f ;
 
1369
}
 
1370
 
 
1371
static float uToF(UINT16 input)
 
1372
{
 
1373
        float retVal ;
 
1374
 
 
1375
        retVal = (float)((INT16)input) / 32768.0f ;
 
1376
 
 
1377
/*
 
1378
    if ((INT16)input < 0)
 
1379
        retVal = (float)((INT16)input) / 32768.0f ;
 
1380
    else
 
1381
        retVal = (float)((INT16)input) / 32767.0f ;
 
1382
*/
 
1383
 
 
1384
        return retVal ;
 
1385
}
 
1386
 
 
1387
static void normalize(float* x)
 
1388
{
 
1389
        double l2 = (x[0]*x[0]) + (x[1]*x[1]) + (x[2]*x[2]);
 
1390
        double l=sqrt(l2) ;
 
1391
 
 
1392
        x[0] = (float)(x[0] / l) ;
 
1393
        x[1] = (float)(x[1] / l) ;
 
1394
        x[2] = (float)(x[2] / l) ;
 
1395
}
 
1396
 
 
1397
 
 
1398
 
 
1399
/*///////////////////////// */
 
1400
/* POLYGON CLIPPING CODE // */
 
1401
/*///////////////////////// */
 
1402
 
 
1403
/*///////////////////////////////////////////////////////////////////////////////// */
 
1404
/* The remainder of the code in this file is heavily                             // */
 
1405
/*   influenced by, and sometimes copied verbatim from Andrew Zaferakis' SoftGL  // */
 
1406
/*   rasterizing system.  http://www.cs.unc.edu/~andrewz/comp236/                // */
 
1407
/*                                                                               // */
 
1408
/*   Andrew granted permission for its use in MAME in October of 2004.           // */
 
1409
/*///////////////////////////////////////////////////////////////////////////////// */
 
1410
 
 
1411
/* Refer to the clipping planes as numbers */
 
1412
#define HNG64_LEFT   0
 
1413
#define HNG64_RIGHT  1
 
1414
#define HNG64_TOP    2
 
1415
#define HNG64_BOTTOM 3
 
1416
#define HNG64_NEAR   4
 
1417
#define HNG64_FAR    5
 
1418
 
 
1419
 
 
1420
static int Inside(struct polyVert *v, int plane)
 
1421
{
 
1422
        switch(plane)
 
1423
        {
 
1424
        case HNG64_LEFT:
 
1425
                return (v->clipCoords[0] >= -v->clipCoords[3]) ? 1 : 0 ;
 
1426
        case HNG64_RIGHT:
 
1427
                return (v->clipCoords[0] <=  v->clipCoords[3]) ? 1 : 0 ;
 
1428
 
 
1429
        case HNG64_TOP:
 
1430
                return (v->clipCoords[1] <=  v->clipCoords[3]) ? 1 : 0 ;
 
1431
        case HNG64_BOTTOM:
 
1432
                return (v->clipCoords[1] >= -v->clipCoords[3]) ? 1 : 0 ;
 
1433
 
 
1434
        case HNG64_NEAR:
 
1435
                return (v->clipCoords[2] <=  v->clipCoords[3]) ? 1 : 0;
 
1436
                return 1 ;
 
1437
        case HNG64_FAR:
 
1438
                return (v->clipCoords[2] >= -v->clipCoords[3]) ? 1 : 0;
 
1439
                return 1 ;
 
1440
        }
 
1441
 
 
1442
        return 0 ;
 
1443
}
 
1444
 
 
1445
static void Intersect(struct polyVert *input0, struct polyVert *input1, struct polyVert *output, int plane)
 
1446
{
 
1447
        float t = 0.0f ;
 
1448
 
 
1449
        float *Iv0 = input0->clipCoords ;
 
1450
        float *Iv1 = input1->clipCoords ;
 
1451
        float *Ov  = output->clipCoords ;
 
1452
 
 
1453
        float *It0 = input0->texCoords ;
 
1454
        float *It1 = input1->texCoords ;
 
1455
        float *Ot  = output->texCoords ;
 
1456
 
 
1457
        float *Il0 = input0->light ;
 
1458
        float *Il1 = input1->light ;
 
1459
        float *Ol  = output->light ;
 
1460
 
 
1461
        switch(plane)
 
1462
        {
 
1463
        case HNG64_LEFT:
 
1464
                t = (Iv0[0]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[0]+Iv0[0]);
 
1465
                break;
 
1466
        case HNG64_RIGHT:
 
1467
                t = (Iv0[0]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[0]+Iv0[0]);
 
1468
                break;
 
1469
        case HNG64_TOP:
 
1470
                t = (Iv0[1]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[1]+Iv0[1]);
 
1471
                break;
 
1472
        case HNG64_BOTTOM:
 
1473
                t = (Iv0[1]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[1]+Iv0[1]);
 
1474
                break;
 
1475
        case HNG64_NEAR:
 
1476
                t = (Iv0[2]-Iv0[3]) / (Iv1[3]-Iv0[3]-Iv1[2]+Iv0[2]);
 
1477
                break;
 
1478
        case HNG64_FAR:
 
1479
                t = (Iv0[2]+Iv0[3]) / (-Iv1[3]+Iv0[3]-Iv1[2]+Iv0[2]);
 
1480
                break;
 
1481
        }
 
1482
 
 
1483
        Ov[0] = Iv0[0] + (Iv1[0] - Iv0[0]) * t ;
 
1484
        Ov[1] = Iv0[1] + (Iv1[1] - Iv0[1]) * t ;
 
1485
        Ov[2] = Iv0[2] + (Iv1[2] - Iv0[2]) * t ;
 
1486
        Ov[3] = Iv0[3] + (Iv1[3] - Iv0[3]) * t ;
 
1487
 
 
1488
        Ot[0] = It0[0] + (It1[0] - It0[0]) * t ;
 
1489
        Ot[1] = It0[1] + (It1[1] - It0[1]) * t ;
 
1490
        Ot[2] = It0[2] + (It1[2] - It0[2]) * t ;
 
1491
        Ot[3] = It0[3] + (It1[3] - It0[3]) * t ;
 
1492
 
 
1493
        Ol[0] = Il0[0] + (Il1[0] - Il0[0]) * t ;
 
1494
        Ol[1] = Il0[1] + (Il1[1] - Il0[1]) * t ;
 
1495
        Ol[2] = Il0[2] + (Il1[2] - Il0[2]) * t ;
 
1496
}
 
1497
 
 
1498
 
 
1499
 
 
1500
static void PerformFrustumClip(struct polygon *p)
 
1501
{
 
1502
        int i, j ;
 
1503
        int k ;
 
1504
 
 
1505
        /*//////////////////////////////////////////////////////////////////////// */
 
1506
        /* Clip against the volumes defined by the homogeneous clip coordinates // */
 
1507
        /*//////////////////////////////////////////////////////////////////////// */
 
1508
 
 
1509
        struct polygon temp ;
 
1510
 
 
1511
        struct polyVert *v0 ;
 
1512
        struct polyVert *v1 ;
 
1513
        struct polyVert *tv ;
 
1514
 
 
1515
        temp.n = 0;
 
1516
 
 
1517
        /* Skip near and far clipping planes ? */
 
1518
        for (j = 0; j <= HNG64_BOTTOM; j++)
 
1519
        {
 
1520
                for (i = 0; i < p->n; i++)
 
1521
                {
 
1522
                        k = (i+1) % p->n; /* Index of next vertex */
 
1523
 
 
1524
                        v0 = &p->vert[i] ;
 
1525
                        v1 = &p->vert[k] ;
 
1526
 
 
1527
                        tv = &temp.vert[temp.n] ;
 
1528
 
 
1529
                        if (Inside(v0, j) && Inside(v1, j))                                                     /* Edge is completely inside the volume... */
 
1530
                        {
 
1531
                                memcpy(tv, v1, sizeof(struct polyVert)) ;
 
1532
                                temp.n++;
 
1533
                        }
 
1534
 
 
1535
                        else if (Inside(v0, j) && !Inside(v1, j))                                       /* Edge goes from in to out... */
 
1536
                        {
 
1537
                                Intersect(v0, v1, tv, j) ;
 
1538
                                temp.n++;
 
1539
                        }
 
1540
 
 
1541
                        else if (!Inside(v0, j) && Inside(v1, j))                                       /* Edge goes from out to in... */
 
1542
                        {
 
1543
                                Intersect(v0, v1, tv, j) ;
 
1544
                                memcpy(&temp.vert[temp.n+1], v1, sizeof(struct polyVert)) ;
 
1545
                                temp.n+=2;
 
1546
                        }
 
1547
                }
 
1548
 
 
1549
                p->n = temp.n;
 
1550
 
 
1551
                for (i = 0; i < temp.n; i++)
 
1552
                {
 
1553
                        memcpy(&p->vert[i], &temp.vert[i], sizeof(struct polyVert)) ;
 
1554
                }
 
1555
 
 
1556
                temp.n = 0 ;
 
1557
        }
 
1558
}
 
1559
 
 
1560
 
 
1561
/*//////////////////////////// */
 
1562
/* POLYGON RASTERIZING CODE // */
 
1563
/*//////////////////////////// */
 
1564
 
 
1565
/*/////////////////////// */
 
1566
/* wireframe rendering // */
 
1567
/*/////////////////////// */
 
1568
 
 
1569
static void plot(INT32 x, INT32 y, INT32 color, mame_bitmap *bitmap)
 
1570
{
 
1571
        ((UINT32 *)(bitmap->line[y]))[x] = MAKE_ARGB((UINT8)255, (UINT8)color, (UINT8)color, (UINT8)color) ;
 
1572
}
 
1573
 
 
1574
/* Stolen from http://en.wikipedia.org/wiki/Bresenham's_line_algorithm (no copyright denoted) - the non-optimized version */
 
1575
static void drawline2d(INT32 x0, INT32 y0, INT32 x1, INT32 y1, INT32 color, mame_bitmap *bitmap)
 
1576
{
 
1577
#define SWAP(a,b) tmpswap = a; a = b; b = tmpswap;
 
1578
 
 
1579
        INT32 i;
 
1580
        INT32 steep = 1;
 
1581
        INT32 sx, sy;  /* step positive or negative (1 or -1) */
 
1582
        INT32 dx, dy;  /* delta (difference in X and Y between points) */
 
1583
        INT32 e;
 
1584
 
 
1585
        /*
 
1586
    * inline swap. On some architectures, the XOR trick may be faster
 
1587
    */
 
1588
        INT32 tmpswap;
 
1589
 
 
1590
        /*
 
1591
    * optimize for vertical and horizontal lines here
 
1592
    */
 
1593
 
 
1594
        dx = abs(x1 - x0);
 
1595
        sx = ((x1 - x0) > 0) ? 1 : -1;
 
1596
        dy = abs(y1 - y0);
 
1597
        sy = ((y1 - y0) > 0) ? 1 : -1;
 
1598
 
 
1599
        if (dy > dx)
 
1600
        {
 
1601
                steep = 0;
 
1602
                SWAP(x0, y0);
 
1603
                SWAP(dx, dy);
 
1604
                SWAP(sx, sy);
 
1605
        }
 
1606
 
 
1607
        e = (dy << 1) - dx;
 
1608
 
 
1609
        for (i = 0; i < dx; i++)
 
1610
        {
 
1611
                if (steep)
 
1612
                {
 
1613
                        plot(x0,y0,color, bitmap);
 
1614
                }
 
1615
                else
 
1616
                {
 
1617
                        plot(y0,x0,color, bitmap);
 
1618
                }
 
1619
                while (e >= 0)
 
1620
                {
 
1621
                        y0 += sy;
 
1622
                        e -= (dx << 1);
 
1623
                }
 
1624
 
 
1625
                x0 += sx;
 
1626
                e += (dy << 1);
 
1627
        }
 
1628
#undef SWAP
 
1629
}
 
1630
 
 
1631
 
 
1632
static void DrawWireframe(struct polygon *p, mame_bitmap *bitmap)
 
1633
{
 
1634
        int j;
 
1635
        for (j = 0; j < p->n; j++)
 
1636
        {
 
1637
                /* printf("now drawing : %f %f %f, %f %f %f\n", p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[j].clipCoords[2], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[2]) ; */
 
1638
                /* printf("%f %f %f %f\n", p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1]) ; */
 
1639
                drawline2d(p->vert[j].clipCoords[0], p->vert[j].clipCoords[1], p->vert[(j+1)%p->n].clipCoords[0], p->vert[(j+1)%p->n].clipCoords[1], 255, bitmap) ;
 
1640
        }
 
1641
 
 
1642
        /* SHOWS THE CLIPPING // */
 
1643
        /*
 
1644
    for (int j = 1; j < p->n-1; j++)
 
1645
    {
 
1646
        drawline2d(p->vert[0].clipCoords[0],   p->vert[0].clipCoords[1],   p->vert[j].clipCoords[0],   p->vert[j].clipCoords[1],   255, bitmap) ;
 
1647
        drawline2d(p->vert[j].clipCoords[0],   p->vert[j].clipCoords[1],   p->vert[j+1].clipCoords[0], p->vert[j+1].clipCoords[1], 255, bitmap) ;
 
1648
        drawline2d(p->vert[j+1].clipCoords[0], p->vert[j+1].clipCoords[1], p->vert[0].clipCoords[0],   p->vert[0].clipCoords[1],   255, bitmap) ;
 
1649
    }
 
1650
    */
 
1651
}
 
1652
 
 
1653
 
 
1654
/*///////////////////// */
 
1655
/* polygon rendering // */
 
1656
/*///////////////////// */
 
1657
 
 
1658
void RasterizeTriangle_SMOOTH_TEX_PC(mame_bitmap *Color,
 
1659
                                     float A[4], float B[4], float C[4],
 
1660
                                     float Ca[3], float Cb[3], float Cc[3], /* PER-VERTEX RGB COLORS */
 
1661
                                     float Ta[2], float Tb[2], float Tc[2], /* PER-VERTEX (S,T) TEX-COORDS */
 
1662
                                     int Wrapping, int Filtering, int Function) ;
 
1663
 
 
1664
static void DrawShaded(struct polygon *p, mame_bitmap *bitmap)
 
1665
{
 
1666
        /* The perspective-correct texture divide... */
 
1667
        /* !!! There is a very good chance the HNG64 hardware does not do perspective-correct texture-mapping !!! */
 
1668
        int j;
 
1669
        for (j = 0; j < p->n; j++)
 
1670
        {
 
1671
                p->vert[j].clipCoords[3] = 1.0f / p->vert[j].clipCoords[3] ;
 
1672
                p->vert[j].light[0]      = p->vert[j].light[0]     * p->vert[j].clipCoords[3] ;
 
1673
                p->vert[j].light[1]      = p->vert[j].light[1]     * p->vert[j].clipCoords[3] ;
 
1674
                p->vert[j].light[2]      = p->vert[j].light[2]     * p->vert[j].clipCoords[3] ;
 
1675
                p->vert[j].texCoords[0]  = p->vert[j].texCoords[0] * p->vert[j].clipCoords[3] ;
 
1676
                p->vert[j].texCoords[1]  = p->vert[j].texCoords[1] * p->vert[j].clipCoords[3] ;
 
1677
        }
 
1678
 
 
1679
        for (j = 1; j < p->n-1; j++)
 
1680
        {
 
1681
                RasterizeTriangle_SMOOTH_TEX_PC(bitmap,
 
1682
                                                                                p->vert[0].clipCoords, p->vert[j].clipCoords, p->vert[j+1].clipCoords,
 
1683
                                                                                p->vert[0].light,      p->vert[j].light,      p->vert[j+1].light,
 
1684
                                                                                p->vert[0].texCoords,  p->vert[j].texCoords,  p->vert[j+1].texCoords,
 
1685
                                                                                p->texType, p->palIndex, p->texIndex) ;
 
1686
 
 
1687
        }
 
1688
}
 
1689
 
 
1690
 
 
1691
/*********************************************************************/
 
1692
/**   FillSmoothTexPCHorizontalLine                                 **/
 
1693
/**     Input: Color Buffer (framebuffer), depth buffer, width and  **/
 
1694
/**            height of framebuffer, starting, and ending values   **/
 
1695
/**            for x and y, constant y.  Fills horizontally with    **/
 
1696
/**            z,r,g,b interpolation.                               **/
 
1697
/**                                                                 **/
 
1698
/**     Output: none                                                **/
 
1699
/*********************************************************************/
 
1700
INLINE void FillSmoothTexPCHorizontalLine(mame_bitmap *Color,
 
1701
                                          int Wrapping, int Filtering, int Function,
 
1702
                                          int x_start, int x_end, int y, float z_start, float z_delta,
 
1703
                                          float w_start, float w_delta, float r_start, float r_delta,
 
1704
                                          float g_start, float g_delta, float b_start, float b_delta,
 
1705
                                          float s_start, float s_delta, float t_start, float t_delta)
 
1706
{
 
1707
        float *dp = &(depthBuffer[y*Machine->visible_area.max_x+x_start]);
 
1708
 
 
1709
        const UINT8 *gfx = memory_region(REGION_GFX3);
 
1710
        const UINT8 *textureOffset ;
 
1711
        UINT8 paletteEntry ;
 
1712
        float t_coord, s_coord ;
 
1713
 
 
1714
        if (Function >= 0) textureOffset = &gfx[Function * 1024 * 1024] ;
 
1715
        else               textureOffset = 0x00 ;
 
1716
 
 
1717
 
 
1718
        for ( ; x_start <= x_end; x_start++)
 
1719
        {
 
1720
                if (z_start < (*dp))
 
1721
                {
 
1722
                        /* MULTIPLY BACK THROUGH BY W */
 
1723
                        t_coord = t_start / w_start;
 
1724
                        s_coord = s_start / w_start;
 
1725
 
 
1726
                        /* GET THE TEXTURE INDEX */
 
1727
                        if (Function >= 0)
 
1728
                        {
 
1729
                                if (Wrapping == 0x8 || Wrapping == 0xc)
 
1730
                                        paletteEntry = textureOffset[(((int)(s_coord*1024.0f))*1024 + (int)(t_coord*1024.0f))] ;
 
1731
                                else
 
1732
                                        paletteEntry = textureOffset[(((int)(s_coord*512.0f))*1024 + (int)(t_coord*512.0f))] ;
 
1733
 
 
1734
                                /* Naieve Alpha Implementation (?) - don't draw if you're at texture index 0... */
 
1735
                                if (paletteEntry != 0)
 
1736
                                {
 
1737
                                        /* Greyscale texture - for Buriki... */
 
1738
                                        /* ((UINT32 *)(Color->line[y]))[x_start] = MAKE_ARGB(255, (UINT8)paletteEntry, (UINT8)paletteEntry, (UINT8)paletteEntry) ; */
 
1739
 
 
1740
                                        ((UINT32 *)(Color->line[y]))[x_start] = Machine->pens[(128*(Filtering))+paletteEntry] ;
 
1741
                                        *dp = z_start ;
 
1742
                                }
 
1743
                        }
 
1744
                        else
 
1745
                        {
 
1746
                                ((UINT32 *)(Color->line[y]))[x_start] = MAKE_ARGB(255, (UINT8)(r_start/w_start), (UINT8)(g_start/w_start), (UINT8)(b_start/w_start)) ;
 
1747
                                *dp = z_start;
 
1748
                        }
 
1749
                }
 
1750
                dp++;
 
1751
                z_start += z_delta;
 
1752
                w_start += w_delta;
 
1753
                r_start += r_delta;
 
1754
                g_start += g_delta;
 
1755
                b_start += b_delta;
 
1756
                s_start += s_delta;
 
1757
                t_start += t_delta;
 
1758
        }
 
1759
}
 
1760
 
 
1761
/*---------------------------------------------------------------------------- */
 
1762
/* Given 3D triangle ABC in screen space with clipped coordinates within the following */
 
1763
/* bounds: x in [0,W], y in [0,H], z in [0,1]. The origin for (x,y) is in the bottom */
 
1764
/* left corner of the pixel grid. z=0 is the near plane and z=1 is the far plane, */
 
1765
/* so lesser values are closer. The coordinates of the pixels are evenly spaced */
 
1766
/* in x and y 1 units apart starting at the bottom-left pixel with coords */
 
1767
/* (0.5,0.5). In other words, the pixel sample point is in the center of the */
 
1768
/* rectangular grid cell containing the pixel sample. The framebuffer has */
 
1769
/* dimensions width x height (WxH). The Color buffer is a 1D array (row-major */
 
1770
/* order) with 3 unsigned chars per pixel (24-bit color). The Depth buffer is */
 
1771
/* a 1D array (also row-major order) with a float value per pixel */
 
1772
/* For a pixel location (x,y) we can obtain */
 
1773
/* the Color and Depth array locations as: Color[(((int)y)*W+((int)x))*3] */
 
1774
/* (for the red value, green is offset +1, and blue is offset +2 and */
 
1775
/* Depth[((int)y)*W+((int)x)]. Fills the pixels contained in the triangle */
 
1776
/* with the global current color and the properly linearly interpolated depth */
 
1777
/* value (performs Z-buffer depth test before writing new pixel). */
 
1778
/* Pixel samples that lie inside the triangle edges are filled with */
 
1779
/* a bias towards the minimum values (samples that lie exactly on a triangle */
 
1780
/* edge are filled only for minimum x values along a horizontal span and for */
 
1781
/* minimum y values, samples lying on max values are not filled). */
 
1782
/* Per-vertex colors are RGB floating point triplets in [0.0,255.0]. The vertices */
 
1783
/* include their w-components for use in linearly interpolating perspectively */
 
1784
/* correct color (RGB) and texture-coords (st) across the face of the triangle. */
 
1785
/* A texture image of RGB floating point triplets of size TWxWH is also given. */
 
1786
/* Texture colors are normalized RGB values in [0,1]. */
 
1787
/*   clamp and repeat wrapping modes : Wrapping={0,1} */
 
1788
/*   nearest and bilinear filtering: Filtering={0,1} */
 
1789
/*   replace and modulate application modes: Function={0,1} */
 
1790
/*--------------------------------------------------------------------------- */
 
1791
void RasterizeTriangle_SMOOTH_TEX_PC(mame_bitmap *Color,
 
1792
                                     float A[4], float B[4], float C[4],
 
1793
                                     float Ca[3], float Cb[3], float Cc[3], /* PER-VERTEX RGB COLORS */
 
1794
                                     float Ta[2], float Tb[2], float Tc[2], /* PER-VERTEX (S,T) TEX-COORDS */
 
1795
                                     int Wrapping, int Filtering, int Function)
 
1796
{
 
1797
        /* Get our order of points by increasing y-coord */
 
1798
        float *p_min = ((A[1] <= B[1]) && (A[1] <= C[1])) ? A : ((B[1] <= A[1]) && (B[1] <= C[1])) ? B : C;
 
1799
        float *p_max = ((A[1] >= B[1]) && (A[1] >= C[1])) ? A : ((B[1] >= A[1]) && (B[1] >= C[1])) ? B : C;
 
1800
        float *p_mid = ((A != p_min) && (A != p_max)) ? A : ((B != p_min) && (B != p_max)) ? B : C;
 
1801
 
 
1802
        /* Perspectively correct color interpolation, interpolate r/w, g/w, b/w, then divide by 1/w at each pixel (A[3] = 1/w) */
 
1803
        float ca[3], cb[3], cc[3];
 
1804
        float ta[2], tb[2], tc[2];
 
1805
 
 
1806
        float *c_min;
 
1807
        float *c_mid;
 
1808
        float *c_max;
 
1809
 
 
1810
        /* We must keep the tex coords straight with the point ordering */
 
1811
        float *t_min;
 
1812
        float *t_mid;
 
1813
        float *t_max;
 
1814
 
 
1815
        /* Find out control points for y, this divides the triangle into upper and lower */
 
1816
        int   y_min;
 
1817
        int   y_max;
 
1818
        int   y_mid;
 
1819
 
 
1820
        /* Compute the slopes of each line, and color this is used to determine the interpolation */
 
1821
        float x1_slope;
 
1822
        float x2_slope;
 
1823
        float z1_slope;
 
1824
        float z2_slope;
 
1825
        float w1_slope;
 
1826
        float w2_slope;
 
1827
        float r1_slope;
 
1828
        float r2_slope;
 
1829
        float g1_slope;
 
1830
        float g2_slope;
 
1831
        float b1_slope;
 
1832
        float b2_slope;
 
1833
        float s1_slope;
 
1834
        float s2_slope;
 
1835
        float t1_slope;
 
1836
        float t2_slope;
 
1837
 
 
1838
        /* Compute the t values used in the equation Ax = Ax + (Bx - Ax)*t */
 
1839
        /* We only need one t, because it is only used to compute the start. */
 
1840
        /* Create storage for the interpolated x and z values for both lines */
 
1841
        /* also for the RGB interpolation */
 
1842
        float t;
 
1843
        float x1_interp;
 
1844
        float z1_interp;
 
1845
        float w1_interp;
 
1846
        float r1_interp;
 
1847
        float g1_interp;
 
1848
        float b1_interp;
 
1849
        float s1_interp;
 
1850
        float t1_interp;
 
1851
 
 
1852
        float x2_interp;
 
1853
        float z2_interp;
 
1854
        float w2_interp;
 
1855
        float r2_interp;
 
1856
        float g2_interp;
 
1857
        float b2_interp;
 
1858
        float s2_interp;
 
1859
        float t2_interp;
 
1860
 
 
1861
        /* Create storage for the horizontal interpolation of z and RGB color and its starting points */
 
1862
        /* This is used to fill the triangle horizontally */
 
1863
        int   x_start,     x_end;
 
1864
        float z_interp_x,  z_delta_x;
 
1865
        float w_interp_x,  w_delta_x;
 
1866
        float r_interp_x,  r_delta_x;
 
1867
        float g_interp_x,  g_delta_x;
 
1868
        float b_interp_x,  b_delta_x;
 
1869
        float s_interp_x,  s_delta_x;
 
1870
        float t_interp_x,  t_delta_x;
 
1871
 
 
1872
        ca[0] = Ca[0]; ca[1] = Ca[1]; ca[2] = Ca[2];
 
1873
        cb[0] = Cb[0]; cb[1] = Cb[1]; cb[2] = Cb[2];
 
1874
        cc[0] = Cc[0]; cc[1] = Cc[1]; cc[2] = Cc[2];
 
1875
 
 
1876
        /* Perspectively correct tex interpolation, interpolate s/w, t/w, then divide by 1/w at each pixel (A[3] = 1/w) */
 
1877
        ta[0] = Ta[0]; ta[1] = Ta[1];
 
1878
        tb[0] = Tb[0]; tb[1] = Tb[1];
 
1879
        tc[0] = Tc[0]; tc[1] = Tc[1];
 
1880
 
 
1881
        /* We must keep the colors straight with the point ordering */
 
1882
        c_min = (p_min == A) ? ca : (p_min == B) ? cb : cc;
 
1883
        c_mid = (p_mid == A) ? ca : (p_mid == B) ? cb : cc;
 
1884
        c_max = (p_max == A) ? ca : (p_max == B) ? cb : cc;
 
1885
 
 
1886
        /* We must keep the tex coords straight with the point ordering */
 
1887
        t_min = (p_min == A) ? ta : (p_min == B) ? tb : tc;
 
1888
        t_mid = (p_mid == A) ? ta : (p_mid == B) ? tb : tc;
 
1889
        t_max = (p_max == A) ? ta : (p_max == B) ? tb : tc;
 
1890
 
 
1891
        /* Find out control points for y, this divides the triangle into upper and lower */
 
1892
        y_min  = (((int)p_min[1]) + 0.5 >= p_min[1]) ? p_min[1] : ((int)p_min[1]) + 1;
 
1893
        y_max  = (((int)p_max[1]) + 0.5 <  p_max[1]) ? p_max[1] : ((int)p_max[1]) - 1;
 
1894
        y_mid  = (((int)p_mid[1]) + 0.5 >= p_mid[1]) ? p_mid[1] : ((int)p_mid[1]) + 1;
 
1895
 
 
1896
        /* Compute the slopes of each line, and color this is used to determine the interpolation */
 
1897
        x1_slope = (p_max[0] - p_min[0]) / (p_max[1] - p_min[1]);
 
1898
        x2_slope = (p_mid[0] - p_min[0]) / (p_mid[1] - p_min[1]);
 
1899
        z1_slope = (p_max[2] - p_min[2]) / (p_max[1] - p_min[1]);
 
1900
        z2_slope = (p_mid[2] - p_min[2]) / (p_mid[1] - p_min[1]);
 
1901
        w1_slope = (p_max[3] - p_min[3]) / (p_max[1] - p_min[1]);
 
1902
        w2_slope = (p_mid[3] - p_min[3]) / (p_mid[1] - p_min[1]);
 
1903
        r1_slope = (c_max[0] - c_min[0]) / (p_max[1] - p_min[1]);
 
1904
        r2_slope = (c_mid[0] - c_min[0]) / (p_mid[1] - p_min[1]);
 
1905
        g1_slope = (c_max[1] - c_min[1]) / (p_max[1] - p_min[1]);
 
1906
        g2_slope = (c_mid[1] - c_min[1]) / (p_mid[1] - p_min[1]);
 
1907
        b1_slope = (c_max[2] - c_min[2]) / (p_max[1] - p_min[1]);
 
1908
        b2_slope = (c_mid[2] - c_min[2]) / (p_mid[1] - p_min[1]);
 
1909
        s1_slope = (t_max[0] - t_min[0]) / (p_max[1] - p_min[1]);
 
1910
        s2_slope = (t_mid[0] - t_min[0]) / (p_mid[1] - p_min[1]);
 
1911
        t1_slope = (t_max[1] - t_min[1]) / (p_max[1] - p_min[1]);
 
1912
        t2_slope = (t_mid[1] - t_min[1]) / (p_mid[1] - p_min[1]);
 
1913
 
 
1914
        /* Compute the t values used in the equation Ax = Ax + (Bx - Ax)*t */
 
1915
        /* We only need one t, because it is only used to compute the start. */
 
1916
        /* Create storage for the interpolated x and z values for both lines */
 
1917
        /* also for the RGB interpolation */
 
1918
        t = (((float)y_min) + 0.5 - p_min[1]) / (p_max[1] - p_min[1]);
 
1919
        x1_interp = p_min[0] + (p_max[0] - p_min[0]) * t;
 
1920
        z1_interp = p_min[2] + (p_max[2] - p_min[2]) * t;
 
1921
        w1_interp = p_min[3] + (p_max[3] - p_min[3]) * t;
 
1922
        r1_interp = c_min[0] + (c_max[0] - c_min[0]) * t;
 
1923
        g1_interp = c_min[1] + (c_max[1] - c_min[1]) * t;
 
1924
        b1_interp = c_min[2] + (c_max[2] - c_min[2]) * t;
 
1925
        s1_interp = t_min[0] + (t_max[0] - t_min[0]) * t;
 
1926
        t1_interp = t_min[1] + (t_max[1] - t_min[1]) * t;
 
1927
 
 
1928
        t = (((float)y_min) + 0.5 - p_min[1]) / (p_mid[1] - p_min[1]);
 
1929
        x2_interp = p_min[0] + (p_mid[0] - p_min[0]) * t;
 
1930
        z2_interp = p_min[2] + (p_mid[2] - p_min[2]) * t;
 
1931
        w2_interp = p_min[3] + (p_mid[3] - p_min[3]) * t;
 
1932
        r2_interp = c_min[0] + (c_mid[0] - c_min[0]) * t;
 
1933
        g2_interp = c_min[1] + (c_mid[1] - c_min[1]) * t;
 
1934
        b2_interp = c_min[2] + (c_mid[2] - c_min[2]) * t;
 
1935
        s2_interp = t_min[0] + (t_mid[0] - t_min[0]) * t;
 
1936
        t2_interp = t_min[1] + (t_mid[1] - t_min[1]) * t;
 
1937
 
 
1938
        /* First work on the bottom half of the triangle */
 
1939
        /* I'm using y_min as the incrementer because it saves space and we don't need it anymore */
 
1940
        for ( ; y_min < y_mid; y_min++) {
 
1941
 
 
1942
                /* We always want to fill left to right, so we have 2 main cases */
 
1943
                /* Compute the integer starting and ending points and the appropriate z by */
 
1944
                /* interpolating.  Remember the pixels are in the middle of the grid, i.e. (0.5,0.5,0.5) */
 
1945
                if (x1_interp < x2_interp) {
 
1946
                        x_start    = ((((int)x1_interp) + 0.5) >= x1_interp) ? x1_interp : ((int)x1_interp) + 1;
 
1947
                        x_end      = ((((int)x2_interp) + 0.5) <  x2_interp) ? x2_interp : ((int)x2_interp) - 1;
 
1948
                        z_delta_x  = (z2_interp - z1_interp) / (x2_interp - x1_interp);
 
1949
                        w_delta_x  = (w2_interp - w1_interp) / (x2_interp - x1_interp);
 
1950
                        r_delta_x  = (r2_interp - r1_interp) / (x2_interp - x1_interp);
 
1951
                        g_delta_x  = (g2_interp - g1_interp) / (x2_interp - x1_interp);
 
1952
                        b_delta_x  = (b2_interp - b1_interp) / (x2_interp - x1_interp);
 
1953
                        s_delta_x  = (s2_interp - s1_interp) / (x2_interp - x1_interp);
 
1954
                        t_delta_x  = (t2_interp - t1_interp) / (x2_interp - x1_interp);
 
1955
                        t          = (x_start + 0.5 - x1_interp) / (x2_interp - x1_interp);
 
1956
                        z_interp_x = z1_interp + (z2_interp - z1_interp) * t;
 
1957
                        w_interp_x = w1_interp + (w2_interp - w1_interp) * t;
 
1958
                        r_interp_x = r1_interp + (r2_interp - r1_interp) * t;
 
1959
                        g_interp_x = g1_interp + (g2_interp - g1_interp) * t;
 
1960
                        b_interp_x = b1_interp + (b2_interp - b1_interp) * t;
 
1961
                        s_interp_x = s1_interp + (s2_interp - s1_interp) * t;
 
1962
                        t_interp_x = t1_interp + (t2_interp - t1_interp) * t;
 
1963
 
 
1964
                } else {
 
1965
                        x_start    = ((((int)x2_interp) + 0.5) >= x2_interp) ? x2_interp : ((int)x2_interp) + 1;
 
1966
                        x_end      = ((((int)x1_interp) + 0.5) <  x1_interp) ? x1_interp : ((int)x1_interp) - 1;
 
1967
                        z_delta_x  = (z1_interp - z2_interp) / (x1_interp - x2_interp);
 
1968
                        w_delta_x  = (w1_interp - w2_interp) / (x1_interp - x2_interp);
 
1969
                        r_delta_x  = (r1_interp - r2_interp) / (x1_interp - x2_interp);
 
1970
                        g_delta_x  = (g1_interp - g2_interp) / (x1_interp - x2_interp);
 
1971
                        b_delta_x  = (b1_interp - b2_interp) / (x1_interp - x2_interp);
 
1972
                        s_delta_x  = (s1_interp - s2_interp) / (x1_interp - x2_interp);
 
1973
                        t_delta_x  = (t1_interp - t2_interp) / (x1_interp - x2_interp);
 
1974
                        t          = (x_start + 0.5 - x2_interp) / (x1_interp - x2_interp);
 
1975
                        z_interp_x = z2_interp + (z1_interp - z2_interp) * t;
 
1976
                        w_interp_x = w2_interp + (w1_interp - w2_interp) * t;
 
1977
                        r_interp_x = r2_interp + (r1_interp - r2_interp) * t;
 
1978
                        g_interp_x = g2_interp + (g1_interp - g2_interp) * t;
 
1979
                        b_interp_x = b2_interp + (b1_interp - b2_interp) * t;
 
1980
                        s_interp_x = s2_interp + (s1_interp - s2_interp) * t;
 
1981
                        t_interp_x = t2_interp + (t1_interp - t2_interp) * t;
 
1982
                }
 
1983
 
 
1984
                /* Pass the horizontal line to the filler, this could be put in the routine */
 
1985
                /* then interpolate for the next values of x and z */
 
1986
                FillSmoothTexPCHorizontalLine(Color, Wrapping, Filtering, Function,
 
1987
                        x_start, x_end, y_min, z_interp_x, z_delta_x, w_interp_x, w_delta_x,
 
1988
                        r_interp_x, r_delta_x, g_interp_x, g_delta_x, b_interp_x, b_delta_x,
 
1989
                        s_interp_x, s_delta_x, t_interp_x, t_delta_x);
 
1990
                x1_interp += x1_slope;   z1_interp += z1_slope;
 
1991
                x2_interp += x2_slope;   z2_interp += z2_slope;
 
1992
                r1_interp += r1_slope;   r2_interp += r2_slope;
 
1993
                g1_interp += g1_slope;   g2_interp += g2_slope;
 
1994
                b1_interp += b1_slope;   b2_interp += b2_slope;
 
1995
                w1_interp += w1_slope;   w2_interp += w2_slope;
 
1996
                s1_interp += s1_slope;   s2_interp += s2_slope;
 
1997
                t1_interp += t1_slope;   t2_interp += t2_slope;
 
1998
        }
 
1999
 
 
2000
        /* Now do the same thing for the top half of the triangle. */
 
2001
        /* We only need to recompute the x2 line because it changes at the midpoint */
 
2002
        x2_slope = (p_max[0] - p_mid[0]) / (p_max[1] - p_mid[1]);
 
2003
        z2_slope = (p_max[2] - p_mid[2]) / (p_max[1] - p_mid[1]);
 
2004
        w2_slope = (p_max[3] - p_mid[3]) / (p_max[1] - p_mid[1]);
 
2005
        r2_slope = (c_max[0] - c_mid[0]) / (p_max[1] - p_mid[1]);
 
2006
        g2_slope = (c_max[1] - c_mid[1]) / (p_max[1] - p_mid[1]);
 
2007
        b2_slope = (c_max[2] - c_mid[2]) / (p_max[1] - p_mid[1]);
 
2008
        s2_slope = (t_max[0] - t_mid[0]) / (p_max[1] - p_mid[1]);
 
2009
        t2_slope = (t_max[1] - t_mid[1]) / (p_max[1] - p_mid[1]);
 
2010
 
 
2011
        t = (((float)y_mid) + 0.5 - p_mid[1]) / (p_max[1] - p_mid[1]);
 
2012
        x2_interp = p_mid[0] + (p_max[0] - p_mid[0]) * t;
 
2013
        z2_interp = p_mid[2] + (p_max[2] - p_mid[2]) * t;
 
2014
        w2_interp = p_mid[3] + (p_max[3] - p_mid[3]) * t;
 
2015
        r2_interp = c_mid[0] + (c_max[0] - c_mid[0]) * t;
 
2016
        g2_interp = c_mid[1] + (c_max[1] - c_mid[1]) * t;
 
2017
        b2_interp = c_mid[2] + (c_max[2] - c_mid[2]) * t;
 
2018
        s2_interp = t_mid[0] + (t_max[0] - t_mid[0]) * t;
 
2019
        t2_interp = t_mid[1] + (t_max[1] - t_mid[1]) * t;
 
2020
 
 
2021
        /* We've seen this loop before haven't we? */
 
2022
        /* I'm using y_mid as the incrementer because it saves space and we don't need it anymore */
 
2023
        for ( ; y_mid <= y_max; y_mid++) {
 
2024
 
 
2025
                if (x1_interp < x2_interp) {
 
2026
                        x_start    = ((((int)x1_interp) + 0.5) >= x1_interp) ? x1_interp : ((int)x1_interp) + 1;
 
2027
                        x_end      = ((((int)x2_interp) + 0.5) <  x2_interp) ? x2_interp : ((int)x2_interp) - 1;
 
2028
                        z_delta_x  = (z2_interp - z1_interp) / (x2_interp - x1_interp);
 
2029
                        w_delta_x  = (w2_interp - w1_interp) / (x2_interp - x1_interp);
 
2030
                        r_delta_x  = (r2_interp - r1_interp) / (x2_interp - x1_interp);
 
2031
                        g_delta_x  = (g2_interp - g1_interp) / (x2_interp - x1_interp);
 
2032
                        b_delta_x  = (b2_interp - b1_interp) / (x2_interp - x1_interp);
 
2033
                        s_delta_x  = (s2_interp - s1_interp) / (x2_interp - x1_interp);
 
2034
                        t_delta_x  = (t2_interp - t1_interp) / (x2_interp - x1_interp);
 
2035
                        t          = (x_start + 0.5 - x1_interp) / (x2_interp - x1_interp);
 
2036
                        z_interp_x = z1_interp + (z2_interp - z1_interp) * t;
 
2037
                        w_interp_x = w1_interp + (w2_interp - w1_interp) * t;
 
2038
                        r_interp_x = r1_interp + (r2_interp - r1_interp) * t;
 
2039
                        g_interp_x = g1_interp + (g2_interp - g1_interp) * t;
 
2040
                        b_interp_x = b1_interp + (b2_interp - b1_interp) * t;
 
2041
                        s_interp_x = s1_interp + (s2_interp - s1_interp) * t;
 
2042
                        t_interp_x = t1_interp + (t2_interp - t1_interp) * t;
 
2043
 
 
2044
                } else {
 
2045
                        x_start    = ((((int)x2_interp) + 0.5) >= x2_interp) ? x2_interp : ((int)x2_interp) + 1;
 
2046
                        x_end      = ((((int)x1_interp) + 0.5) <  x1_interp) ? x1_interp : ((int)x1_interp) - 1;
 
2047
                        z_delta_x  = (z1_interp - z2_interp) / (x1_interp - x2_interp);
 
2048
                        w_delta_x  = (w1_interp - w2_interp) / (x1_interp - x2_interp);
 
2049
                        r_delta_x  = (r1_interp - r2_interp) / (x1_interp - x2_interp);
 
2050
                        g_delta_x  = (g1_interp - g2_interp) / (x1_interp - x2_interp);
 
2051
                        b_delta_x  = (b1_interp - b2_interp) / (x1_interp - x2_interp);
 
2052
                        s_delta_x  = (s1_interp - s2_interp) / (x1_interp - x2_interp);
 
2053
                        t_delta_x  = (t1_interp - t2_interp) / (x1_interp - x2_interp);
 
2054
                        t          = (x_start + 0.5 - x2_interp) / (x1_interp - x2_interp);
 
2055
                        z_interp_x = z2_interp + (z1_interp - z2_interp) * t;
 
2056
                        w_interp_x = w2_interp + (w1_interp - w2_interp) * t;
 
2057
                        r_interp_x = r2_interp + (r1_interp - r2_interp) * t;
 
2058
                        g_interp_x = g2_interp + (g1_interp - g2_interp) * t;
 
2059
                        b_interp_x = b2_interp + (b1_interp - b2_interp) * t;
 
2060
                        s_interp_x = s2_interp + (s1_interp - s2_interp) * t;
 
2061
                        t_interp_x = t2_interp + (t1_interp - t2_interp) * t;
 
2062
                }
 
2063
 
 
2064
                /* Pass the horizontal line to the filler, this could be put in the routine */
 
2065
                /* then interpolate for the next values of x and z */
 
2066
                FillSmoothTexPCHorizontalLine(Color, Wrapping, Filtering, Function,
 
2067
                        x_start, x_end, y_mid, z_interp_x, z_delta_x, w_interp_x, w_delta_x,
 
2068
                        r_interp_x, r_delta_x, g_interp_x, g_delta_x, b_interp_x, b_delta_x,
 
2069
                        s_interp_x, s_delta_x, t_interp_x, t_delta_x);
 
2070
                x1_interp += x1_slope;   z1_interp += z1_slope;
 
2071
                x2_interp += x2_slope;   z2_interp += z2_slope;
 
2072
                r1_interp += r1_slope;   r2_interp += r2_slope;
 
2073
                g1_interp += g1_slope;   g2_interp += g2_slope;
 
2074
                b1_interp += b1_slope;   b2_interp += b2_slope;
 
2075
                w1_interp += w1_slope;   w2_interp += w2_slope;
 
2076
                s1_interp += s1_slope;   s2_interp += s2_slope;
 
2077
                t1_interp += t1_slope;   t2_interp += t2_slope;
 
2078
        }
 
2079
}