1433 lines
67 KiB
OpenEdge ABL
1433 lines
67 KiB
OpenEdge ABL
;//--------------------------------------------------------------------------------
|
|
;// VCLSML - VCL Standard Macros Library
|
|
;// Version 1.4
|
|
;//
|
|
;// Geoff Audy, January 17th 2002 Initial macro set
|
|
;// Geoff Audy, March 26th 2002 Fixed some macros that were broken
|
|
;// Geoff Audy, March 27th 2002 Added some macros, most from Colin Hughes (SCEE)
|
|
;// Geoff Audy, April 2002 Added some macros, from Dave Etherton (Angel
|
|
;// Studios)
|
|
;// Geoff Audy, May 16th 2002 Added the macro "MatrixMultiplyVertexW1", from
|
|
;// Mike Healey (Rebellion)
|
|
;// Geoff Audy, June 2002 Added "MatrixInverse" from Adrian Stephen
|
|
;// (Luxoflux, via newsgroup)
|
|
;// Geoff Audy, July 2002 Added macros "Arccos", "QuaternionSlerp" and
|
|
;// "DistanceVertexToPlane"
|
|
;// Geoff Audy, October 7th 2002 Added macros "VertexLightDir3W1" and
|
|
;// "VertexLightDir3AmbW1"
|
|
;// Geoff Audy, March 19th 2004 Added a better accuracy "Arccos", from
|
|
;// Morten Mikkelsen (IO Interactive)
|
|
;// Geoff Audy, March 19th 2004 Added macro "Arcsin", from Morten Mikkelsen
|
|
;// (IO Interactive)
|
|
;// Geoff Audy, June 10th 2004 Fixed a bug in the macro "VectorDotProductACC".
|
|
;// "[z]" was missing at the end of the last line
|
|
;// Sandro S., June 18th 2022 Thank you guys for your work...
|
|
;//
|
|
;// Copyright (C) 2002-2004, Sony Computer Entertainment America Inc.
|
|
;// All rights reserved.
|
|
;//
|
|
;// Note: Some macros generate the following temporary variables:
|
|
;// vclsmlftemp: Temporary float register
|
|
;// vclsmlitemp: Temporary integer register
|
|
;// Some macros generate more temporary variables
|
|
;//--------------------------------------------------------------------------------
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixLoad - Load "matrix" from VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixLoad: matrix, offset, vumemlocation
|
|
lq matrix[0], offset+0(vumemlocation)
|
|
lq matrix[1], offset+1(vumemlocation)
|
|
lq matrix[2], offset+2(vumemlocation)
|
|
lq matrix[3], offset+3(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixSave - Save "matrix" to VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixSave: matrix,offset,vumemlocation
|
|
sq matrix[0], offset+0(vumemlocation)
|
|
sq matrix[1], offset+1(vumemlocation)
|
|
sq matrix[2], offset+2(vumemlocation)
|
|
sq matrix[3], offset+3(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixIdentity - Set "matrix" to be an identity matrix
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixIdentity: matrix
|
|
add.x matrix[0], vf00, vf00[w]
|
|
mfir.yzw matrix[0], vi00
|
|
|
|
mfir.xzw matrix[1], vi00
|
|
add.y matrix[1], vf00, vf00[w]
|
|
|
|
mr32 matrix[2], vf00
|
|
|
|
max matrix[3], vf00, vf00
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixCopy - Copy "matrixsrc" to "matrixdest"
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixCopy: matrixdest, matrixsrc
|
|
max matrixdest[0], matrixsrc[0], matrixsrc[0]
|
|
move matrixdest[1], matrixsrc[1]
|
|
max matrixdest[2], matrixsrc[2], matrixsrc[2]
|
|
move matrixdest[3], matrixsrc[3]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixSwap - Swap the content of "matrix1" and "matrix2"
|
|
;// The implementation seems lame, but VCL will convert moves to maxes
|
|
;// if it sees fit
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixSwap: matrix1, matrix2
|
|
move vclsmlftemp, matrix1[0]
|
|
move matrix1[0], matrix2[0]
|
|
move matrix2[0], vclsmlftemp
|
|
|
|
move vclsmlftemp, matrix1[1]
|
|
move matrix1[1], matrix2[1]
|
|
move matrix2[1], vclsmlftemp
|
|
|
|
move vclsmlftemp, matrix1[2]
|
|
move matrix1[2], matrix2[2]
|
|
move matrix2[2], vclsmlftemp
|
|
|
|
move vclsmlftemp, matrix1[3]
|
|
move matrix1[3], matrix2[3]
|
|
move matrix2[3], vclsmlftemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixTranspose - Transpose "matrixsrc" to "matresult". It is safe
|
|
;// for "matrixsrc" and "matresult" to be the same.
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;// Had to modify it though, it was too... smart.
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixTranspose: matresult, matrixsrc
|
|
mr32.y vclsmlftemp, matrixsrc[1]
|
|
add.z matresult[1], vf00, matrixsrc[2][y]
|
|
move.y matresult[2], vclsmlftemp
|
|
mr32.y vclsmlftemp, matrixsrc[0]
|
|
add.z matresult[0], vf00, matrixsrc[2][x]
|
|
mr32.z vclsmlftemp, matrixsrc[1]
|
|
mul.w matresult[1], vf00, matrixsrc[3][y]
|
|
mr32.x vclsmlftemp, matrixsrc[0]
|
|
add.y matresult[0], vf00, matrixsrc[1][x]
|
|
move.x matresult[1], vclsmlftemp
|
|
mul.w vclsmlftemp, vf00, matrixsrc[3][z]
|
|
mr32.z matresult[3], matrixsrc[2]
|
|
move.w matresult[2], vclsmlftemp
|
|
mr32.w vclsmlftemp, matrixsrc[3]
|
|
add.x matresult[3], vf00, matrixsrc[0][w]
|
|
move.w matresult[0], vclsmlftemp
|
|
mr32.y matresult[3], vclsmlftemp
|
|
add.x matresult[2], vf00, vclsmlftemp[y]
|
|
|
|
move.x matresult[0], matrixsrc[0] ;// These 4 instructions will be
|
|
move.y matresult[1], matrixsrc[1] ;// removed if "matrixsrc" and
|
|
move.z matresult[2], matrixsrc[2] ;// "matresult" are the same
|
|
move.w matresult[3], matrixsrc[3] ;//
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixMultiply - Multiply 2 matrices, "matleft" and "matright", and
|
|
;// output the result in "matresult". Dont forget matrix multipli-
|
|
;// cations arent commutative, i.e. left X right wont give you the
|
|
;// same result as right X left.
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixMultiply: matresult, matleft, matright
|
|
mul acc, matright[0], matleft[0][x]
|
|
madd acc, matright[1], matleft[0][y]
|
|
madd acc, matright[2], matleft[0][z]
|
|
madd matresult[0], matright[3], matleft[0][w]
|
|
mul acc, matright[0], matleft[1][x]
|
|
madd acc, matright[1], matleft[1][y]
|
|
madd acc, matright[2], matleft[1][z]
|
|
madd matresult[1], matright[3], matleft[1][w]
|
|
mul acc, matright[0], matleft[2][x]
|
|
madd acc, matright[1], matleft[2][y]
|
|
madd acc, matright[2], matleft[2][z]
|
|
madd matresult[2], matright[3], matleft[2][w]
|
|
mul acc, matright[0], matleft[3][x]
|
|
madd acc, matright[1], matleft[3][y]
|
|
madd acc, matright[2], matleft[3][z]
|
|
madd matresult[3], matright[3], matleft[3][w]
|
|
#endmacro
|
|
|
|
;//----------------------------------------------------
|
|
;// MatrixInverse - Does a full-fledge matrix inversion
|
|
;// of "matsrc", and output the result to "matdest".
|
|
;// Thanks to Adrian Stephen (Luxoflux) for that one
|
|
;// (via newsgroup)
|
|
;//
|
|
;// Note: ACC and Q registers are modified
|
|
;//----------------------------------------------------
|
|
#macro MatrixInverse: matdest, matsrc
|
|
opmula.xyz acc, matsrc[2], matsrc[3] ;c0 = src.z.xyz() ^ src.w.xyz();
|
|
opmsub.xyz c0, matsrc[3], matsrc[2]
|
|
mul.xyz acc, matsrc[2], matsrc[3][w] ;c1 = src.z.xyz() * src.w.w() - src.w.xyz() * src.z.w();
|
|
msub.xyz c1, matsrc[3], matsrc[2][w]
|
|
|
|
mul.xyz t0, c0, matsrc[1] ;dst.x = Vector((src.y.xyz() ^ c1) + c0 * src.y.w()).setw(-DotProd(c0,src.y.xyz()));
|
|
|
|
opmula.xyz acc, matsrc[1], c1
|
|
madd.xyz acc, c0, matsrc[1][w]
|
|
opmsub.xyz matdest[0], c1, matsrc[1]
|
|
|
|
mul.w acc, vf00, vf00[x]
|
|
msub.w acc, vf00, t0[x]
|
|
msub.w acc, vf00, t0[y]
|
|
msub.w matdest[0], vf00, t0[z]
|
|
|
|
mul.xyz t0, c0, matsrc[0] ;dst.y = Vector((c1 ^ src.x.xyz()) - c0 * src.x.w()).setw( DotProd(c0,src.x.xyz()));
|
|
|
|
opmula.xyz acc, c1, matsrc[0]
|
|
msub.xyz acc, c0, matsrc[0][w]
|
|
opmsub.xyz matdest[1], matsrc[0], c1
|
|
|
|
mul det, matsrc[0], matdest[0] ; for determinant calc
|
|
|
|
mul.w acc, vf00, t0[x]
|
|
madd.w acc, vf00, t0[y]
|
|
madd.w matdest[1], vf00, t0[z]
|
|
|
|
add.w acc, det, det[x]
|
|
madd.w acc, vf00, det[y]
|
|
madd.w det, vf00, det[z]
|
|
|
|
opmula.xyz acc, matsrc[0], matsrc[1] ;c0 = src.x.xyz() ^ src.y.xyz();
|
|
opmsub.xyz c0, matsrc[1], matsrc[0]
|
|
mul.xyz acc, matsrc[0], matsrc[1][w] ;c1 = src.x.xyz() * src.y.w() - src.y.xyz() * src.x.w();
|
|
msub.xyz c1, matsrc[1], matsrc[0][w]
|
|
|
|
div Q, vf00[w], det[w]
|
|
|
|
mul.xyz t0, c0, matsrc[3] ;dst.z = Vector((src.w.xyz() ^ c1) + c0 * src.w.w()).setw(-DotProd(c0,src.w.xyz()));
|
|
|
|
opmula.xyz acc, matsrc[3], c1
|
|
madd.xyz acc, c0, matsrc[3][w]
|
|
opmsub.xyz matdest[2], c1, matsrc[3]
|
|
|
|
mul.w acc, vf00, vf00[x]
|
|
msub.w acc, vf00, t0[x]
|
|
msub.w acc, vf00, t0[y]
|
|
msub.w matdest[2], vf00, t0[z]
|
|
|
|
mul.xyz t0, c0, matsrc[2] ;dst.w = Vector((c1 ^ src.z.xyz()) - c0 * src.z.w()).setw( DotProd(c0,src.z.xyz()));
|
|
|
|
opmula.xyz acc, c1, matsrc[2]
|
|
msub.xyz acc, c0, matsrc[2][w]
|
|
opmsub.xyz matdest[3], matsrc[2], c1
|
|
|
|
mul.w acc, vf00, t0[x]
|
|
madd.w acc, vf00, t0[y]
|
|
madd.w matdest[3], vf00, t0[z]
|
|
|
|
mul matdest[0], matdest[0], Q
|
|
mul matdest[1], matdest[1], Q
|
|
mul matdest[2], matdest[2], Q
|
|
mul matdest[3], matdest[3], Q
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// LocalizeLightMatrix - Transform the light matrix "lightmatrix" into
|
|
;// local space, as described by "matrix", and output the result in
|
|
;// "locallightmatrix"
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro LocalizeLightMatrix: locallightmatrix, matrix, lightmatrix
|
|
mul acc, lightmatrix[0], matrix[0][x]
|
|
madd acc, lightmatrix[1], matrix[0][y]
|
|
madd acc, lightmatrix[2], matrix[0][z]
|
|
madd locallightmatrix[0], lightmatrix[3], matrix[0][w]
|
|
|
|
mul acc, lightmatrix[0], matrix[1][x]
|
|
madd acc, lightmatrix[1], matrix[1][y]
|
|
madd acc, lightmatrix[2], matrix[1][z]
|
|
madd locallightmatrix[1], lightmatrix[3], matrix[1][w]
|
|
|
|
mul acc, lightmatrix[0], matrix[2][x]
|
|
madd acc, lightmatrix[1], matrix[2][y]
|
|
madd acc, lightmatrix[2], matrix[2][z]
|
|
madd locallightmatrix[2], lightmatrix[3], matrix[2][w]
|
|
|
|
move locallightmatrix[3], lightmatrix[3]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixMultiplyVertex - Multiply "matrix" by "vertex", and output
|
|
;// the result in "vertexresult"
|
|
;//
|
|
;// Note: Apply rotation, scale and translation
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixMultiplyVertex: vertexresult, matrix, vertex
|
|
mul acc, matrix[0], vertex[x]
|
|
madd acc, matrix[1], vertex[y]
|
|
madd acc, matrix[2], vertex[z]
|
|
madd vertexresult, matrix[3], vertex[w]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixMultiplyVertexW1 - Multiply "matrix" by "vertex", and output
|
|
;// the result in "vertexresult". Assumes 1.f for W field, which will
|
|
;// allow for better optimization in most cases, and leaves W free for
|
|
;// other uses (ADC flags, scale, etc).
|
|
;//
|
|
;// Note: Apply rotation, scale and translation
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixMultiplyVertexW1: vertexresult, matrix, vertex
|
|
mul acc, matrix[3], vf00[w]
|
|
madd acc, matrix[0], vertex[x]
|
|
madd acc, matrix[1], vertex[y]
|
|
madd vertexresult, matrix[2], vertex[z]
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------------------
|
|
;// MatrixMultiplyVertexXYZ1 - Multiply "matrix" by "vertex", and output
|
|
;// the result in "vertexresult"
|
|
;//
|
|
;// Note: Apply rotation, scale and translation
|
|
;// Note: ACC register is modified
|
|
;//---------------------------------------------------------------------
|
|
#macro MatrixMultiplyVertexXYZ1: vertexresult, matrix, vertex
|
|
mul acc, matrix[0], vertex[x]
|
|
madd acc, matrix[1], vertex[y]
|
|
madd acc, matrix[2], vertex[z]
|
|
madd vertexresult, matrix[3], vf00[w]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// MatrixMultiplyVector - Multiply "matrix" by "vector", and output
|
|
;// the result in "vectorresult"
|
|
;//
|
|
;// Note: Apply rotation and scale, but no translation
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro MatrixMultiplyVector: vectorresult, matrix, vector
|
|
mul acc, matrix[0], vector[x]
|
|
madd acc, matrix[1], vector[y]
|
|
madd vectorresult, matrix[2], vector[z]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorLoad - Load "vector" from VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorLoad: vector, offset, vumemlocation
|
|
lq vector, offset(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorSave - Save "vector" to VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorSave: vector, offset, vumemlocation
|
|
sq vector, offset(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorAdd - Add 2 vectors, "vector1" and "vector2" and output the
|
|
;// result in "vectorresult"
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorAdd: vectorresult, vector1, vector2
|
|
add vectorresult, vector1, vector2
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorSub - Subtract "vector2" from "vector1", and output the
|
|
;// result in "vectorresult"
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorSub: vectorresult, vector1, vector2
|
|
sub vectorresult, vector1, vector2
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLoad - Load "vertex" from VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLoad: vertex, offset, vumemlocation
|
|
lq vertex, offset(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexSave - Save "vertex" to VU mem location "vumemlocation" +
|
|
;// "offset"
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexSave: vertex, offset, vumemlocation
|
|
sq vertex, offset(vumemlocation)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexPersCorr - Apply perspective correction onto "vertex" and
|
|
;// output the result in "vertexoutput"
|
|
;//
|
|
;// Note: Q register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexPersCorr: vertexoutput, vertex
|
|
div q, vf00[w], vertex[w]
|
|
mul.xyz vertexoutput, vertex, q
|
|
; mul vertexoutput, vertex, q
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexPersCorrST - Apply perspective correction onto "vertex" and
|
|
;// "st", and output the result in "vertexoutput" and "stoutput"
|
|
;//
|
|
;// Note: Q register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexPersCorrST: vertexoutput, stoutput, vertex, st
|
|
div q, vf00[w], vertex[w]
|
|
mul.xyz vertexoutput, vertex, q
|
|
move.w vertexoutput, vertex
|
|
; mul vertexoutput, vertex, q
|
|
mul stoutput, st, q
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFPtoGsXYZ2 - Convert an XYZW, floating-point vertex to GS
|
|
;// XYZ2 format (ADC bit isnt set)
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFpToGsXYZ2: outputxyz, vertex
|
|
ftoi4.xy outputxyz, vertex
|
|
ftoi0.z outputxyz, vertex
|
|
mfir.w outputxyz, vi00
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFPtoGsXYZ2Adc - Convert an XYZW, floating-point vertex to GS
|
|
;// XYZ2 format (ADC bit is set)
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFpToGsXYZ2Adc: outputxyz, vertex
|
|
ftoi4.xy outputxyz, vertex
|
|
ftoi0.z outputxyz, vertex
|
|
ftoi15.w outputxyz, vf00
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFpToGsXYZF2 - Convert an XYZF, floating-point vertex to GS
|
|
;// XYZF2 format (ADC bit isnt set)
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFpToGsXYZF2: outputxyz, vertex
|
|
ftoi4 outputxyz, vertex
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFpToGsXYZF2Adc - Convert an XYZF, floating-point vertex to GS
|
|
;// XYZF2 format (ADC bit is set)
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFpToGsXYZF2Adc: outputxyz, vertex
|
|
ftoi4 outputxyz, vertex
|
|
mtir vclsmlitemp, outputxyz[w]
|
|
iaddiu vclsmlitemp, 0x7FFF
|
|
iaddi vclsmlitemp, 1
|
|
mfir.w outputxyz, vclsmlitemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// ColorFPtoGsRGBAQ - Convert an RGBA, floating-point color to GS
|
|
;// RGBAQ format
|
|
;//--------------------------------------------------------------------
|
|
#macro ColorFPtoGsRGBAQ: outputrgba, color
|
|
ftoi0 outputrgba, color
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// ColorGsRGBAQtoFP - Convert an RGBA, GS RGBAQ format to floating-
|
|
;// point color
|
|
;//--------------------------------------------------------------------
|
|
#macro ColorGsRGBAQtoFP: outputrgba, color
|
|
itof0 outputrgba, color
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGsPRIM - Create a GS-packed-format PRIM command, according to
|
|
;// a specified immediate value "prim"
|
|
;//
|
|
;// Note: Meant more for debugging purposes than for a final solution
|
|
;//--------------------------------------------------------------------
|
|
#macro CreateGsPRIM: outputprim, prim
|
|
iaddiu vclsmlitemp, vi00, prim
|
|
mfir outputprim, vclsmlitemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGsRGBA - Create a GS-packed-format RGBA command, according to
|
|
;// specified immediate values "r", "g", "b" and "a" (integer 0-255)
|
|
;//
|
|
;// Note: Meant more for debugging purposes than for a final solution
|
|
;//--------------------------------------------------------------------
|
|
#macro CreateGsRGBA: outputrgba, r, g, b, a
|
|
iaddiu vclsmlitemp, vi00, r
|
|
mfir.x outputrgba, vclsmlitemp
|
|
iaddiu vclsmlitemp, vi00, g
|
|
mfir.y outputrgba, vclsmlitemp
|
|
iaddiu vclsmlitemp, vi00, b
|
|
mfir.z outputrgba, vclsmlitemp
|
|
iaddiu vclsmlitemp, vi00, a
|
|
mfir.w outputrgba, vclsmlitemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGsSTQ - Create a GS-packed-format STQ command, according to
|
|
;// specified immediate values "s", "t" and "q" (floats)
|
|
;//
|
|
;// Note: I register is modified
|
|
;// Note: Meant more for debugging purposes than for a final solution
|
|
;//--------------------------------------------------------------------
|
|
#macro CreateGsSTQ: outputstq, s, t, q
|
|
loi s
|
|
add.x outputstq, vf00, i
|
|
loi t
|
|
add.y outputstq, vf00, i
|
|
loi q
|
|
add.z outputstq, vf00, i
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGsUV - Create a GS-packed-format VU command, according to
|
|
;// specified immediate values "u" and "v" (integer -32768 - 32768,
|
|
;// with 4 LSB as precision)
|
|
;//
|
|
;// Note: Meant more for debugging purposes than for a final solution
|
|
;//--------------------------------------------------------------------
|
|
#macro CreateGsUV: outputuv, u, v
|
|
iaddiu vclsmlitemp, vi00, u
|
|
mfir.x outputuv, vclsmlitemp
|
|
iaddiu vclsmlitemp, vi00, v
|
|
mfir.y outputuv, vclsmlitemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGsRGBA - Create a GS-packed-format RGBA command, according to
|
|
;// a specified immediate value "fog" (integer 0-255)
|
|
;//
|
|
;// Note: Meant more for debugging purposes than for a final solution
|
|
;//--------------------------------------------------------------------
|
|
#macro CreateGsFOG: outputfog, fog
|
|
iaddiu vclsmlitemp, vi00, fog * 16
|
|
mfir.w outputfog, vclsmlitemp
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// CreateGifTag - Create a packed-mode giftag, according to specified
|
|
;// immediate values. Currently only support up to 4 registers.
|
|
;//
|
|
;// Note: I register is modified
|
|
;// Note: Definitely meant for debugging purposes, NOT for a final
|
|
;// solution
|
|
;//--------------------------------------------------------------------
|
|
;// MIGHT NOT BE IMPLEMENTABLE AFTER ALL (AT LEAST NOT UNTIL VCL EVALUATES CONSTANTS!)
|
|
;// THAT WOULD HAVE BEEN KINDA COOL... DAMN. --GEOFF
|
|
;//#macro CreateGifTag outputgiftag,nloop,prim,nreg,reg1,reg2,reg3,reg4
|
|
;// iaddiu vclsmlitemp, vi00, nloop + 0x8000
|
|
;// mfir.x outputgiftag, vclsmlitemp
|
|
;// loi 0x00004000 + (prim * 0x8000) + (nreg * 0x10000000)
|
|
;// add.y outputgiftag, vf00, i
|
|
;// iaddiu vclsmlitemp, vi00, reg1 + (reg2 * 16) + (reg3 * 256) + (reg4 * 4096)
|
|
;// mfir.z outputgiftag, vclsmlitemp
|
|
;//#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorDotProduct - Calculate the dot product of "vector1" and
|
|
;// "vector2", and output to "dotproduct"[x]
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorDotProduct: dotproduct, vector1, vector2
|
|
mul.xyz dotproduct, vector1, vector2
|
|
add.x dotproduct, dotproduct, dotproduct[y]
|
|
add.x dotproduct, dotproduct, dotproduct[z]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorDotProductACC - Calculate the dot product of "vector1" and
|
|
;// "vector2", and output to "dotproduct"[x]. This one does it using
|
|
;// the ACC register which, depending on the case, might turn out to be
|
|
;// faster or slower.
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorDotProductACC: dotproduct, vector1, vector2
|
|
max Vector1111, vf00, vf00[w]
|
|
mul vclsmlftemp, vector1, vector2
|
|
add.x acc, vclsmlftemp, vclsmlftemp[y]
|
|
madd.x dotproduct, Vector1111, vclsmlftemp[z]
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorCrossProduct - Calculate the cross product of "vector1" and
|
|
;// "vector2", and output to "vectoroutput"
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorCrossProduct: vectoroutput, vector1, vector2
|
|
opmula.xyz ACC, vector1, vector2
|
|
opmsub.xyz vectoroutput, vector2, vector1
|
|
sub.w vectoroutput, vf00, vf00
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorNormalize - Bring the length of "vector" to 1.f, and output
|
|
;// it to "vectoroutput"
|
|
;//
|
|
;// Note: Q register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorNormalize: vecoutput, vector
|
|
mul.xyz vclsmlftemp, vector, vector
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[y]
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[z]
|
|
rsqrt q, vf00[w], vclsmlftemp[x]
|
|
sub.w vecoutput, vf00, vf00
|
|
mul.xyz vecoutput, vector, q
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VectorNormalizeXYZ - Bring the length of "vector" to 1.f, and out-
|
|
;// put it to "vectoroutput". The "w" field isn't transfered.
|
|
;//
|
|
;// Note: Q register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VectorNormalizeXYZ: vecoutput, vector
|
|
mul.xyz vclsmlftemp, vector, vector
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[y]
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[z]
|
|
rsqrt q, vf00[w], vclsmlftemp[x]
|
|
mul.xyz vecoutput, vector, q
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLightAmb - Apply ambient lighting "ambientrgba" to a vertex
|
|
;// of color "vertexrgba", and output the result in "outputrgba"
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLightAmb: rgbaout,vertexrgba,ambientrgba
|
|
mul rgbaout, vertexrgba, ambientrgba
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLightDir3 - Apply up to 3 directional lights contained in a
|
|
;// light matrix "lightmatrix" to a vertex of color "vertexrgba" and
|
|
;// having a normal "vertexnormal", and output the result in
|
|
;// "outputrgba"
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLightDir3: rgbaout, vertexrgba, vertexnormal, lightcolors, lightnormals
|
|
mul acc, lightnormals[0], vertexnormal[x]
|
|
madd acc, lightnormals[1], vertexnormal[y]
|
|
madd acc, lightnormals[2], vertexnormal[z]
|
|
madd rgbaout, lightnormals[3], vertexnormal[w] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
max rgbaout, rgbaout, vf00[x] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
mul acc, lightcolors[0], rgbaout[x]
|
|
madd acc, lightcolors[1], rgbaout[y]
|
|
madd rgbaout, lightcolors[2], rgbaout[z] ;// Here "rgbaout" is the light applied on the vertex
|
|
mul rgbaout, vertexrgba, rgbaout ;// Here "rgbaout" is the amount of light reflected by the vertex
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLightDir3W1 - Apply up to 3 directional lights contained in a
|
|
;// light matrix "lightmatrix" to a vertex of color "vertexrgba" and
|
|
;// having a normal "vertexnormal", and output the result in
|
|
;// "outputrgba". Assumes 1.0 for the normal's W field
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLightDir3W1: rgbaout, vertexrgba, vertexnormal, lightcolors, lightnormals
|
|
mul acc, lightnormals[0], vertexnormal[x]
|
|
madd acc, lightnormals[1], vertexnormal[y]
|
|
madd acc, lightnormals[2], vertexnormal[z]
|
|
madd rgbaout, lightnormals[3], vf00[w] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
max rgbaout, rgbaout, vf00[x] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
mul acc, lightcolors[0], rgbaout[x]
|
|
madd acc, lightcolors[1], rgbaout[y]
|
|
madd rgbaout, lightcolors[2], rgbaout[z] ;// Here "rgbaout" is the light applied on the vertex
|
|
mul rgbaout, vertexrgba, rgbaout ;// Here "rgbaout" is the amount of light reflected by the vertex
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLightDir3Amb - Apply up to 3 directional lights, plus an
|
|
;// ambient light contained in a light matrix "lightmatrix" to a vertex
|
|
;// of color "vertexrgba" and having a normal "vertexnormal", and
|
|
;// output the result in "outputrgba"
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLightDir3Amb: rgbaout, vertexrgba, vertexnormal, lightcolors, lightnormals
|
|
mul acc, lightnormals[0], vertexnormal[x]
|
|
madd acc, lightnormals[1], vertexnormal[y]
|
|
madd acc, lightnormals[2], vertexnormal[z]
|
|
madd rgbaout, lightnormals[3], vertexnormal[w] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
max rgbaout, rgbaout, vf00[x] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
mul acc, lightcolors[0], rgbaout[x]
|
|
madd acc, lightcolors[1], rgbaout[y]
|
|
madd acc, lightcolors[2], rgbaout[z]
|
|
madd rgbaout, lightcolors[3], rgbaout[w] ;// Here "rgbaout" is the light applied on the vertex
|
|
mul.xyz rgbaout, vertexrgba, rgbaout ;// Here "rgbaout" is the amount of light reflected by the vertex
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexLightDir3AmbW1 - Apply up to 3 directional lights, plus an
|
|
;// ambient light contained in a light matrix "lightmatrix" to a vertex
|
|
;// of color "vertexrgba" and having a normal "vertexnormal", and
|
|
;// output the result in "outputrgba". Assumes 1.0 for the normal's
|
|
;// W field.
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexLightDir3AmbW1: rgbaout, vertexrgba, vertexnormal, lightcolors, lightnormals
|
|
mul acc, lightnormals[0], vertexnormal[x]
|
|
madd acc, lightnormals[1], vertexnormal[y]
|
|
madd acc, lightnormals[2], vertexnormal[z]
|
|
madd rgbaout, lightnormals[3], vf00[w] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
max rgbaout, rgbaout, vf00[x] ;// Here "rgbaout" is the dot product for the 3 lights
|
|
mul acc, lightcolors[0], rgbaout[x]
|
|
madd acc, lightcolors[1], rgbaout[y]
|
|
madd acc, lightcolors[2], rgbaout[z]
|
|
madd rgbaout, lightcolors[3], rgbaout[w] ;// Here "rgbaout" is the light applied on the vertex
|
|
mul.xyz rgbaout, vertexrgba, rgbaout ;// Here "rgbaout" is the amount of light reflected by the vertex
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// FogSetup - Set up fog "fogparams", by specifying "nearfog" and
|
|
;// "farfog". "fogparams" will afterward be ready to be used by fog-
|
|
;// related macros, like "VertexFogLinear" for example.
|
|
;//
|
|
;// Note: I register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro FogSetup: fogparams, nearfogz, farfogz
|
|
sub fogparams, vf00, vf00 ;// Set XYZW to 0
|
|
loi farfogz ;//
|
|
add.w fogparams, fogparams, i ;// fogparam[w] is farfogz
|
|
loi nearfogz
|
|
add.z fogparams, fogparams, fogparams[w]
|
|
sub.z fogparams, fogparams, i
|
|
loi 255.0
|
|
add.xy fogparams, fogparams, i ;// fogparam[y] is 255.0
|
|
sub.x fogparams, fogparams, vf00[w] ;// fogparam[x] is 254.0
|
|
div q, fogparams[y], fogparams[z]
|
|
sub.z fogparams, fogparams, fogparams
|
|
add.z fogparams, fogparams, q ;// fogparam[z] is 255.f / (farfogz - nearfogz)
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFogLinear - Apply fog "fogparams" to a vertex "xyzw", and
|
|
;// output the result in "xyzfoutput". "xyzw" [w] is assumed to be
|
|
;// the distance from the camera. "fogparams" must contain farfogz in
|
|
;// [w], and (255.f / (farfogz - nearfogz)) in [z]. "xyzfoutputf" [w]
|
|
;// will contain a float value between 0.0 and 255.0, inclusively.
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFogLinear: xyzfoutput, xyzw, fogparams
|
|
move.xyz xyzfoutput, xyzw ;// XYZ part won't be modified
|
|
sub.w xyzfoutput, fogparams, xyzw[w] ;// fog = (farfogz - z) * 255.0 /
|
|
mul.w xyzfoutput, xyzfoutput, fogparams[z] ;// (farfogz - nearfogz)
|
|
max.w xyzfoutput, xyzfoutput, vf00[x] ;// Clamp fog values outside the range 0.0-255.0
|
|
mini.w xyzfoutput, xyzfoutput, fogparams[y] ;//
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// VertexFogRemove - Remove any effect of fog to "xyzf". "fogparams"
|
|
;// [ x ] must be set to 254.0. "xyzf" will be modified directly.
|
|
;//--------------------------------------------------------------------
|
|
#macro VertexFogRemove: xyzf, fogparams
|
|
add.w xyzf, vf00, fogparams[x] ;// xyzw[w] = 1.0 + 254.0 = 255.0 = no fog
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushInteger1 - Push "integer1" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushInteger1: stackptr, integer1
|
|
isubiu stackptr, stackptr, 1
|
|
iswr.x integer1, (stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushInteger2 - Push "integer1" and "integer2" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushInteger2: stackptr, integer1, integer2
|
|
isubiu stackptr, stackptr, 1
|
|
iswr.x integer1, (stackptr):VCLSML_STACK
|
|
iswr.y integer2, (stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushInteger3 - Push "integer1", "integer2" and "integer3" on
|
|
;// "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushInteger3: stackptr, integer1, integer2, integer3
|
|
isubiu stackptr, stackptr, 1
|
|
iswr.x integer1, (stackptr):VCLSML_STACK
|
|
iswr.y integer2, (stackptr):VCLSML_STACK
|
|
iswr.z integer3, (stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushInteger4 - Push "integer1", "integer2", "integer3" and
|
|
;// "integer4" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushInteger4: stackptr, integer1, integer2, integer3, integer4
|
|
isubiu stackptr, stackptr, 1
|
|
iswr.x integer1, (stackptr):VCLSML_STACK
|
|
iswr.y integer2, (stackptr):VCLSML_STACK
|
|
iswr.z integer3, (stackptr):VCLSML_STACK
|
|
iswr.w integer4, (stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopInteger1 - Pop "integer1" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopInteger1: stackptr, integer1
|
|
ilwr.x integer1, (stackptr):VCLSML_STACK
|
|
iaddiu stackptr, stackptr, 1
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopInteger2 - Pop "integer1" and "integer2" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopInteger2: stackptr, integer1, integer2
|
|
ilwr.y integer2, (stackptr):VCLSML_STACK
|
|
ilwr.x integer1, (stackptr):VCLSML_STACK
|
|
iaddiu stackptr, stackptr, 1
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopInteger3 - Pop "integer1", "integer2" and "integer3" on
|
|
;// "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopInteger3: stackptr, integer1, integer2, integer3
|
|
ilwr.z integer3, (stackptr):VCLSML_STACK
|
|
ilwr.y integer2, (stackptr):VCLSML_STACK
|
|
ilwr.x integer1, (stackptr):VCLSML_STACK
|
|
iaddiu stackptr, stackptr, 1
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopInteger4 - Pop "integer1", "integer2", "integer3" and
|
|
;// "integer4" on "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopInteger4: stackptr, integer1, integer2, integer3, integer4
|
|
ilwr.w integer4, (stackptr):VCLSML_STACK
|
|
ilwr.z integer3, (stackptr):VCLSML_STACK
|
|
ilwr.y integer2, (stackptr):VCLSML_STACK
|
|
ilwr.x integer1, (stackptr):VCLSML_STACK
|
|
iaddiu stackptr, stackptr, 1
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushMatrix - Push "matrix" onto the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushMatrix: stackptr, matrix
|
|
sq matrix[0], -1(stackptr):VCLSML_STACK
|
|
sq matrix[1], -2(stackptr):VCLSML_STACK
|
|
sq matrix[2], -3(stackptr):VCLSML_STACK
|
|
sq matrix[3], -4(stackptr):VCLSML_STACK
|
|
iaddi stackptr, stackptr, -4
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopMatrix - Pop "matrix" out of the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopMatrix: stackptr, matrix
|
|
lq matrix[0], 0(stackptr):VCLSML_STACK
|
|
lq matrix[1], 1(stackptr):VCLSML_STACK
|
|
lq matrix[2], 2(stackptr):VCLSML_STACK
|
|
lq matrix[3], 3(stackptr):VCLSML_STACK
|
|
iaddi stackptr, stackptr, 4
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushVector - Push "vector" onto the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushVector: stackptr, vector
|
|
sqd vector, (--stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopVector - Pop "vector" out of the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopVector: stackptr, vector
|
|
lqi vector, (stackptr++):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PushVertex - Push "vector" onto the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PushVertex: stackptr, vertex
|
|
sqd vertex, (--stackptr):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// PopVertex - Pop "vertex" out of the "stackptr"
|
|
;//
|
|
;// Note: "stackptr" is updated
|
|
;//--------------------------------------------------------------------
|
|
#macro PopVertex: stackptr, vertex
|
|
lqi vertex, (stackptr++):VCLSML_STACK
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// AngleSinCos - Returns the sin and cos of up to 2 angles, which must
|
|
;// be contained in the X and Z elements of "angle". The sin/cos pair
|
|
;// will be contained in the X/Y elements of "sincos" for the first
|
|
;// angle, and Z/W for the second one.
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;//
|
|
;// Note: ACC and I registers are modified, and a bunch of temporary
|
|
;// variables are created... Maybe bad for VCL register pressure
|
|
;//--------------------------------------------------------------------
|
|
#macro AngleSinCos: angle, sincos
|
|
move.xz sincos, angle ; To avoid modifying the original angles...
|
|
|
|
mul.w sincos, vf00, sincos[z] ; Copy angle from z to w
|
|
add.y sincos, vf00, sincos[x] ; Copy angle from x to y
|
|
|
|
loi 1.570796 ; Phase difference for sin as cos ( PI/2 )
|
|
sub.xz sincos, sincos, I ;
|
|
|
|
abs sincos, sincos ; Mirror cos around zero
|
|
|
|
max Vector1111, vf00, vf00[w] ; Initialise all 1s
|
|
|
|
loi -0.159155 ; Scale so single cycle is range 0 to -1 ( *-1/2PI )
|
|
mul ACC, sincos, I ;
|
|
|
|
loi 12582912.0 ; Apply bias to remove fractional part
|
|
msub ACC, Vector1111, I ;
|
|
madd ACC, Vector1111, I ; Remove bias to leave original int part
|
|
|
|
loi -0.159155 ; Apply original number to leave fraction range only
|
|
msub ACC, sincos, I ;
|
|
|
|
loi 0.5 ; Ajust range: -0.5 to +0.5
|
|
msub sincos, Vector1111, I ;
|
|
|
|
abs sincos, sincos ; Clamp: 0 to +0.5
|
|
|
|
loi 0.25 ; Ajust range: -0.25 to +0.25
|
|
sub sincos, sincos, I ;
|
|
|
|
mul anglepower2, sincos, sincos ; a^2
|
|
|
|
loi -76.574959 ;
|
|
mul k4angle, sincos, I ; k4 a
|
|
|
|
loi -41.341675 ;
|
|
mul k2angle, sincos, I ; k2 a
|
|
|
|
loi 81.602226 ;
|
|
mul k3angle, sincos, I ; k3 a
|
|
|
|
mul anglepower4, anglepower2, anglepower2 ; a^4
|
|
mul k4angle, k4angle, anglepower2 ; k4 a^3
|
|
mul ACC, k2angle, anglepower2 ; + k2 a^3
|
|
|
|
loi 39.710659 ; k5 a
|
|
mul k2angle, sincos, I ;
|
|
|
|
mul anglepower8, anglepower4, anglepower4 ; a^8
|
|
madd ACC, k4angle, anglepower4 ; + k4 a^7
|
|
madd ACC, k3angle, anglepower4 ; + k3 a^5
|
|
loi 6.283185 ;
|
|
madd ACC, sincos, I ; + k1 a
|
|
madd sincos, k2angle, anglepower8 ; + k5 a^9
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// ArcsinAccurate - Returns an accurate arcsin angle of a value, which
|
|
;// must be contained in the X element of "value". X element of "asin"
|
|
;// will contain, on return, the angle corresponding to the value.
|
|
;// Thanks to Morten Mikkelsen (IO Interactive) for that one
|
|
;//
|
|
;// Note: ACC, I registers are modified, and a bunch of temporary
|
|
;// variables are created... Maybe bad for VCL register pressure
|
|
;//--------------------------------------------------------------------
|
|
#macro ArcsinAccurate: value, asin
|
|
|
|
add.x acc, vf00, vf00[w]
|
|
msub.x Xc, value, value
|
|
sqrt Q, Xc[x] ; Xc = sqrt (1 - value * value)
|
|
add.x Xc, vf00, q
|
|
|
|
mr32.w bflip, value ; Sign in w field of bflip
|
|
abs.x Xs, value ; Xs = fabs (value)
|
|
|
|
loi 0x3f3504f3
|
|
subi.x bflip, Xs, i ; bflip = (Xs - sqrt (0.5f)) * I
|
|
loi 0z7F800000 ; I = big float
|
|
mul.xw bflip, bflip, i ;
|
|
mini.xw bflip, bflip, vf00[w] ; Minf (&bflip, bflip, 1), Minf (&Sign, Sign, 1) sign should only be zeroif bflip is, so offs should not be affected by this case
|
|
|
|
loi -1 ; I = -1.0
|
|
max.xw bflip, bflip, i ; Maxf (&bflip, bflip, -1), Maxf (&Sign, Sign, -1) if x is already zero, then scaling by zero will not matter either when sign is applied
|
|
|
|
add.x acc, vf00, bflip[w]
|
|
madd.x offs, bflip, bflip[w] ; offs = Sign + Sign * bflip
|
|
mul.x bflip, bflip, bflip[w] ; bflip *= Sign
|
|
|
|
mini.x temp, Xc, Xs ; temp = fmin (Xc, Xs)
|
|
mul.x temp, temp, bflip ; temp *= bflip
|
|
|
|
loi 0x3f490fdb ;
|
|
mul.x acc, offs, i ; MULA (offs, piquat)
|
|
|
|
loi -1.0 ; s1 = -1 (0xbf800000)
|
|
madd.x acc, temp, i ; MADDA (s1, temp)
|
|
|
|
mul.x x2, temp, temp ; x2 = temp * temp
|
|
loi 0xbe2aaaab ; s2 = -1 / 6
|
|
mul.x S2, temp, i ; S2 = s2 * temp
|
|
|
|
madd.x acc, S2, x2 ; MADDA (S2, x2)
|
|
|
|
mul.x x3, temp, x2 ; x3 = temp * x2
|
|
loi 0xbd36db6e ; s4 = -5 / 112
|
|
mul.x S4, x3, i ; S4 = s4 * x3
|
|
mul.x x5, x2, x3 ; x5 = x2 * x3
|
|
mul.x x4, x2, x2 ; x4 = x2 * x2
|
|
|
|
loi 0xbcf8e38e ; s5 = -35 / 1152
|
|
mul.x S5, x4, i ; S5 = s5 * x4
|
|
|
|
loi 0xbd99999a ; s3 = -3 / 40
|
|
mul.x S3, x2, i ; S3 = s3 * x2
|
|
|
|
madd.x acc, S3, x3 ; MADDA (S3, x3)
|
|
madd.x acc, S4, x4 ; MADDA (S4, x4)
|
|
madd.x asin, S5, x5 ; MADD (&r, S5, x5)
|
|
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// ArccosAccurate - Returns an accurate arccos angle of a value, which
|
|
;// must be contained in the X element of "value". X element of "acos"
|
|
;// will contain, on return, the angle corresponding to the value.
|
|
;// Thanks to Morten Mikkelsen (IO Interactive) for that one
|
|
;//
|
|
;// Note: ACC, I registers are modified, and a bunch of temporary
|
|
;// variables are created... Maybe bad for VCL register pressure
|
|
;//--------------------------------------------------------------------
|
|
#macro ArccosAccurate: value, acos
|
|
|
|
add.x acc, vf00, vf00[w]
|
|
msub.x Xc, value, value
|
|
sqrt Q, Xc[x] ; Xc = sqrt (1 - value * value)
|
|
add.x Xc, vf00, q ;
|
|
|
|
mr32.w bflip, value ; Sign in w field of bflip
|
|
abs.x Xs, value ; Xs = fabs (value)
|
|
|
|
loi 0x3f3504f3
|
|
subi.x bflip, Xs, i ; bflip = (Xs - sqrt (0.5f)) * I
|
|
loi 0z7F800000 ; I = big float
|
|
mul.xw bflip, bflip, i ;
|
|
mini.xw bflip, bflip, vf00[w] ; Minf (&bflip, bflip, 1), Minf (&Sign, Sign, 1) sign should only be zeroif bflip is, so offs should not be affected by this case
|
|
|
|
loi -1 ; I = -1.0
|
|
max.xw bflip, bflip, i ; Maxf (&bflip, bflip, -1), Maxf (&Sign, Sign, -1) if x is already zero, then scaling by zero will not matter either when sign is applied
|
|
|
|
mul.x bflip, bflip, bflip[w] ; bflip *= sign
|
|
loi 2.0
|
|
sub.w bflip, bflip, i ; (Sign - 2)
|
|
add.x offs, bflip, bflip[w] ; offs = (Sign - 2) + Sign * bflip
|
|
|
|
mini.x temp, Xc, Xs ; temp = fmin (Xc, Xs)
|
|
mul.x temp, temp, bflip ; temp *= bflip
|
|
|
|
loi 0xbf490fdb
|
|
mul.x acc, offs, i ; MULA (offs, -piquat)
|
|
|
|
loi 1.0 ; s1 = 1 (0x3f800000)
|
|
madd.x acc, temp, i ; MADDA (s1, temp)
|
|
|
|
mul.x x2, temp, temp ; x2 = temp * temp
|
|
loi 0x3e2aaaab ; s2 = 1 / 6
|
|
mul.x S2, temp, i ; S2 = s2 * temp
|
|
|
|
madd.x acc, S2, x2 ; MADDA (S2, x2)
|
|
|
|
mul.x x3, temp, x2 ; x3 = temp * x2
|
|
loi 0x3d36db6e ; s4 = 5 / 112
|
|
mul.x S4, x3, i ; S4 = s4 * x3
|
|
mul.x x5, x2, x3 ; x5 = x2 * x3
|
|
mul.x x4, x2, x2 ; x4 = x2 * x2
|
|
|
|
loi 0x3cf8e38e ; s5 = 35 / 1152
|
|
mul.x S5, x4, i ; S5 = s5 * x4
|
|
|
|
loi 0x3d99999a ; s3 = 3 / 40
|
|
mul.x S3, x2, i ; S3 = s3 * x2
|
|
|
|
madd.x acc, S3, x3 ; MADDA (S3, x3)
|
|
madd.x acc, S4, x4 ; MADDA (S4, x4)
|
|
madd.x acos, S5, x5 ; MADD (&r, S5, x5)
|
|
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// Arccos - Returns the arccos angle of up to 2 values, which must be
|
|
;// contained in the X and Z elements of "value". X and Z elements of
|
|
;// "acos" will contain, on return, the angles corresponding to the 2
|
|
;// values.
|
|
;//
|
|
;// ARCCOS(value) may be approximated with the following:
|
|
;// mirror = value * -HALFPI + HALFPI;
|
|
;// ARCCOS(value) = 2 * mirror -
|
|
;// (sin (value * HALFPI) * -HALFPI + HALFPI);
|
|
;//
|
|
;// Note: ACC and I registers are modified, and a bunch of temporary
|
|
;// variables are created... Maybe bad for VCL register pressure
|
|
;//--------------------------------------------------------------------
|
|
#macro Arccos: value, acos
|
|
loi 1.570796326 ; value * HALFPI
|
|
mul.xz acos, value, i ;
|
|
|
|
move.xz mirror, value ; Important to do it here, or else it would be invalid for "value" & "acos" to be the same
|
|
|
|
;//// This part is really just a copy of AngleSinCos
|
|
loi 1.570796326 ; Phase difference for sin as cos ( PI/2 )
|
|
sub.xz acos, acos, I ;
|
|
|
|
abs.xz acos, acos ; Mirror cos around zero
|
|
|
|
max.xz Vector1111, vf00, vf00[w] ; Initialise all 1s
|
|
|
|
loi -0.159155 ; Scale so single cycle is range 0 to -1 ( *-1/2PI )
|
|
mul.xz ACC, acos, I ;
|
|
|
|
loi 12582912.0 ; Apply bias to remove fractional part
|
|
msub.xz ACC, Vector1111, I ;
|
|
madd.xz ACC, Vector1111, I ; Remove bias to leave original int part
|
|
|
|
loi -0.159155 ; Apply original number to leave fraction range only
|
|
msub.xz ACC, acos, I ;
|
|
|
|
loi 0.5 ; Ajust range: -0.5 to +0.5
|
|
msub.xz acos, Vector1111, I ;
|
|
|
|
abs.xz acos, acos ; Clamp: 0 to +0.5
|
|
|
|
loi 0.25 ; Ajust range: -0.25 to +0.25
|
|
sub.xz acos, acos, I ;
|
|
|
|
mul.xz anglepower2, acos, acos ; a^2
|
|
|
|
loi -76.574959 ;
|
|
mul.xz k4angle, acos, I ; k4 a
|
|
|
|
loi -41.341675 ;
|
|
mul.xz k2angle, acos, I ; k2 a
|
|
|
|
loi 81.602226 ;
|
|
mul.xz k3angle, acos, I ; k3 a
|
|
|
|
mul.xz anglepower4, anglepower2, anglepower2 ; a^4
|
|
mul.xz k4angle, k4angle, anglepower2 ; k4 a^3
|
|
mul.xz ACC, k2angle, anglepower2 ; + k2 a^3
|
|
|
|
loi 39.710659 ; k5 a
|
|
mul.xz k2angle, acos, I ;
|
|
|
|
mul.xz anglepower8, anglepower4, anglepower4 ; a^8
|
|
madd.xz ACC, k4angle, anglepower4 ; + k4 a^7
|
|
madd.xz ACC, k3angle, anglepower4 ; + k3 a^5
|
|
loi 6.283185 ;
|
|
madd.xz ACC, acos, I ; + k1 a
|
|
madd.xz acos, k2angle, anglepower8 ; + k5 a^9
|
|
;//// This part was really just a copy of AngleSinCos
|
|
|
|
loi -1.570796326 ; mirror = value * -HALFPI + HALFPI
|
|
mul.xz mirror, mirror, i ;
|
|
sub.xz mirror, mirror, i ;
|
|
|
|
mul.xz acos, acos, i ;
|
|
sub.xz acos, acos, i ;
|
|
|
|
add.xz mirror, mirror, mirror ; acos = 2 * mirror - (sin (value * HALFPI) * -HALFPI + HALFPI)
|
|
sub.xz acos, mirror, acos ; Final result in "x"
|
|
#endmacro
|
|
|
|
;//------------------------------------------------------------------------------
|
|
;// QuaternionSlerp - Spherical interpolation between 2 quaternions. "quatfrom"
|
|
;// corresponds to time 0.0, and "quatto" corresponds to time 1.0. The X element
|
|
;// of "qtime" must contain the desired time value (0.0 - 1.0). The result will
|
|
;// be returned in "quatdest".
|
|
;//
|
|
;// Note: ACC, I and Q registers are modified
|
|
;//------------------------------------------------------------------------------
|
|
#macro QuaternionSlerp: quatdest, quatfrom, quatto, qtime
|
|
mul vclsmlftemp, quatfrom, quatto ; vclsmlftemp.x = dotproduct4 (quatfrom, quatto)
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[y] ;
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[z] ;
|
|
add.x vclsmlftemp, vclsmlftemp, vclsmlftemp[w] ;
|
|
|
|
loi -1.0 ;
|
|
|
|
move QSLquatto1, quatto ; We want to keep the angle between the 2 vectors <= PI
|
|
iaddiu vclsmlitemp, vi00, 0x80 ; (vclsmlftemp >= 0.0)
|
|
fmand vclsmlitemp, vclsmlitemp ;
|
|
ibeq vclsmlitemp, vi00, QSL1@ ;
|
|
|
|
mul.x vclsmlftemp, vclsmlftemp, i ; Inverse the "quatto" vector, so the angle between the
|
|
mul QSLquatto1, QSLquatto1, i ; 2 vectors will become < PI
|
|
|
|
QSL1@:
|
|
loi 0.999 ; If the angle is too small, we gotta do a linear
|
|
sub.x vf00, vclsmlftemp, i ; interpolation, because the slerp will fail
|
|
iaddiu vclsmlitemp, vi00, 0x80 ; (if (0.999 - vclsmlftemp.x < 0.0) it is too small)
|
|
fmand vclsmlitemp, vclsmlitemp ;
|
|
ibne vclsmlitemp, vi00, QSL2@ ;
|
|
|
|
add.x vclsmlftemp, vf00, qtime ; vclsmlftemp.x = qtime.x
|
|
add.z vclsmlftemp, vf00, vf00[w] ; vclsmlftemp.z = 1.0 - qtime.x
|
|
sub.z vclsmlftemp, vclsmlftemp, qtime[x] ;
|
|
|
|
b QSL3@ ; Go straight to the weighting part
|
|
|
|
QSL2@:
|
|
Arccos vclsmlftemp, QSLangle ; QSLangle.x = acos (vclsmlftemp.x)
|
|
AngleSinCos QSLangle, QSLsinom ; QSLsinom.x = sin (QSLangle.x)
|
|
|
|
add.z qtime, vf00, vf00[w] ; qtime.z = 1.0 - qtime.x
|
|
sub.z qtime, qtime, qtime[x] ;
|
|
|
|
mul.xz vclsmlftemp, qtime, QSLangle[x] ; vclsmlftemp.x = sin (time * QSLangle)
|
|
AngleSinCos vclsmlftemp, vclsmlftemp ; vclsmlftemp.z = sin ((1.0 - time) * QSLangle)
|
|
|
|
div q, vf00[w], QSLsinom[x] ; vclsmlftemp.x = vclsmlftemp.x / QSLsinom.x
|
|
mul.xz vclsmlftemp, vclsmlftemp, q ; vclsmlftemp.z = vclsmlftemp.z / QSLsinom.x
|
|
|
|
QSL3@:
|
|
mul acc, quatfrom, vclsmlftemp[z] ; Now that we have the src and dest scale (0.0 - 1.0), get the final result
|
|
madd quatdest, QSLquatto1, vclsmlftemp[x] ;
|
|
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// QuaternionToMatrix - Converts a quaternion rotation to a matrix
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;//
|
|
;// Note: ACC and I registers are modified
|
|
;//--------------------------------------------------------------------
|
|
#macro QuaternionToMatrix: matresult, quaternion
|
|
mula.xyz ACC, quaternion, quaternion ; xx yy zz
|
|
|
|
loi 1.414213562
|
|
muli vclsmlftemp, quaternion, I ; x sqrt2 y sqrt2 z sqrt2 w sqrt2
|
|
|
|
mr32.w matresult[0], vf00 ; Set rhs matrix line 0 to 0
|
|
mr32.w matresult[1], vf00 ;
|
|
mr32.w matresult[2], vf00 ; Set rhs matrix
|
|
move matresult[3], vf00 ; Set bottom line to 0 0 0 1
|
|
|
|
madd.xyz vcl_2qq, quaternion, quaternion ; 2xx 2yy 2zz
|
|
addw.xyz Vector111, vf00, vf00 ; 1 1 1 -
|
|
|
|
opmula.xyz ACC, vclsmlftemp, vclsmlftemp ; 2yz 2xz 2xy -
|
|
msubw.xyz vclsmlftemp2, vclsmlftemp, vclsmlftemp ; 2yz-2xw 2xz-2yz 2xy-2zw -
|
|
maddw.xyz vclsmlftemp3, vclsmlftemp, vclsmlftemp ; 2yz+2xw 2xz+2yz 2xy+2zw -
|
|
addaw.xyz ACC, vf00, vf00 ; 1 1 1 -
|
|
msubax.yz ACC, Vector111, vcl_2qq ; 1 1-2xx 1-2xx
|
|
|
|
msuby.z matresult[2], Vector111, vcl_2qq ; - - 1-2xx-2yy -
|
|
msubay.x ACC, Vector111, vcl_2qq ; 1-2yy 1-2xx 1-2xx-2yy -
|
|
msubz.y matresult[1], Vector111, vcl_2qq ; - 1-2xx-2zz - -
|
|
mr32.y matresult[0], vclsmlftemp2
|
|
msubz.x matresult[0], Vector111, vcl_2qq ; 1-2yy-2zz - - -
|
|
mr32.x matresult[2], vclsmlftemp2
|
|
addy.z matresult[0], vf00, vclsmlftemp3
|
|
mr32.w vclsmlftemp, vclsmlftemp2
|
|
mr32.z matresult[1], vclsmlftemp
|
|
addx.y matresult[2], vf00, vclsmlftemp3
|
|
mr32.y vclsmlftemp3, vclsmlftemp3
|
|
mr32.x matresult[1], vclsmlftemp3
|
|
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// QuaternionMultiply - Multiplies "quaternion1" and "quaternion2",
|
|
;// and puts the result in "quatresult".
|
|
;// Thanks to Colin Hughes (SCEE) for that one
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro QuaternionMultiply: quatresult, quaternion1, quaternion2
|
|
mul vclsmlftemp, quaternion1, quaternion2 ; xx yy zz ww
|
|
|
|
opmula.xyz ACC, quaternion1, quaternion2 ; Start Outerproduct
|
|
madd.xyz ACC, quaternion1, quaternion2[w]; Add w2.xyz1
|
|
madd.xyz ACC, quaternion2, quaternion1[w]; Add w1.xyz2
|
|
opmsub.xyz quatresult, quaternion2, quaternion1 ; Finish Outerproduct
|
|
|
|
sub.w ACC, vclsmlftemp, vclsmlftemp[z] ; ww - zz
|
|
msub.w ACC, vf00, vclsmlftemp[y] ; ww - zz - yy
|
|
msub.w quatresult, vf00, vclsmlftemp[x] ; ww - zz - yy - xx
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// TriangleWinding - Compute winding of triangle relative to "eyepos"
|
|
;// result is nonzero if winding is CW (actually depends on your
|
|
;// coordinate system)
|
|
;// Thanks to David Etherton (Angel Studios) for that one
|
|
;//
|
|
;// Note: ACC register is modified
|
|
;//--------------------------------------------------------------------
|
|
#macro TriangleWinding: result, vert1, vert2, vert3, eyepos
|
|
sub.xyz tw_vert12, vert2, vert1
|
|
sub.xyz tw_vert13, vert3, vert1
|
|
|
|
opmula.xyz ACC, tw_vert12, tw_vert13
|
|
opmsub.xyz tw_normal, tw_vert13, tw_vert12
|
|
|
|
sub.xyz tw_dot, eyepos, vert1
|
|
|
|
mul.xyz tw_dot, tw_dot, tw_normal
|
|
add.x tw_dot, tw_dot, tw_dot[y]
|
|
add.x tw_dot, tw_dot, tw_dot[z]
|
|
|
|
fsand result, 0x2
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// STATUSFLAGS_BGTZ - Branch if status shows "greater than zero".
|
|
;// Thanks to David Etherton (Angel Studios) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro STATUSFLAGS_BGTZ: label
|
|
fsand vclsmlitemp, 0x3 ; NEG | ZERO
|
|
ibeq vclsmlitemp, VI00, label ; Jump if NEITHER NEG NOR ZERO
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// STATUSFLAGS_BGEZ - Branch if status shows "greater or equal to
|
|
;// zero".
|
|
;// Thanks to David Etherton (Angel Studios) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro STATUSFLAGS_BGEZ: label
|
|
fsand vclsmlitemp, 0x2 ; NEG
|
|
ibeq vclsmlitemp, VI00, label ; Jump if NOT NEG
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// STATUSFLAGS_BLEZ - Branch if status shows "less or equal to zero".
|
|
;// Thanks to David Etherton (Angel Studios) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro STATUSFLAGS_BLEZ: label
|
|
fsand vclsmlitemp, 0x3 ; NEG | ZERO
|
|
ibne vclsmlitemp, VI00, label ; Jump if NEG OR ZERO
|
|
#endmacro
|
|
|
|
;//--------------------------------------------------------------------
|
|
;// STATUSFLAGS_BLTZ - Branch if status shows "less than zero".
|
|
;// Thanks to David Etherton (Angel Studios) for that one
|
|
;//--------------------------------------------------------------------
|
|
#macro STATUSFLAGS_BLTZ: label
|
|
fsand vclsmlitemp, 0x2 ; NEG
|
|
ibne vclsmlitemp, VI00, label ; Jump if NEG
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// DistanceVertexToPlane - Return the distance between a
|
|
;// homegeneous vertex "vertex" and a plane (described as
|
|
;// ABCD) "plane", and the result is returned in "distance".
|
|
;//---------------------------------------------------------
|
|
#macro DistanceVertexToPlane: distance, vertex, plane
|
|
mul distance, vertex, plane
|
|
add.x distance, distance, distance[y]
|
|
add.x distance, distance, distance[z]
|
|
add.x distance, distance, distance[w]
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// ResetClipFlags -
|
|
;// VCL won't let us use CLIP without first zeroing
|
|
;//---------------------------------------------------------
|
|
#macro ResetClipFlags
|
|
fcset 0x000000
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// PerformClipCheck - checks if the vertex is outside the viewing frustum.
|
|
;// If it is, then the appropriate clipping flags are set.
|
|
;// Not using sqi instruction, because VCL cannot optimize it.
|
|
;// Primtag contains information about how many polys we will send
|
|
;// 2 - Bitwise AND the clipping flags with 0x3FFFF, this makes sure that
|
|
;// we get the clipping judgement for the last three verts
|
|
;// (i.e. that make up the triangle we are about to draw)
|
|
;// 3 - Add 0x7FFF. If any of the clipping flags were set this will
|
|
;// cause the triangle not to be drawn (any values above 0x8000
|
|
;// that are stored in the w component of XYZ2 will set the ADC
|
|
;// bit, which tells the GS not to perform a drawing kick on this
|
|
;// triangle.
|
|
;//---------------------------------------------------------
|
|
#macro PerformClipCheck: t_vertex, t_destAddress, t_destAddressOffset
|
|
clipw.xyz t_vertex, t_vertex
|
|
fcand VI01, 0x3FFFF
|
|
iaddiu adcBit, VI01, 0x7FFF
|
|
isw.w adcBit, t_destAddressOffset(t_destAddress)
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// ScaleVertexToGSFormat - Scale vertex to GS screen space
|
|
;// 2 - Multiply and add the scales -> vert = vert * scale + scale
|
|
;// 3 - Convert vertex to 12:4 fixed point format
|
|
;//---------------------------------------------------------
|
|
#macro ScaleVertexToGSFormat: t_scale, t_vertex
|
|
mula.xyz acc, t_scale, vf00[w]
|
|
madd.xyz t_vertex, t_vertex, t_scale
|
|
ftoi4.xyz t_vertex, t_vertex
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// PerformTexturePerspectiveCorrection
|
|
;//---------------------------------------------------------
|
|
#macro PerformTexturePerspectiveCorrection: t_resultStq, t_stq
|
|
mulq t_resultStq, t_stq, q
|
|
#endmacro
|
|
|
|
;//---------------------------------------------------------
|
|
;// FixColor - Clamp colors to 0-255 and convert to integer
|
|
;//
|
|
;// 1. Load 255 and put it into the alpha value
|
|
;// 2. Clamp result to 0-255 values
|
|
;// 3. And write to the output buffer
|
|
;//---------------------------------------------------------
|
|
#macro FixColor: t_color
|
|
loi 255
|
|
mini.xyz t_color, t_color, i
|
|
max.xyz t_color, t_color, vf00[x]
|
|
ftoi0 t_color, t_color
|
|
#endmacro
|