Skip to content

Latest commit

 

History

History
469 lines (363 loc) · 17.3 KB

File metadata and controls

469 lines (363 loc) · 17.3 KB

Geometrytransformationenginegte

Source: https://problemkaputt.de/psx-spx.htm Section: Geometrytransformationenginegte

Geometry Transformation Engine (GTE) GTE Overview

GTE Registers

GTE Saturation

GTE Opcode Summary

GTE Coordinate Calculation Commands

GTE General Purpose Calculation Commands

GTE Color Calculation Commands

GTE Division Inaccuracy

GTE Registers

Note in some functions format is different from the one that's given here.

Matrix Registers

Rotation matrix (RT)   Light matrix (LLM)     Light Color matrix (LCM)
cop2r32.lsbs=RT11      cop2r40.lsbs=L11       cop2r48.lsbs=LR1
cop2r32.msbs=RT12      cop2r40.msbs=L12       cop2r48.msbs=LR2
cop2r33.lsbs=RT13      cop2r41.lsbs=L13       cop2r49.lsbs=LR3
cop2r33.msbs=RT21      cop2r41.msbs=L21       cop2r49.msbs=LG1
cop2r34.lsbs=RT22      cop2r42.lsbs=L22       cop2r50.lsbs=LG2
cop2r34.msbs=RT23      cop2r42.msbs=L23       cop2r50.msbs=LG3
cop2r35.lsbs=RT31      cop2r43.lsbs=L31       cop2r51.lsbs=LB1
cop2r35.msbs=RT32      cop2r43.msbs=L32       cop2r51.msbs=LB2
cop2r36     =RT33      cop2r44     =L33       cop2r52     =LB3

Each element is 16bit (1bit sign, 3bit integer, 12bit fraction). Reading the last elements (RT33,L33,LB3) returns the 16bit value sign-expanded to 32bit.

Translation Vector (TR) (Input, R/W?)

cop2r37 (cnt5) - TRX - Translation vector X (R/W?)
cop2r38 (cnt6) - TRY - Translation vector Y (R/W?)
cop2r39 (cnt7) - TRZ - Translation vector Z (R/W?)

Each element is 32bit (1bit sign, 31bit integer).

Used only for MVMVA, RTPS, RTPT commands.

Background Color (BK) (Input?, R/W?)

cop2r45 (cnt13) - RBK - Background color red component
cop2r46 (cnt14) - GBK - Background color green component
cop2r47 (cnt15) - BBK - Background color blue component

Each element is 32bit (1bit sign, 19bit integer, 12bit fraction).

Far Color (FC) (Input?) (R/W?)

cop2r53 (cnt21) - RFC - Far color red component
cop2r54 (cnt22) - GFC - Far color green component
cop2r55 (cnt23) - BFC - Far color blue component

Each element is 32bit (1bit sign, 27bit integer, 4bit fraction).

Screen Offset and Distance (Input, R/W?)

cop2r56 (cnt24) - OFX - Screen offset X
cop2r57 (cnt25) - OFY - Screen offset Y
cop2r58 (cnt26) - H   - Projection plane distance
cop2r59 (cnt27) - DQA - Depth queing parameter A.(coeff.)
cop2r60 (cnt28) - DQB - Depth queing parameter B.(offset.)

The X and Y values are each 32bit (1bit sign, 15bit integer, 16bit fraction).

The H value is 16bit unsigned (0bit sign, 16bit integer, 0bit fraction). BUG: When reading the H register, the hardware does accidently the 16bit value (ie. values +8000h..+FFFFh are returned as FFFF8000h..FFFFFFFFh) (this bug applies only to "mov rd,cop2r58" opcodes; the actual calculations via RTPS/RTPT opcodes are working okay).

The DQA value is only 16bit (1bit sign, 7bit integer, 8bit fraction).

The DQB value is 32bit (1bit sign, 7bit integer, 24bit? fraction).

Used only for RTPS/RTPT commands.

Average Z Registers (ZSF3/ZSF4=Input, R/W?) (OTZ=Result, R)

cop2r61 (cnt29) ZSF3 |  0|ZSF3 1,3,12| Z3 average scale factor (normally 1/3)
cop2r62 (cnt30) ZSF4 |  0|ZSF4 1,3,12| Z4 average scale factor (normally 1/4)
cop2r7       OTZ (R) |   |OTZ 0,15, 0| Average Z value (for Ordering Table)

Used only for AVSZ3/AVSZ4 commands.

Screen XYZ Coordinate FIFOs

