Understanding+PS2+VIF+Functions

Many PS2 games have 3d models stored on the disc, in a form that the console can quickly load into memory.

A description of the way models are stored in "Champions: Return to Arms", can be found here: http://code.google.com/p/bgda-explorer/wiki/VIFFile

This game and many others use a complex algorithm to generate the Face Index.

Often the face index contains flags. The elements that are greater then 127 are flagged. Thus we need to subtract 128 from each flagged element to get the true value. We also have to divide by a certain integer (always rounding down to whole numbers).

You need to do the subtraction first (if applicable) before dividing.

In the QuickBMS scripting language, you use a IF statement to do the subtraction if the number is greater then 127, if the number is less then 128 then nothing is done. After the IF statement we proceed to divide the number by the constant (usually 3 or 4).

At the core of the VIF function is an alogrithm that generates the face list recursively. This recursively defined function can be implemented in QuickBMS by allocating virtual "memory files (memory_file)" to store and operate on the data. The data is manipulated by allocating empty memory to a memory file, and "filling in" it in one piece at a time according to the recursion.

Here is an actual script that does a partial implementation of the conversion from VIF meshes to 3ds meshes in the game Champions: Return to Arms: http://ps23dformat.wikispaces.com/file/view/ChampionsReturnToArmsVIFto3dsBeta.bms

Here is an implmenation of just the VIF face list algorithm: log MEMORY_FILE1 0 0 ; log MEMORY_FILE2 0 0 ; log MEMORY_FILE3 0 0 ; For jjj = 1 To 1000 ; Put 00 Byte MEMORY_FILE3 ; Next jjj ; Get size ASIZE 0 ; Math size -= 12 ; Math size /= 6 ; GoTo 0xC 0 ; SavePos base 0 ; For ttt = 1 To size ; GoTo base 0 ; Get c1 Byte 0 ; Get d1 Byte 0 ; Get c2 Byte 0 ; Get d2 Byte 0 ; Get c3 Byte 0 ; Get d3 Byte 0 ; SavePos base 0 ; Math c1 /= 3 ; Math c2 /= 3 ; Math c3 /= 3 ; Put c1 Byte MEMORY_FILE1 ; Put c2 Byte MEMORY_FILE1 ; Put c3 Byte MEMORY_FILE1 ; Put d1 Byte MEMORY_FILE2 ; Put d2 Byte MEMORY_FILE2 ; Put d3 Byte MEMORY_FILE2 ; Next ttt ; Math base = 0 ; Math size -= 1 ; For hhh = 0 To size ; GoTo base MEMORY_FILE1 ; Get c1 Byte MEMORY_FILE1 ; Get c2 Byte MEMORY_FILE1 ; Get c3 Byte MEMORY_FILE1 ; SavePos base MEMORY_FILE1 ; GoTo c1 MEMORY_FILE3 ; Put hhh Byte MEMORY_FILE3 ; GoTo c2 MEMORY_FILE3 ; Get ccc Byte MEMORY_FILE3 ; GoTo c3 MEMORY_FILE3 ; Put ccc Byte MEMORY_FILE3 ; Next hhh ; Log output.dat 0 1000 MEMORY_FILE3 ;