When attempting to play the classic racing game Need for Speed SE in a virtualized environment (VirtualBox), I was dismayed to discover that all the in-game videos were completely garbled. Curiously, the introductory video played when the game is first launched looked fine, even though there was no reason to think it should be any different from the in-game videos.
At first glance, it looked like the video mode used by the game didn’t match the data. Indeed the game was using a 320×200 mode at 16bpp, which was rather suspicious. One would expect an 8bpp mode, perhaps the standard VGA mode 13h, which is what the intro video uses.
A more detailed investigation revealed that the garbled video is the result of a subtle bug in NFS SE, rather than any deficiency in the virtualized environment. The game uses a routine called initgraphics which establishes a video mode. The routine predictably takes the requested resolution and color depth as arguments. However, the color depth is optional and if supplied as zero, the routine will choose a suitable mode. And that’s where the problem lies.
The initgraphics routine will use a 16bpp mode if found, otherwise it will fall back to an 8bpp mode. For some reason, or more likely, for no specific reason at all, the game uses the default color depth (zero) when playing in-game videos. However, the video playback in fact assumes an 8bpp mode and the output will be garbled (as shown above) if a different color depth is used.
So how come this bug was not found when Need for Speed SE was first released? That’s easy—at the time, the 320×200 mode at 16bpp was very unusual and not supported by the VESA BIOS built into the graphics cards. In that situation, the initgraphics routine falls back to 8bpp and all is well. But in a more modern environment, the 16bpp mode will be available and used, causing the video to be garbled.
How to fix this? One possibility is to make the 320×200, 16bpp mode unavailable, but that is not so easy and is only a workaround rather than a real fix. The better solution is to patch the game executable (NFS.EXE) to avoid the whole automatic color depth selection nonsense, which is not only unnecessary but wrong. All it takes is changing one byte where the arguments are passed to initgraphics in the video playback setup code, and using 8 instead of 0 for the color depth.
In my copy of NFS SE, that is the byte at offset 607E6h in the NFS.EXE file (dated 6-17-96, size 1,254,591 bytes). After changing it from zero to 8, the in-game videos appear like this: