New graphics mode: CGA in 1024 colors

Original author: VileR
  • Transfer
image

We are talking about the demo " 8088 MPH ", which won the competition Revision 2015 's Oldskool Demo. We, along with Trixter , reenigne and Scali, did it. And I got the opportunity not only to work with a group of programming wizards, but also to break world records in making demos for the good old IBM PC, mom and dad of the modern x86 platform.

If for some reason you didn’t have an IBM PC XT x86 with a CGA adapter at hand, you can watch the demo on YouTube:



Technical details are contained in the reenigne post , and I decided to tell this story in a more visual way.

A trick to support a large palette was invented by me some time ago when I looked at the reenigne code that performed composite CGI emulation for DOSBox . Having brought to a decent appearance the concept of this hack, I told reenigne about it so that it would look at my solution and test it on real hardware. As a result, we had a recipe:

- take two friends, albeit undocumented, hack. Mix together to get the desired effect
- add another hack
- check, fix, repeat

The beginning of the tutorial is written specifically for those who are not very familiar with CGA.

Old Trick # 1: 16-color RGBI Graphics


CGA Essentials: The First Graphic Standard for PC. 16 kb memory buffer, works with MC6845 CRTC. Video output: NTSC via RCA plug, or DE9 connector outputting RGBI signal (red, green, blue, intensity). The last option is just what people present when they hear about CGA - a digital TTL signal, each component can be turned on or off, for a total of 16 colors.

The standard modes supported in the BIOS are high resolution (640x200) in 2 colors and medium (320x200) in 4 colors. Do not turn around: in high resolution, only the fill color can be changed, and the background color is always black. On average, you can change the background color, and the other three are predefined by fixed palettes .

IBM casually mentionedabout another mode, in 16 colors and low resolution, which is "not supported in ROM" - and did not give any information on how to work with it. But this casket opened with a crowbar.

Low resolution mode


This is not a graphics mode, but a slightly modified text mode of 80 columns. You correct CRTC registers and get 100 lines instead of 25. It turns out that the character occupies an 8x2 pixel rectangle - a quarter of the usual 8x8. Filling the screen with the magic ASCII character 0xDE divides each character into left and right “pixels” that correspond to the background and fill. These two colors can be individually assigned to any of the 16 values ​​of the CGA mode, as in any CGA text mode - the main thing is to remember to turn off the flicker.

image

In the picture there is an 8x8 cell for the 0xDE symbol (yellow - fill, black - background). In low-resolution mode, only the top two rows of pixels are displayed on the screen (raster lines), and you get two rectangles of 4x2 pixels side by side.

There you have it: 160x100 @ 16c. It has been used at least since 1983 , but has not gained popularity. To make it look neat, you need to spend precious CPU resources, otherwise you cannot avoid the “snow” on the screen.

Macrocom Method


You may ask - since this is a text mode, why not use the entire set of ASCII characters? Really. In the mid-80s, this technique was tested by daredevils from Macrocom , combining a trick of 100 lines with ASCII-art, and received what is called “hellish ANSI”.

image

In the picture: part of the text screen 80x100 characters using random ASCII characters to emulate high-resolution graphics. Only the top two rows of raster lines in each character line are displayed.

In the middle - what the screen would look like if you saw the whole characters.

On the right is the font from ROM, the two upper raster lines of each character are highlighted.

Using a character set in a cunning way, you can make the viewer think that he sees the 640x200 mode, although each 8x2 symbol can contain only 2 colors. And to draw in this mode from scratch is an activity for special gourmets ...

This trick only indirectly relates to our demo: we relied on composite displays. Even if the composite CGA output were not so buggy in 80-column mode, it still could not be output to NTSC in such detail.

Old trick number 2: 16 colors through composite output


Digital RGB monitors were rare in the CGA era, but CGA also provided composite output with a picture almost NTSC compatible. Here we sacrifice permission, but then get back with flowers.

Direct colors


image

At the composite output, a palette of 16 colors is represented by a series of color signals in which the hue is determined by the phase relative to the reference signal (the NTSC color burst). The frequency of NTSC in color (3.579545 MHz) just corresponds to 160 color cycles per active line of the CGA raster.

