~ubuntu-branches/debian/experimental/mednafen/experimental

« back to all changes in this revision

Viewing changes to src/psx/gpu_polygon.inc

  • Committer: Package Import Robot
  • Author(s): Stephen Kitt
  • Date: 2012-01-31 07:21:35 UTC
  • mfrom: (1.2.8)
  • Revision ID: package-import@ubuntu.com-20120131072135-es3dj12y00xcnrsk
Tags: 0.9.19-1
* New upstream WIP version.
* Update copyright information.
* Refresh use-system-tremor.patch and remove psx-big-endian-only.patch.
* Add spelling-fixes.patch based on Lintian's recommendations.
* Build-depend on debhelper 9 or later and remove corresponding Lintian
  override.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
struct tri_vertex
 
2
{
 
3
 int32 x, y;
 
4
 int32 u, v;
 
5
 int32 r, g, b;
 
6
};
 
7
 
 
8
struct i_group
 
9
{
 
10
 int32 u, v;
 
11
 int32 r, g, b;
 
12
 int32 dummy0[3];
 
13
};
 
14
 
 
15
struct i_deltas
 
16
{
 
17
 int32 du_dx, dv_dx;
 
18
 int32 dr_dx, dg_dx, db_dx;
 
19
 int32 dummy0[3];
 
20
 
 
21
 int32 du_dy, dv_dy;
 
22
 int32 dr_dy, dg_dy, db_dy;
 
23
 int32 dummy1[3];
 
24
};
 
25
 
 
26
static INLINE int64 MakePolyXFP(int32 x)
 
27
{
 
28
 return ((int64)x << 32) + ((1LL << 32) - (1 << 11));
 
29
}
 
30
 
 
31
static INLINE int64 MakePolyXFPStep(int32 dx, int32 dy)
 
32
{
 
33
 int64 ret;
 
34
 int64 dx_ex = (int64)dx << 32;
 
35
 
 
36
 if(dx_ex < 0)
 
37
  dx_ex -= dy - 1;
 
38
 
 
39
 if(dx_ex > 0)
 
40
  dx_ex += dy - 1;
 
41
 
 
42
 ret = dx_ex / dy;
 
43
 
 
44
 return(ret);
 
45
}
 
46
 
 
47
static INLINE int32 GetPolyXFP_Int(int64 xfp)
 
48
{
 
49
 return(xfp >> 32);
 
50
}
 
51
 
 
52
//#define CALCIS(x,y) ( A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y) )
 
53
#define CALCIS(x,y) (((B.x - A.x) * (C.y - B.y)) - ((C.x - B.x) * (B.y - A.y)))
 
54
static INLINE bool CalcIDeltas(i_deltas &idl, const tri_vertex &A, const tri_vertex &B, const tri_vertex &C)
 
55
{
 
56
 int64 num = ((int64)COORD_MF_INT(1)) << 32;
 
57
 int64 denom = CALCIS(x, y);
 
58
 int64 one_div;
 
59
 
 
60
 if(!denom)
 
61
  return(false);
 
62
 
 
63
//num -= abs(denom) - 1;
 
64
// num += abs(denom) >> 1;
 
65
 
 
66
 one_div = num / denom;
 
67
 
 
68
 idl.dr_dx = ((one_div * CALCIS(r, y)) + 0x00000000) >> 32;
 
69
 idl.dr_dy = ((one_div * CALCIS(x, r)) + 0x00000000) >> 32;
 
70
 
 
71
 idl.dg_dx = ((one_div * CALCIS(g, y)) + 0x00000000) >> 32;
 
72
 idl.dg_dy = ((one_div * CALCIS(x, g)) + 0x00000000) >> 32;
 
73
 
 
74
 idl.db_dx = ((one_div * CALCIS(b, y)) + 0x00000000) >> 32;
 
75
 idl.db_dy = ((one_div * CALCIS(x, b)) + 0x00000000) >> 32;
 
76
 
 
77
 idl.du_dx = ((one_div * CALCIS(u, y)) + 0x00000000) >> 32;
 
78
 idl.du_dy = ((one_div * CALCIS(x, u)) + 0x00000000) >> 32;
 
79
 
 
80
 idl.dv_dx = ((one_div * CALCIS(v, y)) + 0x00000000) >> 32;
 
81
 idl.dv_dy = ((one_div * CALCIS(x, v)) + 0x00000000) >> 32;
 
82
 
 
83
// printf("  du_dx=%08x, du_dy=%08x\n", idl.du_dx, idl.du_dy);
 
84
 
 
85
 return(true);
 
86
}
 
