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