Colors are directly created by iron as color signals, so we call them “direct colors”. IBM had two versions of CGA , which produced composite video in different ways: the new cards contained additional outlines that allowed bringing the palette in the most correspondence with RGBI. For the demo, we used old cards, since we tested everything on them.

But 16 colors would not be enough for us, right? They are also ugly. But there is a way to do better.

Spurious colors


Due to bandwidth limitations, NTSC does not completely separate color and brightness. Any high-resolution part (whose frequency is greater than the NTSC frequency) is smeared during decoding. Symbols around the edges appear spurious colors.

Remember how we got 160 color cycles per active line of a CGA raster? The CGA standard gives either 320 or 640 active pixels per line. We can turn pixels on and off 2 or 4 times faster than the color rendering frequency. Since these high-frequency details are not fully shared with color information, it turns out that the hue of a pixel or the transition between pixels depends on its position within the color cycle period.

image

Sometimes the NTSC color cycle is represented as a circle - one full period is equal to a 360 ° rotation, and we have 160 full rotations per raster line.

Suppose we have a 640x200 mode, where 4 pixels are placed in one digital cycle - moving one pixel to the left or right, we go along the color wheel 90 °, and, accordingly, change the hue by 90 °. In 320x200 mode, we move the wheel 180 °. That is, to manipulate parts in high resolution means to create colors that are spurious phenomena of imperfect NTSC transmission.

image

In the picture: the result of the inability to fully decode the color in the form of color strokes. Text in 80 columns mode (left) is almost unreadable, unlike text in 40 columns (right).

Different filters are often used to reduce spurious effects on the receiving side. But since it is a technology, not magic, a complete separation of details and colors cannot be done, and other artifacts (such as echoes) are obtained as side effects.

Solid spurious colors


But all these stray colors are just side effects of a non-ideal coding scheme. But, like any disadvantage, it can be turned into an advantage. If you look at these effects, it becomes clear: any periodic composite signal with the same frequency as the color frequency (160 per line) will be decoded as a solid color.

Our 16 direct colors belong to this type of periodic composite signals. But wait - if we play with pixels in high resolution, we can get our own periodic waveforms! Any pattern of dots will do, as long as it repeats at the right frequency. So we get solid colors that are not in the palette of lines.

image

The classic way is to switch to BIOS mode No. 6, 640x200 with 2 colors, white on black, and set the color-burst bit. In this resolution, 4 pixels will fit into the color update period, and for 1 bit per pixel you get 16 patterns — that is, 16 colors.