87
#undef CALCIS
 
88
 
 
89
template<bool goraud, bool textured>
 
90
static INLINE void AddIDeltas_DX(i_group &ig, const i_deltas &idl)
 
91
{
 
92
 if(textured)
 
93
 {
 
94
  ig.u += idl.du_dx;
 
95
  ig.v += idl.dv_dx;
 
96
 }
 
97
 
 
98
 if(goraud)
 
99
 {
 
100
  ig.r += idl.dr_dx;
 
101
  ig.g += idl.dg_dx;
 
102
  ig.b += idl.db_dx;
 
103
 }
 
104
}
 
105
 
 
106
template<bool goraud, bool textured>
 
107
static INLINE void AddIDeltas_DY(i_group &ig, const i_deltas &idl, int32 count = 1)
 
108
{
 
109
 if(textured)
 
110
 {
 
111
  ig.u += idl.du_dy * count;
 
112
  ig.v += idl.dv_dy * count;
 
113
 }
 
114
 
 
115
 if(goraud)
 
116
 {
 
117
  ig.r += idl.dr_dy * count;
 
118
  ig.g += idl.dg_dy * count;
 
119
  ig.b += idl.db_dy * count;
 
120
 }
 
121
}
 
122
 
 
123
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
 
124
INLINE void PS_GPU::DrawSpan(int y, uint32 clut_offset, const int32 x_start, const int32 x_bound, const int32 bv_x, i_group ig, const i_deltas &idl)
 
125
{
 
126
  int32 xs = x_start, xb = x_bound;
 
127
 
 
128
  if(LineSkipTest(y))
 
129
   return;
 
130
 
 
131
  if(xs < xb)   // (xs != xb)
 
132
  {
 
133
   if(xs < ClipX0)
 
134
    xs = ClipX0;
 
135
 
 
136
   if(xb > (ClipX1 + 1))
 
137
    xb = ClipX1 + 1;
 
138
 
 
139
   if(xs < xb)
 
140
    DrawTimeAvail -= (xb - xs) * ((BlendMode >= 0) ? 2 : 1);
 
141
 
 
142
   if(textured)
 
143
   {
 
144
    ig.u += (xs - bv_x) * idl.du_dx;
 
145
    ig.v += (xs - bv_x) * idl.dv_dx;
 
146
   }
 
147
 
 
148
   if(goraud)
 
149
   {
 
150
    ig.r += (xs - bv_x) * idl.dr_dx;
 
151
    ig.g += (xs - bv_x) * idl.dg_dx;
 
152
    ig.b += (xs - bv_x) * idl.db_dx;
 
153
   }
 
154
 
 
155
   for(int32 x = xs; x < xb; x++)
 
156
   {
 
157
    uint32 r, g, b;
 
158
 
 
159
    if(goraud)
 
160
    {
 
161
     r = RGB8SAT[COORD_GET_INT(ig.r)];
 
162
     g = RGB8SAT[COORD_GET_INT(ig.g)];
 
163
     b = RGB8SAT[COORD_GET_INT(ig.b)];
 
164
    }
 
165
    else
 
166
    {
 
167
     r = COORD_GET_INT(ig.r);
 
168
     g = COORD_GET_INT(ig.g);
 
169
     b = COORD_GET_INT(ig.b);
 
170
    }
 
171
 
 
172
    if(textured)
 
173
    {
 
174
     uint16 fbw = GetTexel<TexMode_TA>(clut_offset, COORD_GET_INT(ig.u), COORD_GET_INT(ig.v));
 
175
 
 
176
     if(fbw)
 
177
     {
 
178
      if(TexMult)
 
179
      {
 
180
       if(dtd)
 
181
        fbw = ModTexel(fbw, r, g, b, x & 3, y & 3);
 
182
       else
 
183
        fbw = ModTexel(fbw, r, g, b, 3, 2); //x & 3, y & 3);
 
184
      }
 
185
      PlotPixel<BlendMode, MaskEval_TA, true>(x, y, fbw);
 
186
     }
 
187
    }
 
188
    else
 
189
    {
 
190
     uint16 pix = 0x8000;
 
191
 
 
192
     if(goraud && dtd)
 
193
     {
 
194
      pix |= DitherLUT[y & 3][x & 3][r] << 0;
 
195
      pix |= DitherLUT[y & 3][x & 3][g] << 5;
 
196
      pix |= DitherLUT[y & 3][x & 3][b] << 10;
 
197
     }
 
198
     else
 
199
     {
 
200
      pix |= (r >> 3) << 0;
 
201
      pix |= (g >> 3) << 5;
 
202
      pix |= (b >> 3) << 10;
 
203
     }
 
204
    
 
205
     PlotPixel<BlendMode, MaskEval_TA, false>(x, y, pix);
 
206
    }
 
207
 
 
208
    AddIDeltas_DX<goraud, textured>(ig, idl);
 
209
    //AddStep<goraud, textured>(perp_coord, perp_step);
 
210
   }
 
211
  }
 
212
}
 
213
 
 
214
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
 
215
void PS_GPU::DrawTriangle(tri_vertex *vertices, uint32 clut)
 
216
{
 
217
 i_deltas idl;
 
218
 
 
219
#if 0
 
220
 vertices[0].y = COORD_MF_INT(rand());
 
221
 vertices[1].y = COORD_MF_INT(rand());
 
222
 vertices[2].y = COORD_MF_INT(rand());
 
223
 
 
224
 vertices[0].x = COORD_MF_INT(rand());
 
225
 vertices[1].x = COORD_MF_INT(rand());
 
226
 vertices[2].x = COORD_MF_INT(rand());
 
227
#endif
 
228
 
 
229
 if(vertices[2].y < vertices[1].y)
 
230
 {
 
231
  tri_vertex tmp = vertices[1];
 
232
  vertices[1] = vertices[2];
 
233
  vertices[2] = tmp;
 
234
 }
 
235
 
 
236
 if(vertices[1].y < vertices[0].y)
 
237
 {
 
238
  tri_vertex tmp = vertices[0];
 
239
  vertices[0] = vertices[1];
 
240
  vertices[1] = tmp;
 
241
 }
 
242
 
 
243
 if(vertices[2].y < vertices[1].y)
 
244
 {
 
245
  tri_vertex tmp = vertices[1];
 
246
  vertices[1] = vertices[2];
 
247
  vertices[2] = tmp;
 
248
 }
 
249
 
 
250
 if(vertices[0].y == vertices[2].y)
 
251
  return;
 
252
 
 
253
 if((vertices[2].y - vertices[0].y) >= 1024)
 
254
 {
 
255
  PSX_WARNING("[GPU] Triangle height too large: %d", (vertices[2].y - vertices[0].y));
 
256
  return;
 
257
 }
 
258
 
 
259
 if(abs(vertices[2].x - vertices[0].x) >= 1024 ||
 
260
    abs(vertices[2].x - vertices[1].x) >= 1024 ||
 
261
    abs(vertices[1].x - vertices[0].x) >= 1024)
 
262
 {
 
263
  PSX_WARNING("[GPU] Triangle width too large: %d %d %d", abs(vertices[2].x - vertices[0].x), abs(vertices[2].x - vertices[1].x), abs(vertices[1].x - vertices[0].x));
 
264
  return;
 
265
 }
 
266
 
 
267
 if(!CalcIDeltas(idl, vertices[0], vertices[1], vertices[2]))
 
268
  return;
 
269
 
 
270
 // [0] should be top vertex, [2] should be bottom vertex, [1] should be off to the side vertex.
 
271
 //
 
272
 //
 
273
 int32 y_start = vertices[0].y;
 
274
 int32 y_middle = vertices[1].y;
 
275
 int32 y_bound = vertices[2].y;
 
276
 
 
277
 int64 base_coord;
 
278
 int64 base_step;
 
279
 
 
280
 int64 bound_coord_ul;
 
281
 int64 bound_coord_us;
 
282
 
 
283
 int64 bound_coord_ll;
 
284
 int64 bound_coord_ls;
 
285
 
 
286
 bool right_facing;
 
287
 //bool bottom_up;
 
288
 i_group ig;
 
289
 
 
290
 ig.u = COORD_MF_INT(vertices[0].u) + (1 << (COORD_FBS - 1));
 
291
 ig.v = COORD_MF_INT(vertices[0].v) + (1 << (COORD_FBS - 1));
 
292
 ig.r = COORD_MF_INT(vertices[0].r);
 
293
 ig.g = COORD_MF_INT(vertices[0].g);
 
294
 ig.b = COORD_MF_INT(vertices[0].b);
 
295
 
 
296
 base_coord = MakePolyXFP(vertices[0].x); //COORD_MF_INT(vertices[0].x) + ((1 << COORD_FBS) - 1);
 
297
 base_step = MakePolyXFPStep((vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y)); //ROUND_HELPER(COORD_MF_INT(vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y));
 
298
 
 
299
 bound_coord_ul = MakePolyXFP(vertices[0].x); // + ((1 << COORD_FBS) - 1);
 
300
 bound_coord_ll = MakePolyXFP(vertices[1].x); // + ((1 << COORD_FBS) - 1);
 
301
 
 
302
 //
 
303
 //
 
304
 //
 
305
 
 
306
 
 
307
 if(vertices[1].y == vertices[0].y)
 
308
 {
 
309
  bound_coord_us = 0;
 
310
  right_facing = (bool)(vertices[1].x > vertices[0].x);
 
311
 }
 
312
 else
 
313
 {
 
314
  bound_coord_us = MakePolyXFPStep((vertices[1].x - vertices[0].x), (vertices[1].y - vertices[0].y));
 
315
  right_facing = (bool)(bound_coord_us > base_step);
 
316
 }
 
317
 
 
318
 if(vertices[2].y == vertices[1].y)
 
319
  bound_coord_ls = 0;
 
320
 else
 
321
  bound_coord_ls = MakePolyXFPStep((vertices[2].x - vertices[1].x), (vertices[2].y - vertices[1].y));
 
322
 
 
323
 if(y_start < ClipY0)
 
324
 {
 
325
  int32 count = ClipY0 - y_start;
 
326
 
 
327
  y_start = ClipY0;
 
328
  base_coord += base_step * count;
 
329
  bound_coord_ul += bound_coord_us * count;
 
330
 
 
331
  AddIDeltas_DY<goraud, textured>(ig, idl, count);
 
332
 
 
333
  if(y_middle < ClipY0)
 
334
  {
 
335
   int32 count_ls = ClipY0 - y_middle;
 
336
 
 
337
   y_middle = ClipY0;
 
338
   bound_coord_ll += bound_coord_ls * count_ls;
 
339
  }
 
340
 }
 
341
 
 
342
 if(y_bound > (ClipY1 + 1))
 
343
 {
 
344
  y_bound = ClipY1 + 1;
 
345
 
 
346
  if(y_middle > y_bound)
 
347
   y_middle = y_bound;
 
348
 }
 
349
 
 
350
 if(right_facing)
 
351
 {
 
352
  for(int32 y = y_start; y < y_middle; y++)
 
353
  {
 
354
   DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ul), vertices[0].x, ig, idl);
 
355
   base_coord += base_step;
 
356
   bound_coord_ul += bound_coord_us;
 
357
   AddIDeltas_DY<goraud, textured>(ig, idl);
 
358
  }
 
