spu: handle non-playing channel irqs
[pcsx_rearmed.git] / plugins / gpu_unai / gpu_raster_polygon.h
1 /***************************************************************************
2 *   Copyright (C) 2010 PCSX4ALL Team                                      *
3 *   Copyright (C) 2010 Unai                                               *
4 *                                                                         *
5 *   This program is free software; you can redistribute it and/or modify  *
6 *   it under the terms of the GNU General Public License as published by  *
7 *   the Free Software Foundation; either version 2 of the License, or     *
8 *   (at your option) any later version.                                   *
9 *                                                                         *
10 *   This program is distributed in the hope that it will be useful,       *
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13 *   GNU General Public License for more details.                          *
14 *                                                                         *
15 *   You should have received a copy of the GNU General Public License     *
16 *   along with this program; if not, write to the                         *
17 *   Free Software Foundation, Inc.,                                       *
18 *   51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA.           *
19 ***************************************************************************/
20
21 ///////////////////////////////////////////////////////////////////////////////
22 //  GPU internal polygon drawing functions
23
24 ///////////////////////////////////////////////////////////////////////////////
25 void gpuDrawF3(const PP gpuPolySpanDriver)
26 {
27         const int li=linesInterlace;
28         s32 temp;
29         s32 xa, xb, xmin, xmax;
30         s32 ya, yb, ymin, ymax;
31         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
32         s32 y0, y1, y2;
33
34         x0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[2]);  GPU_TESTRANGE(x0);
35         y0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[3]);  GPU_TESTRANGE(y0);
36         x1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[4]);  GPU_TESTRANGE(x1);
37         y1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[5]);  GPU_TESTRANGE(y1);
38         x2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[6]);  GPU_TESTRANGE(x2);
39         y2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[7]);  GPU_TESTRANGE(y2);
40
41         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
42         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
43
44         xmin = DrawingArea[0];  xmax = DrawingArea[2];
45         ymin = DrawingArea[1];  ymax = DrawingArea[3];
46
47         {
48                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
49                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
50                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
51                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
52                 if( rx0>=rx1 || ry0>=ry1) return;
53         }
54         
55         PixelData = GPU_RGB16(PacketBuffer.U4[0]);
56
57         if (y0 >= y1)
58         {
59                 if( y0!=y1 || x0>x1 )
60                 {
61                         GPU_SWAP(x0, x1, temp);
62                         GPU_SWAP(y0, y1, temp);
63                 }
64         }
65         if (y1 >= y2)
66         {
67                 if( y1!=y2 || x1>x2 )
68                 {
69                         GPU_SWAP(x1, x2, temp);
70                         GPU_SWAP(y1, y2, temp);
71                 }
72         }
73         if (y0 >= y1)
74         {
75                 if( y0!=y1 || x0>x1 )
76                 {
77                         GPU_SWAP(x0, x1, temp);
78                         GPU_SWAP(y0, y1, temp);
79                 }
80         }
81
82         ya = y2 - y0;
83         yb = y2 - y1;
84         dx =(x2 - x1) * ya - (x2 - x0) * yb;
85
86         for (s32 loop0 = 2; loop0; --loop0)
87         {
88                 if (loop0 == 2)
89                 {
90                         ya = y0;
91                         yb = y1;
92                         x3 = i2x(x0);
93                         x4 = y0!=y1 ? x3 : i2x(x1);
94                         if (dx < 0)
95                         {
96                                 dx3 = xLoDivx((x2 - x0), (y2 - y0));
97                                 dx4 = xLoDivx((x1 - x0), (y1 - y0));
98                         }
99                         else
100                         {
101                                 dx3 = xLoDivx((x1 - x0), (y1 - y0));
102                                 dx4 = xLoDivx((x2 - x0), (y2 - y0));
103                         }
104                 }
105                 else
106                 {
107                         ya = y1;
108                         yb = y2;
109                         if (dx < 0)
110                         {
111                                 x4  = i2x(x1);
112                                 x3  = i2x(x0) + (dx3 * (y1 - y0));
113                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
114                         }
115                         else
116                         {
117                                 x3  = i2x(x1);
118                                 x4  = i2x(x0) + (dx4 * (y1 - y0));
119                                 dx3 = xLoDivx((x2 - x1), (y2 - y1));
120                         }
121                 }
122
123                 temp = ymin - ya;
124                 if (temp > 0)
125                 {
126                         ya  = ymin;
127                         x3 += dx3*temp;
128                         x4 += dx4*temp;
129                 }
130                 if (yb > ymax) yb = ymax;
131                 if (ya>=yb) continue;
132
133                 x3+= fixed_HALF;
134                 x4+= fixed_HALF;
135
136                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
137                 
138                 if (!progressInterlace)
139                 {
140                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4)
141                         {
142                                 if (ya&li) continue;
143                                 xa = x2i(x3);
144                                 xb = x2i(x4);
145                                 if( (xa>xmax) || (xb<xmin) ) continue;
146                                 if(xa < xmin) xa = xmin;
147                                 if(xb > xmax) xb = xmax;
148                                 xb-=xa;
149                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
150                         }
151                 }
152                 else
153                 {
154                         bool flag=progressInterlace_flag;
155                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4)
156                         {
157                                 if ((ya&li) && (flag=!flag)) continue;
158                                 xa = x2i(x3);
159                                 xb = x2i(x4);
160                                 if( (xa>xmax) || (xb<xmin) ) continue;
161                                 if(xa < xmin) xa = xmin;
162                                 if(xb > xmax) xb = xmax;
163                                 xb-=xa;
164                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
165                         }
166                 }
167         }
168 }
169
170 /*----------------------------------------------------------------------
171 FT3
172 ----------------------------------------------------------------------*/
173
174 void gpuDrawFT3(const PP gpuPolySpanDriver)
175 {
176         const int li=linesInterlace;
177         s32 temp;
178         s32 xa, xb, xmin, xmax;
179         s32 ya, yb, ymin, ymax;
180         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
181         s32 y0, y1, y2;
182         s32 u0, u1, u2, u3, du3=0;
183         s32 v0, v1, v2, v3, dv3=0;
184
185         x0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[2] );   GPU_TESTRANGE(x0);
186         y0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[3] );   GPU_TESTRANGE(y0);
187         x1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[6] );   GPU_TESTRANGE(x1);
188         y1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[7] );   GPU_TESTRANGE(y1);
189         x2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[10]);   GPU_TESTRANGE(x2);
190         y2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[11]);   GPU_TESTRANGE(y2);
191
192         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
193         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
194
195         xmin = DrawingArea[0];  xmax = DrawingArea[2];
196         ymin = DrawingArea[1];  ymax = DrawingArea[3];
197
198         {
199                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
200                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
201                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
202                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
203                 if( rx0>=rx1 || ry0>=ry1) return;
204         }
205         
206         u0 = PacketBuffer.U1[8];  v0 = PacketBuffer.U1[9];
207         u1 = PacketBuffer.U1[16]; v1 = PacketBuffer.U1[17];
208         u2 = PacketBuffer.U1[24]; v2 = PacketBuffer.U1[25];
209
210         r4 = s32(PacketBuffer.U1[0]);
211         g4 = s32(PacketBuffer.U1[1]);
212         b4 = s32(PacketBuffer.U1[2]);
213         dr4 = dg4 = db4 = 0;
214
215         if (y0 >= y1)
216         {
217                 if( y0!=y1 || x0>x1 )
218                 {
219                         GPU_SWAP(x0, x1, temp);
220                         GPU_SWAP(y0, y1, temp);
221                         GPU_SWAP(u0, u1, temp);
222                         GPU_SWAP(v0, v1, temp);
223                 }
224         }
225         if (y1 >= y2)
226         {
227                 if( y1!=y2 || x1>x2 )
228                 {
229                         GPU_SWAP(x1, x2, temp);
230                         GPU_SWAP(y1, y2, temp);
231                         GPU_SWAP(u1, u2, temp);
232                         GPU_SWAP(v1, v2, temp);
233                 }
234         }
235         if (y0 >= y1)
236         {
237                 if( y0!=y1 || x0>x1 )
238                 {
239                         GPU_SWAP(x0, x1, temp);
240                         GPU_SWAP(y0, y1, temp);
241                         GPU_SWAP(u0, u1, temp);
242                         GPU_SWAP(v0, v1, temp);
243                 }
244         }
245
246         ya  = y2 - y0;
247         yb  = y2 - y1;
248         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
249         du4 = (u2 - u1) * ya - (u2 - u0) * yb;
250         dv4 = (v2 - v1) * ya - (v2 - v0) * yb;
251
252         s32 iF,iS;
253         xInv( dx, iF, iS);
254         du4 = xInvMulx( du4, iF, iS);
255         dv4 = xInvMulx( dv4, iF, iS);
256         tInc = ((u32)(du4<<7)&0x7fff0000) | ((u32)(dv4>>9)&0x00007fff);
257         tMsk = (TextureWindow[2]<<23) | (TextureWindow[3]<<7) | 0x00ff00ff;
258
259         for (s32 loop0 = 2; loop0; --loop0)
260         {
261                 if (loop0 == 2)
262                 {
263                         ya = y0;
264                         yb = y1;
265                         u3 = i2x(u0);
266                         v3 = i2x(v0);
267                         x3 = i2x(x0);
268                         x4 = y0!=y1 ? x3 : i2x(x1);
269                         if (dx < 0)
270                         {
271                                 xInv( (y2 - y0), iF, iS);
272                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
273                                 du3 = xInvMulx( (u2 - u0), iF, iS);
274                                 dv3 = xInvMulx( (v2 - v0), iF, iS);
275                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
276                         }
277                         else
278                         {
279                                 xInv( (y1 - y0), iF, iS);
280                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
281                                 du3 = xInvMulx( (u1 - u0), iF, iS);
282                                 dv3 = xInvMulx( (v1 - v0), iF, iS);
283                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
284                         }
285                 }
286                 else
287                 {
288                         ya = y1;
289                         yb = y2;
290                         if (dx < 0)
291                         {
292                                 temp = y1 - y0;
293                                 u3 = i2x(u0) + (du3 * temp);
294                                 v3 = i2x(v0) + (dv3 * temp);
295                                 x3 = i2x(x0) + (dx3 * temp);
296                                 x4 = i2x(x1);
297                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
298                         }
299                         else
300                         {
301                                 u3 = i2x(u1);
302                                 v3 = i2x(v1);
303                                 x3 = i2x(x1);
304                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
305                                 xInv( (y2 - y1), iF, iS);
306                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
307                                 du3 = xInvMulx( (u2 - u1), iF, iS);
308                                 dv3 = xInvMulx( (v2 - v1), iF, iS);
309                         }
310                 }
311
312                 temp = ymin - ya;
313                 if (temp > 0)
314                 {
315                         ya  = ymin;
316                         x3 += dx3*temp;
317                         x4 += dx4*temp;
318                         u3 += du3*temp;
319                         v3 += dv3*temp;
320                 }
321                 if (yb > ymax) yb = ymax;
322                 if (ya>=yb) continue;
323
324                 x3+= fixed_HALF;
325                 x4+= fixed_HALF;
326                 u3+= fixed_HALF;
327                 v4+= fixed_HALF;
328
329                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
330
331                 if (!progressInterlace)
332                 {
333                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3)
334                         {
335                                 if (ya&li) continue;
336                                 xa = x2i(x3);
337                                 xb = x2i(x4);
338                                 if( (xa>xmax) || (xb<xmin) ) continue;
339
340                                 temp = xmin - xa;
341                                 if(temp > 0)
342                                 {
343                                         xa  = xmin;
344                                         u4 = u3 + du4*temp;
345                                         v4 = v3 + dv4*temp;
346                                 }
347                                 else
348                                 {
349                                         u4 = u3;
350                                         v4 = v3;
351                                 }
352                                 if(xb > xmax) xb = xmax;
353                                 xb-=xa;
354                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
355                         }
356                 }
357                 else
358                 {
359                         bool flag=progressInterlace_flag;
360                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3)
361                         {
362                                 if ((ya&li) && (flag=!flag)) continue;
363                                 xa = x2i(x3);
364                                 xb = x2i(x4);
365                                 if( (xa>xmax) || (xb<xmin) ) continue;
366
367                                 temp = xmin - xa;
368                                 if(temp > 0)
369                                 {
370                                         xa  = xmin;
371                                         u4 = u3 + du4*temp;
372                                         v4 = v3 + dv4*temp;
373                                 }
374                                 else
375                                 {
376                                         u4 = u3;
377                                         v4 = v3;
378                                 }
379                                 if(xb > xmax) xb = xmax;
380                                 xb-=xa;
381                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
382                         }
383                 }
384         }
385 }
386
387 /*----------------------------------------------------------------------
388 G3
389 ----------------------------------------------------------------------*/
390
391 void gpuDrawG3(const PP gpuPolySpanDriver)
392 {
393         const int li=linesInterlace;
394         s32 temp;
395         s32 xa, xb, xmin, xmax;
396         s32 ya, yb, ymin, ymax;
397         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
398         s32 y0, y1, y2;
399         s32 r0, r1, r2, r3, dr3=0;
400         s32 g0, g1, g2, g3, dg3=0;
401         s32 b0, b1, b2, b3, db3=0;
402
403         x0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[2] );    GPU_TESTRANGE(x0);
404         y0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[3] );    GPU_TESTRANGE(y0);
405         x1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[6] );    GPU_TESTRANGE(x1);
406         y1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[7] );    GPU_TESTRANGE(y1);
407         x2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[10]);    GPU_TESTRANGE(x2);
408         y2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[11]);    GPU_TESTRANGE(y2);
409
410         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
411         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
412
413         xmin = DrawingArea[0];  xmax = DrawingArea[2];
414         ymin = DrawingArea[1];  ymax = DrawingArea[3];
415
416         {
417                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
418                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
419                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
420                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
421                 if( rx0>=rx1 || ry0>=ry1) return;
422         }
423         
424         r0 = PacketBuffer.U1[0];        g0 = PacketBuffer.U1[1];        b0 = PacketBuffer.U1[2];
425         r1 = PacketBuffer.U1[8];        g1 = PacketBuffer.U1[9];        b1 = PacketBuffer.U1[10];
426         r2 = PacketBuffer.U1[16];       g2 = PacketBuffer.U1[17];       b2 = PacketBuffer.U1[18];
427
428         if (y0 >= y1)
429         {
430                 if( y0!=y1 || x0>x1 )
431                 {
432                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
433                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);         GPU_SWAP(b0, b1, temp);
434                 }
435         }
436         if (y1 >= y2)
437         {
438                 if( y1!=y2 || x1>x2 )
439                 {
440                         GPU_SWAP(x1, x2, temp);         GPU_SWAP(y1, y2, temp);
441                         GPU_SWAP(r1, r2, temp);         GPU_SWAP(g1, g2, temp);   GPU_SWAP(b1, b2, temp);
442                 }
443         }
444         if (y0 >= y1)
445         {
446                 if( y0!=y1 || x0>x1 )
447                 {
448                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
449                         GPU_SWAP(r0, r1, temp);   GPU_SWAP(g0, g1, temp);               GPU_SWAP(b0, b1, temp);
450                 }
451         }
452
453         ya  = y2 - y0;
454         yb  = y2 - y1;
455         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
456         dr4 = (r2 - r1) * ya - (r2 - r0) * yb;
457         dg4 = (g2 - g1) * ya - (g2 - g0) * yb;
458         db4 = (b2 - b1) * ya - (b2 - b0) * yb;
459
460         s32 iF,iS;
461         xInv(            dx, iF, iS);
462         dr4 = xInvMulx( dr4, iF, iS);
463         dg4 = xInvMulx( dg4, iF, iS);
464         db4 = xInvMulx( db4, iF, iS);
465         u32 dr = (u32)(dr4<< 8)&(0xffffffff<<21);   if(dr4<0) dr+= 1<<21;
466         u32 dg = (u32)(dg4>> 3)&(0xffffffff<<10);   if(dg4<0) dg+= 1<<10;
467         u32 db = (u32)(db4>>14)&(0xffffffff    );   if(db4<0) db+= 1<< 0;
468         lInc = db + dg + dr;
469
470         for (s32 loop0 = 2; loop0; --loop0)
471         {
472                 if (loop0 == 2)
473                 {
474                         ya = y0;
475                         yb = y1;
476                         r3 = i2x(r0);
477                         g3 = i2x(g0);
478                         b3 = i2x(b0);
479                         x3 = i2x(x0);
480                         x4 = y0!=y1 ? x3 : i2x(x1);
481                         if (dx < 0)
482                         {
483                                 xInv(           (y2 - y0), iF, iS);
484                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
485                                 dr3 = xInvMulx( (r2 - r0), iF, iS);
486                                 dg3 = xInvMulx( (g2 - g0), iF, iS);
487                                 db3 = xInvMulx( (b2 - b0), iF, iS);
488                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
489                         }
490                         else
491                         {
492                                 xInv(           (y1 - y0), iF, iS);
493                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
494                                 dr3 = xInvMulx( (r1 - r0), iF, iS);
495                                 dg3 = xInvMulx( (g1 - g0), iF, iS);
496                                 db3 = xInvMulx( (b1 - b0), iF, iS);
497                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
498                         }
499                 }
500                 else
501                 {
502                         ya = y1;
503                         yb = y2;
504                         if (dx < 0)
505                         {
506                                 temp = y1 - y0;
507                                 r3  = i2x(r0) + (dr3 * temp);
508                                 g3  = i2x(g0) + (dg3 * temp);
509                                 b3  = i2x(b0) + (db3 * temp);
510                                 x3  = i2x(x0) + (dx3 * temp);
511                                 x4  = i2x(x1);
512                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
513                         }
514                         else
515                         {
516                                 r3 = i2x(r1);
517                                 g3 = i2x(g1);
518                                 b3 = i2x(b1);
519                                 x3 = i2x(x1);
520                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
521
522                                 xInv(           (y2 - y1), iF, iS);
523                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
524                                 dr3 = xInvMulx( (r2 - r1), iF, iS);
525                                 dg3 = xInvMulx( (g2 - g1), iF, iS);
526                                 db3 = xInvMulx( (b2 - b1), iF, iS);
527                         }
528                 }
529
530                 temp = ymin - ya;
531                 if (temp > 0)
532                 {
533                         ya  = ymin;
534                         x3 += dx3*temp;   x4 += dx4*temp;
535                         r3 += dr3*temp;   g3 += dg3*temp;   b3 += db3*temp;
536                 }
537                 if (yb > ymax) yb = ymax;
538                 if (ya>=yb) continue;
539
540                 x3+= fixed_HALF;  x4+= fixed_HALF;
541                 r3+= fixed_HALF;  g3+= fixed_HALF;  b3+= fixed_HALF;
542
543                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
544                 
545                 if (!progressInterlace)
546                 {
547                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, r3+=dr3, g3+=dg3, b3+=db3)
548                         {
549                                 if (ya&li) continue;
550                                 xa = x2i(x3);
551                                 xb = x2i(x4);
552                                 if( (xa>xmax) || (xb<xmin) ) continue;
553
554                                 temp = xmin - xa;
555                                 if(temp > 0)
556                                 {
557                                         xa  = xmin;
558                                         r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
559                                 }
560                                 else
561                                 {
562                                         r4 = r3;  g4 = g3;  b4 = b3;
563                                 }
564                                 if(xb > xmax) xb = xmax;
565                                 xb-=xa;
566                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
567                         }
568                 }
569                 else
570                 {
571                         bool flag=progressInterlace_flag;
572                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, r3+=dr3, g3+=dg3, b3+=db3)
573                         {
574                                 if ((ya&li) && (flag=!flag)) continue;
575                                 xa = x2i(x3);
576                                 xb = x2i(x4);
577                                 if( (xa>xmax) || (xb<xmin) ) continue;
578
579                                 temp = xmin - xa;
580                                 if(temp > 0)
581                                 {
582                                         xa  = xmin;
583                                         r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
584                                 }
585                                 else
586                                 {
587                                         r4 = r3;  g4 = g3;  b4 = b3;
588                                 }
589                                 if(xb > xmax) xb = xmax;
590                                 xb-=xa;
591                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
592                         }
593                 }
594         }
595 }
596
597 /*----------------------------------------------------------------------
598 GT3
599 ----------------------------------------------------------------------*/
600
601 void gpuDrawGT3(const PP gpuPolySpanDriver)
602 {
603         const int li=linesInterlace;
604         s32 temp;
605         s32 xa, xb, xmin, xmax;
606         s32 ya, yb, ymin, ymax;
607         s32 x0, x1, x2, x3, dx3=0, x4, dx4=0, dx;
608         s32 y0, y1, y2;
609         s32 u0, u1, u2, u3, du3=0;
610         s32 v0, v1, v2, v3, dv3=0;
611         s32 r0, r1, r2, r3, dr3=0;
612         s32 g0, g1, g2, g3, dg3=0;
613         s32 b0, b1, b2, b3, db3=0;
614
615         x0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[2] );   GPU_TESTRANGE(x0);
616         y0 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[3] );   GPU_TESTRANGE(y0);
617         x1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[8] );   GPU_TESTRANGE(x1);
618         y1 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[9] );   GPU_TESTRANGE(y1);
619         x2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[14]);   GPU_TESTRANGE(x2);
620         y2 = GPU_EXPANDSIGN_POLY(PacketBuffer.S2[15]);   GPU_TESTRANGE(y2);
621
622         x0 += DrawingOffset[0];   x1 += DrawingOffset[0];   x2 += DrawingOffset[0];
623         y0 += DrawingOffset[1];   y1 += DrawingOffset[1];   y2 += DrawingOffset[1];
624
625         xmin = DrawingArea[0];  xmax = DrawingArea[2];
626         ymin = DrawingArea[1];  ymax = DrawingArea[3];
627
628         {
629                 int rx0 = Max2(xmin,Min3(x0,x1,x2));
630                 int ry0 = Max2(ymin,Min3(y0,y1,y2));
631                 int rx1 = Min2(xmax,Max3(x0,x1,x2));
632                 int ry1 = Min2(ymax,Max3(y0,y1,y2));
633                 if( rx0>=rx1 || ry0>=ry1) return;
634         }
635
636         r0 = PacketBuffer.U1[0];        g0 = PacketBuffer.U1[1];        b0 = PacketBuffer.U1[2];
637         u0 = PacketBuffer.U1[8];        v0 = PacketBuffer.U1[9];
638         r1 = PacketBuffer.U1[12];       g1 = PacketBuffer.U1[13];       b1 = PacketBuffer.U1[14];
639         u1 = PacketBuffer.U1[20];       v1 = PacketBuffer.U1[21];
640         r2 = PacketBuffer.U1[24];       g2 = PacketBuffer.U1[25];       b2 = PacketBuffer.U1[26];
641         u2 = PacketBuffer.U1[32];       v2 = PacketBuffer.U1[33];
642
643         if (y0 >= y1)
644         {
645                 if( y0!=y1 || x0>x1 )
646                 {
647                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
648                         GPU_SWAP(u0, u1, temp);         GPU_SWAP(v0, v1, temp);
649                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);   GPU_SWAP(b0, b1, temp);
650                 }
651         }
652         if (y1 >= y2)
653         {
654                 if( y1!=y2 || x1>x2 )
655                 {
656                         GPU_SWAP(x1, x2, temp);         GPU_SWAP(y1, y2, temp);
657                         GPU_SWAP(u1, u2, temp);         GPU_SWAP(v1, v2, temp);
658                         GPU_SWAP(r1, r2, temp);   GPU_SWAP(g1, g2, temp);               GPU_SWAP(b1, b2, temp);
659                 }
660         }
661         if (y0 >= y1)
662         {
663                 if( y0!=y1 || x0>x1 )
664                 {
665                         GPU_SWAP(x0, x1, temp);         GPU_SWAP(y0, y1, temp);
666                         GPU_SWAP(u0, u1, temp);         GPU_SWAP(v0, v1, temp);
667                         GPU_SWAP(r0, r1, temp);         GPU_SWAP(g0, g1, temp);         GPU_SWAP(b0, b1, temp);
668                 }
669         }
670
671         ya  = y2 - y0;
672         yb  = y2 - y1;
673         dx  = (x2 - x1) * ya - (x2 - x0) * yb;
674         du4 = (u2 - u1) * ya - (u2 - u0) * yb;
675         dv4 = (v2 - v1) * ya - (v2 - v0) * yb;
676         dr4 = (r2 - r1) * ya - (r2 - r0) * yb;
677         dg4 = (g2 - g1) * ya - (g2 - g0) * yb;
678         db4 = (b2 - b1) * ya - (b2 - b0) * yb;
679
680         s32 iF,iS;
681
682         xInv(            dx, iF, iS);
683         du4 = xInvMulx( du4, iF, iS);
684         dv4 = xInvMulx( dv4, iF, iS);
685         dr4 = xInvMulx( dr4, iF, iS);
686         dg4 = xInvMulx( dg4, iF, iS);
687         db4 = xInvMulx( db4, iF, iS);
688         u32 dr = (u32)(dr4<< 8)&(0xffffffff<<21);   if(dr4<0) dr+= 1<<21;
689         u32 dg = (u32)(dg4>> 3)&(0xffffffff<<10);   if(dg4<0) dg+= 1<<10;
690         u32 db = (u32)(db4>>14)&(0xffffffff    );   if(db4<0) db+= 1<< 0;
691         lInc = db + dg + dr;
692         tInc = ((u32)(du4<<7)&0x7fff0000) | ((u32)(dv4>>9)&0x00007fff);
693         tMsk = (TextureWindow[2]<<23) | (TextureWindow[3]<<7) | 0x00ff00ff;
694
695         for (s32 loop0 = 2; loop0; --loop0)
696         {
697                 if (loop0 == 2)
698                 {
699                         ya = y0;
700                         yb = y1;
701                         u3 = i2x(u0);
702                         v3 = i2x(v0);
703                         r3 = i2x(r0);
704                         g3 = i2x(g0);
705                         b3 = i2x(b0);
706                         x3 = i2x(x0);
707                         x4 = y0!=y1 ? x3 : i2x(x1);
708                         if (dx < 0)
709                         {
710                                 xInv(           (y2 - y0), iF, iS);
711                                 dx3 = xInvMulx( (x2 - x0), iF, iS);
712                                 du3 = xInvMulx( (u2 - u0), iF, iS);
713                                 dv3 = xInvMulx( (v2 - v0), iF, iS);
714                                 dr3 = xInvMulx( (r2 - r0), iF, iS);
715                                 dg3 = xInvMulx( (g2 - g0), iF, iS);
716                                 db3 = xInvMulx( (b2 - b0), iF, iS);
717                                 dx4 = xLoDivx ( (x1 - x0), (y1 - y0));
718                         }
719                         else
720                         {
721                                 xInv(           (y1 - y0), iF, iS);
722                                 dx3 = xInvMulx( (x1 - x0), iF, iS);
723                                 du3 = xInvMulx( (u1 - u0), iF, iS);
724                                 dv3 = xInvMulx( (v1 - v0), iF, iS);
725                                 dr3 = xInvMulx( (r1 - r0), iF, iS);
726                                 dg3 = xInvMulx( (g1 - g0), iF, iS);
727                                 db3 = xInvMulx( (b1 - b0), iF, iS);
728                                 dx4 = xLoDivx ( (x2 - x0), (y2 - y0));
729                         }
730                 }
731                 else
732                 {
733                         ya = y1;
734                         yb = y2;
735                         if (dx < 0)
736                         {
737                                 temp = y1 - y0;
738                                 u3  = i2x(u0) + (du3 * temp);
739                                 v3  = i2x(v0) + (dv3 * temp);
740                                 r3  = i2x(r0) + (dr3 * temp);
741                                 g3  = i2x(g0) + (dg3 * temp);
742                                 b3  = i2x(b0) + (db3 * temp);
743                                 x3  = i2x(x0) + (dx3 * temp);
744                                 x4  = i2x(x1);
745                                 dx4 = xLoDivx((x2 - x1), (y2 - y1));
746                         }
747                         else
748                         {
749                                 u3 = i2x(u1);
750                                 v3 = i2x(v1);
751                                 r3 = i2x(r1);
752                                 g3 = i2x(g1);
753                                 b3 = i2x(b1);
754                                 x3 = i2x(x1);
755                                 x4 = i2x(x0) + (dx4 * (y1 - y0));
756
757                                 xInv(           (y2 - y1), iF, iS);
758                                 dx3 = xInvMulx( (x2 - x1), iF, iS);
759                                 du3 = xInvMulx( (u2 - u1), iF, iS);
760                                 dv3 = xInvMulx( (v2 - v1), iF, iS);
761                                 dr3 = xInvMulx( (r2 - r1), iF, iS);
762                                 dg3 = xInvMulx( (g2 - g1), iF, iS);
763                                 db3 = xInvMulx( (b2 - b1), iF, iS);
764                         }
765                 }
766
767                 temp = ymin - ya;
768                 if (temp > 0)
769                 {
770                         ya  = ymin;
771                         x3 += dx3*temp;   x4 += dx4*temp;
772                         u3 += du3*temp;   v3 += dv3*temp;
773                         r3 += dr3*temp;   g3 += dg3*temp;   b3 += db3*temp;
774                 }
775                 if (yb > ymax) yb = ymax;
776                 if (ya>=yb) continue;
777
778                 x3+= fixed_HALF;  x4+= fixed_HALF;
779                 u3+= fixed_HALF;  v4+= fixed_HALF;
780                 r3+= fixed_HALF;  g3+= fixed_HALF;  b3+= fixed_HALF;
781                 u16* PixelBase  = &((u16*)GPU_FrameBuffer)[FRAME_OFFSET(0, ya)];
782                 
783                 if (!progressInterlace)
784                 {
785                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3, r3+=dr3, g3+=dg3,        b3+=db3)
786                         {
787                                 if (ya&li) continue;
788                                 xa = x2i(x3);
789                                 xb = x2i(x4);
790                                 if( (xa>xmax) || (xb<xmin))     continue;
791
792                                 temp = xmin - xa;
793                                 if(temp > 0)
794                                 {
795                                         xa  = xmin;
796                                         u4 = u3 + du4*temp;   v4 = v3 + dv4*temp;
797                                         r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
798                                 }
799                                 else
800                                 {
801                                         u4 = u3;  v4 = v3;
802                                         r4 = r3;  g4 = g3;  b4 = b3;
803                                 }
804                                 if(xb > xmax) xb = xmax;
805                                 xb-=xa;
806                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
807                         }
808                 }
809                 else
810                 {
811                         bool flag=progressInterlace_flag;
812                         for(;ya<yb;++ya, PixelBase += FRAME_WIDTH, x3+=dx3, x4+=dx4, u3+=du3, v3+=dv3, r3+=dr3, g3+=dg3,        b3+=db3)
813                         {
814                                 if ((ya&li) && (flag=!flag)) continue;
815                                 xa = x2i(x3);
816                                 xb = x2i(x4);
817                                 if ((xa>xmax) || (xb<xmin))     continue;
818
819                                 temp = xmin - xa;
820                                 if(temp > 0)
821                                 {
822                                         xa  = xmin;
823                                         u4 = u3 + du4*temp;   v4 = v3 + dv4*temp;
824                                         r4 = r3 + dr4*temp;   g4 = g3 + dg4*temp;   b4 = b3 + db4*temp;
825                                 }
826                                 else
827                                 {
828                                         u4 = u3;  v4 = v3;
829                                         r4 = r3;  g4 = g3;  b4 = b3;
830                                 }
831                                 if(xb > xmax) xb = xmax;
832                                 xb-=xa;
833                                 if(xb>0) gpuPolySpanDriver(PixelBase + xa,xb);
834                         }
835                 }
836         }
837 }