See also: challenge, responses, and more responses.
Updates:
- 2022-07-05 – Updated with a second requirement and test program.
The 1980 Radio Shack Color Computer (and the Color Computer 2 revisions) used a Motorola MC6847 Video Display Generator chip. This video chip was used in a variety of other systems, and one can easily recognize it by its 32×16 text mode characters with the square letter “O”. I recently spotted it in a YouTube video by Atari Archives discussing the Atari VCS Hangman cartridge (see 5:04 if this direct link doesn’t work):
I was unfamiliar with the AFP Imagination Machine mentioned in the video, but CoCo Crew co-host John Linville confirmed it indeed used the same CoCo VDG chip. The “nuclear green” background color and blocky low-resolution “semigraphics” do stand out.
I also stumbled upon it in a list of unreleased Atari products. A company named Unitronics was planning an Atari VCS Expander System that would allow loading games from a built-in tape deck. In a screen shot for the device (which looked like a cassette player that plugged into the top of the Atari), the nuclear green CoCo screen can be clearly seen:
http://www.ataricompendium.com/game_library/unreleased/unreleased.html#unitronics
The screenshot in the first picture appears similar to that of Radio Shacks’ Color Computer – same color scheme and maximum of 32 characters per line.
http://www.ataricompendium.com/game_library/unreleased/unreleased.html
And, there was even going to be a conversion of the 1980 CoCo ROM-Pak Space Assault and a screen shot was used of the CoCo version
http://www.ataricompendium.com/game_library/unreleased/unreleased.html#spaceassault
The screenshot shown in a brochure for the Expander System (picture #1) is actually the Radio Shack Color Computer game Space Assault (picture #2). The game was licensed to Tandy by Image Producers Inc. in 1981. Perhaps Unitronics was going to license the game for the Expander. If the game shown in the brochure is actually running on the Expander, that would mean the Expander used the same graphics chip as the CoCo – the MC6847 VDG chip.
http://www.ataricompendium.com/game_library/unreleased/unreleased.html
Until recently, I had no idea anything but the Radio Shack CoCo and MC-10s, as well as the UK’s Dragon computers (and, I guess, the French MC-10 clone, Alice) used the VDG chip.
64x32x8 … technically.
Ignoring using solid color character blocks in the 32×16 text mode, the lowest resolution graphics mode in the VDG was a 64×32 mode that could use 8 colors plus black. It did this by dividing each text block of the 32×16 text screen into a 2×2 graphics character. They weren’t true pixels, but instead where just characters made with all possible 2×2 variations in eight different colors. You could PRINT them using CHR$:

This reminds me of how the Commodore VIC-20 worked with its extended PETSCII character set, but instead of all the weird lines and shapes and card suit symbols, it was 2×2 graphics blocks with different colors. Much like the standard VIC-20 text mode, each text position could only contain one color plus black. Thus, while you could have eight colors on the screen, you could never have more than one color (plus black) in a character’s 2×2 block.
Rendering graphics in this mode was tricky, since you could not have more than a single color (plus black) in any 2×2 block.
In BASIC, you could set the top left pixel to yellow using:
SET(0,0,2)
…but you would see it would change all the other pixels in the 2×2 block to black:

And if you tried to set two pixels side-by-side to different colors:
SET(0,0,2):SET(1,0,5)
…it would turn any other set pixel in that 2×2 block to the new color:

I am sure I learned this limitation when I first started playing with a CoCo in Radio Shack back in 1982.
Because of this “all pixels must be the same color” effect of the SET command, doing a random pixel plotting program…
0 REM 64x32.bas
10 POKE 65495,0:CLS 0
20 SET(RND(64)-1,RND(32)-1,RND(8)-1)
30 GOTO 20
…starts out as you might expect…

…but after awhile, every pixel has been set so new sets will change everything in that 2×2 block to the same color:

I know I wrote this program at that Radio Shack ;-)
Black is not a color
The early “Getting Started With Color BASIC” manual that came with the CoCo described the SET() command as being able to use the following colors:
- 0 – black
- 1 – green
- 2 – yellow
- 3 – blue
- 4 – red
- 5 – buff
- 6 – cyan
- 7 – magenta
- 8 – orange
But that manual was a bit incorrect. While you can try to SET(x,y,0), you won’t get black. The SET() command treats 0 and 1 as the same green color.
In fact, from what I can see, there is no way to set just a black pixel on the green text screen other than setting all the other pixels in that 2×2 block to the background screen green (color 1).
0 REM setblack.bas
10 CLS
20 SET(1,0,1):SET(0,1,1):SET(1,1,1)
30 GOTO 30
I guess the SET() command was really designed to work on a black screen (CLS 0). In fact, when viewing the Color BASIC disassembly in the “Color BASIC Unravelled” book, I even see it checks for this specifically:
CHANGE COLOR NUMBERS FROM 0-8 TO (-1 TO 7) BRANCH IF SET(X,Y,0)
It looks like they could have allowed it to support this, based on how the code checks what’s in the character initially. Maybe it was an oversight, or maybe it was just a lack of ROM space.
Regardless of the reason … I recently wanted to draw a black pixel on the green screen, and found doing so quite challenging.
The “draw black” challenge
Given a clear txt screen (CLS without any color), create a BASIC subroutine starting at line 100 that will plot a single black pixel using variable X and Y. Basically, make it act as if SET(X,Y,0) would actually set a black pixel like the BASIC manual implied.
It will be called like this:
10 CLS
20 FOR A=0 TO 31
30 X=A:Y=A:GOSUB 100
40 NEXT
50 GOTO 50
That above code would draw a diagonal black line from the top left of the screen down to the middle bottom of the screen.
To erase a pixel, we’d just use SET(X,Y,1) to place a green pixel there.
Is there a clever way to do this? Leave your efforts in the comments, or send them to me via e-mail.
UPDATE: Even more challenge
Some very clever solutions have been offered which solve the issue of drawing the diagonal line. But, can they also draw horizontal? One clever one was fast, but did not work for non-diagonals. Here is the second test program to try to make work:

