My code and schematics are now up on Github. Hurrah.
While I was previously terribly excited by my flashing animation, I hadn't really noticed that the test stripes I'd put in the image were uneven, although this is pretty clearly visible:
Was this an artefact of the generating hardware's timing, or just the way that the monitor samples the data? 768x480 is not exactly a standard resolution, so it may be somewhat confused. If I go through the monitor's menu, it does indeed appear to be confused:
So, I tried to deconfuse it a bit. I reduced the horizontal resolution to 640 pixels, although this made the horizontal timing a bit strange, and I'm not sure the monitor believed me. However, between that and hitting the appropriate monitor menu items to get it to resync, I got the following output:
And here we can clearly see the pixels that the image maps to, and it appears there's a fairly consistent 2-to-3 source pixels to screen pixels mapping. It looks very much like the monitor trying to work out how to scale the image.
I may try a few more experiments to see how the monitor goes about its mapping, and try to work out why it decided to discretize rather than interpolate. It's kind of a shame I don't have a chunky old dumb analogue monitor any more to play around with.