Million-Color Palette For IBM PC & PCjr
John Klein and Jeff Klein
It's amazing but true—with this stunning technique you can generate more than a million apparent color variations on a PCjr. You can even display 256 colors simultaneously. The effects are less dramatic on a PC, but it's still possible to generate many more than the standard 16 colors. The programs require an Enhanced Model PCjr or a PC with color/graphics card, plus a TV set or composite color monitor. The palette is more limited on an RGB monitor, but still impressive.
No longer is your PC or PCjr restricted to a palette of 16 colors and the inability to display them all in higher resolutions. Now you can choose to display 256 colors from a palette of over 1,000,000 colors in high resolution, and display an entire palette of 256 colors in medium resolution. And each color is distinct and solid.
The secret is a combination of a technique called tile painting and the trick of fooling a TV or composite monitor into displaying new solid colors. To understand how it works, let's examine the way graphics are stored, changed, and displayed on the IBM video screen.
A Byte Of Pixels
Graphics images are stored differently in the computer's memory for each different graphics mode or screen. In its simplest form, the color of each pixel—the smallest controllable dot on the screen—is stored in a section of memory. This video memory is arranged by its location or coordinates on the screen. The image you see on the screen, therefore, is a copy of the contents of video memory. (Actually, screens are divided into several layers when stored in memory, but that's not important for this discussion; we're concerned with how the colors of pixels are represented in memory, not how each pixel is arranged.)
To figure out how many pixels can be represented in a byte of memory, remember that a byte is made up of eight bits, and a bit is the smallest unit of memory (a bit is either a zero or a one). Simply divide the amount of memory required for a certain screen mode by the number of pixels on the screen. The memory requirements for each screen mode are shown in Table 1.
Table 1: Screen Mode Memory Requirements
|Screen Mode||Resolution||Number of Colors||Memory per Screen||Pixels/Byte||Bits/pixel|
|1||320 X 200||4||16K*||4||2|
|2||640 X 200||2||16K||8||1|
|3||160 X 200||16||16K||2||4|
|4||320 X 200||4||16K||4||2|
|5||320 X 200||16||32K||2||4|
|6||640 X 200||4||32K||4||2|
*1K = 1024 bytes
Remember that RGB stands for the three primary colors of light: red, green, and blue. All colors can be made by mixing these three primary colors. That's why RGB monitors, color TVs, and composite color monitors have three electron guns inside their picture tubes, instead of the single gun found in black and white TVs and monochrome monitors. There is a red gun, a green gun, and a blue gun, all of which are controlled by the computer to produce color. If none of the guns is lighting a pixel, the pixel appears black.
Colors are represented in memory by arranging bits to denote which electron guns should be turned on or off when lighting the corresponding pixel. For instance, if a certain pixel is supposed to be blue, the group of bits representing that pixel in memory shows the blue gun is on and the others off. (A bit set to 1 means on, and 0 means off.) All the possible combinations of the three electron guns account for eight colors. To get eight more colors, the intensity, also called luminance, is varied by mixing a little white with the first eight colors. That's why the IBM PC and PCjr have a total of 16 color variations: two shades each of eight colors.
Table 2 shows how each of the 16 colors is represented. Remember that each bit turns an electron gun. either on or off. Notice how many bits it takes to represent all the possible combinations. It takes four bits, or half of a byte (sometimes called a nybble) to represent all 16 colors. So, all screen modes which use four bits to represent a pixel are 16-color modes. Only four-color combinations are possible with two bits, and only two combinations are possible with one bit. That's why some screen modes can display only four or two colors at a time.
The PCjr's PALETTE command can switch which colors are being displayed, but it can't add any more colors. You're still limited to the maximum number of colors for each screen mode.
Once you're familiar with how pixels are represented in video memory, the technique of tile painting is easier to understand. Tile painting uses the PAINT command found in PCjr Cartridge BASIC and IBM BASICA to fill the bytes of screen memory with certain patterns of ones and zeros. This pattern is programmable, and it represents what is displayed on the TV or monitor. Instead of painting with the actual color, you paint with the bit pattern of the color. By using bit patterns, you can actually paint with more than one color around some specified border color.
PAINT (x, y), CHR$ (bit pattern) + CHR$ (bit pattern) + …, boundary color
The bit pattern consists of eight bits, so its decimal equivalent can range from 0 to 255 (integers only). The bit pattern must represent the colors of the pixels per byte of the screen mode you're using. This means four colors can be painted at a time in SCREEN 4 and 6, while only two colors can be painted at a time in SCREEN 3 and 5. The color patterns are put in memory next to each other as vertical lines on the screen. The following example paints SCREEN 1 with vertical bands of blue and green lines:
10 SCREEN 1 : CLS 20 PAINT (l, l), CHR$ (102), 3
The reason why the lines are blue and green can be seen when the number 102 is expressed in binary, revealing the bit pattern:
102 = 01100110
Table 3 shows how decimal 102 is derived from this binary number.
Table 2: Color Bits
Table 3: Converting Binary to Decimal
|Value for each digit||128||64||32||16||8||4||2||1||01 = 0001 = blue|
|10 = 0010 = green|
|128 * 0 = 0|
|64 * 1 = 64|
|32 * 1 = 32|
|16 * 0 = 0|
|8 * 0 = 0|
|4 * 1 = 4|
|2 * 1 = 2|
|1 * 0 = 0|
SCREEN 1 stores four pixels per byte, so the pattern works out to these colors:
But here's where things get tricky. If the computer is plugged into a color TV or composite color monitor (not an RGB monitor), you won't see the blue and green vertical lines that are supposed to be there. Instead, you'll see a solid bar of color that's sort of blue. And the blue is not one of the normal 16 colors available. It is a new color—one of the 256 shades that can be created this way on SCREEN 1 of the PCjr, and one of the 16 shades that can be created on SCREEN 1 of the PC.
What's happening here is something called artifacting. This effect takes advantage of the limited resolution of TVs and composite color monitors. When two very small pixels are placed next to each other on these screens, there isn't enough resolution to display them properly. As a result, the pixels tend to blend together and create a false color—an artifact color. The color wouldn't be visible if the screen had more resolution, which is why you usually need a TV or composite color monitor to observe this effect. RGB monitors have enough resolution to display the pixels as they're supposed to appear.
Creating New Colors
If the binary pattern 10 01 10 01 is used in the above example instead of 01 10 01 10, the shade is slightly different—blue-green-blue-green does not appear the same as green-blue-green-blue on a color TV or or composite monitor. They mix differently to create an entirely new shade of blue-green.
The PC can mix a fewer number of colors than the PCjr for two reasons. The first is that the PC has only two graphics modes, SCREEN 1 and SCREEN 2. Tile painting produces only 16 colors in SCREEN 1 and five shades of gray in SCREEN 2. Still, these are more colors than what are normally available in these modes. The second reason is that the PC does not have a PALETTE command as the PCjr does. The PC does have a second color palette in SCREEN 1, but the mixed colors look the same as the first palette on a color TV or composite monitor.
On SCREEN 6, available only in PCjr Cartridge BASIC, there are four pixels per byte. Because the pixels are very small (640 X 400 per screen), vertical bands of four different colors can be mixed to form shades of any color. In medium resolution, 320 X 200, vertical bands of two different colors form new solid colors. Tile painting doesn't work in low resolution, 160 X 200, because the pixels are too large.
For a demonstration of how closely spaced vertical bands create new colors, enter and run Program 1 (for the PCjr only). Using the LINE command instead of PAINT, line 20 fills the first 40 columns of SCREEN 6 with purple bands on every line that is a multiple of four: 0, 4, 8, 12, and so on. Line 30 fills the next 40 columns with the same color on every vertical line that is a multiple of four plus one: 1, 5, 9,13, and so on. Then the program fills the screen with lines of the other two colors available in SCREEN 6. The result, on a TV or composite monitor, is 12 different colors instead of the four you'd expect.
Adding up all the different combinations of four colors results in 256 shades, and all 256 can be displayed on the screen at the same time. When you take into account that the PALETTE command can change any of the four basic colors into any of the other 16 colors, there are 1,092,016 possible shades in high resolution.
Program 2 (for the PCjr only) proves it can be done. This program displays 256 shades on the screen by drawing the vertical lines using only the first four colors. After painting all the shades, it randomly changes the palettes. If the colors selected by the PALETTE command were never repeated, it would take about an hour and a half to cycle through all one million colors.
Colors In Other Modes
In SCREEN 5, there are 256 possible colors, as demonstrated by Program 3 (also for the PCjr only). In SCREEN 4 and SCREEN 1, which are the same resolution, only four basic colors are available, so tile painting lets us display up to 16 hues simultaneously. With the PALETTE command on the PCjr, you can select these 16 colors from 256 possibilities. Program 4 displays 16 shades, then uses the PALETTE command to get the rest. Vertical bands with four colors don't blend in this mode, so somehow bands of two must be painted. The secret is in line 40. Since there are four pixels per byte, the last half of the byte has to be reflected in the first half. This technique insures that only two colors are in each band of four. The first half is the same as the last half, so the first band of two will be the same as the last band of two. Program 4 will also work on the PC, but without the PALETTE command (line 80) you are limited to only 16 colors.
Tile painting doesn't work correctly in SCREEN 2, high resolution with two colors, because this screen is always in black and white. However, you can get five shades of gray, as shown by Program 5(for PC and PCjr). Solid lines form the brightest white. Lines separated by one line of black give the next-brightest white. Lines separated by two or three lines of black yield the next two shades. The middle gray can't be displayed when using the PAINT command, because it's not possible to create a bit pattern that represents two blacks and then a white. Table 4 shows which bit patterns generate the various shades of gray.
Tile painting doesn't work at all in SCREEN 3 because the pixels are too large. To see a demo of tile painting in SCREEN 1 for the PC or PCjr, run Program 6. It fills the screen with circles, displaying up to 256 colors on the PCjr and 16 colors on the PC.
Program 7, for the PC and PCjr with an RGB monitor, demonstrates the usefulness of the many new colors in a fascinating experiment. It uses SCREEN 1 and tile painting, but in a different way than seen above. Closely spaced vertical lines don't blend together on an RGB monitor, so the previous technique won't work. So instead, Program 7 uses the second part of the PAINT, command. The first CHR$ (bit pattern) controls the horizontal line above the second CHR$ (bit pattern). Now the PAINT command can control the horizontal as well as the vertical lines, forming a checkerboard.
Although the checkerboard blends the lines together to create new colors, the colors aren't as solid as those produced by vertical lines on a TV or composite monitor. Indeed, the effect won't look very pretty on a TV or composite monitor; it's passable on an RGB.
Program 8 (for the PCjr only) employs the same technique as Program 7, but uses SCREEN 5 on the PCjr to create all 240 possible colors on the RGB monitor at once. The PALETTE command won't create any new shades here, because all 16 colors and their possible combinations are displayed.
Program 9 (for the PCjr only) is the same as the last two, but uses SCREEN 6 on the PCjr. It does a much better job of blending, although the colors still aren't perfectly solid. Ten shades are displayed at once and the PALETTE command cycles through all 240 possible shades.
Painting Your Own Programs
To use the new colors in your own programs, simply choose one of the following example programs which uses the same screen mode. Table 5 summarizes the programs and the number of color variations possible in each.
If you're programming on a PCjr, remove the lines that deal with changing the palette. You can change palettes on the PCjr in direct mode until most of the shades you want are on the screen. We suggest not changing the palettes in the 16-color modes, because the unchanged palette creates the widest variety of colors with the least amount of extra work.
In four-color modes, the screen displays 16 shades. Pick the color you want, then refer to Table 6 for the corresponding decimal and hexadecimal translations of the bit patterns required.
If you're using a 16-color mode with a TV or composite monitor, the screen displays 256 shades and the bit patterns can be figured as follows: First choose the color. Then, starting at zero at the upper-left corner of the screen, count in hex across the screen to the column with the color you want. Remember to count in hex (0 through 9, then A through F). Then, still working in hex, count the number of rows down to the color you want. These two numbers form the bit pattern of the chosen color. Use them as shown below:
PAINT (x, y), CHR$ (&H row column), boundary
Example: If row = A and column = 2, then
PAINT (x, y), CHR$ (&HA2), boundary
If you're using an RGB monitor with a 16-color mode, choose which two of the 16 colors to make into the checkerboard. Then write each of their numbers in hex (0-F). Use these numbers as the bit pattern as shown below. Switching the first and second colors will create the checkerboard.
PAINT (x, y), CHR$&H 1st color 2nd color) + CHR$ (&H 2nd color 1st color), boundary
Example: If 1st color = B (light cyan) and 2nd color = 2 (green), then
PAINT (x, y), CHR$ (&HB2) + CHR$ (&H2B)
IBM boasts of only the checkerboard technique for shading colors. I find the other method more fascinating. Now you can enhance your screens with a new palette of bright, solid colors, which formerly were thought to be impossible on an IBM.
Table 4: Gray Scales in SCREEN 2
|color 1 =||1 1 1 1 1 1 1 1||= 256 =||&HFF =||White|
|0 1 0 1 0 1 0 1||= 85 =||&H55 =||Dull White|
|(Not accessible)||=||Middle Gray|
|0 0 0 1 0 0 0 1||= 17 =||&H11 =||Dark Gray|
|color 0 =||0 0 0 0 0 0 0 0||= 0 =||&H00 =||Black|
Table 5: Program Descriptions
|Program||Screen Mode||Max Colors||Colors per Screen||PC or PCjr||Display Device|
|Program 1||SCREEN 6||1, 092, 016||256||PCjr||TV or CC *.|
|Program 2||SCREEN 6||1, 092, 016||256||PCjr||TV or CC|
|Program 3||SCREEN 5||256||256||PCjr||TV or CC|
|Program 4||SCREEN 1 or 4||256||16||PCjr||TV or CC|
|SCREEN 1||16||16||PC||TV or CC|
|Program 5||SCREEN 2||5||5||PC/PCjr||TV or CC|
|Program 6||SCREEN 1||256||16||PCjr||TV or CC|
|16||16||PC||TV or CC|
|Program 7||SCREEN 1 or 4||240||10||PCjr||RGB|
|Program 8||SCREEN 5||240||240||PCjr||RGB|
|Program 9||SCREEN 6||240||10||PCjr||RGB|
* CC = Composite color monitor
Table 6: Translations of Bit Patterns in Four-Color Modes
|TV or Composite||RGB|
|0||0||&H00||0 + 0||&H00 + &H00|
|1||17||&H11||17 + 70||&H11 + &H44|
|2||34||&H22||34 + 136||&H22 + &H88|
|4||51||&H33||51 + 204||&H33 + &HCC|
|5||70||&H44||70 + 17||&H44 + &H11|
|6||102||&H66||102 + 153||&H66 + &H99|
|7||119||&H77||119 + 221||&H77 + &HDD|
|8||136||&H88||136 + 34||&H88 + &H22|
|9||153||&H99||153 + 102||&H99 + &H66|
|10||176||&HAA||176 + 176||&HAA + &HAA|
|11||187||&HBB||187 + 238||&HBB + &HEE|
|12||204||&HCC||204 + 51||&HCC + &H33|
|13||221||&HDD||221 + 119||&HDD + &H77|
|14||238||&HEE||238 + 187||&HEE + &HBB|
|15||255||&HFF||255 + 255||&HFF + &HFF|
For instructions on entering these listings, please refer to "COMPUTE!'s Guide to Typing In Programs" published bimonthly in compute!. Also, see Table 5 for a description of the programs.
Program 1: PCjr
IE 10 CLEAR, , , 32768! : SCREEN 6 : CLS : KEY OFF DJ 20 FOR X = 0 TO 40 STEP 4 : LINE (X, 0) - (X, 200), 3 : NEXT JH 30 FOR X = 41 TO 80 STEP 4 : LINE (X, 0) - (X, 200), 3 : NEXT 1A 40 FOR X = 82 TO 120 STEP 4 : LINE (X, 0) - (X, 200), 3 : NEXT GJ 50 FOR X = 123 TO 160 STEP 4 : LINE (X, 0) - (X, 200), 3 : : NEXT FA 60 FOR X = 160 TO 200 STEP 4 : LINE (X, 0) - (X, 200), 1 : NEXT HN 70 FOR X = 201 TO 240 STEP 4 : LINE (X, 0) - (X, 200), 1 : NEXT PO 80 FOR X = 242 TO 280 STEP 4 : LINE (X, 0) - (X, 200), 1 : NEXT NH 90 FOR X = 283 TO 320 STEP 4 : LINE (X, 0) - (X, 200), 1 : NEXT 00 100 FOR X = 320 TO 360 STEP 4 : LINE (X, 0) - (X, 200), 2 : NEXT MN 110 FOR X = 361 TO 400 STEP 4 : LINE (X, 0) - (X, 200), 2 : NEXT OL 120 FOR X = 402 TO 440 STEP 4 : LINE (X, 0) - (X, 200), 2 : NEXT G6 130 FOR X = 443 TO 480 STEP 4 : LINE (X, 0) - (X, 200), 2 : NEXT
Program 2 : PCjr
IE 10 CLEAR, , , 32768! : SCREEN 6 : CLS : KEY OFF LO 20 RANDOMIZE TIMER : Z = - l : A = INT (640/16) HB 30 FOR Y = 0 TO 15 DE 40 FOR X = 0 TO 15 : Z = Z + 1 ED 50 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 3, B PC 60 IF Z < > 0 THEN PAINT (X * A + 1, Y * 12.5 + l), CHR * (Z), 3 MH 70 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 0, B JI 80 NEXT X, Y DD 90 PALETTE RND * 3, RND * 15 : GOTO 90
Program 3 : PCjr
HK 10 CLEAR, , , 32768! : SCREEN 5 : CLS : KEY OFF BB 20 RANDOMIZE TIMER : Z = - l : A = INT (320/16) HB 30 FOR Y = 0 TO 15 DE 40 FOR X = 0 TO 15 : Z = Z + 1 ED 50 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 3, B PC 60 IF Z< >0 THEN PAINT (X * A + 1, Y * 12.5 + 1), CHRS (Z), 3 MH 70 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 0, B JI 80 NEXT X, Y KC 90 GOTO 90
Program 4: PC/PCjr
CA 10 SCREEN 1 : CLS : KEY OFF : COLOR,0 MM 20 RANDOMIZE VAL(RIGHT$(TIME$, 2)) : Z = - l : A = INT (320/16): Y = 0 DD 30 FOR X = 0 TO 15 : Z = Z + 1 II 40 LINE (X * A, 0) - (X * A + A, 200), 3 Kl 50 IF Z<>0 THEN PAINT (X * A + 1, 1), CHR$ (Z + Z * 16), 3 CD 60 LINE (X * A, 0) - (X * A + A, 200, 0, B QM 70 NEXT X GL 80 PALETTE RND * 3, RND * 15: 60 T0 80: ' Remove this line for PC
Program 5: PC/PCjr
CF 10 SCREEN 2, 1 : CLS: KEY OFF MJ 20 FOR X = l TO 100: LINE (X, l) - (X, 200),1 : NEXT X DH 30 FOR X = 101 TO 200 STEP 2: LINE (X, 1) - (X, 200), 1 : NEXT X HN 40 FOR X = 201 TO 300 STEP 3: LINE (X, 1) - (X, 200), 1 : NEXT X KD 50 FOR X = 301 TO 400 STEP 4: LINE (X, 1) - (X, 200), 1 : NEXT X IE 60 GOTO 60
Program 6: PC/PCjr
CA 10 SCREEN 1: CLS: KEY OFF: COLOR LD 20 RANDOMIZE VAL(RIGHT$(TIME$, 2)) GD 30 X = RND * 320: Y = RND * 200: R = RND* 10 + 10: TILE = INT(RND * (15) + 1) BM 40 CIRCLE (X, Y), R, 3:PAINT (X, Y),CHR$ (TILE + TILE * 16), 3 : CIRCLE (X, Y), R, 0 AE 50 IF RND * 10>B THEN PALETTE R ND * 3 + 1, RND * 15:’ Remove this line for PC EA 60 GOTO 20
Program 7: PC/PCjr
CA 10 SCREEN 1: CLS: KEY OFF: COLOR, 0 CD 20 RANDOMIZE VAL(RIGHT$ (TIME$, 2)): Z = -1: A = INT (320/16) : Y = 0: C = 0 DD 30 FOR X = 0 TO 15: Z = Z + 1 NN 40 LINE (X * A, 0) - (X * A + A, 200), 3, B: Y = Z + Z * 16 : Q = Y * 4: R = INT (Q/256): Q = Q-R * 256 + R KF 50 IF Z <> THEN PAINT (X * A + 1, 1),CHR$ (Y) + CHR$ (Q), 3 CD 60 LINE (X * A, 0) - (X * A + A, 200), 0, B QM 70 NEXT X GL 80 PALETTE RND * 3, RND * 15: GOTO 80:’ Remove this line for PC EN 90 C = l-C : COLOR, C : FOR Z = l TO 100: NEXT: GOTO 80:’ Remove this line for PC
Program 8: PCjr
HK 10 CLEAR, , , 32768! : SCREEN 5 : CL SS : KEY OFF BB 20 RANDOMIZE TIMER:Z = -l: A = INT (320/16) HB 30 FOR Y = 0 TO 15 DE 40 FOR X = 0 TO 15: Z = Z + 1 JD 50 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 3, B: Q = (Z) * l6 : R = INT(Q/256):Q = Q - R * 256 + R DC 60 IF Z<>0 THEN PAINT (X * A + 1, Y * 12.5 + 1), CHR$(Z) + CHR; (Q), 3 MH 70 LINE (X * A, Y * 12.5) - (X * A + A, Y * 12.5 + 12.5), 0, B JI 80 NEXT X, Y KC 90 GOTO 90
Program 9: PCjr
IE 10 CLEAR, , , 32768! : SCREEN 6 : CLS : KEY OFF BB 20 RANDOMIZE TIMER : Z = -1: A = INT (640/16) : Y = 0 DD 30 FOR X = 0 TO 15 : Z = Z + 1 MN 40 LINE (X * A, 0)-(X * A + A, 200), 3, B: Y = Z + Z * 16 : Q = Y * 4: R = INT(Q/256):Q = Q - R * 256 + R KF 50 IF Z < >0 THEN PAINT (X * A + 1, 1), CHR$ (Y) + CHR$ (Q), 3 CD 60 LINE (X * A, 0) - (X * A + A, 200), 0, B QM 70 NEXT X BE 30 PALETTE RND * 3, RND * 15: GOTO 80