Discovering a New VGA Mode

A project log for Beckman DU 600 Reverse Engineering

Reverse engineering process for a 68332 based system

joe.zatarskijoe.zatarski 12/23/2016 at 06:330 Comments

Given that the CL-GD5429 on the Beckman motherboard only has 512KB of memory, yet supports 1280x1024 modes (and 1600x1200 interlaced), I began to look into ways to support higher resolution modes about a year ago, sometime in early 2016. 1280x1024x4bpp uses 640KB of video memory. If I could find a way to reduce the bit depth to 1 or 2bpp, I would cut the memory usage down enough to support a 1280x1024 display in the limited 512KB of memory available to the 5429.

Having some experience with the common modes supported on VGA, I knew that there were CGA compatibility modes using 1 and 2bpp color depths, so this is where I began my search. However, I quickly realized that these modes were not efficient with memory. They were designed purely for compatibility, and nothing else, effectively being 4bpp modes themselves that masked off 2 or 3 bits resulting in the 1 and 2bpp modes. This was a dead end.

However, during my browsing of the 5429 technical reference manual, I noticed a pair of bits that sounded promising. These two were the 'Shift and Load 32' and 'Shift and Load 16' bits in the VGA Sequencer's clocking register (SR1).

According to the Cirrus Logic technical reference, the Shift and Load 32 bit, "controls the Display Data Shifters in the Graphics Controller according to the following table:"

SR1[4]SR1[2]Data Shifters Loaded
00Every character clock
01Every 2nd character clock
1XEvery 4th character clock

To me, these two fields sounded potentially like the answer to 1 and 2bpp modes. One 'character' on the VGA when doing graphics was 8 pixels. Due to the organization of VGA memory being (logically) 32 bits wide, 8 4-bit pixels normally fit into one word, meaning you would logically load the video shift registers once per character clock. Together, the '4' video shifters would shift out 4 bits at a time, one set of 4 for each pixel. However, in 2 or 1bpp modes, you would have 16 or 32 pixels per word respectively, equaling 2 or 4 characters worth of pixels each. So, in this case, you would load the data shifters once every 2 or 4 character clocks since one word now was equivalent to that number of characters worth of pixels. While the video shift registers are normally thought to be 4 independent 8-bit shift registers, I theorize (at least in these modes) that the shift registers actually feed into each other, producing a 32 bit shift register chain, with 'taps' every 8 bits for the bits which go to the attribute controller (which translates 4 bit values into the 8-bit color values going to the pallette DAC).

However, this brings up another point: 4 bits still go to the attribute controller, even in these cases where only 1 or 2 bits should be used. These can cause odd colors to be produced as the bits shift through the shifters, and the farther right pixels act as more significant bits. For example, suppose we have a monochrome bit stream loaded into the shifters like this:





8 pixel clocks later, the shifters will look like this:





In the first example, the 4 bit attribute is 0110, while in the second it is 0011. For a 1bpp mode, we actually only care about the LSB of this nibble. Luckily, there are ways to remedy this in the attribute controller. The first way, is to use the 'Enable Color Plane' bits in the 'Color Plane Enable Register' (AR12). These bits allow you to AND mask off the other bits in the attributes. Loading with a value of 0001 selects just the LSB for 1bpp modes, and loading with a value of 0101 selects the two relevant bits for 2bpp modes. The other way to remedy this issue is to load the attribute controller palette registers such that the colors selected are independent of the bits which should not influence the color. For example, making all of the even attributes one color, while all the odd attributes are another color, effectively ignores all but the LSB, giving the same effect. Similarly, making colors 0000, 0010, 1000, and 1010 all the same effectively ignores bit 1 and 3 for 2bpp modes. Either method of ignoring the irrelevant bits works correctly. This is also a point to bring up potential differences in VGA chipsets. It's possible that on certain chips, the roles of bits may be reversed. On some chipsets, the bit that should be used is the MSB, while the bits to ignore are the 3 lower bits, and similar for 2bpp modes. I have not encountered a chip like this, but that doesn't mean it doesn't exist (small tested sample size of 2).

Lastly, a timing issue seems to arise causing the display to repeat the first 24 pixels on the left before the display properly begins. This is solved by setting another field properly, this time in the CRTC. The display enable skew field in the 'Horizontal Blanking End Register' (CR3) should be set to 3, and this appears to remedy the issue.

Sometime in january of 2016, I managed to finally test and implement the 1bpp variant of this mode successfully. Somewhat through trial and error, I was able to find out the third point about display enable skew, as well as the general behavior, after much experimentation, with the various 'shift and load' bit settings described in the first part. The important thing is that the mode worked. I then became curious what other chipsets this mode was possible on. I had proven it on a CL-GD5429, but did it work on others? Unfortunately, I don't have a genuine IBM VGA controller to try this on, but I also managed to test it on my Compaq 4/50CX, which has some sort of WDC SVGA controller. I initially had issues with this, but eventually I realized that using the laptop panel ignored settings in the various CRTC registers, including the display enable skew settings. By changing to an externally connected VGA display, I was able to change the timing and the mode worked. Given a datasheet for the exact chip in the laptop, I'm sure I could develop a specific fix, but this is one limitation of the mode. If the CRTC registers are ignored like this on other laptops, this can cause the same issue making the 24-pixel repeat issue unfixable. I tested on a more modern pentium 4 era machine, but could not get this mode to work at all regardless of what I tried. I suspect the graphics chip simply doesn't support it. I got strange erratic behavior on the video output as soon as I set the shift and load 32 bit. I also attempted to run on my modern intel i5 laptop, however I couldn't get it to boot DOS and run the QBASIC program I had made to test this, so I didn't manage to test it here.

Given the way that the purpose of otherwise mysterious bits and fields within the VGA registers seemed to just fall into place once I began working on this, I theorize that the intention of the designers of the IBM VGA chip was to support these modes to begin with. However, the software to use them was never implemented, and the documentation was too poor for anyone to implement them in low level software. Furthermore, the falling prices of RAM meant that soon the low-memory variants of VGA would have gone away, meaning that 640x480x4bpp was supported by most, if not all VGA cards soon after introduction of the VGA controller. Given that the VGA card hardly supported any higher resolution modes than the normal 640x480, there would have been no need to attempt to squeeze more pixels out of the memory available (256KB on normal VGA).

I also don't know how many different cards would have supported this mode. For that matter, I don't know if IBM VGA supports this mode.

The usefulness of these modes are limited on the VGA controller anyway. One thing they do allow is a larger virtual framebuffer, which the VGA's window into can pan and scroll around within. Speaking of which, panning and scrolling is still fully supported even with 1 and 2bpp modes, which seems like more evidence of planned support for these modes in the VGA hardware. Normally, you can achieve 1-word panning on VGA easily by changing the display start address. 1 word in 4bpp mode corresponds to 8 pixels. However, the VGA supports hardware fine panning of 32 pixels through a combination of two fields. In 1bpp mode, the 1-word panning ends up producing 32 pixels of panning. This, combined with fine panning, still allows individual single-pixel panning capabilities. This seems to suggest the creators of VGA designed this with a 1bpp mode in mind, since otherwise only 8 pixels of fine panning are required in a 4bpp mode. The fields used for 'fine' panning are actually the combination of an 8-pixel coarse 'byte' panning field in CR8 and a 1 pixel fine panning field in AR13. Together they give a range of 0-31 pixels of panning, combined with the memory address word-panning, allowing full panning of any image.