1 /******************************************************************************/
2 /* Mednafen Sony PS1 Emulation Module                                         */
3 /******************************************************************************/
4 /* gte.cpp:
5 **  Copyright (C) 2011-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 
22 #pragma GCC optimize ("no-unroll-loops,no-peel-loops")
23 
24 #ifndef PSXDEV_GTE_TESTING
25 #include "psx.h"
26 #include "gte.h"
27 #endif
28 
29 /* Notes:
30 
31  AVSZ3/AVSZ4:
32 	OTZ is MAC0 >> 12
33 	OTZ overflow/underflow flag is set in an overflow condition even if MAC0 == 0.
34 	sf field bit has no effect?
35 
36  FLAG register:
37 	Bits present mask: 0xfffff000
38 
39 	Checksum bit can't be directly set, it's apparently calculated like (bool)(FLAGS & 0x7f87e000)
40 
41 	Instructions effectively clear it 0 at start. (todo: test "invalid" instructions)
42 
43  X/Y FIFO [3] register write pushes a copy down to [2]
44 
45 */
46 
47 #ifndef PSXDEV_GTE_TESTING
48 namespace MDFN_IEN_PSX
49 {
50 #endif
51 
52 typedef struct
53 {
54  int16 MX[3][3];
55  int16 dummy;
56 } gtematrix;
57 #ifndef PSXDEV_GTE_TESTING
58 static_assert(sizeof(gtematrix) == 20, "gtematrix wrong size!");
59 #endif
60 
61 typedef struct
62 {
63  union
64  {
65   struct
66   {
67    uint8 R;
68    uint8 G;
69    uint8 B;
70    uint8 CD;
71   };
72   uint8 Raw8[4];
73  };
74 } gtergb;
75 
76 typedef struct
77 {
78  int16 X;
79  int16 Y;
80 } gtexy;
81 
82 static uint32 CR[32];
83 static uint32 FLAGS;	// Temporary for instruction execution, copied into CR[31] at end of instruction execution.
84 
85 typedef union
86 {
87  gtematrix All[4];
88  int32 Raw[4][5];	// Don't read from this(Raw[][]), only write(and when writing, if running on a big-endian platform, swap the upper 16-bits with the lower 16-bits)
89  int16 Raw16[4][10];
90 
91  struct
92  {
93   gtematrix Rot;
94   gtematrix Light;
95   gtematrix Color;
96   gtematrix AbbyNormal;
97  };
98 } Matrices_t;
99 
100 static Matrices_t Matrices;
101 
102 static union
103 {
104  int32 All[4][4];	// Really only [4][3], but [4] to ease address calculation.
105 
106  struct
107  {
108   int32 T[4];
109   int32 B[4];
110   int32 FC[4];
111   int32 Null[4];
112  };
113 } CRVectors;
114 
115 static int32 OFX;
116 static int32 OFY;
117 static uint16 H;
118 static int16 DQA;
119 static int32 DQB;
120 
121 static int16 ZSF3;
122 static int16 ZSF4;
123 
124 
125 // Begin DR
126 static int16 Vectors[3][4];
127 static gtergb RGB;
128 static uint16 OTZ;
129 
130 static int16 IR[4];
131 
132 #define IR0 IR[0]
133 #define IR1 IR[1]
134 #define IR2 IR[2]
135 #define IR3 IR[3]
136 
137 static gtexy XY_FIFO[4];
138 static uint16 Z_FIFO[4];
139 static gtergb RGB_FIFO[3];
140 static int32 MAC[4];
141 static uint32 LZCS;
142 static uint32 LZCR;
143 
144 static uint32 Reg23;
145 // end DR
146 
Sat5(int16 cc)147 static INLINE uint8 Sat5(int16 cc)
148 {
149  if(cc < 0)
150   cc = 0;
151  if(cc > 0x1F)
152   cc = 0x1F;
153  return(cc);
154 }
155 
156 //
157 // Newton-Raphson division table.  (Initialized at startup; do NOT save in save states!)
158 //
159 static uint8 DivTable[0x100 + 1];
CalcRecip(uint16 divisor)160 static INLINE uint32 CalcRecip(uint16 divisor)
161 {
162  int32 x = (0x101 + DivTable[(((divisor & 0x7FFF) + 0x40) >> 7)]);
163  int32 tmp = (((int32)divisor * -x) + 0x80) >> 8;
164  int32 tmp2 = ((x * (131072 + tmp)) + 0x80) >> 8;
165 
166  return(tmp2);
167 }
168 
GTE_Init(void)169 void GTE_Init(void)
170 {
171  for(uint32_t divisor = 0x8000; divisor < 0x10000; divisor += 0x80)
172  {
173   uint32_t xa = 512;
174 
175   for(unsigned i = 1; i < 5; i++)
176   {
177    xa = (xa * (1024 * 512 - ((divisor >> 7) * xa))) >> 18;
178   }
179 
180   DivTable[(divisor >> 7) & 0xFF] = ((xa + 1) >> 1) - 0x101;
181   //printf("%04x, %02x\n", divisor, ((xa + 1) >> 1) - 0x101);
182  }
183 
184  //
185  // To avoid a bounds limiting if statement in the emulation code:
186  DivTable[0x100] = DivTable[0xFF];
187 }
188 
GTE_Power(void)189 void GTE_Power(void)
190 {
191  memset(CR, 0, sizeof(CR));
192  //memset(DR, 0, sizeof(DR));
193 
194  memset(Matrices.All, 0, sizeof(Matrices.All));
195  memset(CRVectors.All, 0, sizeof(CRVectors.All));
196  OFX = 0;
197  OFY = 0;
198  H = 0;
199  DQA = 0;
200  DQB = 0;
201  ZSF3 = 0;
202  ZSF4 = 0;
203 
204 
205  memset(Vectors, 0, sizeof(Vectors));
206  memset(&RGB, 0, sizeof(RGB));
207  OTZ = 0;
208  IR0 = 0;
209  IR1 = 0;
210  IR2 = 0;
211  IR3 = 0;
212 
213  memset(XY_FIFO, 0, sizeof(XY_FIFO));
214  memset(Z_FIFO, 0, sizeof(Z_FIFO));
215  memset(RGB_FIFO, 0, sizeof(RGB_FIFO));
216  memset(MAC, 0, sizeof(MAC));
217  LZCS = 0;
218  LZCR = 0;
219 
220  Reg23 = 0;
221 }
222 
223 // TODO: Don't save redundant state, regarding CR cache variables
GTE_StateAction(StateMem * sm,const unsigned load,const bool data_only)224 void GTE_StateAction(StateMem *sm, const unsigned load, const bool data_only)
225 {
226  SFORMAT StateRegs[] =
227  {
228   SFVAR(CR),
229   SFVAR(FLAGS),
230 
231   SFVARN(Matrices.Raw16, "&Matrices.Raw16[0][0]"),
232 
233   SFVARN(CRVectors.All, "&CRVectors.All[0][0]"),
234 
235   SFVAR(OFX),
236   SFVAR(OFY),
237   SFVAR(H),
238   SFVAR(DQA),
239   SFVAR(DQB),
240 
241   SFVAR(ZSF3),
242   SFVAR(ZSF4),
243   SFVARN(Vectors, "&Vectors[0][0]"),
244 
245   SFVAR(RGB.Raw8),
246   SFVAR(OTZ),
247   SFVAR(IR),
248 
249   SFVAR(XY_FIFO[0].X),
250   SFVAR(XY_FIFO[0].Y),
251   SFVAR(XY_FIFO[1].X),
252   SFVAR(XY_FIFO[1].Y),
253   SFVAR(XY_FIFO[2].X),
254   SFVAR(XY_FIFO[2].Y),
255   SFVAR(XY_FIFO[3].X),
256   SFVAR(XY_FIFO[3].Y),
257 
258   SFVAR(Z_FIFO),
259 
260   SFVAR(RGB_FIFO[0].Raw8),
261   SFVAR(RGB_FIFO[1].Raw8),
262   SFVAR(RGB_FIFO[2].Raw8),
263 
264   SFVAR(MAC),
265 
266   SFVAR(LZCS),
267   SFVAR(LZCR),
268   SFVAR(Reg23),
269 
270   SFEND
271  };
272 
273  MDFNSS_StateAction(sm, load, data_only, StateRegs, "GTE");
274 
275  if(load)
276  {
277 
278  }
279 }
280 
281 
GTE_WriteCR(unsigned int which,uint32 value)282 void GTE_WriteCR(unsigned int which, uint32 value)
283 {
284  static const uint32 mask_table[32] = {
285 	/* 0x00 */
286 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
287 
288 	/* 0x08 */
289 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
290 
291 	/* 0x10 */
292 	0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
293 
294 	/* 0x18 */
295 	0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF, 0x0000FFFF, 0x0000FFFF, 0xFFFFFFFF
296  };
297 
298  //PSX_WARNING("[GTE] Write CR %d, 0x%08x", which, value);
299 
300  value &= mask_table[which];
301 
302  CR[which] = value | (CR[which] & ~mask_table[which]);
303 
304  if(which < 24)
305  {
306   int we = which >> 3;
307   which &= 0x7;
308 
309   if(which >= 5)
310    CRVectors.All[we][which - 5] = value;
311   else
312   {
313    #ifdef MSB_FIRST
314    Matrices.Raw[we][which] = (value << 16) | (value >> 16);
315    #else
316    Matrices.Raw[we][which] = value;
317    #endif
318   }
319   return;
320  }
321 
322  switch(which)
323  {
324   case 24:
325 	OFX = value;
326 	break;
327 
328   case 25:
329 	OFY = value;
330 	break;
331 
332   case 26:
333 	H = value;
334 	break;
335 
336   case 27:
337 	DQA = value;
338 	break;
339 
340   case 28:
341 	DQB = value;
342 	break;
343 
344   case 29:
345 	ZSF3 = value;
346 	break;
347 
348   case 30:
349 	ZSF4 = value;
350 	break;
351 
352   case 31:
353 	CR[31] = (value & 0x7ffff000) | ((value & 0x7f87e000) ? (1 << 31) : 0);
354 	break;
355  }
356 }
357 
GTE_ReadCR(unsigned int which)358 uint32 GTE_ReadCR(unsigned int which)
359 {
360  uint32 ret = 0;
361 
362  switch(which)
363  {
364   default:
365 	ret = CR[which];
366 	if(which == 4 || which == 12 || which == 20)
367 	 ret = (int16)ret;
368 	break;
369 
370   case 24:
371 	ret = OFX;
372 	break;
373 
374   case 25:
375 	ret = OFY;
376 	break;
377 
378   case 26:
379 	ret = (int16)H;
380 	break;
381 
382   case 27:
383 	ret = (int16)DQA;
384 	break;
385 
386   case 28:
387 	ret = DQB;
388 	break;
389 
390   case 29:
391 	ret = (int16)ZSF3;
392 	break;
393 
394   case 30:
395 	ret = (int16)ZSF4;
396 	break;
397 
398   case 31:
399 	ret = CR[31];
400 	break;
401  }
402 
403  return(ret);
404 }
405 
GTE_WriteDR(unsigned int which,uint32 value)406 void GTE_WriteDR(unsigned int which, uint32 value)
407 {
408  switch(which & 0x1F)
409  {
410   case 0:
411 	Vectors[0][0] = value;
412 	Vectors[0][1] = value >> 16;
413 	break;
414 
415   case 1:
416 	Vectors[0][2] = value;
417 	break;
418 
419   case 2:
420 	Vectors[1][0] = value;
421 	Vectors[1][1] = value >> 16;
422 	break;
423 
424   case 3:
425 	Vectors[1][2] = value;
426 	break;
427 
428   case 4:
429 	Vectors[2][0] = value;
430 	Vectors[2][1] = value >> 16;
431 	break;
432 
433   case 5:
434 	Vectors[2][2] = value;
435 	break;
436 
437   case 6:
438 	RGB.R = value >> 0;
439 	RGB.G = value >> 8;
440 	RGB.B = value >> 16;
441 	RGB.CD = value >> 24;
442 	break;
443 
444   case 7:
445 	OTZ = value;
446 	break;
447 
448   case 8:
449 	IR0 = value;
450 	break;
451 
452   case 9:
453 	IR1 = value;
454 	break;
455 
456   case 10:
457 	IR2 = value;
458 	break;
459 
460   case 11:
461 	IR3 = value;
462 	break;
463 
464   case 12:
465 	XY_FIFO[0].X = value;
466 	XY_FIFO[0].Y = value >> 16;
467 	break;
468 
469   case 13:
470 	XY_FIFO[1].X = value;
471 	XY_FIFO[1].Y = value >> 16;
472 	break;
473 
474   case 14:
475 	XY_FIFO[2].X = value;
476 	XY_FIFO[2].Y = value >> 16;
477 	XY_FIFO[3].X = value;
478 	XY_FIFO[3].Y = value >> 16;
479 	break;
480 
481   case 15:
482 	XY_FIFO[3].X = value;
483 	XY_FIFO[3].Y = value >> 16;
484 
485 	XY_FIFO[0] = XY_FIFO[1];
486 	XY_FIFO[1] = XY_FIFO[2];
487 	XY_FIFO[2] = XY_FIFO[3];
488 	break;
489 
490   case 16:
491 	Z_FIFO[0] = value;
492 	break;
493 
494   case 17:
495 	Z_FIFO[1] = value;
496 	break;
497 
498   case 18:
499 	Z_FIFO[2] = value;
500 	break;
501 
502   case 19:
503 	Z_FIFO[3] = value;
504 	break;
505 
506   case 20:
507 	RGB_FIFO[0].R = value;
508 	RGB_FIFO[0].G = value >> 8;
509 	RGB_FIFO[0].B = value >> 16;
510 	RGB_FIFO[0].CD = value >> 24;
511 	break;
512 
513   case 21:
514 	RGB_FIFO[1].R = value;
515 	RGB_FIFO[1].G = value >> 8;
516 	RGB_FIFO[1].B = value >> 16;
517 	RGB_FIFO[1].CD = value >> 24;
518 	break;
519 
520   case 22:
521 	RGB_FIFO[2].R = value;
522 	RGB_FIFO[2].G = value >> 8;
523 	RGB_FIFO[2].B = value >> 16;
524 	RGB_FIFO[2].CD = value >> 24;
525 	break;
526 
527   case 23:
528 	Reg23 = value;
529 	break;
530 
531   case 24:
532 	MAC[0] = value;
533 	break;
534 
535   case 25:
536 	MAC[1] = value;
537 	break;
538 
539   case 26:
540 	MAC[2] = value;
541 	break;
542 
543   case 27:
544 	MAC[3] = value;
545 	break;
546 
547   case 28:
548 	IR1 = ((value >> 0) & 0x1F) << 7;
549 	IR2 = ((value >> 5) & 0x1F) << 7;
550 	IR3 = ((value >> 10) & 0x1F) << 7;
551 	break;
552 
553   case 29:	// Read-only
554 	break;
555 
556   case 30:
557 	LZCS = value;
558 	LZCR = MDFN_lzcount32(value ^ ((int32)value >> 31));
559 	break;
560 
561   case 31:	// Read-only
562 	break;
563  }
564 }
565 
GTE_ReadDR(unsigned int which)566 uint32 GTE_ReadDR(unsigned int which)
567 {
568  uint32 ret = 0;
569 
570  switch(which & 0x1F)
571  {
572   case 0:
573 	ret = (uint16)Vectors[0][0] | ((uint16)Vectors[0][1] << 16);
574 	break;
575 
576   case 1:
577 	ret = (int16)Vectors[0][2];
578 	break;
579 
580   case 2:
581 	ret = (uint16)Vectors[1][0] | ((uint16)Vectors[1][1] << 16);
582 	break;
583 
584   case 3:
585 	ret = (int16)Vectors[1][2];
586 	break;
587 
588   case 4:
589 	ret = (uint16)Vectors[2][0] | ((uint16)Vectors[2][1] << 16);
590 	break;
591 
592   case 5:
593 	ret = (int16)Vectors[2][2];
594 	break;
595 
596   case 6:
597 	ret = RGB.R | (RGB.G << 8) | (RGB.B << 16) | (RGB.CD << 24);
598 	break;
599 
600   case 7:
601 	ret = (uint16)OTZ;
602 	break;
603 
604   case 8:
605 	ret = (int16)IR0;
606 	break;
607 
608   case 9:
609 	ret = (int16)IR1;
610 	break;
611 
612   case 10:
613 	ret = (int16)IR2;
614 	break;
615 
616   case 11:
617 	ret = (int16)IR3;
618 	break;
619 
620   case 12:
621 	ret = (uint16)XY_FIFO[0].X | ((uint16)XY_FIFO[0].Y << 16);
622 	break;
623 
624   case 13:
625 	ret = (uint16)XY_FIFO[1].X | ((uint16)XY_FIFO[1].Y << 16);
626 	break;
627 
628   case 14:
629 	ret = (uint16)XY_FIFO[2].X | ((uint16)XY_FIFO[2].Y << 16);
630 	break;
631 
632   case 15:
633 	ret = (uint16)XY_FIFO[3].X | ((uint16)XY_FIFO[3].Y << 16);
634 	break;
635 
636   case 16:
637 	ret = (uint16)Z_FIFO[0];
638 	break;
639 
640   case 17:
641 	ret = (uint16)Z_FIFO[1];
642 	break;
643 
644   case 18:
645 	ret = (uint16)Z_FIFO[2];
646 	break;
647 
648   case 19:
649 	ret = (uint16)Z_FIFO[3];
650 	break;
651 
652   case 20:
653 	ret = RGB_FIFO[0].R | (RGB_FIFO[0].G << 8) | (RGB_FIFO[0].B << 16) | (RGB_FIFO[0].CD << 24);
654 	break;
655 
656   case 21:
657 	ret = RGB_FIFO[1].R | (RGB_FIFO[1].G << 8) | (RGB_FIFO[1].B << 16) | (RGB_FIFO[1].CD << 24);
658 	break;
659 
660   case 22:
661 	ret = RGB_FIFO[2].R | (RGB_FIFO[2].G << 8) | (RGB_FIFO[2].B << 16) | (RGB_FIFO[2].CD << 24);
662 	break;
663 
664   case 23:
665 	ret = Reg23;
666 	break;
667 
668   case 24:
669 	ret = MAC[0];
670 	break;
671 
672   case 25:
673 	ret = MAC[1];
674 	break;
675 
676   case 26:
677 	ret = MAC[2];
678 	break;
679 
680   case 27:
681 	ret = MAC[3];
682 	break;
683 
684   case 28:
685   case 29:
686 	ret = Sat5(IR1 >> 7) | (Sat5(IR2 >> 7) << 5) | (Sat5(IR3 >> 7) << 10);
687 	break;
688 
689   case 30:
690 	ret = LZCS;
691 	break;
692 
693   case 31:
694 	ret = LZCR;
695 	break;
696  }
697  return(ret);
698 }
699 
700 #define sign_x_to_s64(_bits, _value) (((int64)((uint64)(_value) << (64 - _bits))) >> (64 - _bits))
A_MV(unsigned which,int64 value)701 static INLINE int64 A_MV(unsigned which, int64 value)
702 {
703  if(value >= (1LL << 43))
704   FLAGS |= 1 << (30 - which);
705 
706  if(value < -(1LL << 43))
707   FLAGS |= 1 << (27 - which);
708 
709  return sign_x_to_s64(44, value);
710 }
711 
F(int64 value)712 static INLINE int64 F(int64 value)
713 {
714  if(value < -2147483648LL)
715  {
716   // flag set here
717   FLAGS |= 1 << 15;
718  }
719 
720  if(value > 2147483647LL)
721  {
722   // flag set here
723   FLAGS |= 1 << 16;
724  }
725  return(value);
726 }
727 
728 
Lm_B(unsigned int which,int32 value,int lm)729 static INLINE int16 Lm_B(unsigned int which, int32 value, int lm)
730 {
731  int32 tmp = lm << 15;
732 
733  if(value < (-32768 + tmp))
734  {
735   // set flag here
736   FLAGS |= 1 << (24 - which);
737   value = -32768 + tmp;
738  }
739 
740  if(value > 32767)
741  {
742   // Set flag here
743   FLAGS |= 1 << (24 - which);
744   value = 32767;
745  }
746 
747  return(value);
748 }
749 
750 
Lm_B_PTZ(unsigned int which,int32 value,int32 ftv_value,int lm)751 static INLINE int16 Lm_B_PTZ(unsigned int which, int32 value, int32 ftv_value, int lm)
752 {
753  int32 tmp = lm << 15;
754 
755  if(ftv_value < -32768)
756  {
757   FLAGS |= 1 << (24 - which);
758  }
759 
760  if(ftv_value > 32767)
761  {
762   FLAGS |= 1 << (24 - which);
763  }
764 
765  if(value < (-32768 + tmp))
766  {
767   value = -32768 + tmp;
768  }
769 
770  if(value > 32767)
771  {
772   value = 32767;
773  }
774 
775  return(value);
776 }
777 
Lm_C(unsigned int which,int32 value)778 static INLINE uint8 Lm_C(unsigned int which, int32 value)
779 {
780  if(value & ~0xFF)
781  {
782   // Set flag here
783   FLAGS |= 1 << (21 - which);	// Tested with GPF
784 
785   if(value < 0)
786    value = 0;
787 
788   if(value > 255)
789    value = 255;
790  }
791 
792  return(value);
793 }
794 
Lm_D(int32 value,int unchained)795 static INLINE int32 Lm_D(int32 value, int unchained)
796 {
797  // Not sure if we should have it as int64, or just chain on to and special case when the F flags are set.
798  if(!unchained)
799  {
800   if(FLAGS & (1 << 15))
801   {
802    FLAGS |= 1 << 18;
803    return(0);
804   }
805 
806   if(FLAGS & (1 << 16))
807   {
808    FLAGS |= 1 << 18;
809    return(0xFFFF);
810   }
811  }
812 
813  if(value < 0)
814  {
815   // Set flag here
816   value = 0;
817   FLAGS |= 1 << 18;	// Tested with AVSZ3
818  }
819  else if(value > 65535)
820  {
821   // Set flag here.
822   value = 65535;
823   FLAGS |= 1 << 18;	// Tested with AVSZ3
824  }
825 
826  return(value);
827 }
828 
Lm_G(unsigned int which,int32 value)829 static INLINE int32 Lm_G(unsigned int which, int32 value)
830 {
831  if(value < -1024)
832  {
833   // Set flag here
834   value = -1024;
835   FLAGS |= 1 << (14 - which);
836  }
837 
838  if(value > 1023)
839  {
840   // Set flag here.
841   value = 1023;
842   FLAGS |= 1 << (14 - which);
843  }
844 
845  return(value);
846 }
847 
848 // limit to 4096, not 4095
Lm_H(int32 value)849 static INLINE int32 Lm_H(int32 value)
850 {
851  if(value < 0)
852  {
853   value = 0;
854   FLAGS |= 1 << 12;
855  }
856 
857  if(value > 4096)
858  {
859   value = 4096;
860   FLAGS |= 1 << 12;
861  }
862 
863  return(value);
864 }
865 
MAC_to_RGB_FIFO(void)866 static INLINE void MAC_to_RGB_FIFO(void)
867 {
868  RGB_FIFO[0] = RGB_FIFO[1];
869  RGB_FIFO[1] = RGB_FIFO[2];
870  RGB_FIFO[2].R = Lm_C(0, MAC[1] >> 4);
871  RGB_FIFO[2].G = Lm_C(1, MAC[2] >> 4);
872  RGB_FIFO[2].B = Lm_C(2, MAC[3] >> 4);
873  RGB_FIFO[2].CD = RGB.CD;
874 }
875 
876 
MAC_to_IR(int lm)877 static INLINE void MAC_to_IR(int lm)
878 {
879  IR1 = Lm_B(0, MAC[1], lm);
880  IR2 = Lm_B(1, MAC[2], lm);
881  IR3 = Lm_B(2, MAC[3], lm);
882 }
883 
MultiplyMatrixByVector(const gtematrix * matrix,const int16 * v,const int32 * crv,uint32 sf,int lm)884 static INLINE void MultiplyMatrixByVector(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm)
885 {
886  unsigned i;
887 
888  for(i = 0; i < 3; i++)
889  {
890   int64 tmp;
891   int32 mulr[3];
892 
893   tmp = (uint64)(int64)crv[i] << 12;
894 
895   if(matrix == &Matrices.AbbyNormal)
896   {
897    if(i == 0)
898    {
899     mulr[0] = -((RGB.R << 4) * v[0]);
900     mulr[1] = (RGB.R << 4) * v[1];
901     mulr[2] = IR0 * v[2];
902    }
903    else
904    {
905     mulr[0] = (int16)CR[i] * v[0];
906     mulr[1] = (int16)CR[i] * v[1];
907     mulr[2] = (int16)CR[i] * v[2];
908    }
909   }
910   else
911   {
912    mulr[0] = matrix->MX[i][0] * v[0];
913    mulr[1] = matrix->MX[i][1] * v[1];
914    mulr[2] = matrix->MX[i][2] * v[2];
915   }
916 
917   tmp = A_MV(i, tmp + mulr[0]);
918   if(crv == CRVectors.FC)
919   {
920    Lm_B(i, tmp >> sf, false);
921    tmp = 0;
922   }
923 
924   tmp = A_MV(i, tmp + mulr[1]);
925   tmp = A_MV(i, tmp + mulr[2]);
926 
927   MAC[1 + i] = tmp >> sf;
928  }
929 
930 
931  MAC_to_IR(lm);
932 }
933 
934 
MultiplyMatrixByVector_PT(const gtematrix * matrix,const int16 * v,const int32 * crv,uint32 sf,int lm)935 static INLINE void MultiplyMatrixByVector_PT(const gtematrix *matrix, const int16 *v, const int32 *crv, uint32 sf, int lm)
936 {
937  int64 tmp[3];
938  unsigned i;
939 
940  for(i = 0; i < 3; i++)
941  {
942   int32 mulr[3];
943 
944   tmp[i] = (uint64)(int64)crv[i] << 12;
945 
946   mulr[0] = matrix->MX[i][0] * v[0];
947   mulr[1] = matrix->MX[i][1] * v[1];
948   mulr[2] = matrix->MX[i][2] * v[2];
949 
950   tmp[i] = A_MV(i, tmp[i] + mulr[0]);
951   tmp[i] = A_MV(i, tmp[i] + mulr[1]);
952   tmp[i] = A_MV(i, tmp[i] + mulr[2]);
953 
954   MAC[1 + i] = tmp[i] >> sf;
955  }
956 
957  IR1 = Lm_B(0, MAC[1], lm);
958  IR2 = Lm_B(1, MAC[2], lm);
959  //printf("FTV: %08x %08x\n", crv[2], (uint32)(tmp[2] >> 12));
960  IR3 = Lm_B_PTZ(2, MAC[3], tmp[2] >> 12, lm);
961 
962  Z_FIFO[0] = Z_FIFO[1];
963  Z_FIFO[1] = Z_FIFO[2];
964  Z_FIFO[2] = Z_FIFO[3];
965  Z_FIFO[3] = Lm_D(tmp[2] >> 12, true);
966 }
967 
968 
969 #define DECODE_FIELDS							\
970  const uint32 sf MDFN_NOWARN_UNUSED = (instr & (1 << 19)) ? 12 : 0;		\
971  const uint32 mx MDFN_NOWARN_UNUSED = (instr >> 17) & 0x3;			\
972  const uint32 v_i = (instr >> 15) & 0x3;				\
973  const int32* cv MDFN_NOWARN_UNUSED = CRVectors.All[(instr >> 13) & 0x3];	\
974  const int lm MDFN_NOWARN_UNUSED = (instr >> 10) & 1;			\
975  int16 v[3] MDFN_NOWARN_UNUSED;					\
976  if(v_i == 3)							\
977  {								\
978   v[0] = IR1;							\
979   v[1] = IR2;							\
980   v[2] = IR3;							\
981  }								\
982  else								\
983  {								\
984   v[0] = Vectors[v_i][0];					\
985   v[1] = Vectors[v_i][1];					\
986   v[2] = Vectors[v_i][2];					\
987  }
988 
989 
SQR(uint32 instr)990 static INLINE int32 SQR(uint32 instr)
991 {
992  DECODE_FIELDS;
993 
994  MAC[1] = ((IR1 * IR1) >> sf);
995  MAC[2] = ((IR2 * IR2) >> sf);
996  MAC[3] = ((IR3 * IR3) >> sf);
997 
998  MAC_to_IR(lm);
999 
1000  return(5);
1001 }
1002 
MVMVA(uint32 instr)1003 static INLINE int32 MVMVA(uint32 instr)
1004 {
1005  DECODE_FIELDS;
1006 
1007  MultiplyMatrixByVector(&Matrices.All[mx], v, cv, sf, lm);
1008 
1009  return(8);
1010 }
1011 
CountLeadingZeroU16(uint16 val)1012 static INLINE unsigned CountLeadingZeroU16(uint16 val)
1013 {
1014  unsigned ret = 0;
1015 
1016  while(!(val & 0x8000) && ret < 16)
1017  {
1018   val <<= 1;
1019   ret++;
1020  }
1021 
1022  return ret;
1023 }
1024 
Divide(uint32 dividend,uint32 divisor)1025 static INLINE uint32 Divide(uint32 dividend, uint32 divisor)
1026 {
1027  //if((Z_FIFO[3] * 2) > H)
1028  if((divisor * 2) > dividend)
1029  {
1030   unsigned shift_bias = CountLeadingZeroU16(divisor);
1031 
1032   dividend <<= shift_bias;
1033   divisor <<= shift_bias;
1034 
1035   return std::min<uint32>(0x1FFFF, ((uint64)dividend * CalcRecip(divisor | 0x8000) + 32768) >> 16);
1036  }
1037  else
1038  {
1039   FLAGS |= 1 << 17;
1040   return 0x1FFFF;
1041  }
1042 }
1043 
TransformXY(int64 h_div_sz)1044 static INLINE void TransformXY(int64 h_div_sz)
1045 {
1046  MAC[0] = F((int64)OFX + IR1 * h_div_sz) >> 16;
1047  XY_FIFO[3].X = Lm_G(0, MAC[0]);
1048 
1049  MAC[0] = F((int64)OFY + IR2 * h_div_sz) >> 16;
1050  XY_FIFO[3].Y = Lm_G(1, MAC[0]);
1051 
1052  XY_FIFO[0] = XY_FIFO[1];
1053  XY_FIFO[1] = XY_FIFO[2];
1054  XY_FIFO[2] = XY_FIFO[3];
1055 }
1056 
TransformDQ(int64 h_div_sz)1057 static INLINE void TransformDQ(int64 h_div_sz)
1058 {
1059  MAC[0] = F((int64)DQB + DQA * h_div_sz);
1060  IR0 = Lm_H(((int64)DQB + DQA * h_div_sz) >> 12);
1061 }
1062 
RTPS(uint32 instr)1063 static INLINE int32 RTPS(uint32 instr)
1064 {
1065  DECODE_FIELDS;
1066  int64 h_div_sz;
1067 
1068  MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[0], CRVectors.T, sf, lm);
1069  h_div_sz = Divide(H, Z_FIFO[3]);
1070 
1071  TransformXY(h_div_sz);
1072  TransformDQ(h_div_sz);
1073 
1074  return(15);
1075 }
1076 
RTPT(uint32 instr)1077 static INLINE int32 RTPT(uint32 instr)
1078 {
1079  DECODE_FIELDS;
1080  int i;
1081 
1082  for(i = 0; i < 3; i++)
1083  {
1084   int64 h_div_sz;
1085 
1086   MultiplyMatrixByVector_PT(&Matrices.Rot, Vectors[i], CRVectors.T, sf, lm);
1087   h_div_sz = Divide(H, Z_FIFO[3]);
1088 
1089   TransformXY(h_div_sz);
1090 
1091   if(i == 2)
1092    TransformDQ(h_div_sz);
1093  }
1094 
1095  return(23);
1096 }
1097 
NormColor(uint32 sf,int lm,uint32 v)1098 static INLINE void NormColor(uint32 sf, int lm, uint32 v)
1099 {
1100  int16 tmp_vector[3];
1101 
1102  MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1103 
1104  tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1105  MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1106 
1107  MAC_to_RGB_FIFO();
1108 }
1109 
NCS(uint32 instr)1110 static INLINE int32 NCS(uint32 instr)
1111 {
1112  DECODE_FIELDS;
1113 
1114  NormColor(sf, lm, 0);
1115 
1116  return(14);
1117 }
1118 
NCT(uint32 instr)1119 static int32 NCT(uint32 instr)
1120 {
1121  DECODE_FIELDS;
1122  int i;
1123 
1124  for(i = 0; i < 3; i++)
1125   NormColor(sf, lm, i);
1126 
1127  return(30);
1128 }
1129 
NormColorColor(uint32 v,uint32 sf,int lm)1130 static INLINE void NormColorColor(uint32 v, uint32 sf, int lm)
1131 {
1132  int16 tmp_vector[3];
1133 
1134  MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1135 
1136  tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1137  MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1138 
1139  MAC[1] = ((RGB.R << 4) * IR1) >> sf;
1140  MAC[2] = ((RGB.G << 4) * IR2) >> sf;
1141  MAC[3] = ((RGB.B << 4) * IR3) >> sf;
1142 
1143  MAC_to_IR(lm);
1144 
1145  MAC_to_RGB_FIFO();
1146 }
1147 
NCCS(uint32 instr)1148 static INLINE int32 NCCS(uint32 instr)
1149 {
1150  DECODE_FIELDS;
1151 
1152  NormColorColor(0, sf, lm);
1153  return(17);
1154 }
1155 
1156 
NCCT(uint32 instr)1157 static INLINE int32 NCCT(uint32 instr)
1158 {
1159  int i;
1160  DECODE_FIELDS;
1161 
1162  for(i = 0; i < 3; i++)
1163   NormColorColor(i, sf, lm);
1164 
1165  return(39);
1166 }
1167 
DepthCue(int mult_IR123,int RGB_from_FIFO,uint32 sf,int lm)1168 static INLINE void DepthCue(int mult_IR123, int RGB_from_FIFO, uint32 sf, int lm)
1169 {
1170  int32 RGB_temp[3];
1171  int32 IR_temp[3] = { IR1, IR2, IR3 };
1172  int i;
1173 
1174  //assert(sf);
1175 
1176  if(RGB_from_FIFO)
1177  {
1178   RGB_temp[0] = RGB_FIFO[0].R << 4;
1179   RGB_temp[1] = RGB_FIFO[0].G << 4;
1180   RGB_temp[2] = RGB_FIFO[0].B << 4;
1181  }
1182  else
1183  {
1184   RGB_temp[0] = RGB.R << 4;
1185   RGB_temp[1] = RGB.G << 4;
1186   RGB_temp[2] = RGB.B << 4;
1187  }
1188 
1189  if(mult_IR123)
1190  {
1191   for(i = 0; i < 3; i++)
1192   {
1193    MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - RGB_temp[i] * IR_temp[i])) >> sf;
1194    MAC[1 + i] = A_MV(i, (RGB_temp[i] * IR_temp[i] + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf;
1195   }
1196  }
1197  else
1198  {
1199   for(i = 0; i < 3; i++)
1200   {
1201    MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)CRVectors.FC[i] << 12) - (int32)((uint32)RGB_temp[i] << 12))) >> sf;
1202    MAC[1 + i] = A_MV(i, ((int64)((uint64)(int64)RGB_temp[i] << 12) + IR0 * Lm_B(i, MAC[1 + i], false))) >> sf;
1203   }
1204  }
1205 
1206  MAC_to_IR(lm);
1207 
1208  MAC_to_RGB_FIFO();
1209 }
1210 
1211 
DCPL(uint32 instr)1212 static INLINE int32 DCPL(uint32 instr)
1213 {
1214  DECODE_FIELDS;
1215 
1216  DepthCue(true, false, sf, lm);
1217 
1218  return(8);
1219 }
1220 
1221 
DPCS(uint32 instr)1222 static INLINE int32 DPCS(uint32 instr)
1223 {
1224  DECODE_FIELDS;
1225 
1226  DepthCue(false, false, sf, lm);
1227 
1228  return(8);
1229 }
1230 
DPCT(uint32 instr)1231 static INLINE int32 DPCT(uint32 instr)
1232 {
1233  int i;
1234  DECODE_FIELDS;
1235 
1236  for(i = 0; i < 3; i++)
1237  {
1238   DepthCue(false, true, sf, lm);
1239  }
1240 
1241  return(17);
1242 }
1243 
INTPL(uint32 instr)1244 static INLINE int32 INTPL(uint32 instr)
1245 {
1246  DECODE_FIELDS;
1247 
1248  MAC[1] = A_MV(0, ((int64)((uint64)(int64)CRVectors.FC[0] << 12) - (int32)((uint32)(int32)IR1 << 12))) >> sf;
1249  MAC[2] = A_MV(1, ((int64)((uint64)(int64)CRVectors.FC[1] << 12) - (int32)((uint32)(int32)IR2 << 12))) >> sf;
1250  MAC[3] = A_MV(2, ((int64)((uint64)(int64)CRVectors.FC[2] << 12) - (int32)((uint32)(int32)IR3 << 12))) >> sf;
1251 
1252  MAC[1] = A_MV(0, ((int64)((uint64)(int64)IR1 << 12) + IR0 * Lm_B(0, MAC[1], false)) >> sf);
1253  MAC[2] = A_MV(1, ((int64)((uint64)(int64)IR2 << 12) + IR0 * Lm_B(1, MAC[2], false)) >> sf);
1254  MAC[3] = A_MV(2, ((int64)((uint64)(int64)IR3 << 12) + IR0 * Lm_B(2, MAC[3], false)) >> sf);
1255 
1256  MAC_to_IR(lm);
1257 
1258  MAC_to_RGB_FIFO();
1259 
1260  return(8);
1261 }
1262 
1263 
NormColorDepthCue(uint32 v,uint32 sf,int lm)1264 static INLINE void NormColorDepthCue(uint32 v, uint32 sf, int lm)
1265 {
1266  int16 tmp_vector[3];
1267 
1268  MultiplyMatrixByVector(&Matrices.Light, Vectors[v], CRVectors.Null, sf, lm);
1269 
1270  tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1271  MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1272 
1273  DepthCue(true, false, sf, lm);
1274 }
1275 
NCDS(uint32 instr)1276 static INLINE int32 NCDS(uint32 instr)
1277 {
1278  DECODE_FIELDS;
1279 
1280  NormColorDepthCue(0, sf, lm);
1281 
1282  return(19);
1283 }
1284 
NCDT(uint32 instr)1285 static INLINE int32 NCDT(uint32 instr)
1286 {
1287  int i;
1288  DECODE_FIELDS;
1289 
1290  for(i = 0; i < 3; i++)
1291  {
1292   NormColorDepthCue(i, sf, lm);
1293  }
1294 
1295  return(44);
1296 }
1297 
CC(uint32 instr)1298 static INLINE int32 CC(uint32 instr)
1299 {
1300  DECODE_FIELDS;
1301  int16 tmp_vector[3];
1302 
1303  tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1304  MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1305 
1306  MAC[1] = ((RGB.R << 4) * IR1) >> sf;
1307  MAC[2] = ((RGB.G << 4) * IR2) >> sf;
1308  MAC[3] = ((RGB.B << 4) * IR3) >> sf;
1309 
1310  MAC_to_IR(lm);
1311 
1312  MAC_to_RGB_FIFO();
1313 
1314  return(11);
1315 }
1316 
CDP(uint32 instr)1317 static INLINE int32 CDP(uint32 instr)
1318 {
1319  DECODE_FIELDS;
1320  int16 tmp_vector[3];
1321 
1322  tmp_vector[0] = IR1; tmp_vector[1] = IR2; tmp_vector[2] = IR3;
1323  MultiplyMatrixByVector(&Matrices.Color, tmp_vector, CRVectors.B, sf, lm);
1324 
1325  DepthCue(true, false, sf, lm);
1326 
1327  return(13);
1328 }
1329 
NCLIP(uint32 instr)1330 static INLINE int32 NCLIP(uint32 instr)
1331 {
1332  DECODE_FIELDS;
1333 
1334  MAC[0] = F( (int64)(XY_FIFO[0].X * (XY_FIFO[1].Y - XY_FIFO[2].Y)) + (XY_FIFO[1].X * (XY_FIFO[2].Y - XY_FIFO[0].Y)) + (XY_FIFO[2].X * (XY_FIFO[0].Y - XY_FIFO[1].Y))
1335 	  );
1336 
1337  return(8);
1338 }
1339 
AVSZ3(uint32 instr)1340 static INLINE int32 AVSZ3(uint32 instr)
1341 {
1342  DECODE_FIELDS;
1343 
1344  MAC[0] = F(((int64)ZSF3 * (Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3])));
1345 
1346  OTZ = Lm_D(MAC[0] >> 12, false);
1347 
1348  return(5);
1349 }
1350 
AVSZ4(uint32 instr)1351 static INLINE int32 AVSZ4(uint32 instr)
1352 {
1353  DECODE_FIELDS;
1354 
1355  MAC[0] = F(((int64)ZSF4 * (Z_FIFO[0] + Z_FIFO[1] + Z_FIFO[2] + Z_FIFO[3])));
1356 
1357  OTZ = Lm_D(MAC[0] >> 12, false);
1358 
1359  return(5);
1360 }
1361 
1362 
1363 // -32768 * -32768 - 32767 * -32768 = 2147450880
1364 // (2 ^ 31) - 1 =		      2147483647
OP(uint32 instr)1365 static INLINE int32 OP(uint32 instr)
1366 {
1367  DECODE_FIELDS;
1368 
1369  MAC[1] = ((Matrices.Rot.MX[1][1] * IR3) - (Matrices.Rot.MX[2][2] * IR2)) >> sf;
1370  MAC[2] = ((Matrices.Rot.MX[2][2] * IR1) - (Matrices.Rot.MX[0][0] * IR3)) >> sf;
1371  MAC[3] = ((Matrices.Rot.MX[0][0] * IR2) - (Matrices.Rot.MX[1][1] * IR1)) >> sf;
1372 
1373  MAC_to_IR(lm);
1374 
1375  return(6);
1376 }
1377 
GPF(uint32 instr)1378 static INLINE int32 GPF(uint32 instr)
1379 {
1380  DECODE_FIELDS;
1381 
1382  MAC[1] = (IR0 * IR1) >> sf;
1383  MAC[2] = (IR0 * IR2) >> sf;
1384  MAC[3] = (IR0 * IR3) >> sf;
1385 
1386  MAC_to_IR(lm);
1387 
1388  MAC_to_RGB_FIFO();
1389 
1390  return(5);
1391 }
1392 
GPL(uint32 instr)1393 static INLINE int32 GPL(uint32 instr)
1394 {
1395  DECODE_FIELDS;
1396 
1397  MAC[1] = A_MV(0, (int64)((uint64)(int64)MAC[1] << sf) + (IR0 * IR1)) >> sf;
1398  MAC[2] = A_MV(1, (int64)((uint64)(int64)MAC[2] << sf) + (IR0 * IR2)) >> sf;
1399  MAC[3] = A_MV(2, (int64)((uint64)(int64)MAC[3] << sf) + (IR0 * IR3)) >> sf;
1400 
1401  MAC_to_IR(lm);
1402 
1403  MAC_to_RGB_FIFO();
1404 
1405  return(5);
1406 }
1407 
1408 /*
1409 
1410 ---------------------------------------------------------------------------------------------
1411 | 24 23 22 21 20 | 19 | 18 17 | 16 15 | 14 13 | 12  11 | 10 | 9  8  7  6 | 5  4  3  2  1  0 |
1412 |-------------------------------------------------------------------------------------------|
1413 |    (unused)    | sf |  mx   |   v   |   cv  |(unused)| lm |  (unused)  |     opcode       |
1414 ---------------------------------------------------------------------------------------------
1415  (unused) = unused, ignored
1416 
1417  sf = shift 12
1418 
1419  mx = matrix selection
1420 
1421  v = source vector
1422 
1423  cv = add vector(translation/back/far color(bugged)/none)
1424 
1425  (unused) = unused, ignored
1426 
1427  lm = limit negative results to 0
1428 
1429  (unused) = unused, ignored
1430 
1431  opcode = operation code
1432 */
1433 
GTE_Instruction(uint32 instr)1434 int32 GTE_Instruction(uint32 instr)
1435 {
1436  const unsigned code = instr & 0x3F;
1437  int32 ret = 1;
1438 
1439  FLAGS = 0;
1440 
1441  switch(code)
1442  {
1443   default:
1444 #ifndef PSXDEV_GTE_TESTING
1445 	   PSX_WARNING("[GTE] Unknown instruction code: 0x%02x", code);
1446 #endif
1447 	   break;
1448 
1449   case 0x00:	// alternate?
1450   case 0x01:
1451 	ret = RTPS(instr);
1452 	break;
1453 
1454 /*
1455   case 0x02:	// UNSTABLE?
1456 	break;
1457 
1458   case 0x03:	// UNSTABLE?
1459 	break;
1460 
1461   case 0x04:	// Probably simple with v,cv,sf,mx,lm ignored.  Same calculation as 0x3B?
1462 	break;
1463 
1464   case 0x05:	// UNSTABLE?
1465 	break;
1466 */
1467 
1468   case 0x06:
1469 	ret = NCLIP(instr);
1470 	break;
1471 
1472 /*
1473   case 0x07:	// UNSTABLE?
1474 	break;
1475 
1476   case 0x08:	// UNSTABLE?
1477 	break;
1478 
1479   case 0x09:	// UNSTABLE?
1480 	break;
1481 
1482   case 0x0A:	// UNSTABLE?
1483 	break;
1484 
1485   case 0x0B:	// UNSTABLE?
1486 	break;
1487 
1488 */
1489 
1490   case 0x0C:
1491 	ret = OP(instr);
1492 	break;
1493 
1494 /*
1495   case 0x0D:	// UNSTABLE?
1496 	break;
1497 
1498   case 0x0E:	// UNSTABLE?
1499 	break;
1500 
1501   case 0x0F:	// UNSTABLE?
1502 	break;
1503 */
1504 
1505   case 0x10:
1506 	ret = DPCS(instr);
1507 	break;
1508 
1509   case 0x11:
1510 	ret = INTPL(instr);
1511 	break;
1512 
1513   case 0x12:
1514 	ret = MVMVA(instr);
1515 	break;
1516 
1517   case 0x13:
1518 	ret = NCDS(instr);
1519 	break;
1520 
1521   case 0x14:
1522 	ret = CDP(instr);
1523 	break;
1524 
1525 
1526 /*
1527   case 0x15:	// does one push on RGB FIFO, what else...
1528 	break;
1529 */
1530 
1531   case 0x16:
1532 	ret = NCDT(instr);
1533 	break;
1534 
1535 /*
1536   case 0x17:	// PARTIALLY UNSTABLE(depending on sf or v or cv or mx or lm???), similar behavior under some conditions to 0x16?
1537 	break;
1538 
1539   case 0x18:
1540 	break;
1541 
1542   case 0x19:
1543 	break;
1544 */
1545 
1546   // case 0x1A handled next to case 0x29
1547 
1548   case 0x1B:
1549 	ret = NCCS(instr);
1550 	break;
1551 
1552   case 0x1C:
1553 	ret = CC(instr);
1554 	break;
1555 
1556 /*
1557   case 0x1D:
1558 	break;
1559 */
1560 
1561   case 0x1E:
1562 	ret = NCS(instr);
1563 	break;
1564 
1565 /*
1566   case 0x1F:
1567 	break;
1568 */
1569 
1570   case 0x20:
1571 	ret = NCT(instr);
1572 	break;
1573 /*
1574   case 0x21:
1575 	break;
1576 
1577   case 0x22:	// UNSTABLE?
1578 	break;
1579 
1580   case 0x23:
1581 	break;
1582 
1583   case 0x24:
1584 	break;
1585 
1586   case 0x25:
1587 	break;
1588 
1589   case 0x26:
1590 	break;
1591 
1592   case 0x27:
1593 	break;
1594 */
1595 
1596   case 0x28:
1597 	ret = SQR(instr);
1598 	break;
1599 
1600   case 0x1A:	// Alternate for 0x29?
1601   case 0x29:
1602 	ret = DCPL(instr);
1603 	break;
1604 
1605   case 0x2A:
1606 	ret = DPCT(instr);
1607 	break;
1608 
1609 /*
1610   case 0x2B:
1611 	break;
1612 
1613   case 0x2C:
1614 	break;
1615 */
1616 
1617   case 0x2D:
1618 	ret = AVSZ3(instr);
1619 	break;
1620 
1621   case 0x2E:
1622 	ret = AVSZ4(instr);
1623 	break;
1624 
1625 /*
1626   case 0x2F:	// UNSTABLE?
1627 	break;
1628 */
1629 
1630   case 0x30:
1631 	ret = RTPT(instr);
1632 	break;
1633 
1634 /*
1635   case 0x31:	// UNSTABLE?
1636 	break;
1637 
1638   case 0x32:	// UNSTABLE?
1639 	break;
1640 
1641   case 0x33:	// UNSTABLE?
1642 	break;
1643 
1644   case 0x34:	// UNSTABLE?
1645 	break;
1646 
1647   case 0x35:	// UNSTABLE?
1648 	break;
1649 
1650   case 0x36:	// UNSTABLE?
1651 	break;
1652 
1653   case 0x37:	// UNSTABLE?
1654 	break;
1655 
1656   case 0x38:
1657 	break;
1658 
1659   case 0x39:	// Probably simple with v,cv,sf,mx,lm ignored.
1660 	break;
1661 
1662   case 0x3A:	// Probably simple with v,cv,sf,mx,lm ignored.
1663 	break;
1664 
1665   case 0x3B:	// Probably simple with v,cv,sf,mx,lm ignored.  Same calculation as 0x04?
1666 	break;
1667 
1668   case 0x3C:	// UNSTABLE?
1669 	break;
1670 */
1671 
1672   case 0x3D:
1673 	ret = GPF(instr);
1674 	break;
1675 
1676   case 0x3E:
1677 	ret = GPL(instr);
1678 	break;
1679 
1680   case 0x3F:
1681 	ret = NCCT(instr);
1682 	break;
1683  }
1684 
1685  if(FLAGS & 0x7f87e000)
1686   FLAGS |= 1 << 31;
1687 
1688  CR[31] = FLAGS;
1689 
1690  return(ret - 1);
1691 }
1692 
1693 #ifndef PSXDEV_GTE_TESTING
1694 }
1695 #endif
1696