359
 
 
360
  for(int32 y = y_middle; y < y_bound; y++)
 
361
  {
 
362
   DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ll), vertices[0].x, ig, idl);
 
363
   base_coord += base_step;
 
364
   bound_coord_ll += bound_coord_ls;
 
365
   AddIDeltas_DY<goraud, textured>(ig, idl);
 
366
  }
 
367
 }
 
368
 else
 
369
 {
 
370
  for(int32 y = y_start; y < y_middle; y++)
 
371
  {
 
372
   DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ul), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
 
373
   base_coord += base_step;
 
374
   bound_coord_ul += bound_coord_us;
 
375
   AddIDeltas_DY<goraud, textured>(ig, idl);
 
376
  }
 
377
 
 
378
  for(int32 y = y_middle; y < y_bound; y++)
 
379
  {
 
380
   DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ll), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
 
381
   base_coord += base_step;
 
382
   bound_coord_ll += bound_coord_ls;
 
383
   AddIDeltas_DY<goraud, textured>(ig, idl);
 
384
  }
 
385
 }
 
386
 
 
387
#if 0
 
388
 printf("[GPU] Vertices: %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d)\n\n\n", vertices[0].x, vertices[0].y,
 
389
        vertices[0].r, vertices[0].g, vertices[0].b,
 
390
        vertices[1].x, vertices[1].y,
 
391
        vertices[1].r, vertices[1].g, vertices[1].b,
 
392
        vertices[2].x, vertices[2].y,
 
393
        vertices[2].r, vertices[2].g, vertices[2].b);
 
