Fixed! It was a faulty I2C EEPROM. There are three on the board, two are clearly for monitor EDID information (VGA & DVI), the third is configuration storage. On the DSO could see that the SCK line was not toggling, so I lifted the eeprom off the board and it started to clock... the EEPROM had failed. I replaced it with a scavenged part and blanked it, which didn't fix the problem, so I flashed it with all zeros... fixed.
Further messing around I figured out why it corrupted the output, three signed 8 bit bytes control the R, G & B intensity values, where 0x64 is the highest configurable via the OSD interface, but since the I2C wasn't reading it was returning 0xFF... welcome to integer overflow city

. It also explains the faulty menu as it's configurable X/Y position was also out of bounds.
Interestingly I can also change the service information too (hours on, etc).
struct serviceInfo // @ 0x0
{
char[8] monitorOnTime;
char[8] panelOnTime;
char[16] unknown; // might be a GUID or serial, no way to know without a working eeprom to compare with.
char[8] powerCycleCount;
}
struct menuPosition // @ 0x47
{
uint8_t x, y; //maximum value = 0x64
}
The serviceInfo values are not integers but strings and only 6 bytes are shown in the OSD but all 8 are used. They use some non standard character map (not ASCII):
Ord Character
0x00 0
0x01 1
0x02 2
0x03 3
...
0x09 9
0x0A "
...
0x41 p
More can be discovered through trial and error, comparing dumps. One undocumented feature I have noted when just setting the entire eeprom to an arbitrary value (0x4) is a soft fade in rather then a sharp turn on when waking up, it would be nice to find the byte that turns this on

.
I don't have time at the moment but later I will poke at it a bit more and see what else lurks in this EEPROM
