OK, let's start from the beginning (this will be a useful intellectual exercise and perhaps create some useful documentation that might help future development.
A projected light works by mapping points in 3D space into texture coordinates, which are then used to sample a 2D light falloff texture and a separate 1D gradient texture resulting in a final color for each illuminated pixel. Every point within the light volume should be transformed into a triplet of texture coordinates, where the X and Y coordinates (conventionally called S and T in a shader) run from 0.0 to 1.0, and the Z coordinate runs from 0.5 at the origin to 0.0 at the target plane. The other half of the Z range (from 0.5 to 1.0) is actually behind the light origin but we clamp this to 0 to avoid the light projecting backwards as well as forwards.
The projected light is defined by four vectors:
The origin in 3D space (the tip of the pyramid).
A light_target vector, labelled t in the diagram, which points from the origin to the center of the target plane, and is considered the light's local -Z axis.
A light_right vector, labelled r in the diagram, which goes from the center of the target plane to its rightmost edge, and is considered the lights +X axis.
A light_up vector, labelled u in the diagram, which goes from the center of the target plane to its uppermost edge, and is considered the light's +Y axis.
Based on these vectors, and the expected resulting texture coordinates, we can assume certain properties of our projection matrix P which we need to construct:
P · (0, 0, 0) = (0, 0, 0.5)
The origin point must have a Z texture coordinate of 0.5, which is the brightest part of the Z falloff texture.
For all x and y: P · (x, y, 0) = (0, 0, 0.5)
Because of the singularity at the light origin point, any point with Z=0 should have X and Y coordinates reduced to 0.
P · t = (0.5, 0.5, 0)
The target vector points to the center of the projected backplane, which has texture X/Y coordinates of 0.5 and a Z coordinate of 0 (the darkest point in the Z falloff texture).
P · (t + r + u) = (1, 1, 0)
The "top right" corner, reached by travelling along the target vector then along both the right and up vector, should be at the (1.0, 1.0) edge of the 2D falloff texture.
P · (t - r - u) = (0, 0, 0)
Likewise the "bottom right" corner, reached by travelling along the target vector than backwards along the right and up vectors, should be at the (0.0, 0.0) edge of the 2D falloff texture.
A reasonable approach to debugging, therefore, will be to print out the transformations of these vector combinations under our projection matrix P, and see how far off they are the expected texture coordinates.