dfxvideo: avoid division like plague
[pcsx_rearmed.git] / plugins / dfxvideo / prim.c
1 /***************************************************************************
2                           prim.c  -  description
3                              -------------------
4     begin                : Sun Oct 28 2001
5     copyright            : (C) 2001 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version. See also the license.txt file for *
14  *   additional informations.                                              *
15  *                                                                         *
16  ***************************************************************************/
17
18 ////////////////////////////////////////////////////////////////////////
19 // globals
20 ////////////////////////////////////////////////////////////////////////
21
22 BOOL           bUsingTWin=FALSE;
23 TWin_t         TWin;
24 //unsigned long  clutid;                                 // global clut
25 unsigned short usMirror=0;                             // sprite mirror
26 int            iDither=0;
27 int32_t        drawX;
28 int32_t        drawY;
29 int32_t        drawW;
30 int32_t        drawH;
31 uint32_t       dwCfgFixes;
32 uint32_t       dwActFixes=0;
33 int            iUseFixes;
34 int            iUseDither=0;
35 BOOL           bDoVSyncUpdate=FALSE;
36
37 // USE_NASM
38 static inline unsigned short BGR24to16 (uint32_t BGR)
39 {
40  return (unsigned short)(((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6));
41 }
42
43 ////////////////////////////////////////////////////////////////////////
44 // Update global TP infos
45 ////////////////////////////////////////////////////////////////////////
46
47 static inline void UpdateGlobalTP(unsigned short gdata)
48 {
49  GlobalTextAddrX = (gdata << 6) & 0x3c0;               // texture addr
50
51  GlobalTextAddrY = (gdata << 4) & 0x100;
52
53  GlobalTextTP = (gdata >> 7) & 0x3;                    // tex mode (4,8,15)
54
55  if(GlobalTextTP==3) GlobalTextTP=2;                   // seen in Wild9 :(
56
57  GlobalTextABR = (gdata >> 5) & 0x3;                   // blend mode
58
59  lGPUstatusRet&=~0x000001ff;                           // Clear the necessary bits
60  lGPUstatusRet|=(gdata & 0x01ff);                      // set the necessary bits
61
62  switch(iUseDither)
63  {
64   case 0:
65    iDither=0;
66   break;
67   case 1:
68    if(lGPUstatusRet&0x0200) iDither=2;
69    else iDither=0;
70   break;
71   case 2:
72    iDither=2;
73   break;
74  }
75 }
76
77 ////////////////////////////////////////////////////////////////////////
78
79 static inline void SetRenderMode(uint32_t DrawAttributes)
80 {
81  DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE;
82
83  if(SHADETEXBIT(DrawAttributes)) 
84   {g_m1=g_m2=g_m3=128;}
85  else
86   {
87    if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0))
88     DrawAttributes|=0x007f7f7f;
89
90    g_m1=(short)(DrawAttributes&0xff);
91    g_m2=(short)((DrawAttributes>>8)&0xff);
92    g_m3=(short)((DrawAttributes>>16)&0xff);
93   }
94 }
95
96 ////////////////////////////////////////////////////////////////////////
97
98 // oki, here are the psx gpu coord rules: poly coords are
99 // 11 bit signed values (-1024...1023). If the x or y distance 
100 // exceeds 1024, the polygon will not be drawn. 
101 // Since quads are treated as two triangles by the real gpu,
102 // this 'discard rule' applies to each of the quad's triangle 
103 // (so one triangle can be drawn, the other one discarded). 
104 // Also, y drawing is wrapped at 512 one time,
105 // then it will get negative (and therefore not drawn). The
106 // 'CheckCoord' funcs are a simple (not comlete!) approach to
107 // do things right, I will add a better detection soon... the 
108 // current approach will be easier to do in hw/accel plugins, imho
109
110 // 11 bit signed
111 #define SIGNSHIFT 21
112 #define CHKMAX_X 1024
113 #define CHKMAX_Y 512
114
115 static inline void AdjustCoord4(void)
116 {
117  lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
118  lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
119  lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
120  lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);
121  ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
122  ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
123  ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
124  ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);
125 }
126
127 static inline void AdjustCoord3(void)
128 {
129  lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
130  lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
131  lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
132  ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
133  ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
134  ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
135 }
136
137 static inline void AdjustCoord2(void)
138 {
139  lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
140  lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
141  ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
142  ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
143 }
144
145 static inline void AdjustCoord1(void)
146 {
147  lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
148  ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
149
150  if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)
151   lx0+=2048;
152
153  if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)
154   ly0+=2048;
155 }
156
157 ////////////////////////////////////////////////////////////////////////
158 // special checks... nascar, syphon filter 2, mgs
159 ////////////////////////////////////////////////////////////////////////
160
161 // xenogears FT4: not removed correctly right now... the tri 0,1,2
162 // should get removed, the tri 1,2,3 should stay... pfff
163
164 // x -466 1023 180 1023
165 // y   20 -228 222 -100
166
167 // 0 __1
168 //  \ / \    .
169 //   2___3
170
171 static inline BOOL CheckCoord4(void)
172 {
173  if(lx0<0)
174   {
175    if(((lx1-lx0)>CHKMAX_X) ||
176       ((lx2-lx0)>CHKMAX_X)) 
177     {
178      if(lx3<0)
179       {
180        if((lx1-lx3)>CHKMAX_X) return TRUE;
181        if((lx2-lx3)>CHKMAX_X) return TRUE;
182       }
183     }
184   }
185  if(lx1<0)
186   {
187    if((lx0-lx1)>CHKMAX_X) return TRUE;
188    if((lx2-lx1)>CHKMAX_X) return TRUE;
189    if((lx3-lx1)>CHKMAX_X) return TRUE;
190   }
191  if(lx2<0)
192   {
193    if((lx0-lx2)>CHKMAX_X) return TRUE;
194    if((lx1-lx2)>CHKMAX_X) return TRUE;
195    if((lx3-lx2)>CHKMAX_X) return TRUE;
196   }
197  if(lx3<0)
198   {
199    if(((lx1-lx3)>CHKMAX_X) ||
200       ((lx2-lx3)>CHKMAX_X))
201     {
202      if(lx0<0)
203       {
204        if((lx1-lx0)>CHKMAX_X) return TRUE;
205        if((lx2-lx0)>CHKMAX_X) return TRUE;
206       }
207     }
208   }
209  
210
211  if(ly0<0)
212   {
213    if((ly1-ly0)>CHKMAX_Y) return TRUE;
214    if((ly2-ly0)>CHKMAX_Y) return TRUE;
215   }
216  if(ly1<0)
217   {
218    if((ly0-ly1)>CHKMAX_Y) return TRUE;
219    if((ly2-ly1)>CHKMAX_Y) return TRUE;
220    if((ly3-ly1)>CHKMAX_Y) return TRUE;
221   }
222  if(ly2<0)
223   {
224    if((ly0-ly2)>CHKMAX_Y) return TRUE;
225    if((ly1-ly2)>CHKMAX_Y) return TRUE;
226    if((ly3-ly2)>CHKMAX_Y) return TRUE;
227   }
228  if(ly3<0)
229   {
230    if((ly1-ly3)>CHKMAX_Y) return TRUE;
231    if((ly2-ly3)>CHKMAX_Y) return TRUE;
232   }
233
234  return FALSE;
235 }
236
237 static inline BOOL CheckCoord3(void)
238 {
239  if(lx0<0)
240   {
241    if((lx1-lx0)>CHKMAX_X) return TRUE;
242    if((lx2-lx0)>CHKMAX_X) return TRUE;
243   }
244  if(lx1<0)
245   {
246    if((lx0-lx1)>CHKMAX_X) return TRUE;
247    if((lx2-lx1)>CHKMAX_X) return TRUE;
248   }
249  if(lx2<0)
250   {
251    if((lx0-lx2)>CHKMAX_X) return TRUE;
252    if((lx1-lx2)>CHKMAX_X) return TRUE;
253   }
254  if(ly0<0)
255   {
256    if((ly1-ly0)>CHKMAX_Y) return TRUE;
257    if((ly2-ly0)>CHKMAX_Y) return TRUE;
258   }
259  if(ly1<0)
260   {
261    if((ly0-ly1)>CHKMAX_Y) return TRUE;
262    if((ly2-ly1)>CHKMAX_Y) return TRUE;
263   }
264  if(ly2<0)
265   {
266    if((ly0-ly2)>CHKMAX_Y) return TRUE;
267    if((ly1-ly2)>CHKMAX_Y) return TRUE;
268   }
269
270  return FALSE;
271 }
272
273
274 static inline BOOL CheckCoord2(void)
275 {
276  if(lx0<0)
277   {
278    if((lx1-lx0)>CHKMAX_X) return TRUE;
279   }
280  if(lx1<0)
281   {
282    if((lx0-lx1)>CHKMAX_X) return TRUE;
283   }
284  if(ly0<0)
285   {
286    if((ly1-ly0)>CHKMAX_Y) return TRUE;
287   }
288  if(ly1<0)
289   {
290    if((ly0-ly1)>CHKMAX_Y) return TRUE;
291   }
292
293  return FALSE;
294 }
295
296 static inline BOOL CheckCoordL(short slx0,short sly0,short slx1,short sly1)
297 {
298  if(slx0<0)
299   {
300    if((slx1-slx0)>CHKMAX_X) return TRUE;
301   }
302  if(slx1<0)
303   {
304    if((slx0-slx1)>CHKMAX_X) return TRUE;
305   }
306  if(sly0<0)
307   {
308    if((sly1-sly0)>CHKMAX_Y) return TRUE;
309   }
310  if(sly1<0)
311   {
312    if((sly0-sly1)>CHKMAX_Y) return TRUE;
313   }
314
315  return FALSE;
316 }
317
318
319 ////////////////////////////////////////////////////////////////////////
320 // mask stuff... used in silent hill
321 ////////////////////////////////////////////////////////////////////////
322
323 static inline void cmdSTP(unsigned char * baseAddr)
324 {
325  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
326
327  lGPUstatusRet&=~0x1800;                                   // Clear the necessary bits
328  lGPUstatusRet|=((gdata & 0x03) << 11);                    // Set the necessary bits
329
330  if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;}
331  else        {sSetMask=0;     lSetMask=0;         }
332
333  if(gdata&2) bCheckMask=TRUE;
334  else        bCheckMask=FALSE;
335 }
336  
337 ////////////////////////////////////////////////////////////////////////
338 // cmd: Set texture page infos
339 ////////////////////////////////////////////////////////////////////////
340
341 static void cmdTexturePage(unsigned char * baseAddr)
342 {
343  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
344
345  lGPUstatusRet&=~0x000007ff;
346  lGPUstatusRet|=(gdata & 0x07ff);
347  
348  usMirror=gdata&0x3000;
349  
350  UpdateGlobalTP((unsigned short)gdata);
351  GlobalTextREST = (gdata&0x00ffffff)>>9;
352 }
353
354 ////////////////////////////////////////////////////////////////////////
355 // cmd: turn on/off texture window
356 ////////////////////////////////////////////////////////////////////////
357
358 static void cmdTextureWindow(unsigned char *baseAddr)
359 {
360  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
361
362  uint32_t YAlign,XAlign;
363
364  lGPUInfoVals[INFO_TW]=gdata&0xFFFFF;
365
366  if(gdata & 0x020)
367   TWin.Position.y1 = 8;    // xxxx1
368  else if (gdata & 0x040)
369   TWin.Position.y1 = 16;   // xxx10
370  else if (gdata & 0x080)
371   TWin.Position.y1 = 32;   // xx100
372  else if (gdata & 0x100)
373   TWin.Position.y1 = 64;   // x1000
374  else if (gdata & 0x200)
375   TWin.Position.y1 = 128;  // 10000
376  else
377   TWin.Position.y1 = 256;  // 00000
378  TWin.ymask = TWin.Position.y1 - 1;
379
380   // Texture window size is determined by the least bit set of the relevant 5 bits
381
382  if (gdata & 0x001)
383   TWin.Position.x1 = 8;    // xxxx1
384  else if (gdata & 0x002)
385   TWin.Position.x1 = 16;   // xxx10
386  else if (gdata & 0x004)
387   TWin.Position.x1 = 32;   // xx100
388  else if (gdata & 0x008)
389   TWin.Position.x1 = 64;   // x1000
390  else if (gdata & 0x010)
391   TWin.Position.x1 = 128;  // 10000
392  else
393   TWin.Position.x1 = 256;  // 00000
394  TWin.xmask = TWin.Position.x1 - 1;
395
396  // Re-calculate the bit field, because we can't trust what is passed in the data
397
398
399  YAlign = (uint32_t)(32 - (TWin.Position.y1 >> 3));
400  XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3));
401
402  // Absolute position of the start of the texture window
403
404  TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3);
405  TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3);
406
407  if((TWin.Position.x0 == 0 &&                          // tw turned off
408      TWin.Position.y0 == 0 &&
409      TWin.Position.x1 == 0 &&
410      TWin.Position.y1 == 0) ||  
411      (TWin.Position.x1 == 256 &&
412       TWin.Position.y1 == 256))
413   {
414    bUsingTWin = FALSE;                                 // -> just do it
415   }                                                    
416  else                                                  // otherwise
417   {
418    bUsingTWin = TRUE;                                  // -> tw turned on
419   }
420 }
421
422 ////////////////////////////////////////////////////////////////////////
423 // cmd: start of drawing area... primitives will be clipped inside
424 ////////////////////////////////////////////////////////////////////////
425
426
427
428 static void cmdDrawAreaStart(unsigned char * baseAddr)
429 {
430  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
431
432  drawX  = gdata & 0x3ff;                               // for soft drawing
433
434    lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF;
435    drawY  = (gdata>>10)&0x3ff;
436    if(drawY>=512) drawY=511;                           // some security
437 }
438
439 ////////////////////////////////////////////////////////////////////////
440 // cmd: end of drawing area... primitives will be clipped inside
441 ////////////////////////////////////////////////////////////////////////
442
443 static void cmdDrawAreaEnd(unsigned char * baseAddr)
444 {
445  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
446
447  drawW  = gdata & 0x3ff;                               // for soft drawing
448
449    lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF;
450    drawH  = (gdata>>10)&0x3ff;
451    if(drawH>=512) drawH=511;                           // some security
452 }
453
454 ////////////////////////////////////////////////////////////////////////
455 // cmd: draw offset... will be added to prim coords
456 ////////////////////////////////////////////////////////////////////////
457
458 static void cmdDrawOffset(unsigned char * baseAddr)
459 {
460  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
461
462  PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff);
463
464    lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF;
465    PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff);
466  
467  PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21);
468  PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21);
469 }
470  
471 ////////////////////////////////////////////////////////////////////////
472 // cmd: load image to vram
473 ////////////////////////////////////////////////////////////////////////
474
475 static void primLoadImage(unsigned char * baseAddr)
476 {
477  unsigned short *sgpuData = ((unsigned short *) baseAddr);
478
479  VRAMWrite.x      = GETLEs16(&sgpuData[2])&0x3ff;
480  VRAMWrite.y      = GETLEs16(&sgpuData[3])&511;
481  VRAMWrite.Width  = GETLEs16(&sgpuData[4]);
482  VRAMWrite.Height = GETLEs16(&sgpuData[5]);
483
484  DataWriteMode = DR_VRAMTRANSFER;
485
486  VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x;
487  VRAMWrite.RowsRemaining = VRAMWrite.Width;
488  VRAMWrite.ColsRemaining = VRAMWrite.Height;
489 }
490
491 ////////////////////////////////////////////////////////////////////////
492 // cmd: vram -> psx mem
493 ////////////////////////////////////////////////////////////////////////
494
495 static void primStoreImage(unsigned char * baseAddr)
496 {
497  unsigned short *sgpuData = ((unsigned short *) baseAddr);
498
499  VRAMRead.x      = GETLEs16(&sgpuData[2])&0x03ff;
500  VRAMRead.y      = GETLEs16(&sgpuData[3])&511;
501  VRAMRead.Width  = GETLEs16(&sgpuData[4]);
502  VRAMRead.Height = GETLEs16(&sgpuData[5]);
503
504  VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x;
505  VRAMRead.RowsRemaining = VRAMRead.Width;
506  VRAMRead.ColsRemaining = VRAMRead.Height;
507
508  DataReadMode = DR_VRAMTRANSFER;
509
510  lGPUstatusRet |= GPUSTATUS_READYFORVRAM;
511 }
512
513 ////////////////////////////////////////////////////////////////////////
514 // cmd: blkfill - NO primitive! Doesn't care about draw areas...
515 ////////////////////////////////////////////////////////////////////////
516
517 static void primBlkFill(unsigned char * baseAddr)
518 {
519  uint32_t *gpuData = ((uint32_t *) baseAddr);
520  short *sgpuData = ((short *) baseAddr);
521
522  short sX = GETLEs16(&sgpuData[2]);
523  short sY = GETLEs16(&sgpuData[3]);
524  short sW = GETLEs16(&sgpuData[4]) & 0x3ff;
525  short sH = GETLEs16(&sgpuData[5]) & 0x3ff;
526
527  sW = (sW+15) & ~15;
528
529  // Increase H & W if they are one short of full values, because they never can be full values
530  if (sH >= 1023) sH=1024;
531  if (sW >= 1023) sW=1024; 
532
533  // x and y of end pos
534  sW+=sX;
535  sH+=sY;
536
537  FillSoftwareArea(sX, sY, sW, sH, BGR24to16(GETLE32(&gpuData[0])));
538
539  bDoVSyncUpdate=TRUE;
540 }
541  
542 ////////////////////////////////////////////////////////////////////////
543 // cmd: move image vram -> vram
544 ////////////////////////////////////////////////////////////////////////
545
546 static void primMoveImage(unsigned char * baseAddr)
547 {
548  short *sgpuData = ((short *) baseAddr);
549
550  short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j;
551
552  imageX0 = GETLEs16(&sgpuData[2])&0x03ff;
553  imageY0 = GETLEs16(&sgpuData[3])&511;
554  imageX1 = GETLEs16(&sgpuData[4])&0x03ff;
555  imageY1 = GETLEs16(&sgpuData[5])&511;
556  imageSX = GETLEs16(&sgpuData[6]);
557  imageSY = GETLEs16(&sgpuData[7]);
558
559  if((imageX0 == imageX1) && (imageY0 == imageY1)) return; 
560  if(imageSX<=0)  return;
561  if(imageSY<=0)  return;
562
563  if((imageY0+imageSY)>512 ||
564     (imageX0+imageSX)>1024       ||
565     (imageY1+imageSY)>512 ||
566     (imageX1+imageSX)>1024)
567   {
568    int i,j;
569    for(j=0;j<imageSY;j++)
570     for(i=0;i<imageSX;i++)
571      psxVuw [(1024*((imageY1+j)&511))+((imageX1+i)&0x3ff)]=
572       psxVuw[(1024*((imageY0+j)&511))+((imageX0+i)&0x3ff)];
573
574    bDoVSyncUpdate=TRUE;
575  
576    return;
577   }
578  
579  if(imageSX&1)                                         // not dword aligned? slower func
580   {
581    unsigned short *SRCPtr, *DSTPtr;
582    unsigned short LineOffset;
583
584    SRCPtr = psxVuw + (1024*imageY0) + imageX0;
585    DSTPtr = psxVuw + (1024*imageY1) + imageX1;
586
587    LineOffset = 1024 - imageSX;
588
589    for(j=0;j<imageSY;j++)
590     {
591      for(i=0;i<imageSX;i++) *DSTPtr++ = *SRCPtr++;
592      SRCPtr += LineOffset;
593      DSTPtr += LineOffset;
594     }
595   }
596  else                                                  // dword aligned
597   {
598    uint32_t *SRCPtr, *DSTPtr;
599    unsigned short LineOffset;
600    int dx=imageSX>>1;
601
602    SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0);
603    DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1);
604
605    LineOffset = 512 - dx;
606
607    for(j=0;j<imageSY;j++)
608     {
609      for(i=0;i<dx;i++) *DSTPtr++ = *SRCPtr++;
610      SRCPtr += LineOffset;
611      DSTPtr += LineOffset;
612     }
613   }
614
615  imageSX+=imageX1;
616  imageSY+=imageY1;
617
618  bDoVSyncUpdate=TRUE;
619 }
620
621 ////////////////////////////////////////////////////////////////////////
622 // cmd: draw free-size Tile 
623 ////////////////////////////////////////////////////////////////////////
624
625 static void primTileS(unsigned char * baseAddr)
626 {
627  uint32_t *gpuData = ((uint32_t*)baseAddr);
628  short *sgpuData = ((short *) baseAddr);
629  short sW = GETLEs16(&sgpuData[4]) & 0x3ff;
630  short sH = GETLEs16(&sgpuData[5]) & 511;              // mmm... limit tiles to 0x1ff or height?
631
632  lx0 = GETLEs16(&sgpuData[2]);
633  ly0 = GETLEs16(&sgpuData[3]);
634
635  if(!(dwActFixes&8)) AdjustCoord1();
636                       
637  // x and y of start
638  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
639  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
640  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
641  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
642
643  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
644
645   FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
646                         BGR24to16(GETLE32(&gpuData[0])));          
647
648  bDoVSyncUpdate=TRUE;
649 }
650
651 ////////////////////////////////////////////////////////////////////////
652 // cmd: draw 1 dot Tile (point)
653 ////////////////////////////////////////////////////////////////////////
654
655 static void primTile1(unsigned char * baseAddr)
656 {
657  uint32_t *gpuData = ((uint32_t*)baseAddr);
658  short *sgpuData = ((short *) baseAddr);
659  short sH = 1;
660  short sW = 1;
661
662  lx0 = GETLEs16(&sgpuData[2]);
663  ly0 = GETLEs16(&sgpuData[3]);
664
665  if(!(dwActFixes&8)) AdjustCoord1();
666
667  // x and y of start
668  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
669  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
670  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
671  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
672
673  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
674
675  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
676                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
677
678  bDoVSyncUpdate=TRUE;
679 }
680
681 ////////////////////////////////////////////////////////////////////////
682 // cmd: draw 8 dot Tile (small rect)
683 ////////////////////////////////////////////////////////////////////////
684
685 static void primTile8(unsigned char * baseAddr)
686 {
687  uint32_t *gpuData = ((uint32_t*)baseAddr);
688  short *sgpuData = ((short *) baseAddr);
689  short sH = 8;
690  short sW = 8;
691
692  lx0 = GETLEs16(&sgpuData[2]);
693  ly0 = GETLEs16(&sgpuData[3]);
694
695  if(!(dwActFixes&8)) AdjustCoord1();
696
697  // x and y of start
698  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
699  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
700  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
701  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
702
703  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
704
705  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
706                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
707
708  bDoVSyncUpdate=TRUE;
709 }
710
711 ////////////////////////////////////////////////////////////////////////
712 // cmd: draw 16 dot Tile (medium rect)
713 ////////////////////////////////////////////////////////////////////////
714
715 static void primTile16(unsigned char * baseAddr)
716 {
717  uint32_t *gpuData = ((uint32_t*)baseAddr);
718  short *sgpuData = ((short *) baseAddr);
719  short sH = 16;
720  short sW = 16;
721
722  lx0 = GETLEs16(&sgpuData[2]);
723  ly0 = GETLEs16(&sgpuData[3]);
724
725  if(!(dwActFixes&8)) AdjustCoord1();
726
727  // x and y of start
728  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
729  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
730  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
731  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
732
733  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
734
735  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
736                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
737
738  bDoVSyncUpdate=TRUE;
739 }
740
741 ////////////////////////////////////////////////////////////////////////
742 // cmd: small sprite (textured rect)
743 ////////////////////////////////////////////////////////////////////////
744
745 static void primSprt8(unsigned char * baseAddr)
746 {
747  uint32_t *gpuData = ((uint32_t *) baseAddr);
748  short *sgpuData = ((short *) baseAddr);
749
750  lx0 = GETLEs16(&sgpuData[2]);
751  ly0 = GETLEs16(&sgpuData[3]);
752
753  if(!(dwActFixes&8)) AdjustCoord1();
754
755  SetRenderMode(GETLE32(&gpuData[0]));
756
757  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8);
758  else
759  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,8,8);
760  else           DrawSoftwareSprite(baseAddr,8,8,
761                                    baseAddr[8],
762                                    baseAddr[9]);
763
764  bDoVSyncUpdate=TRUE;
765 }
766
767 ////////////////////////////////////////////////////////////////////////
768 // cmd: medium sprite (textured rect)
769 ////////////////////////////////////////////////////////////////////////
770
771 static void primSprt16(unsigned char * baseAddr)
772 {
773  uint32_t *gpuData = ((uint32_t *) baseAddr);
774  short *sgpuData = ((short *) baseAddr);
775
776  lx0 = GETLEs16(&sgpuData[2]);
777  ly0 = GETLEs16(&sgpuData[3]);
778
779  if(!(dwActFixes&8)) AdjustCoord1();
780
781  SetRenderMode(GETLE32(&gpuData[0]));
782
783  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16);
784  else
785  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,16,16);
786  else           DrawSoftwareSprite(baseAddr,16,16,
787                                    baseAddr[8],
788                                    baseAddr[9]);
789
790  bDoVSyncUpdate=TRUE;
791 }
792
793 ////////////////////////////////////////////////////////////////////////
794 // cmd: free-size sprite (textured rect)
795 ////////////////////////////////////////////////////////////////////////
796
797 // func used on texture coord wrap
798 static void primSprtSRest(unsigned char * baseAddr,unsigned short type)
799 {
800  uint32_t *gpuData = ((uint32_t *) baseAddr);
801  short *sgpuData = ((short *) baseAddr);
802  unsigned short sTypeRest=0;
803
804  short s;
805  short sX = GETLEs16(&sgpuData[2]);
806  short sY = GETLEs16(&sgpuData[3]);
807  short sW = GETLEs16(&sgpuData[6]) & 0x3ff;
808  short sH = GETLEs16(&sgpuData[7]) & 0x1ff;
809  short tX = baseAddr[8];
810  short tY = baseAddr[9];
811
812  switch(type)
813   {
814    case 1:
815     s=256-baseAddr[8];
816     sW-=s;
817     sX+=s;
818     tX=0;
819     break;
820    case 2:
821     s=256-baseAddr[9];
822     sH-=s;
823     sY+=s;
824     tY=0;
825     break;
826    case 3:
827     s=256-baseAddr[8];
828     sW-=s;
829     sX+=s;
830     tX=0;
831     s=256-baseAddr[9];
832     sH-=s;
833     sY+=s;
834     tY=0;
835     break;
836    case 4:
837     s=512-baseAddr[8];
838     sW-=s;
839     sX+=s;
840     tX=0;
841     break;
842    case 5:
843     s=512-baseAddr[9];
844     sH-=s;
845     sY+=s;
846     tY=0;
847     break;
848    case 6:
849     s=512-baseAddr[8];
850     sW-=s;
851     sX+=s;
852     tX=0;
853     s=512-baseAddr[9];
854     sH-=s;
855     sY+=s;
856     tY=0;
857     break;
858   }
859
860  SetRenderMode(GETLE32(&gpuData[0]));
861
862  if(tX+sW>256) {sW=256-tX;sTypeRest+=1;}
863  if(tY+sH>256) {sH=256-tY;sTypeRest+=2;}
864
865  lx0 = sX;
866  ly0 = sY;
867
868  if(!(dwActFixes&8)) AdjustCoord1();
869
870  DrawSoftwareSprite(baseAddr,sW,sH,tX,tY);
871
872  if(sTypeRest && type<4)  
873   {
874    if(sTypeRest&1  && type==1)  primSprtSRest(baseAddr,4);
875    if(sTypeRest&2  && type==2)  primSprtSRest(baseAddr,5);
876    if(sTypeRest==3 && type==3)  primSprtSRest(baseAddr,6);
877   }
878
879 }
880                                      
881 ////////////////////////////////////////////////////////////////////////
882
883 static void primSprtS(unsigned char * baseAddr)
884 {
885  uint32_t *gpuData = ((uint32_t *) baseAddr);
886  short *sgpuData = ((short *) baseAddr);
887  short sW,sH;
888
889  lx0 = GETLEs16(&sgpuData[2]);
890  ly0 = GETLEs16(&sgpuData[3]);
891
892  if(!(dwActFixes&8)) AdjustCoord1();
893
894  sW = GETLEs16(&sgpuData[6]) & 0x3ff;
895  sH = GETLEs16(&sgpuData[7]) & 0x1ff;
896
897  SetRenderMode(GETLE32(&gpuData[0]));
898
899  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH);
900  else
901  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,sW,sH);
902  else          
903   {
904    unsigned short sTypeRest=0;
905    short tX=baseAddr[8];
906    short tY=baseAddr[9];
907
908    if(tX+sW>256) {sW=256-tX;sTypeRest+=1;}
909    if(tY+sH>256) {sH=256-tY;sTypeRest+=2;}
910
911    DrawSoftwareSprite(baseAddr,sW,sH,tX,tY);
912
913    if(sTypeRest) 
914     {
915      if(sTypeRest&1)  primSprtSRest(baseAddr,1);
916      if(sTypeRest&2)  primSprtSRest(baseAddr,2);
917      if(sTypeRest==3) primSprtSRest(baseAddr,3);
918     }
919
920   }
921
922  bDoVSyncUpdate=TRUE;
923 }
924
925 ////////////////////////////////////////////////////////////////////////
926 // cmd: flat shaded Poly4
927 ////////////////////////////////////////////////////////////////////////
928
929 static void primPolyF4(unsigned char *baseAddr)
930 {
931  uint32_t *gpuData = ((uint32_t *) baseAddr);
932  short *sgpuData = ((short *) baseAddr);
933
934  lx0 = GETLEs16(&sgpuData[2]);
935  ly0 = GETLEs16(&sgpuData[3]);
936  lx1 = GETLEs16(&sgpuData[4]);
937  ly1 = GETLEs16(&sgpuData[5]);
938  lx2 = GETLEs16(&sgpuData[6]);
939  ly2 = GETLEs16(&sgpuData[7]);
940  lx3 = GETLEs16(&sgpuData[8]);
941  ly3 = GETLEs16(&sgpuData[9]);
942
943  if(!(dwActFixes&8)) 
944   {
945    AdjustCoord4();
946    if(CheckCoord4()) return;
947   }
948
949  offsetPSX4();
950  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
951
952  drawPoly4F(GETLE32(&gpuData[0]));
953
954  bDoVSyncUpdate=TRUE;
955 }
956
957 ////////////////////////////////////////////////////////////////////////
958 // cmd: smooth shaded Poly4
959 ////////////////////////////////////////////////////////////////////////
960
961 static void primPolyG4(unsigned char * baseAddr)
962 {
963  uint32_t *gpuData = (uint32_t *)baseAddr;
964  short *sgpuData = ((short *) baseAddr);
965
966  lx0 = GETLEs16(&sgpuData[2]);
967  ly0 = GETLEs16(&sgpuData[3]);
968  lx1 = GETLEs16(&sgpuData[6]);
969  ly1 = GETLEs16(&sgpuData[7]);
970  lx2 = GETLEs16(&sgpuData[10]);
971  ly2 = GETLEs16(&sgpuData[11]);
972  lx3 = GETLEs16(&sgpuData[14]);
973  ly3 = GETLEs16(&sgpuData[15]);
974
975  if(!(dwActFixes&8))
976   {
977    AdjustCoord4();
978    if(CheckCoord4()) return;
979   }
980
981  offsetPSX4();
982  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
983
984  drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), 
985             GETLE32(&gpuData[4]), GETLE32(&gpuData[6]));
986
987  bDoVSyncUpdate=TRUE;
988 }
989
990 ////////////////////////////////////////////////////////////////////////
991 // cmd: flat shaded Texture3
992 ////////////////////////////////////////////////////////////////////////
993
994 static void primPolyFT3(unsigned char * baseAddr)
995 {
996  uint32_t *gpuData = ((uint32_t *) baseAddr);
997  short *sgpuData = ((short *) baseAddr);
998
999  lx0 = GETLEs16(&sgpuData[2]);
1000  ly0 = GETLEs16(&sgpuData[3]);
1001  lx1 = GETLEs16(&sgpuData[6]);
1002  ly1 = GETLEs16(&sgpuData[7]);
1003  lx2 = GETLEs16(&sgpuData[10]);
1004  ly2 = GETLEs16(&sgpuData[11]);
1005
1006  lLowerpart=GETLE32(&gpuData[4])>>16;
1007  UpdateGlobalTP((unsigned short)lLowerpart);
1008
1009  if(!(dwActFixes&8))
1010   {
1011    AdjustCoord3();
1012    if(CheckCoord3()) return;
1013   }
1014
1015  offsetPSX3();
1016  SetRenderMode(GETLE32(&gpuData[0]));
1017
1018  drawPoly3FT(baseAddr);
1019
1020  bDoVSyncUpdate=TRUE;
1021 }
1022
1023 ////////////////////////////////////////////////////////////////////////
1024 // cmd: flat shaded Texture4
1025 ////////////////////////////////////////////////////////////////////////
1026
1027 static void primPolyFT4(unsigned char * baseAddr)
1028 {
1029  uint32_t *gpuData = ((uint32_t *) baseAddr);
1030  short *sgpuData = ((short *) baseAddr);
1031
1032  lx0 = GETLEs16(&sgpuData[2]);
1033  ly0 = GETLEs16(&sgpuData[3]);
1034  lx1 = GETLEs16(&sgpuData[6]);
1035  ly1 = GETLEs16(&sgpuData[7]);
1036  lx2 = GETLEs16(&sgpuData[10]);
1037  ly2 = GETLEs16(&sgpuData[11]);
1038  lx3 = GETLEs16(&sgpuData[14]);
1039  ly3 = GETLEs16(&sgpuData[15]);
1040
1041  lLowerpart=GETLE32(&gpuData[4])>>16;
1042  UpdateGlobalTP((unsigned short)lLowerpart);
1043
1044  if(!(dwActFixes&8))
1045   {
1046    AdjustCoord4();
1047    if(CheckCoord4()) return;
1048   }
1049
1050  offsetPSX4();
1051
1052  SetRenderMode(GETLE32(&gpuData[0]));
1053
1054  drawPoly4FT(baseAddr);
1055
1056  bDoVSyncUpdate=TRUE;
1057 }
1058
1059 ////////////////////////////////////////////////////////////////////////
1060 // cmd: smooth shaded Texture3
1061 ////////////////////////////////////////////////////////////////////////
1062
1063 static void primPolyGT3(unsigned char *baseAddr)
1064 {    
1065  uint32_t *gpuData = ((uint32_t *) baseAddr);
1066  short *sgpuData = ((short *) baseAddr);
1067
1068  lx0 = GETLEs16(&sgpuData[2]);
1069  ly0 = GETLEs16(&sgpuData[3]);
1070  lx1 = GETLEs16(&sgpuData[8]);
1071  ly1 = GETLEs16(&sgpuData[9]);
1072  lx2 = GETLEs16(&sgpuData[14]);
1073  ly2 = GETLEs16(&sgpuData[15]);
1074
1075  lLowerpart=GETLE32(&gpuData[5])>>16;
1076  UpdateGlobalTP((unsigned short)lLowerpart);
1077
1078  if(!(dwActFixes&8))
1079   {
1080    AdjustCoord3();
1081    if(CheckCoord3()) return;
1082   }
1083            
1084  offsetPSX3();
1085  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1086
1087  if(SHADETEXBIT(GETLE32(&gpuData[0])))
1088   {
1089    gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1090    gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1091    gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1092   }
1093
1094  drawPoly3GT(baseAddr);
1095
1096  bDoVSyncUpdate=TRUE;
1097 }
1098
1099 ////////////////////////////////////////////////////////////////////////
1100 // cmd: smooth shaded Poly3
1101 ////////////////////////////////////////////////////////////////////////
1102
1103 static void primPolyG3(unsigned char *baseAddr)
1104 {    
1105  uint32_t *gpuData = ((uint32_t *) baseAddr);
1106  short *sgpuData = ((short *) baseAddr);
1107
1108  lx0 = GETLEs16(&sgpuData[2]);
1109  ly0 = GETLEs16(&sgpuData[3]);
1110  lx1 = GETLEs16(&sgpuData[6]);
1111  ly1 = GETLEs16(&sgpuData[7]);
1112  lx2 = GETLEs16(&sgpuData[10]);
1113  ly2 = GETLEs16(&sgpuData[11]);
1114
1115  if(!(dwActFixes&8))
1116   {
1117    AdjustCoord3();
1118    if(CheckCoord3()) return;
1119   }
1120
1121  offsetPSX3();
1122  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1123
1124  drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4]));
1125
1126  bDoVSyncUpdate=TRUE;
1127 }
1128
1129 ////////////////////////////////////////////////////////////////////////
1130 // cmd: smooth shaded Texture4
1131 ////////////////////////////////////////////////////////////////////////
1132
1133 static void primPolyGT4(unsigned char *baseAddr)
1134
1135  uint32_t *gpuData = ((uint32_t *) baseAddr);
1136  short *sgpuData = ((short *) baseAddr);
1137
1138  lx0 = GETLEs16(&sgpuData[2]);
1139  ly0 = GETLEs16(&sgpuData[3]);
1140  lx1 = GETLEs16(&sgpuData[8]);
1141  ly1 = GETLEs16(&sgpuData[9]);
1142  lx2 = GETLEs16(&sgpuData[14]);
1143  ly2 = GETLEs16(&sgpuData[15]);
1144  lx3 = GETLEs16(&sgpuData[20]);
1145  ly3 = GETLEs16(&sgpuData[21]);
1146
1147  lLowerpart=GETLE32(&gpuData[5])>>16;
1148  UpdateGlobalTP((unsigned short)lLowerpart);
1149
1150  if(!(dwActFixes&8))
1151   {
1152    AdjustCoord4();
1153    if(CheckCoord4()) return;
1154   }
1155
1156  offsetPSX4();
1157  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1158
1159  if(SHADETEXBIT(GETLE32(&gpuData[0])))
1160   {
1161    gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1162    gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1163    gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1164    gpuData[9] = (gpuData[9]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1165   }
1166
1167  drawPoly4GT(baseAddr);
1168
1169  bDoVSyncUpdate=TRUE;
1170 }
1171
1172 ////////////////////////////////////////////////////////////////////////
1173 // cmd: smooth shaded Poly3
1174 ////////////////////////////////////////////////////////////////////////
1175
1176 static void primPolyF3(unsigned char *baseAddr)
1177 {    
1178  uint32_t *gpuData = ((uint32_t *) baseAddr);
1179  short *sgpuData = ((short *) baseAddr);
1180
1181  lx0 = GETLEs16(&sgpuData[2]);
1182  ly0 = GETLEs16(&sgpuData[3]);
1183  lx1 = GETLEs16(&sgpuData[4]);
1184  ly1 = GETLEs16(&sgpuData[5]);
1185  lx2 = GETLEs16(&sgpuData[6]);
1186  ly2 = GETLEs16(&sgpuData[7]);
1187
1188  if(!(dwActFixes&8))
1189   {
1190    AdjustCoord3();
1191    if(CheckCoord3()) return;
1192   }
1193
1194  offsetPSX3();
1195  SetRenderMode(GETLE32(&gpuData[0]));
1196
1197  drawPoly3F(GETLE32(&gpuData[0]));
1198
1199  bDoVSyncUpdate=TRUE;
1200 }
1201
1202 ////////////////////////////////////////////////////////////////////////
1203 // cmd: skipping shaded polylines
1204 ////////////////////////////////////////////////////////////////////////
1205
1206 static void primLineGSkip(unsigned char *baseAddr)
1207 {    
1208  uint32_t *gpuData = ((uint32_t *) baseAddr);
1209  int iMax=255;
1210  int i=2;
1211
1212  ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1213  lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1214
1215  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4))
1216   {
1217    i++;
1218    ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1219    lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1220    i++;if(i>iMax) break;
1221   }
1222 }
1223
1224 ////////////////////////////////////////////////////////////////////////
1225 // cmd: shaded polylines
1226 ////////////////////////////////////////////////////////////////////////
1227
1228 static void primLineGEx(unsigned char *baseAddr)
1229 {    
1230  uint32_t *gpuData = ((uint32_t *) baseAddr);
1231  int iMax=255;
1232  uint32_t lc0,lc1;
1233  short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE;
1234
1235  sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1236  slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1237
1238  if(!(dwActFixes&8)) 
1239   {
1240    slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1241    sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1242   }
1243
1244  lc1 = gpuData[0] & 0xffffff;
1245
1246  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1247
1248  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4))
1249   {
1250    sly0=sly1; slx0=slx1; lc0=lc1;
1251    lc1=GETLE32(&gpuData[i]) & 0xffffff;
1252
1253    i++;
1254
1255    // no check needed on gshaded polyline positions
1256    // if((gpuData[i] & 0xF000F000) == 0x50005000) break;
1257
1258    sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1259    slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1260
1261    if(!(dwActFixes&8))
1262     {
1263      slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1264      sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1265      if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE;
1266     }
1267
1268    if ((lx0 != lx1) || (ly0 != ly1))
1269     {
1270      ly0=sly0;
1271      lx0=slx0;
1272      ly1=sly1;
1273      lx1=slx1;
1274               
1275      offsetPSX2();
1276      if(bDraw) DrawSoftwareLineShade(lc0, lc1);
1277     }
1278    i++;  
1279    if(i>iMax) break;
1280   }
1281
1282  bDoVSyncUpdate=TRUE;
1283 }
1284
1285 ////////////////////////////////////////////////////////////////////////
1286 // cmd: shaded polyline2
1287 ////////////////////////////////////////////////////////////////////////
1288
1289 static void primLineG2(unsigned char *baseAddr)
1290 {    
1291  uint32_t *gpuData = ((uint32_t *) baseAddr);
1292  short *sgpuData = ((short *) baseAddr);
1293
1294  lx0 = GETLEs16(&sgpuData[2]);
1295  ly0 = GETLEs16(&sgpuData[3]);
1296  lx1 = GETLEs16(&sgpuData[6]);
1297  ly1 = GETLEs16(&sgpuData[7]);
1298
1299  if(!(dwActFixes&8))
1300   {
1301    AdjustCoord2();
1302    if(CheckCoord2()) return;
1303   }
1304
1305  if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;}
1306
1307  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1308  offsetPSX2();
1309  DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2]));
1310
1311  bDoVSyncUpdate=TRUE;
1312 }
1313
1314 ////////////////////////////////////////////////////////////////////////
1315 // cmd: skipping flat polylines
1316 ////////////////////////////////////////////////////////////////////////
1317
1318 static void primLineFSkip(unsigned char *baseAddr)
1319 {
1320  uint32_t *gpuData = ((uint32_t *) baseAddr);
1321  int i=2,iMax=255;
1322
1323  ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1324  lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1325
1326  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3))
1327   {
1328    ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1329    lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1330    i++;if(i>iMax) break;
1331   }             
1332 }
1333
1334 ////////////////////////////////////////////////////////////////////////
1335 // cmd: drawing flat polylines
1336 ////////////////////////////////////////////////////////////////////////
1337
1338 static void primLineFEx(unsigned char *baseAddr)
1339 {
1340  uint32_t *gpuData = ((uint32_t *) baseAddr);
1341  int iMax;
1342  short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE;
1343
1344  iMax=255;
1345
1346  sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1347  slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1348  if(!(dwActFixes&8))
1349   {
1350    slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1351    sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1352   }
1353
1354  SetRenderMode(GETLE32(&gpuData[0]));
1355
1356  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3))
1357   {
1358    sly0 = sly1;slx0=slx1;
1359    sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1360    slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1361    if(!(dwActFixes&8))
1362     {
1363      slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1364      sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1365
1366      if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE;
1367     }
1368
1369    ly0=sly0;
1370    lx0=slx0;
1371    ly1=sly1;
1372    lx1=slx1;
1373
1374    offsetPSX2();
1375    if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0]));
1376
1377    i++;if(i>iMax) break;
1378   }
1379
1380  bDoVSyncUpdate=TRUE;
1381 }
1382
1383 ////////////////////////////////////////////////////////////////////////
1384 // cmd: drawing flat polyline2
1385 ////////////////////////////////////////////////////////////////////////
1386
1387 static void primLineF2(unsigned char *baseAddr)
1388 {
1389  uint32_t *gpuData = ((uint32_t *) baseAddr);
1390  short *sgpuData = ((short *) baseAddr);
1391
1392  lx0 = GETLEs16(&sgpuData[2]);
1393  ly0 = GETLEs16(&sgpuData[3]);
1394  lx1 = GETLEs16(&sgpuData[4]);
1395  ly1 = GETLEs16(&sgpuData[5]);
1396
1397  if(!(dwActFixes&8))
1398   {
1399    AdjustCoord2();
1400    if(CheckCoord2()) return;
1401   }
1402
1403  if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;}
1404                     
1405  offsetPSX2();
1406  SetRenderMode(GETLE32(&gpuData[0]));
1407
1408  DrawSoftwareLineFlat(GETLE32(&gpuData[0]));
1409
1410  bDoVSyncUpdate=TRUE;
1411 }
1412
1413 ////////////////////////////////////////////////////////////////////////
1414 // cmd: well, easiest command... not implemented
1415 ////////////////////////////////////////////////////////////////////////
1416
1417 static void primNI(unsigned char *bA)
1418 {
1419 }
1420
1421 ////////////////////////////////////////////////////////////////////////
1422 // cmd func ptr table
1423 ////////////////////////////////////////////////////////////////////////
1424
1425
1426 void (*primTableJ[256])(unsigned char *) = 
1427 {
1428     // 00
1429     primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI,
1430     // 08
1431     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1432     // 10
1433     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1434     // 18
1435     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1436     // 20
1437     primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3,
1438     // 28
1439     primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4,
1440     // 30
1441     primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3,
1442     // 38
1443     primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4,
1444     // 40
1445     primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI,
1446     // 48
1447     primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,
1448     // 50
1449     primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI,
1450     // 58
1451     primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,
1452     // 60
1453     primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS,
1454     // 68
1455     primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI,
1456     // 70
1457     primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8,
1458     // 78
1459     primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16,
1460     // 80
1461     primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1462     // 88
1463     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1464     // 90
1465     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1466     // 98
1467     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1468     // a0
1469     primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1470     // a8
1471     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1472     // b0
1473     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1474     // b8
1475     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1476     // c0
1477     primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1478     // c8
1479     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1480     // d0
1481     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1482     // d8
1483     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1484     // e0
1485     primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI,
1486     // e8
1487     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1488     // f0
1489     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1490     // f8
1491     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI
1492 };
1493
1494 ////////////////////////////////////////////////////////////////////////
1495 // cmd func ptr table for skipping
1496 ////////////////////////////////////////////////////////////////////////
1497
1498 void (*primTableSkip[256])(unsigned char *) = 
1499 {
1500     // 00
1501     primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI,
1502     // 08
1503     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1504     // 10
1505     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1506     // 18
1507     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1508     // 20
1509     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1510     // 28
1511     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1512     // 30
1513     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1514     // 38
1515     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1516     // 40
1517     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1518     // 48
1519     primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,
1520     // 50
1521     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1522     // 58
1523     primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,
1524     // 60
1525     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1526     // 68
1527     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1528     // 70
1529     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1530     // 78
1531     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1532     // 80
1533     primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1534     // 88
1535     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1536     // 90
1537     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1538     // 98
1539     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1540     // a0
1541     primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1542     // a8
1543     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1544     // b0
1545     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1546     // b8
1547     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1548     // c0
1549     primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1550     // c8
1551     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1552     // d0
1553     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1554     // d8
1555     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1556     // e0
1557     primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI,
1558     // e8
1559     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1560     // f0
1561     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1562     // f8
1563     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI
1564 };