…that would have been my next computer after my Commodore VIC-20. $600 back in 1983 would be over $2000 in 2026. There was really no way I was talking my grandmother in to buying me a $2000 home computer back when folks were still unsure why anyone would want a home computer.
But, if I did, I’d be much more excited about the return of Commodore. The FPGA recreation, where they are making them using the original molds from the 1980s, has sold over 20,000 units. Likewise, reports of TheC64 (an emulator that looks like a mini C64) estimated to have sold over 300,000 units tells me the love Commodore users had for their 8-bit machines still lives on the same way it does in our CoCo community for our 8-bit systems.
Commodore 64 for sale at Best Buy?
Today I learned that the replica Commodore 64s are for sale at Best Buy (for shipment only, through a third party seller):
Historically, the C64 is the “largest selling computer model of all time” — a feat we will likely never see beaten since modern PCs and Macs have such a short lifespan on store shelves before they are replaced by a different model. While overall there have been more Macs or PCs sold, those have all been different models over the years. (This is the main thing I had against “more PCs sold than Macs” back in the 1990s — you were comparing thousands and thousands of different PC models collectively against a handful of Mac models; but as soon as you compared individual models, the iMac was one of the largest models sold of any computer of its era.)
And the VIC-20, too!
The VIC-20 was far from the best selling system of its era, yet even it got a TheVIC20 release in a full size replica model with an emulator inside. I had to order main from the UK, so it annoyingly has the “correct” spelling of Colour instead of the Americanized version ;-)
Replica Commodore VIC-20: TheVIC20.
There have also been replicas of things like the ZX Spectrum and other “obscure to us in the USA” models.
Maybe one day they will come for our community and we’ll see a mainstream emulator replica of a CoCo.
One can hope.
Congrats, new Commodore. Maybe I can finally get that C64 I would have loved to have 40 years ago.
Over in the CoCo Facebook group, Erico Patricio Monteiro asked an interesting question:
“Would it be possible to PRINT a transparent character?”
– Erico Patricio Monteiro
His idea was for putting stuff on the CoCo’s text screen without wiping out the background. He used an example of PRINT”OOOOX” where “O” represented the transparent character. The way I see it, if you had the first line printed like this:
PRINT @0,"ABCDEFG";
…and you had such a transparent character and did this:
PRINT @0,"OOOXOOO";
…your top line would then look like this:
ABCXEFG
This reminded me of how my Commodore VIC-20 had cursor movement characters you could embed in a PRINT statement. Once you typed the quote, you could now embed typeable escape codes to change colors, clear the screen, home the cursor, insert or delete characters, or just move the cursor up, down, left or right. This made VIC-20 program listings require a graphical printer to represent those characters. Here is something from the VIC-20 manual:
This is many pages into the manual, after it had explained how you can embed things like color changes or reverse video. The program listings in the VIC-20 manual had graphical characters in them, and you had to learn what to type to recreate them:
Program listings for the VIC looked weird ;-)
At some point, Commodore BASIC listings were represented with text strings instead of the graphical characters, making a modern listing look like this:
Then you just had to know what key was “black” or “left” (three times, as the “left*3” indicates).
But I digress…
Since there was no PRINT@ or LOCATE on the VIC-20, any time you wanted to print something in a particular spot on the screen you had to print the HOME (move cursor to top left of the screen) character then use a bunch of cursor controls to move to where you wanted to print.
This was … not optimal. And thus, most BASIC VIC-20 programs would print their information (lives left, etc.) on the top of the screen since it was shorter code just to home and print there:
VIC-20 Sky-Ape-Er, screen 3.
My Sky-Ape-Er VIC-20 game had a timer, and I got it in that top corner like this:
You will notice the above snipped says “reverse on” and has “time” in lowercase, but on my screenshot it is uppercase without being reversed. That is due to the character sets of the VIC-20 where some modes were upper and lower, some were upper with reverse, and other combinations. For the mode I was in, reverse was getting the uppercase characters (and uppercase characters typed with SHIFT would be the graphical characters for those keys).
“But that’s really not important to this story…”
If you look at the Color BASIC Unraveled book you can find the Console Out routine (PUTCHR) on page 84. I did not want to type it all in here, but I did find this GitHub repository by tomctomc that has this already in a text file:
; CONSOLE OUT
PUTCHR JSR >RVEC3 ; HOOK INTO RAM
PSHS B ; SAVE ACCB
LDB DEVNUM ; GET DEVICE NUMBER
INCB ; SET FLAGS
PULS B ; RESTORE ACCB
BMI LA2BF ; SEND TO LINE PRINTER
BNE LA30A ; SEND TO SCREEN
...snip...
; PUT A CHARACTER ON THE SCREEN
LA30A PSHS X,B,A ; SAVE REGISTERS
LDX CURPOS ; POINT X TO CURRENT CHARACTER POSITION
LA30E CMPA #BS ; IS IT BACKSPACE?
BNE LA31D ; NO
CMPX #VIDRAM ; AT TOP OF SCREEN?
BEQ LA35D ; YES - DO NOT ALLOW BACKSPACE
LDA #$60 ; BLANK
STA ,-X ; PUT IN PREVIOUS POSITION
BRA LA344 ; SAVE NEW CURPOS
LA31D CMPA #CR ; ENTER KEY?
BNE LA32F ; BRANCH IF NOT
LDX CURPOS ; GET CURRENT CHAR POSITION
LA323 LDA #$60 ; BLANK
STA ,X+ ; PUT IT ON SCREEN
TFR X,D
BITB #$1F ; TEST FOR BEGINNING OF NEW LINE
BNE LA323 ; PUT OUT BLANKS TILL NEW LINE
BRA LA344 ; CHECK FOR SCROLLING
LA32F CMPA #SPACE
BCS LA35D ; BRANCH IF CONTROL CHARACTER
TSTA ; SET FLAGS
BMI LA342 ; IT IS GRAPHIC CHARACTER
CMPA #$40
BCS LA340 ; BRANCH IF NUMBER OR SPECIAL CHARACTER
CMPA #$60 ; UPPER/LOWER CASE?
BCS LA342 ; BRANCH IF UPPER CASE ALPHA
ANDA #$DF ; CLEAR BIT 5, FORCE ASCII LOWER CASE TO BE UPPER CASE
LA340 EORA #$40 ; INVERT BIT 6, CHANGE UPPER CASE TO LOWER & VICE VERSA
LA342 STA ,X+ ; STORE CHARACTER TO SCREEN
LA344 STX CURPOS ; SAVE CURRENT CHAR POSITION
CMPX #VIDRAM+511 ; END OF SCREEN BUFFER?
BLS LA35D ; RETURN IF NO NEED TO SCROLL
You can see at LA30A the code begins checking for things like backspace and enter. Eventually at LA342 it puts the character on the screen an increments X which is the current screen location. It then has code (not shown) that detects being at the bottom of the screen and scrolling up a line if needed.
To patch this CHROUT routine to support a “transparent” character, I think we’d just have to intercept the code at LA342 and decide if it should put a character on the screen (STA ,X+) or just increment X (LEAX 1,X or something) without putting anything there.
And that would be a real simply patch. A CoCo 1/2 with 64K could run the program that copies the ROM into RAM then switches over, then this could code easily be patched.
And while we were there, maybe it could be extended to support cursor movements as well, replicating how the VIC-20 output works.
This should mean there were at least five versions of this manual. Does anyone have sources for other editions?
Also, the 1981 version was credited to Commodore International, Ltd. but the 1982 5th edition says Commodore Electronics, Ltd. What’s the story on the name change? Or was one the Commodore business from a different area of the world?
The reason behind this quest is to try to see how many versions of the type-in VIC-20 games were printed in these manuals. R.M. Smedley noticed that there were some minor differences in the Tank-V-UFO game listed in the 1981 version versus the 1982 version — specifically around lines 134-135.
I would like to find the other editions of this manual and try to type in all the program listings as accurately as possible so they can be compared.
TL:DNR – I figured out how I might port one of my old VIC-20 games to the CoCo so it actually looks like the VIC-20 game ;-)
The VIC-20 has a 22×23 text screen. The CoCo has a 32×16 text screen. At the time, going from a width of 22 characters to 32 seemed like a huge upgrade. After all, you could scroll up and down to get more lines, but you couldn’t scroll left and right to get more columns.
I knew there was no way I could port any of my old character-based VIC-20 games to the CoCo without altering the screen layouts. Games that were written to use the 22×23 display, such as my Sky-Ape-Er, could not be replicated on the CoCo’s 32×16 text screen with 100% size accuracy.
VIC-20 Sky-Ape Er, screen 1.
Without reprogrammable characters, anything on the CoCo’s text screen would look far less graphical. Each text blog could either be a letter/number/punctuation character, or a 2×2 block of one color plus black.
Even if I did try to use these blocky characters to port any of my VIC-20 games, they would not be accurate since the width and height were different. I would have to redesign them to fit the CoCo screen:
Above, you can see I tried to get the “spirit” of the game on the screen, but there are less steps for each level, and 10 more horizontal spaces on each level, so the gameplay would be quite different. (To get to the top takes 12 jumps on the VIC, but only 8 on the CoCo version.)
With 32×16 there is simply no way I could accurately recreate a 22×23 game.
At least, not in text mode.
I knew the CoCo’s 32 column screen was equivalent to the 256 pixel width hi-res screen, and it would be larger than whatever the VIC’s 22 column screen was. Therefore, I figured the VIC’s 23 row screen must be larger than the CoCo’s 16 row screen.
When I started revisiting my VIC-20 programs, I remember that each screen character was 8×8. That made the 22 columns represent 176 pixels (22*8), and the 23 rows represented 184 (23*8). 176×184 is smaller than the CoCo’s 256×192 screen! I had always thought the CoCo’s text characters were 8×8, but that was just the data used to draw them. There were a few extra lines between each row that I had never considered.
On the CoCo, 32 columns at 8 pixels each is 256 — that is what I would expect. But when it came to rows, if each character were 8 pixels high, that would only be 96 pixels tall (16*8)! I had never bothered to “math” this. The 192 horizontal resolution meant that each of the 16 rows was 12 pixels tall! That means the CoCo text font was really more like 8×12.
This led me to experimenting with the VIC-20 font data. I could display a full VIC-20 display of 176×184 with room to spare on the CoCo’s 256×192 screen. I wrote about this in an earlier article and made this example showing the 22×23 VIC-20 character set drawn on the CoCo screen:
VIC-20 20×32 screen displaying PETSCII on a CoCo
The VIC-20 did not have a graphics mode, and did everything by putting characters on the text screen. You were able to reprogram what those characters looked like. You could do some pretty neat things just by PRINTing or POKEing to the text screen.
This is how I made my Factory TNT game. I drew the screen like this…
Factory TNT for the VIC-20
…then remapped the characters to be my graphics:
VIC-20 Factory TNT.
I wanted to accurately represent that screen on a CoCo, I would have to do it using the CoCo’s hi-res 256×192 graphics screen. I could bring over all the actual character data and recreate it accurately, though the aspect ratio would be off a bit… It might look like this:
CoCo Factory TNT concept
Missing is the “MEN:” and “SCORE:” text labels on the top line. Those font characters would have to be brought over, as well. The VIC would let you remap A, B, C, D, etc. to be different characters, and if you used inverse video (or something like that) while in this “reprogrammed character mode”, they would show up as normal uppercase letters on the screen.
This was just a quick experiment, but perhaps I can also bring over just the VIC-20 font letters needed for “MEN:” and “LIVES:”. Maybe I’d want the whole alphabet so I could add a title screen or instructions. Factory TNT 2024, perhaps?
To be continued… Maybe.
(Okay. Definitely. I have already started working on a multi-part article series about this endeavor.)
Let me begin this installment by presenting the current Lights Out code with some renumbering done and a few minor improvements.
0 REM LITESOUT-P7.BAS
10 REM SETUP 20 DIM L(9,9)
100 REM START NEW GAME 110 GOSUB 5000 120 REM INITIALIZE GRID 130 MV=0 140 GOSUB 4000 150 REM SHOW GRID 160 GOSUB 1000 170 REM CHECK FOR WIN 180 IF LO=0 THEN 300 190 REM INPUT SQUARE 200 GOSUB 2000 210 REM TOGGLE SQUARES 220 GOSUB 3000 230 REM REPEAT 240 MV=MV+1 250 GOTO 150
300 REM GAME WON 310 PRINT "YOU WON IN";MV;"MOVES." 320 INPUT "PLAY AGAIN (Y/N)";Q$ 330 IF Q$="Y" THEN 100 340 PRINT "GAME OVER" 350 END
1000 REM SHOW GRID 1010 PRINT "GAME NUMBER:";GN 1020 PRINT " "; 1030 FOR A=1 TO GS 1040 PRINT RIGHT$(STR$(A),2); 1050 NEXT:PRINT 1060 FOR Y=0 TO GS-1 1070 PRINT RIGHT$(STR$(Y+1),2);" "; 1080 FOR X=0 TO GS-1 1090 IF L(X,Y) THEN PRINT "X ";:GOTO 1110 1100 PRINT ". "; 1110 NEXT 1120 PRINT 1130 NEXT 1140 PRINT "MOVES:";MV;"LIGHTS ON:";LO 1150 RETURN
2000 REM INPUT SQUARE 2010 S$=MID$(STR$(GS),2):PRINT "X,Y (1-";S$;",1-";S$;" OR 0,0)"; 2020 INPUT X,Y 2030 IF X=0 THEN IF Y=0 THEN 320 2040 IF X<1 OR X>GS OR Y<1 OR Y>GS THEN 2010 2050 X=X-1:Y=Y-1 2060 RETURN
3000 REM TOGGLE SQUARES 3010 L(X,Y)=NOT L(X,Y):LO=LO-(L(X,Y)*2+1) 3020 IF X>0 THEN L(X-1,Y)=NOT L(X-1,Y):LO=LO-(L(X-1,Y)*2+1) 3030 IF X<GS-1 THEN L(X+1,Y)=NOT L(X+1,Y):LO=LO-(L(X+1,Y)*2+1) 3040 IF Y>0 THEN L(X,Y-1)=NOT L(X,Y-1):LO=LO-(L(X,Y-1)*2+1) 3050 IF Y<GS-1 THEN L(X,Y+1)=NOT L(X,Y+1):LO=LO-(L(X,Y+1)*2+1) 3060 RETURN
4000 REM INITIALIZE GRID 4010 INPUT "GRID SIZE (3-10, ENTER=5)";GS 4020 IF GS=0 THEN GS=5 4030 IF GS<3 OR GS>10 THEN 4010 4040 PRINT "INITIALIZING..." 4050 FOR A=1 TO 10*GS 4060 Y=RND(GS)-1 4070 X=RND(GS)-1 4080 GOSUB 3000 4090 NEXT 4100 RETURN
5000 REM SELECT GAME 5010 PRINT "PLAY SPECIFIC GAME # (Y/N)?" 5020 S=S+1:A$=INKEY$:IF A$="" THEN 5020 5030 IF A$="Y" THEN 5070 5040 IF A$="N" THEN A=RND(-S) 5050 GN=RND(65535):A=RND(-GN) 5060 GOTO 5100 5070 INPUT "PLAY GAME (1-65535)";GN 5080 IF GN<1 OR GN>65535 THEN 5060 5090 A=RND(-GN) 5100 RETURN
As I tested this version, I noticed my random grid generator was not very good–at least on a large 10×10 grid. It really needed to do more random light toggling for larger grids. This change would go in this line – maybe just doing a “grid size * X”, like “10*GS” or something. I am still trying things, but for now I made it do more random toggles the larger the grid size is (line 4050).
I also made it so the default grid size was 5 (line 4010).
And I fixed some output where it printed a numeric variable. In Color BASIC, there is an extra space printed before and after printing a number:
PRINT "*";42;"*" * 42 *
And, technically, it’s not a space before a number — it’s a place for the sign (none if positive, “-” if negative):
PRINT "*";-42;"*" *-42 *
Since I knew I was only printing a positive number, I just got rid of that leading space, and the one after it. I did this by converting the number to a string using STR$. That will convert it to a string with the first space (a place for the sign) but no space after it:
PRINT "*";STR$(42);"*" * 42*
Then all I needed to do was trim off that leading space. In the old days, I would have done this by getting the length of the string using LEN$ and then using RIGHT$ to get just the character(s) after that leading space:
N=42 N$=STR$(N) L=LEN(N$) PRINT RIGHT$(N$,L-1)
But in recent years, someone commented on this site (I believe) about how you could use MID$ without a size and just specify the starting position in a string, and it would return everything from that position to the end:
N=42 PRINT MID$(STR$(N),2)
Nice! “Wish I knew then what I know now…”
But I digress…
We now have a fairly “feature complete” version of Lights Out that runs in very basic BASIC — it doesn’t even make use of ELSE.
Before I move on to making this look a lot nicer on a CoCo, I thought it might be fun to port it to a VIC-20. I made use of the wonderful CBM prg Studio Windows-based tool that can build BASIC or assembly programs for all kinds of Commodore machines. I just pasted in my source, and then found a few minor things I would need to change to run on the VIC-20’s CBM BASIC.
The first thing I did after pasting the code in to the editor was to convert it all to lowercase. That seems to be how that BASIC works, as SHIFT characters turn in to PETSCII graphics characters.
Now I would be able to build the program.
It would build right away, but not run on the VIC yet until I fix two things that are different between Color BASIC and CBM BASIC:
A$=INKEY$ must be changed to GET A$
RND(x) must be changed to INT(RND(1)*X)-1 (Doing the random seed using RND(-X) works the same way on the VIC, and could be left alone.)
CoCo: 5020 S=S+1:A$=INKEY$:IF A$="" THEN 5020
VIC: 5020 S=S+1:GET A$:IF A$="" THEN 5020
CoCo: 4060 Y=RND(GS)-1
VIC: 4060 Y=INT(RND(1)*GS)
CoCo: 4070 X=RND(GS)-1
VIC: 4070 X=INT(RND(1)*GS)
After that, I tried to RUN it and ran in to a problem with INPUT:
From testing, it seems that long prompts on INPUT cause issues, possibly related to how the VIC’s full screen editor works. I sent a tweet to 8-Bit Show and Tell to see what he knew, and did a simple workaround by breaking up the prompt and the input on separate screen lines:
I thought I might have the same issue with the “select square” input, but that prompt does not overlap to the next line so it worked… or so I thought. With the default grid size of 5×5, the prompt looked like:
X,Y (0-5,0-5 OR 0,0)?(space) *(cursor here)
That seemed to work just fine, but when I did a grid of 10×10, it made the prompt longer, wrapping the “?” of INPUT to the next line:
X,Y (0-10,0-10 OR 0,0) ? *(cursor here)
So I needed to fix that, too. I had already had to break that one up in to a PRINT and an INPUT since I was printing variables in the prompt, so I just took the semicolon off from the end of the PRINT:
2000 rem input square 2010 s$=mid$(str$(gs),2):print "x,y (1-";s$;",1-";s$;" or 0,0)" 2020 input x,y
Now I had what appeared to be a working version of the game for VIC-20. BUT, it would need some work to reformat the prompts to fit on aโ22-column screen, versus the 32- column CoCo screen. For anyone who wants to work on that, here is the VIC-20 version with the lines in bold that have changes from the CoCo version:
0 rem litesout-p7.bas
10 rem setup 20 dim l(9,9)
100 rem start new game 110 gosub 5000 120 rem initialize grid 130 mv=0 140 gosub 4000 150 rem show grid 160 gosub 1000 170 rem check for win 180 if lo=0 then 300 190 rem input square 200 gosub 2000 210 rem toggle squares 220 gosub 3000 230 rem repeat 240 mv=mv+1 250 goto 150
300 rem game won 310 print "you won in";mv;"moves." 320 input "play again (y/n)";q$ 330 if q$="y" then 100 340 print "game over" 350 end
1000 rem show grid 1010 print "game number:";gn 1020 print " "; 1030 for a=1 to gs 1040 print right$(str$(a),2); 1050 next:print 1060 for y=0 to gs-1 1070 print right$(str$(y+1),2);" "; 1080 for x=0 to gs-1 1090 if l(x,y) then print "x ";:goto 1110 1100 print ". "; 1110 next 1120 print 1130 next 1140 print "moves:";mv;"lights on:";lo 1150 return
2000 rem input square 2010 s$=mid$(str$(gs),2):print "x,y (1-";s$;",1-";s$;" or 0,0)" 2020 input x,y 2030 if x=0 then if y=0 then 320 2040 if x<1 or x>gs or y<1 or y>gs then 2010 2050 x=x-1:y=y-1 2060 return
3000 rem toggle squares 3010 l(x,y)=not l(x,y):lo=lo-(l(x,y)*2+1) 3020 if x>0 then l(x-1,y)=not l(x-1,y):lo=lo-(l(x-1,y)*2+1) 3030 if x<gs-1 then l(x+1,y)=not l(x+1,y):lo=lo-(l(x+1,y)*2+1) 3040 if y>0 then l(x,y-1)=not l(x,y-1):lo=lo-(l(x,y-1)*2+1) 3050 if y<gs-1 then l(x,y+1)=not l(x,y+1):lo=lo-(l(x,y+1)*2+1) 3060 return
4000 rem initialize grid 4010 print "grid size (3-10, enter=5)":input gs 4020 if gs=0 then gs=5 4030 if gs<3 or gs>10 then 4010 4040 print "initializing..." 4050 for a=1 to 10*gs 4060 y=int(rnd(1)*gs) 4070 x=int(rnd(1)*gs) 4080 gosub 3000 4090 next 4100 return
5000 rem select game 5010 print "play specific game # (y/n)?" 5020 rem s=s+1:a$=inkey$:if a$="" then 5020 5021 s=s+1:get a$:if a$="" then 5020 5030 if a$="y" then 5070 5040 if a$="n" then a=rnd(-s) 5050 gn=rnd(65535):a=rnd(-gn) 5051 rem gn=int(rnd(1)*65535)-1:a=rnd(-gn) 5060 goto 5100 5070 input "play game (1-65535)";gn 5080 if gn<1 or gn>65535 then 5060 5090 a=rnd(-gn) 5100 return
The more I look at this code, the more optimizations I want to make to it.
But for now, that is a version for CoCo, and a version for Commodore. It should be easy to port to other flavors of BASIC. Let me know if you port it to something.
Now that I know how to write the game, the next goal will be to make it look a lot better on the CoCo (and maybe VIC-20 as well, if I feel ambitious).
But I think I need a brake from Lights Out for a bit…
In 1982 (possibly 1981?), I received my first computer, a Commodore VIC-20.
I taught myself BASIC and ended up sending in a simple game to a newsletter called VIC-NIC News.
Recently, someone sent me a scan of my program submission, ending a quest I had been on for almost a decade.
Here is that article from VIC-NIC News #6 (Volume 2, Number 4) from July/August 1983:
I thought it would be fun to walk through the program and see what it does…
0 rem 2024/2/11 fixed joystick
I added this line when I “fixed” the joystick routine so it could properly read the RIGHT direction. That fix, and the two numbers checked for moving the cup left or right, will be different than the original version published back in 1983.
1 print"{clear}{down*3} eggs" 2 print"{down*3} by allen huffman" 3 print"{down*2}vic-nic news july 1983" 4 forj=1to5000:next
I believe these lines were added by the VIC-NIC NEWS. The {words} in curly braces are ASCII notation for the Commodore escape codes you could put in PRINT statements. {clear} is the code for clearing the screen, and {down} is the code for moving the cursor down one line. Therefore, that clears the screen then moves down three lines before spacing over to print the game title. The text would print in UPPERCASE and the code appears in UPPERCASE on an actual VIC-20. These lines just print a simple title screen, then wait for a few seconds before starting the game.
5 poke36879,8:printchr$(147)
Heh. I remember joking that everything on the VIC-20 used the POKE command, and sure enough, the very first thing I do in my program was a POKE. I consulted a useful VIC-20 memory map document to find this:
900F 36879 Screen and border color register
bits 4-7 select background color
bits 0-2 select border color
bit 3 selects inverted or normal mode
The value of 8 is bit 3 , so I was leaving “normal” mode on and setting background and border colors to 0. I don’t recall what this does, so I tried it in the VICE VIC-20 emulator and see it makes the screen black with blue text:
Checking the PEEK value of 36879 on startup shows it defaults to 27, which is the bit pattern 00101011.
As I searched for information on the colors, I found the wikipedia page for the VIC’s video chip. It lists the 16 colors the VIC-20 could produce as follows:
0 โ black 1 โ white 2 โ red 3 โ cyan 4 โ purple 5 โ green 6 โ blue 7 โ yellow 8 โ orange 9 โ light orange 10 โ light red 11 โ light cyan 12 โ light purple 13 โ light green 14 โ light blue 15 โ light yellow
With only three bits for the border color, the border can only use colors 0-7 (black through yellow). The background color uses four bits, so it can be any of the sixteen colors (0-15). I may have known this at the time, but if so, I had forgotten that the border could not be set to match all the possible screen colors.
In my case, setting the background and border to 0 makes it black.
If I had taken the original value (00101011, 27) and just cleared bit 3 (invert/normal, 00100011, 19), I see that it changes the text/foreground to inverted video:
Interesting. So I guess we are seeing inverted video on a black screen with black border? I really don’t know why, and I suspect I just saw that POKE in a magazine and liked it.
The print of CHR$(147) is the escape code that clears the screen. (Yep, there was not even a CLS type command in Commodore BASIC.)
10 b=8130:m=3:sc=0 15 e=int(rnd(1)*20)+7703
Two of these variables deal with locations within screen memory:
1E00-1FFF 7680-8191 Screen memory
B is the memory location of the player’s bucket. This is some spot on the bottom line of the screen. 7680 represents the top left character of the VIC’s 22×23 text screen. If you do the math, that is 506 bytes of memory used to represent the screen. But, screen memory of 7680-8191 is 512 bytes. The actual last visible byte on the screen is 8185. The player’s bucket is at 55 spots earlier, which is two full lines (22 bytes each) and 11 (half way in a 22 line screen). I am not sure why I started the game on the third line UP from the bottom, but I did.
M is how many men are left. Video games were very male-centric in the early days, I guess. Actually, in the early years, I don’t recall ever knowing a single girl that played video games, and do not recall seeing any in the arcades I went to, either.
SC is the score, which starts at 0.
E is the memory location of the falling egg. It starts at 7703 (the second byte of the second line) and then adds a random value of 0-19to it. This means I left out the left and right column of the screen for some reason. Looking at how I designed my later Factory TNT game, where the game had a border on the left and right and also a few lines at the bottom of conveyor belt graphics…
VIC-20 Factory TNT.
…it makes me wonder if I was already planning something like that for Eggs, but left it out to make the program smaller and easier to type in from a newsletter. (Above, you see I start the cup in Factory TNT 5 lines up, instead of 3 like Eggs, but it also limits the falling bombs under the spigots not using the left and right side of the screen. Curious.)
20 printchr$(19);chr$(5);"score:";sc
CHR$(19) homes the cursor to the top left. This would be like doing “PRINT@0,;” on the CoCo. The “SCORE:” is then printed with the current value.
25 pokeb,21:pokee,81
The character of 21 (a letter “U”) is POKEd to the player location, and a character 81 (filled circle) is POKEd to the falling egg location.
This code, which I must have gotten from some magazine, is the joystick code. The code in the original article used incorrect memory locations, and was unable to read the “right” direction. I must not have known why, and just changed the published version to use UP and DOWN to move left and right (or, maybe it worked for me, but VIC-NIC NEWS couldn’t get it to work due to a typo and changed the directions?). Either way, memory location 37152 contains the “right” joystick switch, and 37137 contains the “up, down, left and fire” switches. The bits in one of these gets used for different things, to the POKEs to 37154 are used to toggle one of the bytes from joystick mode to keyboard mode. When you do that POKE, part of the keyboard stops working, so it has to be POKEd back at the end.
Because of how this works — if you BREAK the program at the wrong time, during those lines when it is POKEd to joystick, you won’t be able to type all the characters on the keyboard. A frustrating issue ;-)
The joystick line basically takes the 4-bits (up, down, left and fire) from one memory location and the 1-bit (right) from the other location and combines them in to one byte. Because the bits read “1” when NOT pressed, and “0” when pressed, the code also inverts the results so “1” now means ON.
This IF statements check for directions. J=0 means nothing is pressed, so skip the rest. J=4 means the left button is pressed, so decrement the bucket location by one (moving it one to the left). J=16 means the right button is pressed, so increment the bucket location by one (moving it to the right).
65 ifb=8120thenb=b+1 70 ifb=8141thenb=b-1
These two checks make sure the bucket did not move too far left or right. B=8120 checks to see if the new position is in the first column. If so, too far, so move it back to the right one place. B=8141 is checking for the right column and if it is there, it moves it back left one. With am minor change, I could have made it so you could “wrap around” the screen, where if you moved to the right it would reset the position to the left, and vise versa. That might be an interesting update or option. (Allowing you to quickly “warp” from the left side of the screen to the right to catch an egg you might have otherwise missed.)
Hmm, thinking about this, maybe I shortened the number of rows that the egg drops so ensure you always had less time to move and catch it, increasing the challenge?
75 pokeb,21 80 pokee,32 85 e=e+22 90 pokee,81
At line 75, the player’s basket location has been updated so we POKE the “U” character (21) back on the screen. We then POKE a space (32) to where the egg is, erasing it. The Egg location is incremented by 22, moving it down to the next line, then the Egg character (81) is POKEd back to that new location.
Much like how the basket is checked against the left and right column of the screen, some checks for the falling egg location are done here. If the egg location is at or greater than 8120 (first character of three lines from the bottom of the screen) then it is checked to see if it is the same position of the basket (the player caught the egg).
I’d have to benchmark this and see if that “e>=8120” even needs to be there. If that condition is not true, it would just skip quickly to the end of the line and move on. I’m expecting the overhead of checking “e=b” is less (no long number to parse) so it would probably be faster to just always check “e=b”. If the egg was caught, GOTO 110 happens to increment the score.
There is another check for >=8120 and then “e<>b” skipping to another line. This is poorly coded. If the check for “bottom” line was needed, something like this might be better:
IF E>8120 THEN xxx IF E=B THEN 110 (player caught it) ...else, player did not, handle here xxx continue on...
Something like that would simplify the logic, speed it up, and reduce the program size. But hey, I was just learning BASIC.
After this, if the egg did not reach the bottom and get caught or not caught, it goes back up to line 25 to continue the program loop.
110 sc=sc+10:pokee,32:goto15
This is where we go when the player catches an egg. Score is incremented by 10, the egg is erased by POKEing a space there, and then we go to line 15 where a new egg position will be created and the process will start over.
115 m=m-1:pokee,32 120 ifm=0then135 125 goto15
115 is where we end up if the egg reaches the bottom and the player did NOT catch it. The “men left” variable will be decremented, and the egg erased.
If M gets to 0, then game over, which is handled at line 135.
Otherwise, we go back to line 15 to make a new falling egg and continue.
CHR$(17) is the escape code to move the cursor down one line, so the first line moves down five lines.
CHR$(32) is a space, so the second line prints six spaces over.
CHR$(158) sets the text color to yellow, it seems, and prints “GAME OVER”.
Then, for some reason, I don’t use the CHR$(17) to move down, and instead use the embedded screen code. This makes me wonder if I did this, or if it was changed by the VIC-NIC NEWSLETTER folks.
My choice of looking for “Y” or “N” is interesting. This works, and is short, but it is not how I would do it today. If GET A$ catches a “Y” we just RUN to start everything over. If it is an “N” we just END and stop right there. Otherwise we go back and check again.
This is kinda clever, since I would have thought of writing it like:
xxx GET A$:IF A$="" THEN xxx IF A$="Y" THEN RUN IF A$="N" THEN END GOTO xxx
…and that would be larger. Was I smarter then?
And that, my friends, is my first published program. I do not know how close this code is to what became Factory TNT (it would have been trivial to rewrite from scratch) but I can definitely see similarities — it is effectively the same program, just with more graphics, sound and such added in the Factory TNT version.
And now I guess that is all I can possibly write about this program.
In my recently-recovered “first program I ever had published,” I noticed that the joystick was not working. I was testing on VICE (the Versatile Commodore Emulator) on a Mac. The code that I had to read the joystick was clearly something I found in a magazine or somewhere because I have no idea what it does:
I suspected maybe a typo was introduced when VIC-NIC NEWS typed in my program to print it out for publication. I did some searching to see how you were supposed to read the VIC-20 joystick. I was surprised that the Commodore VIC-20 manual didn’t offer any code to do this.
The VIC is designed to handle only one joystick, and it takes two bytes to control that joystick. In the VIC, location 37137 is PEEKed to read the joystick for the up, down, left, and fire button movements. Location 37152 is PEEKed to detect movements to the right.
…
To see just how easy it is to detect movement on the joystick, plug in your joystick, type in one of the following short programs, and then RUN. The programs simply PEEK the joystick control bytes, and then PRINT that reading to the screen.
For the VIC-20:
10 PRINT PEEK(37137), PEEK(37152) : GOTO 10
– Atari Magazine, issue 42
Curious. My code was not using either of those addresses. Either my code or this magazine had a typo.
I tried those two PEEKs in VICE and noticed only the fire button was making the values change. This matched the VICE joystick display also showing only the fire button working.
I then thought the joystick I was using (a USB joystick that came with my TheVIC20) might have an issue. I tested it using a joystick test program, and it appeared to read all directions correctly.
A bit of more searching and I found that the Mac version of VICE has has an issue with joysticks not working since sometime in 2022:
Even if my code was correct (to be determined), I would not be able to test it on the Mac version of VICE.
I then tried running Eggs from the Windows version of VICE and was able to see the joystick work — but, it was using UP and DOWN to move the cup left and right. Odd. I know I must have intended for it to use left and right, because my typed instructions clearly stated:
“Use joystick to move the cup left and right to catch falling eggs.”
– Eggs instructions.
While technically it didn’t say “move the joystick left or right,” I think it would have been a very odd choice for me to use “up” to mean left, and “down” to mean right, in a game like this.
This led me back to suspecting a typo in my joystick code. I went back to those two PEEKs from Atari magazine and tested them on the Windows version of VICE. This time, it seemed to change for all directions other than right. It gave values for Up, Up-Left, Left, Left-Down and Down, as well as the button. Clearly, this code was wrong (or maybe the Windows version of VICE also had an issue).
I decided to figure out where my joystick code came from. I searched for this code:
…and archive.org actually had a single match! It was found in Issue #8 of The TORPET (Toronto Pet) on page 31. This Commodore PET publication had a section about the then-new VIC-20. For fun, here is the entirety of their VIC-20 section:
VIC NOTES by John O’Hare
As of Mid October, 15,000 VIC’s have been sold in Japan, 15,000 more in the U.S., and, though not yet available in Europe, orders are accumulating fast. -JS
If you really want a color PET, Commodore suggests you consider buying a VIC as a peripheral for your PET! Seriously, it uses Upgrade BASIC V2, is cassette compatible, and has excellent color compared to Apple, and Atari. -JS
Some VIC POKE locations are:
51 decrements when key hit. 204 cursor on flag. 56 pointer to top of memory. 211 cursor column. 67 holds 1 when key hit. 214 cursor row. 197 value of key depressed. 36865 border position (vertical). 145 flag for left shift key. 36864 border position (horizontal). 245 detects special keys. 36869 pointer to character generator. 240= norm. 255 = 7168.
To read a joystick on a VIC (standard ATARI joystick works), use the following subroutine:
JO Values returned are: 1 = up, 17 = up and rt, 16= right, 18 = down and r t, 2 = down, 6 = down and Ift, 4= left, 5= up and Ift.
VIC GAME REVIEWS
VIC GAMES PAC, $25 from Creative Software. 3 VIC arcade games: VIC Trap, Seawolf, and Bounce Out. Seawolf and Bounce Out are machine language, with very fast action. Very good games, but could be better if they used Hi Res graphics. -JOH
– The TORPET, Issue #8, Page 31
Wow, early days – reporting only 15,000 VIC-20s had been sold at that point!
In my code, I check for the value of 18 to move the bucket left (“ifj=18thenb=b-1”) and a value of 17 to move the bucket right (“ifj=17thenb=b+1”). That matches the values for up and down in this TORPET article! I guess I really did mean for up and down to move left and right.
But I have a theory about this, which I will get to in a moment…
The thing I immediately noticed was this code used two different memory locations, while my program (as listed in VIC-NIC NEWS) used the same memory location twice. I consulted a VIC-20 memory map to see what all the various addresses are for:
37137 – Port A output register: (PA0) Bit 0=Serial CLK IN, (PA1) Bit 1=Serial DATA IN, (PA2) Bit 2=Joy 0, (PA3) Bit 3=Joy 1, (PA4) Bit 4=Joy 2, (PA5) Bit 5 = Lightpen/Fire button, (PA6) Bit 6=Cassette switch sense, (PA7) Bit 7=Serial ATN out
37151 – Port A (Sense cassette switch)
37152 – Port B output register: keyboard column scan, (PB3) Bit 3 =cassette write line, (PB7) Bit 7 =Joy 3
37154 – Data direction register B
The TORPET code looked wrong since one of the locations it was using had nothing to do with the joystick.
The Atari Magazine looked better since it used the two locations that mentioned joystick – 37137 and 37152. 37137 contains three joystick directions (Joy 0-2) plus the button. 37152 contains the final joystick direction (Joy 3). However, running this code doesn’t show anything changing for “right”.
I think the extra POKEs the code I used (and the code in The TORPET used) may explain that. It seems you have to POKE to change the purpose of some of this bits. 37154 is a data direction register for Port B (37152), and before my joystick code I POKE it to 127 which is a binary pattern of 01111111. After doing the joystick PEEK, the code POKEs it to 255, which is 11111111. I am suspecting that that 0 (bit 7) indicates read of whatever is hooked to that bit — which is Joy 3 (PB7). It looks like you turn it to 0, then you can PEEK it, then it gets set back to a 1 after.
…and now the second value changes when the joystick is pressed right. Huzzah!
It looks like the first byte reads up, down, left and fire, and the second is right. The POKE is only used to toggle the right bit on and off to do a read. It should get restored after (set back to 1) but in my quick demo, I didn’t bother to do that and I found I could not type certain keys. Aha, that explains “keyboard column scan.” That bit must be used to read a keyboard column, normally, and can be switched to read the joystick instead.
I will have to explore that more, later, but for now I can clearly see an issue with my code. By using only one of those locations, it is never reading the I/O bit that represents the “right” direction.
37151 does not have anything to do with the joystick. This code takes the PEEK of that location and ANDs it with 60 (bit pattern 00111100) telling me it is expecting to use four bits. That matches the four joystick bits that are at 37137:
Bit 2 – (PA2) Bit 2=Joy 0
Bit 3 – (PA3) Bit 3=Joy 1
Bit 4 – (PA4) Bit 4=Joy 2
Bit 5 – (PA5) Bit 5 = Lightpen/Fire button
I think The TORPET got it wrong, and that second PEEK should be 37137.
The PEEK of 37152 seems okay. It ANDs it with 128 (bit pattern 10000000) which matches looking for that bit for the joystick:
Bit 7 – (PB7) Bit 7 =Joy 3
I suspect Atari Magazine just omitted the POKE needed to have the bits come from the joystick port, and The TORPET just had the wrong address listed. Since I had never heard of The TORPET, I expect I got my code from one of the few magazines I had at the time (Family Computing, Compute or Compute’s Gazette).
I changed my code to use 37137, but it still did not work! Now I could only move to the right by pressing Up+Right.
I think it is time to figure out what this code is trying to do.
Figuring out what this code is trying to do
Let’s start with the “correct” TORPET code and dissect what it is doing:
37137 – Port A output register: (PA0) Bit 0=Serial CLK IN, (PA1) Bit 1=Serial DATA IN, (PA2) Bit 2=Joy 0, (PA3) Bit 3=Joy 1, (PA4) Bit 4=Joy 2, (PA5) Bit 5 = Lightpen/Fire button, (PA6) Bit 6=Cassette switch sense, (PA7) Bit 7=Serial ATN out
37152 – Port B output register: keyboard column scan, (PB3) Bit 3 =cassette write line, (PB7) Bit 7 =Joy 3
PEEK(37152) uses “AND 128” to get just the high bit (bit 7) of Port B, which is the “right” joystick direction. It will either be 0 (no right) or 128 (right). It then divides by 8 which effectively shifts that bit over three places to the right:
10000000 - 128 (original reading) 00010000 - 16 (after the divide by 8)
PEEK(37137) uses “AND 60” to mask out the four bits in the middle. If they were all “on” (you can’t do that with a normal joystick), it would read 00111100. It then divides by 4 which effectively shifts those bits over two places:
00111100 - 60 (original reading if all joystick inputs were "on") 00001111 - 15 (after the divide by 4)
It adds those two values together, so this code is creating a new value of 5 bits, where those five bits represent the joystick switches for up, down, left, right and fire (00011111). From looking at the bit pattern, this new byte represents the following:
Bit 0 – Up
Bit 1 – Down
Bit 2 – Left
Bit 3 – Fire
Bit 4 – Right
Next I wondered why the program uses “NOT.” From checking the PEEKs, I see that when a joystick switch is not on, it shows a 1. When it is activated, it shows a 0. The NOT is used to invert that logic:
If no switches are pressed, the value is 31 (00011111). NOT flips the bits, so that value becomes 11100000. (Actually, I think it is represented as 16-bits, so 11111111111000000.) I believe when you use AND/OR/etc. the value is treated as a 16-bit signed value (-32768 to 32767) with the high bit representing negative. There result is the 31 becomes a -32. This explains the “+32” at the end.
The result is a value that is 0 if no switches are pressed. All of this match (dividing, adding, NOTing) does make the routine slow so maybe we’ll play with speeding it up sometime…
Using this newly created bit pattern, the BASIC program could use specific values to represent a direction (up), or two directions at the same time (up+left). My game did not use the fire button, but I think the way you would check that would be to use AND on the JO value to look for that specific bit, that way the rest of the value could be anything (up+fire, up+left+fire, nothing+fire, etc.).
Here is a test program for the “fixed” TORPET code:
10 rem fixed torpet code 20 gosub 9000 30 if jo and 1 then print "up "; 40 if jo and 2 then print "down "; 50 if jo and 4 then print "left "; 60 if jo and 8 then print "fire "; 70 if jo and 16 then print "right"; 80 if jo<>0 then print 90 goto 20 9000 poke 37154,127 9010 jo=(not((peek(37152)and128)/8+(peek(37137)and60)/4))+32 9020 poke 37154,255 9030 return
Though, a mystery I Have yet to understand, is why do so many VIC-20 joystick references say you can also use 37152 and 37151? This code also works:
Now … why did I use Up and Down in my original Eggs? I think this is because the joystick code I had was broken and never returned a value for right. This was because it was PEEKing the same byte twice instead of the second byte being the one that had the “right” switch! I probably couldn’t get it to work, so I just used UP and DOWN.
Using this “fixed” code, I could now alter my program to work like I originally intended:
And now, while I still wonder why so many VIC articles disagree on how to read the joystick, at least I can move left and right in my 1983 classic VIC-20 game Eggs…
2024-02-10 – Added screen shots, and pasted in the code.
On February 2, 2024, I received an e-mail with the subject: Eggs program
Could this be someone who had a copy of the VIC-NIC News newsletter where my “Eggs” VIC-20 program appeared? The e-mail read:
Hi Allen,
I saw on your website you were looking for a copy of your Eggs program listing that was in The Vic-Nic News magazine.
I went through the issues I have (#1 thru 7) and found the listing in #6. If you still need it, I can scan the page and email it to you or copy it and mail it.
Take care,
(name to be added, pending permission)
– e-mail received on 2/2/2024
I replied back:
“Proof that VIC-NIC NEWS actually existed! I would very much like a scan of that issue. Actually, since this is so difficult to find, would you be willing to scan them all so we could get them uploaded somewhere? Maybe archive.org?
But yes. Please yes. I would very much like that. Very much.”
– my e-mail reply
And today, I received a scan of my Eggs program! I had pretty much given up ever finding a copy.
Thank you thank you thank you!
I recognize my doodles, but had forgotten I sent drawings in. Actually, I believe I sent the program in typed up via a typewriter. The instructions and the “ASCII art” representation of the game screen were typed by me, and the doodles were added. Actually, I did have some kind of thermal printer for my VIC-20, so perhaps I included the program printed out that way (I see it has a few embedded screen control codes in a few PRINT statements). It is very exciting to see this again.
There may still be some typos, and I think there may be an issue with the PEEKs used to read the joystick. Currently, the Mac version of the VICE Emulator has a bug an joysticks don’t work (well, the fire button does, but nothing else). I will test it on my TheVIC20 machine soon.
And here it is in all its glory!
Title Screen – I think they made this title screen. I hope I would have centered things better, if I had done it.
Game Play – A “U” for the players “bucket” (B variable), and a ball for the falling “egg” (E variable):
Does anyone know where Duane Later is these days? Duane wrote the three type-in games from the VIC-20 manual (Tank vs UFO, Killer Comet and Rocket Command). Beyond a few entries on some websites, I cannot find anything else.