Shader programs
The game’s shaders ship compiled for the PlayStation 3’s RSX in the SHADERS sections of the PAKs. A material names its vertex and pixel program by path (shaders\pixel\environment\env_base, without an extension), and the extension picks the entry: .vsp holds vertex programs, .psp pixel (fragment) programs and .shp the index of a shader’s permutations. Observed
Containers
Section titled “Containers”A .vsp or .psp entry is not one program but several, each a CgBinaryProgram (revision 6) padded with zeros to a multiple of 64 bytes and written one after another. Reading every pixel program file of the disc this way, refusing any nonzero padding, leaves no bytes over. Proven · all 765 pixel program files
The 765 .psp entries are in 274 of the 336 PAKs and hold 181,851 programs, of which 3,267 are distinct by their microcode and 20,391,890 instructions in all. Proven · all 336 PAKs
The parameter tables of the programs carry no texture-unit records for the samplers, so a program does not say which material slot feeds which texture unit; see the sampler slots. The vertex programs’ tables also have no names (vertex formats). Observed
Permutation index (.shp)
Section titled “Permutation index (.shp)”A .shp entry is a table of 16-byte entries, one per permutation, followed by a tail of metadata records. The tail is not
padding: the 1,508 .shp files hold 263,175,408 bytes after their tables, and every one of their 312,708 entries points into it.
Proven · all 336 PAKs
Big-endian 32-bit words.
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 4 | u32 | key | Inferred | the permutation key; the load callbacks take the first entry whose key equals the one requested |
| 0x4 | 4 | u32 | metadata offset | Proven | into the tail, relative to the end of the table |
| 0x8 | 4 | u32 | programs | Proven | locates the one or two adjacent programs of the permutation |
| 0xC | 4 | u32 | sizes | Proven | upper 16 bits: the metadata record's size; lower 16 bits: the sizes of its programs, each padded to 64 bytes, summed |
Proven · all 312,708 entries The key’s role is read from the executable’s vertex and fragment load callbacks. Inferred · read from the executable
A metadata record starts with a 44-byte header: the magic 0xAEBE000B for a vertex program or 0xDEDE0007 for a fragment
program, the variant count in byte 20, the descriptor count as 16 bits at 22, and at 24 the 32-bit offset of the descriptors,
20 bytes each (a hash, an encoding and three offsets). The records tile the whole tail, with zero padding to 16-byte alignment
between them. There are 160,617 vertex records (122,217 for one program and 38,400 for two) and 152,091 fragment records (122,331
and 29,760). Proven · all 336 PAKs The hashed descriptors number 114,407 in the vertex records, of 19 distinct hashes, and
4,048,334 in the fragment records, of 208, among them the hashes of the sampler names Color_Map, Normal_Map, Spec_Map and
Effect_Map. Proven · all 336 PAKs The descriptors cover material constants (the vertex constant c467 among them) but not
the shared transform c32 to c35 below, which the sky’s Cg program marks as shared. Observed Whether each variant’s 16-bit
values are texture units has not been checked against the units the game binds. Unknown
Once a program is loaded, the parent resource keeps its relocated metadata and the requested key; a material’s shader handle resolves to that same resource, and the vertex stage takes its program from a run-time array by an explicit variant index. Inferred · read from the executable How the key’s suffix is built from the material and the draw is not established.
Fragment microcode
Section titled “Fragment microcode”The pixel programs are RSX fragment microcode: 16-byte instructions, an instruction that reads an inline constant followed by that constant’s 16 bytes, and an end flag on the last instruction. Sourced · RPCS3
An independent decoder and RPCS3’s disassembler agree on every distinct program of the disc: the operands each prints, the texture units, the inline constants, the end flags and the IF boundaries, over 445,127 distinct instructions and 174,349 inline constants. Proven · all 3,267 distinct programs
The disassembler leaves some operands out, so its text is not a complete reading. Proven · all 3,267 distinct programs
| What RPCS3’s disassembly omits | Count on the disc | Confidence |
|---|---|---|
The second source of TXL and TXB (the level of detail or bias) and the third of TXD (the gradients) |
1,926 sampling operands | Proven · all 3,267 distinct programs |
An inline constant read as the level of detail of a TXL, printed as a NOP |
one program | Proven · all 3,267 distinct programs |
| ALU predicates, saturation and output scale | not counted | Sourced · RPCS3 |
Instruction census
Section titled “Instruction census”The 3,267 distinct pixel programs use 33 of the 62 fragment opcodes a decoder can name. The counts are over the 445,127 distinct instructions (the instructions of each distinct microcode once). Proven · all 3,267 distinct programs
| Opcode | Instructions | Programs | Opcode | Instructions | Programs | |
|---|---|---|---|---|---|---|
ADD |
100,811 | 3,246 | SGE |
4,318 | 2,058 | |
MOV |
83,219 | 3,264 | FLR |
3,647 | 468 | |
MAD |
76,315 | 3,248 | TXL |
1,926 | 1,926 | |
MUL |
59,423 | 3,241 | SLT |
1,916 | 1,724 | |
TEX |
20,446 | 3,249 | MAX |
1,712 | 1,657 | |
DP3 |
15,382 | 2,962 | KIL |
1,564 | 1,564 | |
DIV |
14,908 | 3,208 | FENCB |
1,133 | 1,000 | |
NRM |
14,533 | 3,006 | SEQ |
1,126 | 1,126 | |
FENCT |
8,967 | 2,565 | FRC |
1,060 | 355 | |
DP2 |
6,966 | 3,146 | IFE |
536 | 357 | |
RCP |
5,362 | 1,735 | SGT |
355 | 355 | |
DIVSQ |
5,031 | 3,151 | SIN, COS |
264 each | 264 | |
EX2 |
4,761 | 2,580 | DP4 |
138 | 68 | |
LG2 |
4,694 | 2,581 | SLE |
10 | 2 | |
RSQ |
4,327 | 2,765 | SNE, MIN, RET |
7, 3, 3 | 2, 2, 3 |
Proven · all 3,267 distinct programs
The other 29 opcodes never occur: NOP, DST, PK4, UP4, DDX, DDY, TXP, TXD, LIT, LRP, STR, SFL, PK2,
UP2, POW, PKB, UPB, PK16, UP16, PKG, UPG, DP2A, TXB, REFL, opcode 0x3C, BRK, CAL, LOOP and REP.
Proven · all 3,267 distinct programs The only control flow is IFE (357 programs) and RET (3 programs): there are no loops,
calls or breaks. Proven · all 3,267 distinct programs The IFE word that carries the else offset has the branch flag (bit 31 of
the third word) set in all 536 and the word that carries the end offset has bits 30 and 31 clear in all 536. Proven · all 3,267 distinct programs
The nouveau driver’s NV40 fragment encoder names RSQ, LIT, LRP, POW and REFL as NV30-only opcodes that it lowers
before encoding. Sourced · Mesa nouveau RSQ (opcode 0x1B) occurs 4,327 times in 2,765 of the programs, in 163,899 of the 181,851
program occurrences, so the RSX fragment unit executes it. The other four do not occur. Proven · all 3,267 distinct programs
Header flags and interpolants
Section titled “Header flags and interpolants”The fragment descriptor of the program header agrees with the code. pixel_kill is set in the 1,564 programs that contain a KIL
and in no other. The depth-replace flag, the output-from-H0 flag and the centroid mask are zero in all 3,267, the two-component
texture-coordinate mask is non-zero in all 3,267, and the two padding bytes are zero. Every program writes R0. Proven · all 3,267 distinct programs
No program writes depth, so where depth would be written (R1.z) is not observed. Proven · all 3,267 distinct programs
An instruction reads an interpolant through a four-bit source number in the first word (bits 13 to 16). Source 1 (colour 0) is
read by 9 programs, and source 4 + k is texture coordinate k for k = 0 to 7 and 9. The texture-coordinate mask of the header has
bit k set exactly when a program reads source 4 + k (texture coordinate 8 is never read), in each of the 3,267 programs; the
attribute-input mask has bit 14 + k set for texture coordinates 0 to 7, bit 13 for texture coordinate 9, and bits 0 and 2 in
the 9 programs that read colour 0. Sources 0 (position), 2, 3, 12 and 14 are never read. Proven · all 3,267 distinct programs
The parameter tables of the pixel programs list only uniforms (72,910 parameters, all uniform and all inputs), so no table names an
interpolant. Proven · all 3,267 distinct programs
Instruction words
Section titled “Instruction words”Each 32-bit word of a 16-byte instruction is rotated by 16 bits before its fields are read. The words below are numbered 0 to 3 after that rotation (word 0 holds the opcode and destination, words 1 to 3 the three sources).
| Field | What the 444,588 instructions that are not control flow hold | Confidence |
|---|---|---|
| Word 3 bits 21 to 29 | All ones on the 33,733 instructions that read an interpolant, zero on the other 410,855; bits 19 and 20 are always zero | Proven · all 3,267 distinct programs |
| Word 3 bit 30 | Zero in all 445,127 instructions | Proven · all 3,267 distinct programs |
| Word 3 bit 31 | Set on 6,346 of the 33,733 instructions that read an interpolant, never on the others | Proven · all 3,267 distinct programs |
| Word 1 bits 30 and 31 | Zero in all 445,127 instructions | Proven · all 3,267 distinct programs |
| Word 2 bits 28 to 30 (result scale) | 0 in 428,298; 1 in 7,635; 2 in 384; 5 in 5,702; 6 in 1,127; 7 in 1,442; 3 and 4 never | Proven · all 3,267 distinct programs |
| Word 2 bits 19 to 27 (three 3-bit fields) | Zero in 426,584; otherwise one of five patterns, only in ADD, MAD, MUL, FLR and NRM: first field 4 alone (2,905: 914 ADD, 816 MAD, 1,170 MUL, 5 FLR), second field 4 alone (514: 176 MAD, 338 MUL), second and third fields 4 (48 MAD), first and second fields 4 (4 MUL), and first field 5 on all 14,533 NRM |
Proven · all 3,267 distinct programs |
The one-bit flag in word 3 is a property of the interpolant, not of the instruction: in a program, all reads of one interpolant
carry the same bit 31 in 17,689 of the 17,691 (program, interpolant) pairs. It is clear in 5,300 of the 5,306 pairs for texture
coordinates 0 and 1 and set in 6,334 of 10,078 for texture coordinates 4 to 7; NRM accounts for 6,328 of the 6,346 instructions
that have it. Proven · all 3,267 distinct programs The coordinates that the 10,409 TEX instructions reading an interpolant sample
with are texture coordinate 0 (4,774) or 1 (5,635), and the flag is clear on all of them. Proven · all 3,267 distinct programs
Sampling coordinates are interpolated with perspective correction, so a set bit most likely turns the correction off for that interpolant. Inferred
Bit 31 is a per-interpolant flag that is clear on the sampling coordinates and set on most of the texture coordinates 4 to 7; its
sense is inferred, not shown by a table or a header field. The fields of word 2 above bit 18 are non-zero in only five
patterns, one of them on NRM alone.
Control-flow words
Section titled “Control-flow words”A branch instruction sets bit 31 of word 2, and its opcode is that bit as bit 6 over the six bits of the others: BRK, CAL, IFE, LOOP, REP and RET are
0x40 to 0x45, the codes 0 to 5 of Mesa’s branch opcodes. Sourced · Mesa nouveau, RPCS3
The remaining bits of words 2 and 3 are counts of 32-bit words from the start of the program or small counters, as the two describe them:
| Opcode | Word 2, bits 0 to 30 | Word 3, bits 0 to 30 |
|---|---|---|
IFE |
the else offset | the end offset |
CAL |
the offset of the called subroutine | not used |
LOOP |
three byte fields: the iteration count (bits 2 to 9), the initial counter value (10 to 17), the increment (19 to 26) | the end offset |
REP |
the same three byte fields, which Mesa found always filled with one repeat count | the end offset |
Sourced · Mesa nouveau, RPCS3
The IFE offsets of all 536 instructions on the disc are instruction boundaries (or the end of the program), the else offset at or after the instruction that follows the IFE and the end offset at or after the else offset. Proven · all 3,267 distinct programs
No CAL, LOOP, REP or BRK occurs, so the fields of those are as the two sources describe them and nothing more. Proven · all 3,267 distinct programs
Opcode names
Section titled “Opcode names”RPCS3’s names for the 62 opcode numbers a reader of these programs has an entry for are the ones this page uses. Mesa’s nouveau driver defines 55 of the numbers and names 11 of them differently, and has no name for the other seven:
| Number | RPCS3 | Mesa nouveau | Number | RPCS3 | Mesa nouveau | |
|---|---|---|---|---|---|---|
0x13 |
PK4 |
PK4B |
0x29 |
PK16 |
PK2US |
|
0x14 |
UP4 |
UP4B |
0x2A |
UP16 |
UP2US |
|
0x24 |
PK2 |
PK2H |
0x36 |
REFL |
RFL |
|
0x25 |
UP2 |
UP2H |
0x3C |
LIF |
LITEX2 |
|
0x27 |
PKB |
PK4UB |
0x42 |
IFE |
IF |
|
0x28 |
UPB |
UP4UB |
Sourced · Mesa nouveau, RPCS3
The numbers Mesa does not define are 0x2C (PKG), 0x2D (UPG), 0x38 (DP2), 0x39 (NRM), 0x3B (DIVSQ), 0x3D and 0x3E (FENCT and FENCB). NRM is the most used of them: 14,533 instructions on the disc. Sourced · Mesa nouveau, RPCS3
Vertex microcode
Section titled “Vertex microcode”A .vsp program’s microcode is 16-byte slots of four big-endian 32-bit words, as many as the vertex descriptor’s instruction count says, with bit 0 of the last word set in the final slot and in no other. Proven · all 170 distinct vertex programs
The 199,017 vertex programs of the disc are 170 distinct ones, 5,529 slots in all; the descriptor’s instruction slot is 0 and its user-clip mask 0 in every one. Proven · all 170 distinct vertex programs
A slot is the NV40 vertex instruction: up to two operations (a vector operation and a scalar one, either may be NOP) that share three source operands, one attribute index and one constant index, and each has its own destination and write mask. Sourced · Mesa nouveau
| Word | Bits | Field | What the 5,529 slots hold | Confidence |
|---|---|---|---|---|
| 1 | 22 to 26 | vector opcode | 13 of the 26 opcodes occur (below); no value without a name | Proven · all 170 distinct vertex programs |
| 1 | 27 to 31 | scalar opcode | 7 occur (below); BRA, CAL and the other control-flow values never occur |
Proven · all 170 distinct vertex programs |
| 1 | 8 to 11 | attribute index of every source of type input | read in the program header’s attribute_input_mask |
Proven · all 170 distinct vertex programs |
| 1 | 12 to 21 | constant index of every source of type constant | 828 slots index above 255 and the largest index is 467, the last of 468 constants; bit 21 is never set | Proven · all 170 distinct vertex programs |
| 1, 2, 3 | 0 to 7, 23 to 31; 6 to 22; 0 to 5, 21 to 31 | the three sources, 17 bits each, split across the words | type in bits 0 to 1 (1 temporary, 2 attribute, 3 constant), the temporary in bits 2 to 6, the swizzle in bits 8 to 15 (x highest), negate in bit 16 | Proven · all 170 distinct vertex programs |
| 0 | 21 to 23 | absolute value of source 0, 1, 2 | set on 25 slots (source 0) and 7 (source 1) | Proven · all 170 distinct vertex programs |
| 0 | 26 | saturate | set on 20 slots | Proven · all 170 distinct vertex programs |
| 0 | 15 to 20, 30 | vector destination temporary (63 for none) and the flag that sends the vector result to the output register | Proven · all 170 distinct vertex programs | |
| 3 | 7 to 12, 2 to 6 | scalar destination temporary and flag, and the output destination register shared by both operations | Proven · all 170 distinct vertex programs | |
| 3 | 13 to 16, 17 to 20 | vector and scalar write masks, x in the highest bit of each | Proven · all 170 distinct vertex programs | |
| 0 | 10 to 13, 2 to 9, 14 and 29 | condition test: code, test enable, the lanes it reads, and the update flag (bits 14 and 29 are set together) | test enabled on 9 slots (7 LT, 2 NE), the update flag on 8 |
Proven · all 170 distinct vertex programs |
| 0 | 27; 3 bit 1; 0 bit 24, bits 0 to 1 | relative addressing of attributes and of constants, and the address register and lane | clear on every slot, so no program is relatively addressed | Proven · all 170 distinct vertex programs |
| 0 | 28, 31 | not assigned | zero on every slot | Proven · all 170 distinct vertex programs |
The vector opcodes in use, with their slot counts: MAD 2,244, MUL 1,487, MOV 1,071, ADD 615, MAX 37, DP3 27, SGE 14, FLR 8, FRC 7, DP4 5, DPH 2, SLT 2, and NOP in 10 slots. The scalar opcodes: NOP in 5,186 slots, SIN 115, COS 83, RSQ 52, LG2 36, EX2 36 and RCP 21. Proven · all 170 distinct vertex programs
The nouveau driver and RPCS3 number the scalar branch and call opcodes differently (BRA is 9 and CAL 11 in the first, 8 and 10 in the second), and neither occurs on the disc, so their values are not settled here. Sourced · Mesa nouveau, RPCS3
The program header states what the code does. The attribute-input mask has bit n set exactly when an instruction reads attribute n, the register count is the highest temporary read or written plus one (at least one), and the attribute-output mask is the outputs the code writes: destination 1 sets bit 0, destinations 7 to 14 set bits 14 to 21 (destination n sets bit n + 7), and destination 6 sets bit 13 when written with all four lanes and bit 5 when written with x alone. All of it holds in 170 of 170 programs. Proven · all 170 distinct vertex programs
Destination 0 is the position, written by every program. Destinations 2 to 5 and 15 upward never occur, so the mapping of their bits follows the nouveau driver’s output numbering and is not measured. Sourced · Mesa nouveau
RPCS3’s vertex disassembler, an independent implementation of the same format, run over the 170 microcodes, prints the operations the decode finds (5,862 operations in all): the same opcodes in the same order, the same write masks, the same sources (register, swizzle, negate, absolute value), the same saturate and condition fields, and for every temporary result the same register. A vector MOV with the update flag and no destination temporary (MOVC RC.x, R4.x) writes the condition register alone, and RPCS3 prints RC as its destination. Proven · all 170 distinct vertex programs
Its names for the output destinations are indexed by the destination number as if destination 0 were a colour, so they cannot be used to name an output. Observed
The transform constants
Section titled “The transform constants”Vertex constants c32 to c35 hold the draw’s model-view-projection matrix: the placement’s world transform from the SCP, times the camera’s view, times its projection. Observed · one frame of the CHARLIE training lesson
A capture of the RSX commands of that frame (under RPCS3, at a fixed camera) has 2,105 geometry ranges in 1,516 draw scopes. The 991 ranges drawn with a vertex program of the classes that hold env_base_vs write all sixteen lanes of the four registers in the frame. For 781 of them a placement of the level gives a compatible matrix and for 210 none does. For two rotated placements whose captured vertex bytes equal the stored MMP bytes, and whose captured triangles all belong to that submesh, the four registers equal model × view × projection within 1.2 × 10⁻⁶. Observed · one frame
Those two draws use only part of the submesh’s triangles in their index buffers. Observed · one frame
Of the 991 ranges, 987 use vertex programs whose bytes are also those of programs of other shader families, so a draw’s program
bytes do not identify its material or its permutation key. Observed · one frame
In the captured frame, 210 ranges of the env_base program classes have no placement whose matrix fits the four registers. Whether they are objects placed by something other than the SCP, or the registers mean something else for them, is not established. Unknown
Programs that only scale a texture
Section titled “Programs that only scale a texture”Seven pixel program files contain only programs that sample one texture at the first texture coordinate and multiply the sample by named uniforms: one TEX, then MOV and MUL of registers and named constants, with no other interpolant and no flow control. They are env_skydome (all ten of its programs multiply by GlobalBrightness), env_challenge, env_icon, confident_arrows, confident_line, base_textured_2d_simple (texture unit 0) and albedo_multiply (texture unit 1). No other pixel program file has this form. Proven · all 765 pixel program files
These programs take no light, normal or fog input, so the surfaces they draw (the sky domes, and the materials named for challenge icons and guide arrows) are unlit: their colour is the texture times a constant. Inferred
env_texture, the program of MIKE’s distant panorama cards, is not of this form. Observed
The sky of CHARLIE is geometry: a dome drawn with an env_skydome material (material 510, 300 triangles) and two vista domes (material 4534, 30 and 22 triangles). All 352 triangles face the dome’s centre, so the domes are seen from inside without drawing back faces. Observed · CHARLIE
Its texture sky_skatehangar01_c is a 4096 × 1024 BC1 image of a sunset gradient. Observed
In one env_base permutation the material constant ColorBias is added to the colour, saturated, and the result fades toward ColorConstant; there ColorConstant is a target colour, not a multiplier of the texture. Inferred · read from one permutation
The fog pass
Section titled “The fog pass”Fog is a full-screen pass after the scene, the program rme\shaders\pixel\fsfx\fog.psp in RME.PAK. It reads the depth buffer at texture unit 1 as eight-bit RGB and rebuilds the 24-bit depth from the three bytes, rebuilds a position from it through the uniform matrix MainInv, and blends the scene colour toward the fog colour by a distance factor times a height factor. Inferred · read from the decoded program, not executed
With u, v the screen coordinates and a1 to a8 the fog parameters:
depth = r/2^8 + g/2^16 + b/2^24 (r, g, b the depth bytes)P = MainInv[0]·(2u−1) + MainInv[1]·(1−2v) + MainInv[2]·depth + MainInv[3]; P.xyz /= P.wS(t) = t²(3 − 2t) (smoothstep)tD = saturate((P.z − a1) / (a2 − a1))tH1 = saturate((P.y − a3) / ((a4 − a3)/2))tH2 = saturate((a4 − P.y) / ((a4 − a3)/2))f = S(tD) · S(tH1) · S(tH2)out = scene + f · a8 · ((a5, a6, a7) − scene)So the fog grows smoothly from distance a1 to a2, is strongest at the middle height of the band from a3 to a4 and falls to nothing at either edge, has the colour (a5, a6, a7) and never covers more than a8 of the scene. Inferred · read from the decoded program, not executed
The engine fills MainInv by inverting a camera matrix. That it is the inverse of the projection alone, which would make P.z the depth along the view, is concluded from the code’s structure and not observed. Inferred
The parameters are the arguments of the level scripts’ change_fog call, nine numbers of which the shader reads the first eight; what the ninth controls is not known. Observed The opacity a8 is 0.4157 in CHARLIE, 0.0588 in DELTA and 0.5216 in MIKE, and none of the ten levels sets it to zero. Observed
The band is tested on P.y of the rebuilt position. If MainInv inverts the projection alone, P is in view space and the band moves with the camera; a world-space band would need the view as well. A capture of MainInv from the running game would decide it.
change_fog passes nine values and the fog program reads eight. The ninth may be a transition time or a blend control outside the shader.