394
#endif
 
395
}
 
396
 
 
397
 
 
398
template<int numvertices, bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
 
399
void PS_GPU::Command_DrawPolygon(const uint32 *cb)
 
400
{
 
401
 tri_vertex vertices[4];
 
402
 uint32 raw_colors[4];
 
403
 uint32 clut = 0;
 
404
 //uint32 tpage = 0;
 
405
 
 
406
 if(numvertices == 4)
 
407
  DrawTimeAvail -= 64;  // FIXME, correct time.
 
408
 else
 
409
  DrawTimeAvail -= 32;  // FIXME, correct time.
 
410
 
 
411
 memset(vertices, 0, sizeof(vertices));
 
412
 
 
413
 raw_colors[0] = (*cb & 0xFFFFFF);
 
414
 cb++;
 
415
 
 
416
 vertices[0].x = (int16)(*cb & 0xFFFF);
 
417
 vertices[0].y = (int16)(*cb >> 16);
 
418
 cb++;
 
419
 
 
420
 
 
421
 if(textured)
 
422
 {
 
423
  vertices[0].u = (*cb & 0xFF);
 
424
  vertices[0].v = (*cb >> 8) & 0xFF;
 
425
  clut = ((*cb >> 16) & 0xFFFF) << 4;
 
426
  cb++;
 
427
 }
 
428
 
 
429
 if(goraud)
 
430
 {
 
431
  raw_colors[1] = (*cb & 0xFFFFFF);
 
432
  cb++;
 
433
 }
 
434
 
 
435
 vertices[1].x = (int16)(*cb & 0xFFFF);
 
436
 vertices[1].y = (int16)(*cb >> 16);
 
437
 cb++;
 
438
 
 
439
 if(textured)
 
440
 {
 
441
  vertices[1].u = (*cb & 0xFF);
 
442
  vertices[1].v = (*cb >> 8) & 0xFF;
 
443
  cb++;
 
444
 }
 
445
 
 
446
 if(goraud)
 
447
 {
 
448
  raw_colors[2] = (*cb & 0xFFFFFF);
 
449
  cb++;
 
450
 }
 
451
 
 
452
 vertices[2].x = (int16)(*cb & 0xFFFF);
 
453
 vertices[2].y = (int16)(*cb >> 16);
 
454
 cb++;
 
455
 
 
456
 if(textured)
 
457
 {
 
458
  vertices[2].u = (*cb & 0xFF);
 
459
  vertices[2].v = (*cb >> 8) & 0xFF;
 
460
  cb++;
 
461
 }
 
462
 
 
463
 if(numvertices == 4)
 
464
 {
 
465
  if(goraud)
 
466
  {
 
467
   raw_colors[3] = (*cb & 0xFFFFFF);
 
468
   cb++;
 
469
  }
 
470
 
 
471
  vertices[3].x = (int16)(*cb & 0xFFFF);
 
472
  vertices[3].y = (int16)(*cb >> 16);
 
473
  cb++;
 
474
 
 
475
  if(textured)
 
476
  {
 
477
   vertices[3].u = (*cb & 0xFF);
 
478
   vertices[3].v = (*cb >> 8) & 0xFF;
 
479
   cb++;
 
480
  }
 
481
 }
 
482
 else
 
483
 {
 
484
  raw_colors[3] = raw_colors[0];
 
485
 }
 
486
 
 
487
 if(!goraud)
 
488
  raw_colors[1] = raw_colors[2] = raw_colors[3] = raw_colors[0];
 
489
 
 
490
 for(int i = 0; i < numvertices; i++)
 
491
 {
 
492
  //raw_colors[i] = rand() & 0xFFFFFF;
 
493
 
 
494
  vertices[i].r = raw_colors[i] & 0xFF;
 
495
  vertices[i].g = (raw_colors[i] >> 8) & 0xFF;
 
496
  vertices[i].b = (raw_colors[i] >> 16) & 0xFF;
 
497
 }
 
498
 
 
499
 for(int i = 0; i < numvertices; i++)
 
500
 {
 
501
  vertices[i].x += OffsX;
 
502
  vertices[i].y += OffsY;
 
503
 
 
504
  // TODO: Test number of bits on real system.
 
505
  vertices[i].x = sign_x_to_s32(12, vertices[i].x);
 
506
  vertices[i].y = sign_x_to_s32(12, vertices[i].y);
 
507
 }
 
508
 
 
509
#if 0
 
510
 printf("Draw polygon %d: ", numvertices);
 
511
 
 
512
 for(int i = 0; i < numvertices; i++)
 
513
 {
 
514
  printf("%d:%d ", vertices[i].x, vertices[i].y);
 
515
  //GPURAM[vertices[i].y & 511][vertices[i].x & 1023] = rand();
 
516
 }
 
517
 
 
518
 printf("\n");
 
519
 
 
520
#endif
 
521
 
 
522
 if(textured && !dtd && (raw_colors[0] == raw_colors[1]) && (raw_colors[1] == raw_colors[2]) && (raw_colors[2] == raw_colors[3]) && (raw_colors[0] == 0x808080))
 
523
 {
 
524
  if(numvertices == 3)
 
525
   DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices, clut);
 
526
  else
 
527
  {
 
528
   tri_vertex vertices_tmp[3];
 
529
 
 
530
   memcpy(&vertices_tmp[0], &vertices[1], 3 * sizeof(tri_vertex));
 
531
 
 
532
   DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices, clut);
 
533
   DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices_tmp, clut);
 
534
  }
 
535
  return;
 
536
 }
 
537
 
 
538
 if(numvertices == 3)
 
539
  DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices, clut);
 
540
 else
 
541
 {
 
542
  tri_vertex vertices_tmp[3];
 
543
 
 
544
  memcpy(&vertices_tmp[0], &vertices[1], 3 * sizeof(tri_vertex));
 
545
 
 
546
  DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices, clut);
 
547
  DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices_tmp, clut);
 
548
 }
 
549
}
 
550