cop2r12 - SXY0  rw|SY0 1,15, 0|SX0 1,15, 0| Screen XY fifo (older)
cop2r13 - SXY1  rw|SY1 1,15, 0|SX1 1,15, 0| Screen XY fifo (old)
cop2r14 - SXY2  rw|SY2 1,15, 0|SX2 1,15, 0| Screen XY fifo (new)
cop2r15 - SXYP  rw|SYP 1,15, 0|SXP 1,15, 0| SXY2-mirror with move-on-write
cop2r16 - SZ0   rw|          0|SZ0 0,16, 0| Screen Z fifo (oldest)
cop2r17 - SZ1   rw|          0|SZ1 0,16, 0| Screen Z fifo (older)
cop2r18 - SZ2   rw|          0|SZ2 0,16, 0| Screen Z fifo (old)
cop2r19 - SZ3   rw|          0|SZ3 0,16, 0| Screen Z fifo (new)

SX,SY,SZ are used as Output for RTPS/RTPT. Additionally, SX,SY are used as Input for NCLIP, and SZ is used as Input for AVSZ3/AVSZ4.

The SZn Fifo has 4 stages (required for AVSZ4 command), the SXYn Fifo has only 3 stages, and a special mirrored register: SXYP is a mirror of SXY2, the difference is that writing to SXYP moves SXY2/SXY1 to SXY1/SXY0, whilst writing to SXY2 (or any other SXYn or SZn registers) changes only the written register, but doesn't move any other Fifo entries.

16bit Vectors (R/W)

Vector 0 (V0)         Vector 1 (V1)       Vector 2 (V2)       Vector 3 (IR)
cop2r0.lsbs - VX0     cop2r2.lsbs - VX1   cop2r4.lsbs - VX2   cop2r9  - IR1
cop2r0.msbs - VY0     cop2r2.msbs - VY1   cop2r4.msbs - VY2   cop2r10 - IR2
cop2r1      - VZ0     cop2r3      - VZ1   cop2r5      - VZ2   cop2r11 - IR3

All elements are signed 16bit. The IRn and VZn elements occupy a whole 32bit register, reading these registers returns the 16bit value sign-expanded to 32bit. Note: IRn can be also indirectly accessed via IRGB/ORGB registers.

Color Register and Color FIFO

cop2r6  - RGBC  rw|CODE |B    |G    |R    | Color/code
cop2r20 - RGB0  rw|CD0  |B0   |G0   |R0   | Characteristic color fifo.
cop2r21 - RGB1  rw|CD1  |B1   |G1   |R1   |
cop2r22 - RGB2  rw|CD2  |B2   |G2   |R2   |
cop2r23 - (RES1)  |                       | Prohibited

RES1 seems to be unused... looks like an unused Fifo stage... RES1 is read/write-able... unlike SXYP (for SXYn Fifo) it does not mirror to RGB2, nor does it have a move-on-write function...

Interpolation Factor

cop2r8   IR0   rw|Sign       |IR0 1, 3,12| Intermediate value 0.

Used as Output for RTPS/RTPT, and as Input for various commands.

XX...

cop2r24  MAC0  rw|MAC0 1,31,0            | Sum of products value 0

XX...

cop2r25  MAC1  rw|MAC1 1,31,0            | Sum of products value 1
cop2r26  MAC2  rw|MAC2 1,31,0            | Sum of products value 2
cop2r27  MAC3  rw|MAC3 1,31,0            | Sum of products value 3

cop2r28 - IRGB - Color conversion Input (R/W)

Expands 5:5:5 bit RGB (range 0..1Fh) to 16:16:16 bit RGB (range 0000h..0F80h).

0-4    Red   (0..1Fh) (R/W)  ;multiplied by 80h, and written to IR1
5-9    Green (0..1Fh) (R/W)  ;multiplied by 80h, and written to IR2
10-14  Blue  (0..1Fh) (R/W)  ;multiplied by 80h, and written to IR3
15-31  Not used (always zero) (Read only)

After writing to IRGB, the result can be read from IR3 after TWO nop's, and from IR1,IR2 after THREE nop's (for uncached code, ONE nop would work). When using IR1,IR2,IR3 as parameters for GTE commands, similar timing restrictions might apply... depending on when the specific commands use the parameters?

cop2r29 - ORGB - Color conversion Output (R)

Collapses 16:16:16 bit RGB (range 0000h..0F80h) to 5:5:5 bit RGB (range 0..1Fh). Negative values (8000h..FFFFh/80h) are saturated to 00h, large positive values (1000h..7FFFh/80h) are saturated to 1Fh, there are no overflow or saturation flags set in cop2r63 though.

0-4    Red   (0..1Fh) (R)  ;IR1 divided by 80h, saturated to +00h..+1Fh
5-9    Green (0..1Fh) (R)  ;IR2 divided by 80h, saturated to +00h..+1Fh
10-14  Blue  (0..1Fh) (R)  ;IR3 divided by 80h, saturated to +00h..+1Fh
15-31  Not used (always zero) (Read only)

Any changes to IR1,IR2,IR3 are reflected to this register (and, actually also to IRGB) (ie. ORGB is simply a read-only mirror of IRGB).

cop2r30 - LZCS - Count Leading Bits Source data (R/W)

cop2r31 - LZCR - Count Leading Bits Result (R)

Reading LZCR returns the leading 0 count of LZCS if LZCS is positive and the leading 1 count of LZCS if LZCS is negative. The results are in range 1..32.

cop2r63 (cnt31) - FLAG - Returns any calculation errors.

See GTE Saturation chapter.

GTE Opcode Summary

GTE Command Summary (sorted by Real Opcode bits) (bit0-5)

Opc  Name      Clk Expl.
00h  -             N/A (modifies similar registers than RTPS...)
01h  RTPS      15  Perspective Transformation single
0xh  -             N/A
06h  NCLIP     8   Normal clipping
0xh  -             N/A
0Ch  OP(sf)    6   Outer product of 2 vectors
0xh  -             N/A
10h  DPCS      8   Depth Cueing single
11h  INTPL     8   Interpolation of a vector and far color vector
12h  MVMVA(..) 8   Multiply vector by matrix and add vector (see below)
13h  NCDS      19  Normal color depth cue single vector
14h  CDP       13  Color Depth Que
15h  -             N/A
16h  NCDT      44  Normal color depth cue triple vectors
1xh  -             N/A
1Bh  NCCS      17  Normal Color Color single vector
1Ch  CC        11  Color Color
1Dh  -             N/A
1Eh  NCS       14  Normal color single
1Fh  -             N/A
20h  NCT       30  Normal color triple
2xh  -             N/A
28h  SQR(sf)   5   Square of vector IR
29h  DCPL      8   Depth Cue Color light
2Ah  DPCT      17  Depth Cueing triple (should be fake=08h, but isn't)
2xh  -             N/A
2Dh  AVSZ3     5   Average of three Z values
2Eh  AVSZ4     6   Average of four Z values
2Fh  -             N/A
30h  RTPT      23  Perspective Transformation triple
3xh  -             N/A
3Dh  GPF(sf)   5   General purpose interpolation
3Eh  GPL(sf)   5   General purpose interpolation with base
3Fh  NCCT      39  Normal Color Color triple vector

Unknown if/what happens when using the "N/A" opcodes?

GTE Command Summary (sorted by Fake Opcode bits) (bit20-24)

The fake opcode number in bit20-24 has absolutely no effect on the hardware, it seems to be solely used to (or not to) confuse developers. Having the opcodes sorted by their fake numbers gives a more or less well arranged list:

Fake Name      Clk Expl.
00h  -             N/A
01h  RTPS      15  Perspective Transformation single
02h  RTPT      23  Perspective Transformation triple
03h  -             N/A
04h  MVMVA(..) 8   Multiply vector by matrix and add vector (see below)
05h  -             N/A
06h  DCPL      8   Depth Cue Color light
07h  DPCS      8   Depth Cueing single
08h  DPCT      17  Depth Cueing triple (should be fake=08h, but isn't)
09h  INTPL     8   Interpolation of a vector and far color vector
0Ah  SQR(sf)   5   Square of vector IR
0Bh  -             N/A
0Ch  NCS       14  Normal color single
0Dh  NCT       30  Normal color triple
0Eh  NCDS      19  Normal color depth cue single vector
0Fh  NCDT      44  Normal color depth cue triple vectors
10h  NCCS      17  Normal Color Color single vector
11h  NCCT      39  Normal Color Color triple vector
12h  CDP       13  Color Depth Que
13h  CC        11  Color Color
14h  NCLIP     8   Normal clipping
15h  AVSZ3     5   Average of three Z values
16h  AVSZ4     6   Average of four Z values
17h  OP(sf)    6   Outer product of 2 vectors
18h  -             N/A
19h  GPF(sf)   5   General purpose interpolation
1Ah  GPL(sf)   5   General purpose interpolation with base
1Bh  -             N/A
1Ch  -             N/A
1Dh  -             N/A
1Eh  -             N/A
1Fh  -             N/A

For the sort-effect, DCPT should use fake=08h, but Sony seems to have accidently numbered it fake=0Fh in their devkit (giving it the same fake number as for NCDT). Also, "Wipeout 2097" accidently uses 0140006h (fake=01h and distorted bit18) instead of 1400006h (fake=14h) for NCLIP.

GTE nonsense SDK command numbers (as from SDK file INLINE_A.H)

RTPS   macro               dw   $0000007f              (01x40)
RTPT   macro               dw   $000000bf              (02x40)
DCPL   macro               dw   $00000dff              (37x40)
DPCS   macro               dw   $00000e3f              (38x40)
DPCT   macro               dw   $00000e7f              (39x40)
INTPL  macro               dw   $00000ebf              (3Ax40)
NCS    macro               dw   $00000f7f              (3Dx40)
NCT    macro               dw   $00000fbf              (3Ex40)
NCDS   macro               dw   $00000fff              (3Fx40)
NCDT   macro               dw   $0000103f              (40x40)
NCCS   macro               dw   $0000107f              (41x40)
NCCT   macro               dw   $000010bf              (42x40)
CDP    macro               dw   $000010ff              (43x40)
CC     macro               dw   $0000113f              (44x40)
NCLIP  macro               dw   $0000117f              (45x40)
AVSZ3  macro               dw   $000011bf              (46x40)
AVSZ4  macro               dw   $000011ff              (47x40)
MVMVA  macro sf,mx,v,cv,lm dw   $000013bf|sf
GTE General Purpose Calculation Commands

**COP2 0400012h - 8 Cycles - MVMVA(sf,mx,v,cv,lm)**

Multiply vector by matrix and vector addition.

Mx = matrix specified by mx ;RT/LLM/LCM - Rotation, light or color matrix Vx = vector specified by v ;V0, V1, V2, or [IR1,IR2,IR3] Tx = translation vector specified by cv ;TR or BK or Bugged/FC, or None


Calculation:

MAC1 = (Tx11000h + Mx11Vx1 + Mx12Vx2 + Mx13Vx3) SAR (sf12) MAC2 = (Tx21000h + Mx21Vx1 + Mx22Vx2 + Mx23Vx3) SAR (sf12) MAC3 = (Tx31000h + Mx31Vx1 + Mx32Vx2 + Mx33Vx3) SAR (sf*12) [IR1,IR2,IR3] = [MAC1,MAC2,MAC3]


Multiplies a vector with either the rotation matrix, the light matrix or the
color matrix and then adds the translation vector or background color vector.

Vx=2 selects the far color vector (FC), but this vector is not added correctly
by the hardware: The MAC calculation is split into two parts, part1 does merely
affect the IR saturation flags and resets sum to 0. For example, for MAC1 (and
equivalent for MAC2,MAC3):

IR1 = MAC1 = (Tx11000h + Mx11Vx1) SAR (sf12) ;part1, saturate as if lm=0 IR1 = MAC1 = (Mx12Vx2 + Mx13Vx3) SAR (sf12) ;part2, saturate by lm


Mx=3 selects a garbage matrix (with elements -R*10h, +R*10h, IR0, RT13, RT13,
RT13, RT22, RT22, RT22; whereas, R is LSB of RGBC register).

**COP2 0A00428h+sf*80000h - 5 Cycles - SQR(sf) - Square vector**

[MAC1,MAC2,MAC3] = [IR1IR1,IR2IR2,IR3IR3] SHR (sf12) [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] ;IR1,IR2,IR3 saturated to max 7FFFh


Calculates the square of a vector. The result is, of course, always positive,
so the "lm" flag for negative saturation has no effect.

**COP2 170000Ch+sf*80000h - 6 Cycles - OP(sf,lm) - Outer product of 2 vectors**

[MAC1,MAC2,MAC3] = [IR3D2-IR2D3, IR1D3-IR3D1, IR2D1-IR1D2] SAR (sf*12) [IR1,IR2,IR3] = [MAC1,MAC2,MAC3] ;copy result


Calculates the outer product of two signed 16bit vectors. Note: D1,D2,D3 are
meant to be the RT11,RT22,RT33 elements of the RT matrix "misused" as vector.
lm should be usually zero.

**LZCS/LZCR registers - ? Cycles - Count-Leading-Zeroes/Leading-Ones**

The LZCS/LZCR registers offer a Count-Leading-Zeroes/Leading-Ones function.

GTE Division Inaccuracy

**GTE Division Inaccuracy (for RTPS/RTPT commands)**

Basically, the GTE division does (attempt to) work as so (using 33bit maths):

n = (((H*20000h/SZ3)+1)/2)


alternatly, below would give (almost) the same result (using 32bit maths):

n = ((H*10000h+SZ3/2)/SZ3)


in both cases, the result is saturated about as so:

if n>1FFFFh or division_by_zero then n=1FFFFh, FLAG.Bit17=1, FLAG.Bit31=1


However, the real GTE hardware is using a fast, but less accurate division
mechanism (based on Unsigned Newton-Raphson (UNR) algorithm):

if (H < SZ32) then ;check if overflow z = count_leading_zeroes(SZ3) ;z=0..0Fh (for 16bit SZ3) n = (H SHL z) ;n=0..7FFF8000h d = (SZ3 SHL z) ;d=8000h..FFFFh u = unr_table[(d-7FC0h) SHR 7] + 101h ;u=200h..101h d = ((2000080h - (d * u)) SHR 8) ;d=10000h..0FF01h d = ((0000080h + (d * u)) SHR 8) ;d=20000h..10000h n = min(1FFFFh, (((nd) + 8000h) SHR 16)) ;n=0..1FFFFh else n = 1FFFFh, FLAG.Bit17=1, FLAG.Bit31=1 ;n=1FFFFh plus overflow flag


the GTE's unr_table[000h..100h] consists of following values:

FFh,FDh,FBh,F9h,F7h,F5h,F3h,F1h,EFh,EEh,ECh,EAh,E8h,E6h,E4h,E3h ;
E1h,DFh,DDh,DCh,DAh,D8h,D6h,D5h,D3h,D1h,D0h,CEh,CDh,CBh,C9h,C8h ; 00h..3Fh C6h,C5h,C3h,C1h,C0h,BEh,BDh,BBh,BAh,B8h,B7h,B5h,B4h,B2h,B1h,B0h ; AEh,ADh,ABh,AAh,A9h,A7h,A6h,A4h,A3h,A2h,A0h,9Fh,9Eh,9Ch,9Bh,9Ah ;/ 99h,97h,96h,95h,94h,92h,91h,90h,8Fh,8Dh,8Ch,8Bh,8Ah,89h,87h,86h ;
85h,84h,83h,82h,81h,7Fh,7Eh,7Dh,7Ch,7Bh,7Ah,79h,78h,77h,75h,74h ; 40h..7Fh 73h,72h,71h,70h,6Fh,6Eh,6Dh,6Ch,6Bh,6Ah,69h,68h,67h,66h,65h,64h ; 63h,62h,61h,60h,5Fh,5Eh,5Dh,5Dh,5Ch,5Bh,5Ah,59h,58h,57h,56h,55h ;/ 54h,53h,53h,52h,51h,50h,4Fh,4Eh,4Dh,4Dh,4Ch,4Bh,4Ah,49h,48h,48h ;
47h,46h,45h,44h,43h,43h,42h,41h,40h,3Fh,3Fh,3Eh,3Dh,3Ch,3Ch,3Bh ; 80h..BFh 3Ah,39h,39h,38h,37h,36h,36h,35h,34h,33h,33h,32h,31h,31h,30h,2Fh ; 2Eh,2Eh,2Dh,2Ch,2Ch,2Bh,2Ah,2Ah,29h,28h,28h,27h,26h,26h,25h,24h ;/ 24h,23h,22h,22h,21h,20h,20h,1Fh,1Eh,1Eh,1Dh,1Dh,1Ch,1Bh,1Bh,1Ah ;
19h,19h,18h,18h,17h,16h,16h,15h,15h,14h,14h,13h,12h,12h,11h,11h ; C0h..FFh 10h,0Fh,0Fh,0Eh,0Eh,0Dh,0Dh,0Ch,0Ch,0Bh,0Ah,0Ah,09h,09h,08h,08h ; 07h,07h,06h,06h,05h,05h,04h,04h,03h,03h,02h,02h,01h,01h,00h,00h ;/ 00h ;<-- one extra table entry (for "(d-7FC0h)/80h"=100h) ;-100h


Above can be generated as "unr_table[i]=min(0,(40000h/(i+100h)+1)/2-101h)".

Some special cases: NNNNh/0001h uses a big multiplier (d=20000h), in practice,
this can occur only for 0000h/0001h and 0001h/0001h (due to the H<SZ3*2
overflow check).

The min(1FFFFh) limit is needed for cases like FE3Fh/7F20h, F015h/780Bh, etc.
(these do produce UNR result 20000h, and are saturated to 1FFFFh, but without
setting overflow FLAG bits).