Ian, I've just merged your last commit in my build and works great! I didn't think of a model-level attribute (model->scale), it just makes sense after all
In my version also something wasn't updated correctly because my "modelScale" values weren't always set or were wrong, hence my hybrid solution to rely only on the matrix scaling factor and use "modelScale" just as a trigger.
However by scaling the "matrix*normal" product still produces errors with specular lightning (not visible in the official build). We should first divide the normal vector by its length (or normalize it), then scaling it, and finally multiply it with the matrix.
Also relying on the matrix scale values when "modelScale" is 1.0 (or unset) fixes Lost World overbrightened models. Again, in the official build we cannot see this misbehavior because the sunlight in the shader is always clamped.
Here's my proposed change in <R3DShader.cpp>: