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