frontend: enable SPUIRQWait by default
[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
379   // Texture window size is determined by the least bit set of the relevant 5 bits
380
381  if (gdata & 0x001)
382   TWin.Position.x1 = 8;    // xxxx1
383  else if (gdata & 0x002)
384   TWin.Position.x1 = 16;   // xxx10
385  else if (gdata & 0x004)
386   TWin.Position.x1 = 32;   // xx100
387  else if (gdata & 0x008)
388   TWin.Position.x1 = 64;   // x1000
389  else if (gdata & 0x010)
390   TWin.Position.x1 = 128;  // 10000
391  else
392   TWin.Position.x1 = 256;  // 00000
393
394  // Re-calculate the bit field, because we can't trust what is passed in the data
395
396
397  YAlign = (uint32_t)(32 - (TWin.Position.y1 >> 3));
398  XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3));
399
400  // Absolute position of the start of the texture window
401
402  TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3);
403  TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3);
404
405  if((TWin.Position.x0 == 0 &&                          // tw turned off
406      TWin.Position.y0 == 0 &&
407      TWin.Position.x1 == 0 &&
408      TWin.Position.y1 == 0) ||  
409      (TWin.Position.x1 == 256 &&
410       TWin.Position.y1 == 256))
411   {
412    bUsingTWin = FALSE;                                 // -> just do it
413   }                                                    
414  else                                                  // otherwise
415   {
416    bUsingTWin = TRUE;                                  // -> tw turned on
417   }
418 }
419
420 ////////////////////////////////////////////////////////////////////////
421 // cmd: start of drawing area... primitives will be clipped inside
422 ////////////////////////////////////////////////////////////////////////
423
424
425
426 static void cmdDrawAreaStart(unsigned char * baseAddr)
427 {
428  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
429
430  drawX  = gdata & 0x3ff;                               // for soft drawing
431
432    lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF;
433    drawY  = (gdata>>10)&0x3ff;
434    if(drawY>=512) drawY=511;                           // some security
435 }
436
437 ////////////////////////////////////////////////////////////////////////
438 // cmd: end of drawing area... primitives will be clipped inside
439 ////////////////////////////////////////////////////////////////////////
440
441 static void cmdDrawAreaEnd(unsigned char * baseAddr)
442 {
443  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
444
445  drawW  = gdata & 0x3ff;                               // for soft drawing
446
447    lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF;
448    drawH  = (gdata>>10)&0x3ff;
449    if(drawH>=512) drawH=511;                           // some security
450 }
451
452 ////////////////////////////////////////////////////////////////////////
453 // cmd: draw offset... will be added to prim coords
454 ////////////////////////////////////////////////////////////////////////
455
456 static void cmdDrawOffset(unsigned char * baseAddr)
457 {
458  uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]);
459
460  PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff);
461
462    lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF;
463    PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff);
464  
465  PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21);
466  PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21);
467 }
468  
469 ////////////////////////////////////////////////////////////////////////
470 // cmd: load image to vram
471 ////////////////////////////////////////////////////////////////////////
472
473 static void primLoadImage(unsigned char * baseAddr)
474 {
475  unsigned short *sgpuData = ((unsigned short *) baseAddr);
476
477  VRAMWrite.x      = GETLEs16(&sgpuData[2])&0x3ff;
478  VRAMWrite.y      = GETLEs16(&sgpuData[3])&511;
479  VRAMWrite.Width  = GETLEs16(&sgpuData[4]);
480  VRAMWrite.Height = GETLEs16(&sgpuData[5]);
481
482  DataWriteMode = DR_VRAMTRANSFER;
483
484  VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x;
485  VRAMWrite.RowsRemaining = VRAMWrite.Width;
486  VRAMWrite.ColsRemaining = VRAMWrite.Height;
487 }
488
489 ////////////////////////////////////////////////////////////////////////
490 // cmd: vram -> psx mem
491 ////////////////////////////////////////////////////////////////////////
492
493 static void primStoreImage(unsigned char * baseAddr)
494 {
495  unsigned short *sgpuData = ((unsigned short *) baseAddr);
496
497  VRAMRead.x      = GETLEs16(&sgpuData[2])&0x03ff;
498  VRAMRead.y      = GETLEs16(&sgpuData[3])&511;
499  VRAMRead.Width  = GETLEs16(&sgpuData[4]);
500  VRAMRead.Height = GETLEs16(&sgpuData[5]);
501
502  VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x;
503  VRAMRead.RowsRemaining = VRAMRead.Width;
504  VRAMRead.ColsRemaining = VRAMRead.Height;
505
506  DataReadMode = DR_VRAMTRANSFER;
507
508  lGPUstatusRet |= GPUSTATUS_READYFORVRAM;
509 }
510
511 ////////////////////////////////////////////////////////////////////////
512 // cmd: blkfill - NO primitive! Doesn't care about draw areas...
513 ////////////////////////////////////////////////////////////////////////
514
515 static void primBlkFill(unsigned char * baseAddr)
516 {
517  uint32_t *gpuData = ((uint32_t *) baseAddr);
518  short *sgpuData = ((short *) baseAddr);
519
520  short sX = GETLEs16(&sgpuData[2]);
521  short sY = GETLEs16(&sgpuData[3]);
522  short sW = GETLEs16(&sgpuData[4]) & 0x3ff;
523  short sH = GETLEs16(&sgpuData[5]) & 0x3ff;
524
525  sW = (sW+15) & ~15;
526
527  // Increase H & W if they are one short of full values, because they never can be full values
528  if (sH >= 1023) sH=1024;
529  if (sW >= 1023) sW=1024; 
530
531  // x and y of end pos
532  sW+=sX;
533  sH+=sY;
534
535  FillSoftwareArea(sX, sY, sW, sH, BGR24to16(GETLE32(&gpuData[0])));
536
537  bDoVSyncUpdate=TRUE;
538 }
539  
540 ////////////////////////////////////////////////////////////////////////
541 // cmd: move image vram -> vram
542 ////////////////////////////////////////////////////////////////////////
543
544 static void primMoveImage(unsigned char * baseAddr)
545 {
546  short *sgpuData = ((short *) baseAddr);
547
548  short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j;
549
550  imageX0 = GETLEs16(&sgpuData[2])&0x03ff;
551  imageY0 = GETLEs16(&sgpuData[3])&511;
552  imageX1 = GETLEs16(&sgpuData[4])&0x03ff;
553  imageY1 = GETLEs16(&sgpuData[5])&511;
554  imageSX = GETLEs16(&sgpuData[6]);
555  imageSY = GETLEs16(&sgpuData[7]);
556
557  if((imageX0 == imageX1) && (imageY0 == imageY1)) return; 
558  if(imageSX<=0)  return;
559  if(imageSY<=0)  return;
560
561  if((imageY0+imageSY)>512 ||
562     (imageX0+imageSX)>1024       ||
563     (imageY1+imageSY)>512 ||
564     (imageX1+imageSX)>1024)
565   {
566    int i,j;
567    for(j=0;j<imageSY;j++)
568     for(i=0;i<imageSX;i++)
569      psxVuw [(1024*((imageY1+j)&511))+((imageX1+i)&0x3ff)]=
570       psxVuw[(1024*((imageY0+j)&511))+((imageX0+i)&0x3ff)];
571
572    bDoVSyncUpdate=TRUE;
573  
574    return;
575   }
576  
577  if(imageSX&1)                                         // not dword aligned? slower func
578   {
579    unsigned short *SRCPtr, *DSTPtr;
580    unsigned short LineOffset;
581
582    SRCPtr = psxVuw + (1024*imageY0) + imageX0;
583    DSTPtr = psxVuw + (1024*imageY1) + imageX1;
584
585    LineOffset = 1024 - imageSX;
586
587    for(j=0;j<imageSY;j++)
588     {
589      for(i=0;i<imageSX;i++) *DSTPtr++ = *SRCPtr++;
590      SRCPtr += LineOffset;
591      DSTPtr += LineOffset;
592     }
593   }
594  else                                                  // dword aligned
595   {
596    uint32_t *SRCPtr, *DSTPtr;
597    unsigned short LineOffset;
598    int dx=imageSX>>1;
599
600    SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0);
601    DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1);
602
603    LineOffset = 512 - dx;
604
605    for(j=0;j<imageSY;j++)
606     {
607      for(i=0;i<dx;i++) *DSTPtr++ = *SRCPtr++;
608      SRCPtr += LineOffset;
609      DSTPtr += LineOffset;
610     }
611   }
612
613  imageSX+=imageX1;
614  imageSY+=imageY1;
615
616  bDoVSyncUpdate=TRUE;
617 }
618
619 ////////////////////////////////////////////////////////////////////////
620 // cmd: draw free-size Tile 
621 ////////////////////////////////////////////////////////////////////////
622
623 static void primTileS(unsigned char * baseAddr)
624 {
625  uint32_t *gpuData = ((uint32_t*)baseAddr);
626  short *sgpuData = ((short *) baseAddr);
627  short sW = GETLEs16(&sgpuData[4]) & 0x3ff;
628  short sH = GETLEs16(&sgpuData[5]) & 511;              // mmm... limit tiles to 0x1ff or height?
629
630  lx0 = GETLEs16(&sgpuData[2]);
631  ly0 = GETLEs16(&sgpuData[3]);
632
633  if(!(dwActFixes&8)) AdjustCoord1();
634                       
635  // x and y of start
636  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
637  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
638  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
639  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
640
641  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
642
643   FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
644                         BGR24to16(GETLE32(&gpuData[0])));          
645
646  bDoVSyncUpdate=TRUE;
647 }
648
649 ////////////////////////////////////////////////////////////////////////
650 // cmd: draw 1 dot Tile (point)
651 ////////////////////////////////////////////////////////////////////////
652
653 static void primTile1(unsigned char * baseAddr)
654 {
655  uint32_t *gpuData = ((uint32_t*)baseAddr);
656  short *sgpuData = ((short *) baseAddr);
657  short sH = 1;
658  short sW = 1;
659
660  lx0 = GETLEs16(&sgpuData[2]);
661  ly0 = GETLEs16(&sgpuData[3]);
662
663  if(!(dwActFixes&8)) AdjustCoord1();
664
665  // x and y of start
666  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
667  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
668  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
669  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
670
671  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
672
673  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
674                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
675
676  bDoVSyncUpdate=TRUE;
677 }
678
679 ////////////////////////////////////////////////////////////////////////
680 // cmd: draw 8 dot Tile (small rect)
681 ////////////////////////////////////////////////////////////////////////
682
683 static void primTile8(unsigned char * baseAddr)
684 {
685  uint32_t *gpuData = ((uint32_t*)baseAddr);
686  short *sgpuData = ((short *) baseAddr);
687  short sH = 8;
688  short sW = 8;
689
690  lx0 = GETLEs16(&sgpuData[2]);
691  ly0 = GETLEs16(&sgpuData[3]);
692
693  if(!(dwActFixes&8)) AdjustCoord1();
694
695  // x and y of start
696  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
697  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
698  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
699  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
700
701  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
702
703  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
704                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
705
706  bDoVSyncUpdate=TRUE;
707 }
708
709 ////////////////////////////////////////////////////////////////////////
710 // cmd: draw 16 dot Tile (medium rect)
711 ////////////////////////////////////////////////////////////////////////
712
713 static void primTile16(unsigned char * baseAddr)
714 {
715  uint32_t *gpuData = ((uint32_t*)baseAddr);
716  short *sgpuData = ((short *) baseAddr);
717  short sH = 16;
718  short sW = 16;
719
720  lx0 = GETLEs16(&sgpuData[2]);
721  ly0 = GETLEs16(&sgpuData[3]);
722
723  if(!(dwActFixes&8)) AdjustCoord1();
724
725  // x and y of start
726  ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y;
727  ly0 = ly1 = ly0    +PSXDisplay.DrawOffset.y;
728  lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x;
729  lx0 = lx3 = lx0    +PSXDisplay.DrawOffset.x;
730
731  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
732
733  FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
734                        BGR24to16(GETLE32(&gpuData[0])));          // Takes Start and Offset
735
736  bDoVSyncUpdate=TRUE;
737 }
738
739 ////////////////////////////////////////////////////////////////////////
740 // cmd: small sprite (textured rect)
741 ////////////////////////////////////////////////////////////////////////
742
743 static void primSprt8(unsigned char * baseAddr)
744 {
745  uint32_t *gpuData = ((uint32_t *) baseAddr);
746  short *sgpuData = ((short *) baseAddr);
747
748  lx0 = GETLEs16(&sgpuData[2]);
749  ly0 = GETLEs16(&sgpuData[3]);
750
751  if(!(dwActFixes&8)) AdjustCoord1();
752
753  SetRenderMode(GETLE32(&gpuData[0]));
754
755  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8);
756  else
757  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,8,8);
758  else           DrawSoftwareSprite(baseAddr,8,8,
759                                    baseAddr[8],
760                                    baseAddr[9]);
761
762  bDoVSyncUpdate=TRUE;
763 }
764
765 ////////////////////////////////////////////////////////////////////////
766 // cmd: medium sprite (textured rect)
767 ////////////////////////////////////////////////////////////////////////
768
769 static void primSprt16(unsigned char * baseAddr)
770 {
771  uint32_t *gpuData = ((uint32_t *) baseAddr);
772  short *sgpuData = ((short *) baseAddr);
773
774  lx0 = GETLEs16(&sgpuData[2]);
775  ly0 = GETLEs16(&sgpuData[3]);
776
777  if(!(dwActFixes&8)) AdjustCoord1();
778
779  SetRenderMode(GETLE32(&gpuData[0]));
780
781  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16);
782  else
783  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,16,16);
784  else           DrawSoftwareSprite(baseAddr,16,16,
785                                    baseAddr[8],
786                                    baseAddr[9]);
787
788  bDoVSyncUpdate=TRUE;
789 }
790
791 ////////////////////////////////////////////////////////////////////////
792 // cmd: free-size sprite (textured rect)
793 ////////////////////////////////////////////////////////////////////////
794
795 // func used on texture coord wrap
796 static void primSprtSRest(unsigned char * baseAddr,unsigned short type)
797 {
798  uint32_t *gpuData = ((uint32_t *) baseAddr);
799  short *sgpuData = ((short *) baseAddr);
800  unsigned short sTypeRest=0;
801
802  short s;
803  short sX = GETLEs16(&sgpuData[2]);
804  short sY = GETLEs16(&sgpuData[3]);
805  short sW = GETLEs16(&sgpuData[6]) & 0x3ff;
806  short sH = GETLEs16(&sgpuData[7]) & 0x1ff;
807  short tX = baseAddr[8];
808  short tY = baseAddr[9];
809
810  switch(type)
811   {
812    case 1:
813     s=256-baseAddr[8];
814     sW-=s;
815     sX+=s;
816     tX=0;
817     break;
818    case 2:
819     s=256-baseAddr[9];
820     sH-=s;
821     sY+=s;
822     tY=0;
823     break;
824    case 3:
825     s=256-baseAddr[8];
826     sW-=s;
827     sX+=s;
828     tX=0;
829     s=256-baseAddr[9];
830     sH-=s;
831     sY+=s;
832     tY=0;
833     break;
834    case 4:
835     s=512-baseAddr[8];
836     sW-=s;
837     sX+=s;
838     tX=0;
839     break;
840    case 5:
841     s=512-baseAddr[9];
842     sH-=s;
843     sY+=s;
844     tY=0;
845     break;
846    case 6:
847     s=512-baseAddr[8];
848     sW-=s;
849     sX+=s;
850     tX=0;
851     s=512-baseAddr[9];
852     sH-=s;
853     sY+=s;
854     tY=0;
855     break;
856   }
857
858  SetRenderMode(GETLE32(&gpuData[0]));
859
860  if(tX+sW>256) {sW=256-tX;sTypeRest+=1;}
861  if(tY+sH>256) {sH=256-tY;sTypeRest+=2;}
862
863  lx0 = sX;
864  ly0 = sY;
865
866  if(!(dwActFixes&8)) AdjustCoord1();
867
868  DrawSoftwareSprite(baseAddr,sW,sH,tX,tY);
869
870  if(sTypeRest && type<4)  
871   {
872    if(sTypeRest&1  && type==1)  primSprtSRest(baseAddr,4);
873    if(sTypeRest&2  && type==2)  primSprtSRest(baseAddr,5);
874    if(sTypeRest==3 && type==3)  primSprtSRest(baseAddr,6);
875   }
876
877 }
878                                      
879 ////////////////////////////////////////////////////////////////////////
880
881 static void primSprtS(unsigned char * baseAddr)
882 {
883  uint32_t *gpuData = ((uint32_t *) baseAddr);
884  short *sgpuData = ((short *) baseAddr);
885  short sW,sH;
886
887  lx0 = GETLEs16(&sgpuData[2]);
888  ly0 = GETLEs16(&sgpuData[3]);
889
890  if(!(dwActFixes&8)) AdjustCoord1();
891
892  sW = GETLEs16(&sgpuData[6]) & 0x3ff;
893  sH = GETLEs16(&sgpuData[7]) & 0x1ff;
894
895  SetRenderMode(GETLE32(&gpuData[0]));
896
897  if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH);
898  else
899  if(usMirror)   DrawSoftwareSpriteMirror(baseAddr,sW,sH);
900  else          
901   {
902    unsigned short sTypeRest=0;
903    short tX=baseAddr[8];
904    short tY=baseAddr[9];
905
906    if(tX+sW>256) {sW=256-tX;sTypeRest+=1;}
907    if(tY+sH>256) {sH=256-tY;sTypeRest+=2;}
908
909    DrawSoftwareSprite(baseAddr,sW,sH,tX,tY);
910
911    if(sTypeRest) 
912     {
913      if(sTypeRest&1)  primSprtSRest(baseAddr,1);
914      if(sTypeRest&2)  primSprtSRest(baseAddr,2);
915      if(sTypeRest==3) primSprtSRest(baseAddr,3);
916     }
917
918   }
919
920  bDoVSyncUpdate=TRUE;
921 }
922
923 ////////////////////////////////////////////////////////////////////////
924 // cmd: flat shaded Poly4
925 ////////////////////////////////////////////////////////////////////////
926
927 static void primPolyF4(unsigned char *baseAddr)
928 {
929  uint32_t *gpuData = ((uint32_t *) baseAddr);
930  short *sgpuData = ((short *) baseAddr);
931
932  lx0 = GETLEs16(&sgpuData[2]);
933  ly0 = GETLEs16(&sgpuData[3]);
934  lx1 = GETLEs16(&sgpuData[4]);
935  ly1 = GETLEs16(&sgpuData[5]);
936  lx2 = GETLEs16(&sgpuData[6]);
937  ly2 = GETLEs16(&sgpuData[7]);
938  lx3 = GETLEs16(&sgpuData[8]);
939  ly3 = GETLEs16(&sgpuData[9]);
940
941  if(!(dwActFixes&8)) 
942   {
943    AdjustCoord4();
944    if(CheckCoord4()) return;
945   }
946
947  offsetPSX4();
948  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
949
950  drawPoly4F(GETLE32(&gpuData[0]));
951
952  bDoVSyncUpdate=TRUE;
953 }
954
955 ////////////////////////////////////////////////////////////////////////
956 // cmd: smooth shaded Poly4
957 ////////////////////////////////////////////////////////////////////////
958
959 static void primPolyG4(unsigned char * baseAddr)
960 {
961  uint32_t *gpuData = (uint32_t *)baseAddr;
962  short *sgpuData = ((short *) baseAddr);
963
964  lx0 = GETLEs16(&sgpuData[2]);
965  ly0 = GETLEs16(&sgpuData[3]);
966  lx1 = GETLEs16(&sgpuData[6]);
967  ly1 = GETLEs16(&sgpuData[7]);
968  lx2 = GETLEs16(&sgpuData[10]);
969  ly2 = GETLEs16(&sgpuData[11]);
970  lx3 = GETLEs16(&sgpuData[14]);
971  ly3 = GETLEs16(&sgpuData[15]);
972
973  if(!(dwActFixes&8))
974   {
975    AdjustCoord4();
976    if(CheckCoord4()) return;
977   }
978
979  offsetPSX4();
980  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
981
982  drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), 
983             GETLE32(&gpuData[4]), GETLE32(&gpuData[6]));
984
985  bDoVSyncUpdate=TRUE;
986 }
987
988 ////////////////////////////////////////////////////////////////////////
989 // cmd: flat shaded Texture3
990 ////////////////////////////////////////////////////////////////////////
991
992 static void primPolyFT3(unsigned char * baseAddr)
993 {
994  uint32_t *gpuData = ((uint32_t *) baseAddr);
995  short *sgpuData = ((short *) baseAddr);
996
997  lx0 = GETLEs16(&sgpuData[2]);
998  ly0 = GETLEs16(&sgpuData[3]);
999  lx1 = GETLEs16(&sgpuData[6]);
1000  ly1 = GETLEs16(&sgpuData[7]);
1001  lx2 = GETLEs16(&sgpuData[10]);
1002  ly2 = GETLEs16(&sgpuData[11]);
1003
1004  lLowerpart=GETLE32(&gpuData[4])>>16;
1005  UpdateGlobalTP((unsigned short)lLowerpart);
1006
1007  if(!(dwActFixes&8))
1008   {
1009    AdjustCoord3();
1010    if(CheckCoord3()) return;
1011   }
1012
1013  offsetPSX3();
1014  SetRenderMode(GETLE32(&gpuData[0]));
1015
1016  drawPoly3FT(baseAddr);
1017
1018  bDoVSyncUpdate=TRUE;
1019 }
1020
1021 ////////////////////////////////////////////////////////////////////////
1022 // cmd: flat shaded Texture4
1023 ////////////////////////////////////////////////////////////////////////
1024
1025 static void primPolyFT4(unsigned char * baseAddr)
1026 {
1027  uint32_t *gpuData = ((uint32_t *) baseAddr);
1028  short *sgpuData = ((short *) baseAddr);
1029
1030  lx0 = GETLEs16(&sgpuData[2]);
1031  ly0 = GETLEs16(&sgpuData[3]);
1032  lx1 = GETLEs16(&sgpuData[6]);
1033  ly1 = GETLEs16(&sgpuData[7]);
1034  lx2 = GETLEs16(&sgpuData[10]);
1035  ly2 = GETLEs16(&sgpuData[11]);
1036  lx3 = GETLEs16(&sgpuData[14]);
1037  ly3 = GETLEs16(&sgpuData[15]);
1038
1039  lLowerpart=GETLE32(&gpuData[4])>>16;
1040  UpdateGlobalTP((unsigned short)lLowerpart);
1041
1042  if(!(dwActFixes&8))
1043   {
1044    AdjustCoord4();
1045    if(CheckCoord4()) return;
1046   }
1047
1048  offsetPSX4();
1049
1050  SetRenderMode(GETLE32(&gpuData[0]));
1051
1052  drawPoly4FT(baseAddr);
1053
1054  bDoVSyncUpdate=TRUE;
1055 }
1056
1057 ////////////////////////////////////////////////////////////////////////
1058 // cmd: smooth shaded Texture3
1059 ////////////////////////////////////////////////////////////////////////
1060
1061 static void primPolyGT3(unsigned char *baseAddr)
1062 {    
1063  uint32_t *gpuData = ((uint32_t *) baseAddr);
1064  short *sgpuData = ((short *) baseAddr);
1065
1066  lx0 = GETLEs16(&sgpuData[2]);
1067  ly0 = GETLEs16(&sgpuData[3]);
1068  lx1 = GETLEs16(&sgpuData[8]);
1069  ly1 = GETLEs16(&sgpuData[9]);
1070  lx2 = GETLEs16(&sgpuData[14]);
1071  ly2 = GETLEs16(&sgpuData[15]);
1072
1073  lLowerpart=GETLE32(&gpuData[5])>>16;
1074  UpdateGlobalTP((unsigned short)lLowerpart);
1075
1076  if(!(dwActFixes&8))
1077   {
1078    AdjustCoord3();
1079    if(CheckCoord3()) return;
1080   }
1081            
1082  offsetPSX3();
1083  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1084
1085  if(SHADETEXBIT(GETLE32(&gpuData[0])))
1086   {
1087    gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1088    gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1089    gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1090   }
1091
1092  drawPoly3GT(baseAddr);
1093
1094  bDoVSyncUpdate=TRUE;
1095 }
1096
1097 ////////////////////////////////////////////////////////////////////////
1098 // cmd: smooth shaded Poly3
1099 ////////////////////////////////////////////////////////////////////////
1100
1101 static void primPolyG3(unsigned char *baseAddr)
1102 {    
1103  uint32_t *gpuData = ((uint32_t *) baseAddr);
1104  short *sgpuData = ((short *) baseAddr);
1105
1106  lx0 = GETLEs16(&sgpuData[2]);
1107  ly0 = GETLEs16(&sgpuData[3]);
1108  lx1 = GETLEs16(&sgpuData[6]);
1109  ly1 = GETLEs16(&sgpuData[7]);
1110  lx2 = GETLEs16(&sgpuData[10]);
1111  ly2 = GETLEs16(&sgpuData[11]);
1112
1113  if(!(dwActFixes&8))
1114   {
1115    AdjustCoord3();
1116    if(CheckCoord3()) return;
1117   }
1118
1119  offsetPSX3();
1120  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1121
1122  drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4]));
1123
1124  bDoVSyncUpdate=TRUE;
1125 }
1126
1127 ////////////////////////////////////////////////////////////////////////
1128 // cmd: smooth shaded Texture4
1129 ////////////////////////////////////////////////////////////////////////
1130
1131 static void primPolyGT4(unsigned char *baseAddr)
1132
1133  uint32_t *gpuData = ((uint32_t *) baseAddr);
1134  short *sgpuData = ((short *) baseAddr);
1135
1136  lx0 = GETLEs16(&sgpuData[2]);
1137  ly0 = GETLEs16(&sgpuData[3]);
1138  lx1 = GETLEs16(&sgpuData[8]);
1139  ly1 = GETLEs16(&sgpuData[9]);
1140  lx2 = GETLEs16(&sgpuData[14]);
1141  ly2 = GETLEs16(&sgpuData[15]);
1142  lx3 = GETLEs16(&sgpuData[20]);
1143  ly3 = GETLEs16(&sgpuData[21]);
1144
1145  lLowerpart=GETLE32(&gpuData[5])>>16;
1146  UpdateGlobalTP((unsigned short)lLowerpart);
1147
1148  if(!(dwActFixes&8))
1149   {
1150    AdjustCoord4();
1151    if(CheckCoord4()) return;
1152   }
1153
1154  offsetPSX4();
1155  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1156
1157  if(SHADETEXBIT(GETLE32(&gpuData[0])))
1158   {
1159    gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1160    gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1161    gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1162    gpuData[9] = (gpuData[9]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080);
1163   }
1164
1165  drawPoly4GT(baseAddr);
1166
1167  bDoVSyncUpdate=TRUE;
1168 }
1169
1170 ////////////////////////////////////////////////////////////////////////
1171 // cmd: smooth shaded Poly3
1172 ////////////////////////////////////////////////////////////////////////
1173
1174 static void primPolyF3(unsigned char *baseAddr)
1175 {    
1176  uint32_t *gpuData = ((uint32_t *) baseAddr);
1177  short *sgpuData = ((short *) baseAddr);
1178
1179  lx0 = GETLEs16(&sgpuData[2]);
1180  ly0 = GETLEs16(&sgpuData[3]);
1181  lx1 = GETLEs16(&sgpuData[4]);
1182  ly1 = GETLEs16(&sgpuData[5]);
1183  lx2 = GETLEs16(&sgpuData[6]);
1184  ly2 = GETLEs16(&sgpuData[7]);
1185
1186  if(!(dwActFixes&8))
1187   {
1188    AdjustCoord3();
1189    if(CheckCoord3()) return;
1190   }
1191
1192  offsetPSX3();
1193  SetRenderMode(GETLE32(&gpuData[0]));
1194
1195  drawPoly3F(GETLE32(&gpuData[0]));
1196
1197  bDoVSyncUpdate=TRUE;
1198 }
1199
1200 ////////////////////////////////////////////////////////////////////////
1201 // cmd: skipping shaded polylines
1202 ////////////////////////////////////////////////////////////////////////
1203
1204 static void primLineGSkip(unsigned char *baseAddr)
1205 {    
1206  uint32_t *gpuData = ((uint32_t *) baseAddr);
1207  int iMax=255;
1208  int i=2;
1209
1210  ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1211  lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1212
1213  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4))
1214   {
1215    i++;
1216    ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1217    lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1218    i++;if(i>iMax) break;
1219   }
1220 }
1221
1222 ////////////////////////////////////////////////////////////////////////
1223 // cmd: shaded polylines
1224 ////////////////////////////////////////////////////////////////////////
1225
1226 static void primLineGEx(unsigned char *baseAddr)
1227 {    
1228  uint32_t *gpuData = ((uint32_t *) baseAddr);
1229  int iMax=255;
1230  uint32_t lc0,lc1;
1231  short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE;
1232
1233  sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1234  slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1235
1236  if(!(dwActFixes&8)) 
1237   {
1238    slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1239    sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1240   }
1241
1242  lc1 = gpuData[0] & 0xffffff;
1243
1244  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1245
1246  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4))
1247   {
1248    sly0=sly1; slx0=slx1; lc0=lc1;
1249    lc1=GETLE32(&gpuData[i]) & 0xffffff;
1250
1251    i++;
1252
1253    // no check needed on gshaded polyline positions
1254    // if((gpuData[i] & 0xF000F000) == 0x50005000) break;
1255
1256    sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1257    slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1258
1259    if(!(dwActFixes&8))
1260     {
1261      slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1262      sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1263      if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE;
1264     }
1265
1266    if ((lx0 != lx1) || (ly0 != ly1))
1267     {
1268      ly0=sly0;
1269      lx0=slx0;
1270      ly1=sly1;
1271      lx1=slx1;
1272               
1273      offsetPSX2();
1274      if(bDraw) DrawSoftwareLineShade(lc0, lc1);
1275     }
1276    i++;  
1277    if(i>iMax) break;
1278   }
1279
1280  bDoVSyncUpdate=TRUE;
1281 }
1282
1283 ////////////////////////////////////////////////////////////////////////
1284 // cmd: shaded polyline2
1285 ////////////////////////////////////////////////////////////////////////
1286
1287 static void primLineG2(unsigned char *baseAddr)
1288 {    
1289  uint32_t *gpuData = ((uint32_t *) baseAddr);
1290  short *sgpuData = ((short *) baseAddr);
1291
1292  lx0 = GETLEs16(&sgpuData[2]);
1293  ly0 = GETLEs16(&sgpuData[3]);
1294  lx1 = GETLEs16(&sgpuData[6]);
1295  ly1 = GETLEs16(&sgpuData[7]);
1296
1297  if(!(dwActFixes&8))
1298   {
1299    AdjustCoord2();
1300    if(CheckCoord2()) return;
1301   }
1302
1303  if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;}
1304
1305  DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE;
1306  offsetPSX2();
1307  DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2]));
1308
1309  bDoVSyncUpdate=TRUE;
1310 }
1311
1312 ////////////////////////////////////////////////////////////////////////
1313 // cmd: skipping flat polylines
1314 ////////////////////////////////////////////////////////////////////////
1315
1316 static void primLineFSkip(unsigned char *baseAddr)
1317 {
1318  uint32_t *gpuData = ((uint32_t *) baseAddr);
1319  int i=2,iMax=255;
1320
1321  ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1322  lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1323
1324  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3))
1325   {
1326    ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1327    lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1328    i++;if(i>iMax) break;
1329   }             
1330 }
1331
1332 ////////////////////////////////////////////////////////////////////////
1333 // cmd: drawing flat polylines
1334 ////////////////////////////////////////////////////////////////////////
1335
1336 static void primLineFEx(unsigned char *baseAddr)
1337 {
1338  uint32_t *gpuData = ((uint32_t *) baseAddr);
1339  int iMax;
1340  short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE;
1341
1342  iMax=255;
1343
1344  sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff);
1345  slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff);
1346  if(!(dwActFixes&8))
1347   {
1348    slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1349    sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1350   }
1351
1352  SetRenderMode(GETLE32(&gpuData[0]));
1353
1354  while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3))
1355   {
1356    sly0 = sly1;slx0=slx1;
1357    sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff);
1358    slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff);
1359    if(!(dwActFixes&8))
1360     {
1361      slx1=(short)(((int)slx1<<SIGNSHIFT)>>SIGNSHIFT);
1362      sly1=(short)(((int)sly1<<SIGNSHIFT)>>SIGNSHIFT);
1363
1364      if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE;
1365     }
1366
1367    ly0=sly0;
1368    lx0=slx0;
1369    ly1=sly1;
1370    lx1=slx1;
1371
1372    offsetPSX2();
1373    if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0]));
1374
1375    i++;if(i>iMax) break;
1376   }
1377
1378  bDoVSyncUpdate=TRUE;
1379 }
1380
1381 ////////////////////////////////////////////////////////////////////////
1382 // cmd: drawing flat polyline2
1383 ////////////////////////////////////////////////////////////////////////
1384
1385 static void primLineF2(unsigned char *baseAddr)
1386 {
1387  uint32_t *gpuData = ((uint32_t *) baseAddr);
1388  short *sgpuData = ((short *) baseAddr);
1389
1390  lx0 = GETLEs16(&sgpuData[2]);
1391  ly0 = GETLEs16(&sgpuData[3]);
1392  lx1 = GETLEs16(&sgpuData[4]);
1393  ly1 = GETLEs16(&sgpuData[5]);
1394
1395  if(!(dwActFixes&8))
1396   {
1397    AdjustCoord2();
1398    if(CheckCoord2()) return;
1399   }
1400
1401  if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;}
1402                     
1403  offsetPSX2();
1404  SetRenderMode(GETLE32(&gpuData[0]));
1405
1406  DrawSoftwareLineFlat(GETLE32(&gpuData[0]));
1407
1408  bDoVSyncUpdate=TRUE;
1409 }
1410
1411 ////////////////////////////////////////////////////////////////////////
1412 // cmd: well, easiest command... not implemented
1413 ////////////////////////////////////////////////////////////////////////
1414
1415 static void primNI(unsigned char *bA)
1416 {
1417 }
1418
1419 ////////////////////////////////////////////////////////////////////////
1420 // cmd func ptr table
1421 ////////////////////////////////////////////////////////////////////////
1422
1423
1424 void (*primTableJ[256])(unsigned char *) = 
1425 {
1426     // 00
1427     primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI,
1428     // 08
1429     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1430     // 10
1431     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1432     // 18
1433     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1434     // 20
1435     primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3,
1436     // 28
1437     primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4,
1438     // 30
1439     primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3,
1440     // 38
1441     primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4,
1442     // 40
1443     primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI,
1444     // 48
1445     primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,
1446     // 50
1447     primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI,
1448     // 58
1449     primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,
1450     // 60
1451     primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS,
1452     // 68
1453     primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI,
1454     // 70
1455     primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8,
1456     // 78
1457     primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16,
1458     // 80
1459     primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1460     // 88
1461     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1462     // 90
1463     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1464     // 98
1465     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1466     // a0
1467     primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1468     // a8
1469     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1470     // b0
1471     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1472     // b8
1473     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1474     // c0
1475     primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1476     // c8
1477     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1478     // d0
1479     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1480     // d8
1481     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1482     // e0
1483     primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI,
1484     // e8
1485     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1486     // f0
1487     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1488     // f8
1489     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI
1490 };
1491
1492 ////////////////////////////////////////////////////////////////////////
1493 // cmd func ptr table for skipping
1494 ////////////////////////////////////////////////////////////////////////
1495
1496 void (*primTableSkip[256])(unsigned char *) = 
1497 {
1498     // 00
1499     primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI,
1500     // 08
1501     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1502     // 10
1503     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1504     // 18
1505     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1506     // 20
1507     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1508     // 28
1509     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1510     // 30
1511     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1512     // 38
1513     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1514     // 40
1515     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1516     // 48
1517     primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,
1518     // 50
1519     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1520     // 58
1521     primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,
1522     // 60
1523     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1524     // 68
1525     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1526     // 70
1527     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1528     // 78
1529     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1530     // 80
1531     primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1532     // 88
1533     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1534     // 90
1535     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1536     // 98
1537     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1538     // a0
1539     primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1540     // a8
1541     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1542     // b0
1543     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1544     // b8
1545     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1546     // c0
1547     primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1548     // c8
1549     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1550     // d0
1551     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1552     // d8
1553     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1554     // e0
1555     primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI,
1556     // e8
1557     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1558     // f0
1559     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI,
1560     // f8
1561     primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI
1562 };