In fact, Steve Wozniak did color rendering on Apple] [. In general, on an old CGA card, 16 colors exactly match Apple's 16 low-resolution colors. In short, the pixels themselves are white, the color is transferred only by their mutual arrangement.

But that is not all! CGA, in spite of everything, has an advantage over Apple. Our template pixels do not have to be white. In 620x200 mode, we can set the fill to any of 16 colors (the background is always black). Assigning the same pixel patterns a different color than white, we get a palette for it with a new set of colors. Of course, you can use only one set of 16 colors at a time, but at least you can choose which one.

And we also have a 320x200 mode with a palette of 4 direct colors. And only one of them, No. 0 (background), can be changed freely. For the rest, you can change the intensity, but we can only get green / red / yellow or cyan / magenta / white. To get the undocumented palette blue / red / white, you need to turn off the digital sync bit, which will cause the composite picture to be black and white.

Since the pixels are twice as fatter in this mode, they can only be squeezed into the color update cycle two at a time - but for 2 bits per pixel the total number of spurious colors will still be 16. Possible combinations of palettes and a selectable background color give us several sets of 16 color palettes.

image

Something needs to be clarified here. Because we have 160 color cycles per line, many believe that the CGA graphics modes available by composite signal are 160x200 modes - but this is not entirely true. The effective color resolution is indeed 160x200, and it is impossible to obtain a finer resolution using spurious colors. But, as we saw, in NTSC, the pixel grid and the color grid are not the same thing. Therefore, horizontal resolution is an open question, it depends on the sampling and filtering of the signal, and varies depending on what forms of the color signal you use.

IBM did not document these artifact tricks, but the concept was used even in the oldest games - for example, Microsoft Decathlon and Flight Simulator from 1982. And the limit of 16 colors always remained.

However, if you are still reading the text, you realize that this restriction can be overcome, and you can even guess how.

256 colors


Our selection of 16 stray colors depends on the palette and color register settings. This means that it is necessary to change the registers of specific lines of the raster and get more than 16 colors on the screen. Is not it?

image

At CGA, this has already been done, and this technique can be brought up to 256 colors - but in the demo we did not use this approach. I stumbled upon our technique by pure chance, driven by curiosity.

Remember how a pattern of flowers and dots of the desired length (four pixels in 640x200 or two pixels in 320x200) gives a solid color on the composite display. When I tested composite emulation on DOSBox, I remembered that. And at the same time, I was experimenting with the graphic hack “hellish ANSI”.

Let us return to one of the parts of the ROM font in the 80-column mode, in which the 2 upper lines of the raster are highlighted:

image

Take a look at this symbol, for example:

image

In 80x100 mode, only the top two raster lines are displayed. See these 25% symbol images? Two dots of the fill color and two background dots duplicated horizontally. We are in high resolution mode and 80 columns are displayed, so for each character there are two color cycles - which correspond to these two similar halves. And the two upper lines of the raster are identical.

It is this repeating pattern that gives us solid spurious color in NTSC. This is the same waveform that is available in 320x200 mode. Only now it is available in text mode, where we can freely assign both a fill color and a background color, of their 16 colors.

That is, we already have 256 options - i.e. the ability to display more than 16 colors in CGA without blinking, blurring and other effects.

Possible combinations:

image

512 colors


But that is not all! Moving in this direction, I began to study the font from ROM in search of other useful patterns. Some symbols give us the same waveforms as U - these are H, V, Y and ¥. But only one with another suitable bit sequence is exactly where it is needed - 0x13, or.

The upper two lines of the U raster give the bit mask 11001100 for the fill and background. '' gives 01100110 - a shift to the right, or a phase shift of 90 °. This complements U and creates a good full palette, because we get all the colors that the waveform “... 1100 ...” can offer: moving from 'U' to '', we shift the phase 90 ° (0110); 180 ° and 270 ° are obtained when we swap the colors of the fill and background for 'U' and '', respectively - the same as for '0011' and '1001'.

image

And now we got even more - 512 flowers! Of course, there are actually fewer of them, there are duplicates and very slightly different shades. But this seems to be the limit - there are no other suitable characters in the font. CGA has an alternative “thin” 8x8 font , but firstly, for this you need to poke around in the card, and secondly, there are no useful bit patterns.

Having proudly shared my technique of increasing the number of colors 32 times with reenigne, I did not expect that he would have a truly diabolical plan to double the available number of colors ...

1024 colors


And then comes black magic, all of whose laurels should be attributed to reenigne.

image

Pay attention to these two symbols, which have an interesting first line of the raster. Unfortunately, the second line is different from the first, and this will ruin our solid color effect. These are the ASCII codes 0xB0 and 0xB1. It would be great to be able to cut off a second, inappropriate raster line ... And there is such an opportunity.

Details can be found in the reenigne post, but in short, the idea is this: starting every new CRTC frame with the beginning of a new raster line and playing with the starting address, it is possible to arrange our characters so that the first raster line of each symbol is repeated twice.

And now we can use these two characters, which give us two more palettes of 256 colors:

image

Of course, such a fuss puts a lot of stress on the unfortunate percentage of 4.77MHz 8088, so there is little that can be done except for static pictures. The option with 512 colors and using ASCII 0x55 and 0x13 is much faster - set and forget.

There is another problem with composite displays - a hardware bug, which leads to incorrect vertical synchronization and skipping color snooping. There are compensation methods - but there is no 100% reliable for any monitor. It took a lot of time to test and calibrate.

Well, in the end, we got 1K colors for the 1981 IBM CGA in an effective resolution of 80x100 "puffy pixels". They are chubby both in memory and visually. Of course, 80x100 is too small a field for drawing. But limitations are part of an interesting task that is always present in demos. Keep your monitors in 4K resolution - 0.008 megapixels should be enough for everyone!

image

In the picture: above - the result on a calibrated NTSC display. Below is an option with output to RGBI. Hand-drawn in Photoshop and converted to 80x100 format.

Also popular now: