PS2 Linux Programming

 

Simple Matrix Transformation with VU1

 

 

Introduction

 

In this tutorial VU1 is used to transform the vertices of a textured quad using a transformation matrix that is uploaded to VU1 data memory every frame.

 

 

The Example Program

 

The structure of the packet loaded into VU1 data memory each frame is outline below. The first four locations contain the transformation matrix, this being followed by the GIFTag then the untransformed vertex data.

 

 

Address

Contents

0x000

Matrix Row 0

0x001

Matrix Row 1

0x002

Matrix Row 2

0x003

Matrix Row 3

0x004

GIFTag

0x005

STQ for Vertex 0

0x006

RGBA for Vertex 0

0x007

Position for Vertex 0

0x008

STQ for Vertex 1

0x009

RGBA for Vertex 1

0x00A

Position for Vertex 1

0x00B

STQ for Vertex 2

0x00C

RGBA for Vertex 2

0x00D

Position for Vertex 2

0x00E

STQ for Vertex 3

0x00F

RGBA for Vertex 3

0x010

Position for Vertex 3

 

 

The flow of the main program code is detailed given below:

 

·        The packet sent to VIF1 is 4 kBytes in size. There are VIF codes at the start and end of the packet.

·        The UNPACK VIF Code at the start of the packet unpacks 254 qwords, this being 256 qwords (4 kBytes) minus the 2 qwords containing VIF Codes at the start and end of the packet.

·        The bulk of the VIF packet is pre-built and stored in unswappable SPS2 memory.

·        The transformation matrix is altered slightly each frame and stored in the correct location in the VIF packet.

·        The VIF packet is sent to VU1 each frame to be processed.

 

The VU code in file vu1code.vcl is shown below.

 

 

StartVert

equ 7

; The first vertex is at address 7

NumVerts

equ 4

; There are 4 vertices

 

.include "vcl_sml.inc"

 

.init_vf_all

.init_vi_all

 

.syntax new

 

.vu

 

--enter

--endenter

 

iaddiu

iVert, vi00, 0

; Start vertex counter

iaddiu

iVertPtr, vi00, StartVert

; Point to the first vert

iaddiu

iNumVerts, vi00, NumVerts

; Load the loop end condition

 

 

 

MatrixLoad

fRotMatrix,0,vi00

; Load the matrix from VUMEM 0

 

 

 

 

 

 

loop:

 

; For each vertex

--LoopCS 4,0

 

; Minimum of 4 iterations

 

 

 

lq.xy

fVert, 0(iVertPtr)

; Load the XY components of the vert

MatrixMultiplyVertex

fVert,fRotMatrix,fVert

; Rotate the vertex

ftoi4.xy

fVert, fVert

; Convert to 12:4 fixed point

ftoi0.z

fVert, fVert

; Convert z to integer

mfir.w

fVert, vi00 

; set ADC to zero (DRAW)

sq.xyzw

fVert, 0(iVertPtr)

; Store the newly converted data

addiu

iVert, iVert, 1

; Increment the vertex counter

iaddiu

iVertPtr, iVertPtr, 3

; Increment the vertex pointer

ibne

iVert, iNumVerts, loop

; Branch back to "loop" label if

 

 

; iVert and iNumVerts are not equal

iaddiu

iGIFTag, vi00, 1

; Kick the data at VUMEM location 1

xgkick

iGIFTag

; to the GS

 

 

 

 

--exit

--endexit

 

 

The first thing to be notices about this code is that the file vcl_sml.inc is included. This file (supplied by Sony) contains useful macros. The macro MatrixLoad, loads the matrix data into floating point registers from data memory and the macro MatrixMultiplyVertex multiplies a vector containing vertex data by a matrix.

 

The reader is directed to the tutorial “2D Sprite Movement With Matrices (3D?)” for further information about this process. After the vertex data is transformed, the floating point x and y values are converted into 12:4 fixed point format and the z value is converted into an integer. It can be seen that there are appropriate VU instructions to perform the conversions.

 

Once all of the vertices are transformed they are sent of to the GS using the xgkick instruction for drawing.

 

It is recommended that the details of this VU code are investigated with the addition of the VU Users Manual

 

 

Conclusions

 

In this tutorial VU1 has been used to perform sprite rotation in three dimensions with the application of a transformation matrix.

 

 

Dr Henry S Fortuna

University of Abertay Dundee

h.s.fortuna@abertay.ac.uk