Hi, this isn't so much an issue but rather asking for some assistance from someone who knows a little bit more about VIF tags than I do.
I have successfully written a simple VIF decoder in C# that is missing one crucial step -- actually interpreting the data!
Right now, I can produce logs similar to this:
>> ModelPackage index: 3
>> Processed 3 models / 2 materials.
>> Dumping model info...
**** Model 1 / 3 *****
******** Sub model 1 / 15 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:46
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:23
V3_8_MASKED : +FLAG : ADDR:2, NUM:23
STCYCL : : CL:4, WL:2
ITOP : : ADDR:17
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:48
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:24
V3_8_MASKED : +FLAG : ADDR:2, NUM:24
STCYCL : : CL:4, WL:2
ITOP : : ADDR:18
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:46
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:23
V3_8_MASKED : +FLAG : ADDR:2, NUM:23
STCYCL : : CL:4, WL:2
ITOP : : ADDR:17
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:48
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:24
V3_8_MASKED : +FLAG : ADDR:2, NUM:24
******** Sub model 2 / 15 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:8
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:4
V3_8_MASKED : +FLAG : ADDR:2, NUM:4
... etc ...
******** Sub model 13 / 15 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:46
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:23
V3_8_MASKED : +FLAG : ADDR:2, NUM:23
STCYCL : : CL:4, WL:2
ITOP : : ADDR:17
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:46
******** Sub model 14 / 15 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:28
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:14
******** Sub model 15 / 15 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:8
STCYCL : : CL:4, WL:1
V4_8 : +FLAG : ADDR:0, NUM:4
V3_8_MASKED : +FLAG : ADDR:2, NUM:4
**** Model 2 / 3 *****
******** Sub model 1 / 2 *********
STCYCL : : CL:4, WL:2
STMASK : : MASK:C0C0C0C0
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:48
STCYCL : : CL:4, WL:1
V4_16 : +FLAG : ADDR:0, NUM:24
V3_8_MASKED : +FLAG : ADDR:2, NUM:24
STCYCL : : CL:4, WL:2
ITOP : : ADDR:18
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:48
STCYCL : : CL:4, WL:1
V4_16 : +FLAG : ADDR:0, NUM:24
V3_8_MASKED : +FLAG : ADDR:2, NUM:24
STCYCL : : CL:4, WL:2
MSCNT : :
S_16 : +FLAG +UNSIGNED : ADDR:2, NUM:48
... etc ...
The model/submodel stuff is part of the proprietary model format I'm reading the data from, but it's just basically a bunch of individual meshes split up by their texture index.
Anyways, I don't fully understand what's going on here. It's very difficult to find information about this on the internet, and most people don't seem to refer to the data types by their actual name. Due to this, I don't know if their usage is one and the same for every game, or if every game is different.
The PCSX2 source code was indeed helpful, especially for retrieving the proper names of the data types. However, it's not exactly clear what the _purpose_ of each type is. It only seems to be short-hand for Single, Vector2, Vector3, and Vector4, with the data being 8, 16, or 32-bit (one apparently is RGB555A1).
Then there's the "FLAG" and "UNSIGNED" stuff. Obviously I understand what unsigned data types are, but I have no idea what the FLAG field is supposed to do. Is there a possibility a V4_16 data type won't actually be used for storing floating-points? Will a V3_8 data type always be used to store RGB colors? It's stuff like this I am completely lost on, which is why I would appreciate the help.
Hopefully someone can help me understand this a bit better. I would like to know how STCYCL and STMASK play a part, and I'd love to just refer to PCSX2's source, but it's all split up and I just don't know enough about this stuff to grasp it completely. If anyone has resources that provide detailed information on _how_ this stuff works, and how each tag plays a part in what's going on, I would be extremely grateful. I don't care for the slideshow presentations of how this stuff is fast, or how VIF tags are used to store model data for the PS2 to interpret quickly...I would love to refer to in-depth documentation. How else would game developers convert model formats for use on PS2?!
I do apologize for writing quite a bit here. But I am hoping someone can point me in the right direction, as I would greatly appreciate it. If you're interested in seeing my VIF dumper code, here is the code that produces the log similar to above (the code for each type is just a placeholder, I don't think it's correct), and you can also look here to see the different classes I made for interpreting VIF/GIF data easily. No need for complicating bit shifting or masks when I can just write a class that does it all for me, lol.
Thanks!
Did you try to search some EE (emotion engine) doc on google? Maybe official docs explain vif to game devs.
Btw, ultimately data are sent to GS. You can see if it used as color/texture...
owever, it's not exactly clear what the purpose of each type is. It only seems to be short-hand for Single, Vector2, Vector3, and Vector4, with the data being 8, 16, or 32-bit (one apparently is RGB555A1).
You're pretty much right there, however it always writes 4 vectors of data, regardless of format, just in the cases of V2 and V3 it has "indeterminate" data which tends to be repetition of the data already written or the next block of data coming (from my tests on the PS2 anyway, And1 Streetball and Lemmings rely on this), but data written to the VU's can be integer data or floating point data, there is no specific format that it has to be written in as the VU's can convert between the two.
I should also say at this point that the data is always "unpacked" to 32bits in size so it fills the entire vector, it never overwrites certain bits, it is either the entire 128bits of the row, or nothing.
As for the sign flag, as far as I'm aware, it is just really used for V2 and V3 (or S8, S16) formats and it will extend the sign all the way over to the full 32 bits, so if you do write say 0x8023, it will extend that to 0xffff8023. My only assumption is that is because the VU does deal with signed numbers and it probably doesn't know how to interpret 16bit signed integers as it works in 32bit chunks only.
I hope that helps somewhat.
Thank you @refractionpcsx2, very interesting how you mention it always writes 4 vectors of data. I suppose this is where STCYCL and STMASK come into play? I'm thinking I'll have to take those into account and dump everything into a single vertex buffer (?) and then figure out a way of going about creating the index buffer...
@gregory38 I have looked pretty much everywhere for this sort of information and cannot find it anywhere. Would be nice to find something like that though!
You should definitely find yourself a copy of the official PS2 SDK on google and look through both the documentation of the system and the programmer's manuals. There's a bunch of documents you can find that accurately describe how VIF tags work .
Thank you @refractionpcsx2, very interesting how you mention it always writes 4 vectors of data. I suppose this is where STCYCL and STMASK come into play?
The STCYCL controls how 128bit vectors are "skipped" when writing the VIF data to the VU's, this however has no bearing on the individual 32bit vectors.
STMASK however does have controls for this, it has the ability to write protect individual 32bit vectors when writing the data to the VU, however this is mostly used to add on the ROW/COL data more than anything else.
But yes, it always writes an entire quadword of data unless it is masked, even if the unpack functions are only for 2 or 3 vectors :)
@Fireboyd78 are you question answered ? Could we close this issue ?
@gregory38 Sorry about that, I think I got all the information I needed. Thanks again for the help!