10 CLS 20 FOR A=0 TO 15 30 X=A:Y=A:GOSUB 100 31 X=15-A:Y=16+A:GOSUB 100 32 X=40+A:Y=7:GOSUB 100 33 X=40+A:Y=24:GOSUB 100 34 X=39:Y=8+A:GOSUB 100 35 X=56:Y=8+A:GOSUB 100 40 NEXT 50 GOTO 50
Have fun!
I guess
100 RESET (X,Y) :RETURN
is out of the question? :-)
Try it on a CLS screen and see what happens.
What happens if you prefill the screen with CHR$(143)?
(143 = 128 + 15, I assume that the green “graphics chars” are 128-143 given the screen dump you show)
It works ;)
Well, almost. SET still won’t do it, but RESET does.
Look at Sebastian’s reply from today. Looks like a great solution.
Are you required to use the basic commands to set/clear pixels?
If not you could use the print chr$ codes to output the appropriate “chars”.
If the task is specifically to draw a diagonal line, nothing more and nothing less, you could even draw it by printing the char for one “dot”, do a short delay and then replace it with the char for two diagonal dots, and then loop to the next “char” position on screen.
I suppose it’s open ended enough that any approach would be allowed …. SET/RESET/POINT, POKE/PEEK, etc. the first submission used POKE/PEEK, and he also let me know a much simpler solution I was unaware of which solves the whole issue I was experiencing.
It always bothered me that the CoCo had nine colors in semi-graphics modes. The number nine should raise a red flag for anyone who is familiar with computers and the tendencies for things to be powers of two. Turns out the colors used four bits, three the determine which of the eight colors to show and the fourth bit for on or off. It’s too bad the fourth bit wasn’t light/dark instead of on/off. We could have had sixteen colors instead of just eight/nine with no extra cost in memory usage. Perhaps on/off instead of light intensity was easier to implement in the VDC, still a pity as it would have made the CoCo and all other machines with the MC6847 that much more colorful.
Is it 8 colors, and black, then? It’s a pity those modes were not put in BASIC back then. We’d have seen a much larger set of programs showing off those colors. I think we’ve had more demographics demos and games put out in the past year or so than during the original run of the computer.
It might be because they were somewhat rarely used that the semi-graphics modes have become popular for tinkering with lately. Plus as you pointed out, most of the modes weren’t easily accessible from BASIC which only makes them that much more fun to play with now.
It’s interesting that seven of the eight colors are from the NTSC test pattern (https://en.wikipedia.org/wiki/SMPTE_color_bars) which leads me to believe they’re all a particular frequency distance from each other. This would make the circuitry simpler. The downside is that some of the color combinations on the four color PMODE screens are rather garish. Later graphic generators such as the GIME likely used lookup tables, which allowed for more pleasant colors.
Had that fourth bit been used for luminance instead of simply black/color, we probably would have lost orange (the one CoCo color that’s not part of the NTSC color bars) but gained light and dark versions of the other seven colors. Plus we would have had black and a shade of gray. If I think about it this weekend, I might mock up what that would have looked like. The ultimate fun would be to alter the MC6847 emulation to enable this behavior but that’s a bit beyond my capabilities.
What explains the awful PMODE colors?
10 CLS
20 FOR A=0 TO 31
30 X=A:Y=A:GOSUB 100
40 NEXT
50 GOTO 50
100 SET(X,Y,1):SET(X-(X/2-INT(X/2)=.),Y,1):SET(X-(X/2-INT(X/2)=.),Y-(Y/2-INT(Y/2)=.),1):SET(X,Y-(Y/2-INT(Y/2)=.),1)
101 RESET(X,Y):RETURN
I know that my first suggestion above is a bit of a cheat. Here’s a more robust suggestion:
10 CLS
20 FOR A=0 TO 31
30 X=A:Y=A:GOSUB 100
40 NEXT
50 GOTO 50
100 IFPOINT(X,Y)<.THENXX=(X/2-INT(X/2)=.)-(X/2-INT(X/2)>.):YY=(Y/2-INT(Y/2)=.)-(Y/2-INT(Y/2)>.):SET(X,Y,1):SET(X-XX,Y,1):SET(X-XX,Y-YY,1):SET(X,Y-YY,1)
101 RESET(X,Y):RETURN
Pingback: CoCo MC6847 VDG chip “draw black” challenge responses. | Sub-Etha Software
Hello
I recently read about the vtech Laser 100/200 line in wikipedia and recognize the atomic green color we’re used to.
Here is the quote from wikipedia:
The VZ200 uses the Motorola 6847 video processor, which has a resolution of 256 × 192 pixels made from either 8 × 8 pixel character blocks in a 32 × 24 block screen, or a monochrome bitmapped mode.
Oh wow. Is this the same VTECH that makes all the kid computer toys these days?
I think this is much faster and avoids unnecessary SETs. Instruction 100 will do the POKE only once per character block.
10 CLS
20 FOR A=0 TO 31
30 X=A:Y=A:GOSUB 100
40 NEXT
50 GOTO 50
100 IF POINT(X,Y)<0 THEN POKE 1024+Y*16+X/2,143
101 RESET(X,Y):RETURN
I applaud you. And after testing, here’s a downside… if you try to draw a vertical line with this, I see it ends up setting the whole block. HOWEVER, changing it from A RESET to a SET appears to work for a vertical line, but then won’t work for the diagonal.
Ugh.
Since you have an excellent solution to the specific challenge, let’s make it more challegning: (Article updated with this secondary program.)
10 CLS
20 FOR A=0 TO 15
30 X=A:Y=A:GOSUB 100
31 X=15-A:Y=16+A:GOSUB 100
32 X=40+A:Y=7:GOSUB 100
33 X=40+A:Y=24:GOSUB 100
34 X=39:Y=8+A:GOSUB 100
35 X=56:Y=8+A:GOSUB 100
40 NEXT
50 GOTO 50
Ready! Slight correction to line 100 and voilá.
0 CLS
20 FOR A=0 TO 15
30 X=A:Y=A:GOSUB 100
31 X=15-A:Y=16+A:GOSUB 100
32 X=40+A:Y=7:GOSUB 100
33 X=40+A:Y=24:GOSUB 100
34 X=39:Y=8+A:GOSUB 100
35 X=56:Y=8+A:GOSUB 100
40 NEXT
50 GOTO 50
100 IF POINT(X,Y)<0 THEN POKE 1024+INT(Y/2)*32+INT(X/2),143
101 RESET(X,Y):RETURN
Wow, nicely done. So the concept is, if POINT returns -1, it’s not a graphics block. Then you set it to the green graphics block for the X,Y and use RESET. Do I have it?
Yes
And for maximum speed you could change line 100 from:
100 IF POINT(X,Y)<0 THEN POKE 1024+INT(Y/2)*32+INT(X/2),143
to:
100 IFPOINT(X,Y)<.THEN POKE&H400+INT(Y/2)*&H20+INT(X/2),&H8F
To time the difference, I added these extra lines:
15 TIMER=0
and:
45 PRINT TIMER
This lowers execution time from 188 to 163 timer units, i.e., down to 87% of the original time.
May I share your solution and those benchmark notes in a follow up?
Of course!
I forgot to delete the space between THEN and POKE, however I don’t think it will make a noticeable difference.
Also, in doing speed tests about the number format I verified that using hexadecimal numbers was more convenient only when the numbers in question have two or more digits.
That is good to note. I seem to recall checking . versus 0 versus &H0 but I don’t remember the outcome. Pretty sure . was always fastest. That was one I never knew about until recent years.
Update posted. Thanks again! I tried to squeeze a few more TIMER values out of it, with no luck.
I sucseeded in a few ore optimizations:
*** (1) “Canonic” solution to the problem
*** I decided to keep blank spaces for clarity because their impact on speed is very small
*** Execution time: 184 TU (timer units)
10 CLS
15 TIMER=0
20 FOR A=0 TO 15
30 X=A:Y=A:GOSUB 100
31 X=15-A:Y=16+A:GOSUB 100
32 X=40+A:Y=7:GOSUB 100
33 X=40+A:Y=24:GOSUB 100
34 X=39:Y=8+A:GOSUB 100
35 X=56:Y=8+A:GOSUB 100
40 NEXT
45 PRINT TIMER
50 GOTO 50
100 IF POINT(X,Y)<0 THEN POKE 1024+INT(Y/2)*32+INT(X/2),143
101 RESET(X,Y):RETURN
*** (2) Avoiding PPOINT and using PEEK instead; auxiliary variable ‘M’ is introduced
*** Contrary to what I expected, now it takes about 42% longer than the canonic case!
*** Execution time: 261 TU (timer units)
100 M=1024+INT(Y/2)*32+INT(X/2):IF PEEK(M)<128 THEN POKE M,143
*** (3) Canonic solution with special zero “.” and hexadecimal constants
*** Now this takes about 90% of the canonic solution
*** Execution time: 165 TU (timer units)
100 IF POINT(X,Y)<. THEN POKE &H400+INT(Y/2)*&H20+INT(X/2),&H8F
*** (4) Let’s relax a bit since the POKE function truncates decimals anyway, so we can use X/2 instead of INT(X2)
*** Now this takes about 86% of the canonic solution
*** Execution time: 159 TU (timer units)
100 IF POINT(X,Y)<. THEN POKE &H400+INT(Y/2)*&H20+X/2,&H8F
*** (5) Let’s avoid the division in INT(Y/2)&H20 and use (Y AND &H1E)&H10 instead
*** Now this takes about 82% of the canonic solution!
*** Execution time: 151 TU (timer units)
100 IF POINT(X,Y)<. THEN POKE &H400+(Y AND &H1E)*&H10+X/2,&H8F
All spaces could be removed, except the one between “Y AND”, however this provides a marginal speed increase at the expense of clarity.
Feel free and encouraged to use/repost/share this information.
I may have seen someone say multiplying by .5 was faster than dividing by 2, as well?
I also tried that but it turned out to be slower.