Category Archives: CoCo

Tandy/Radio Shack TRS-80 Color Computer (CoCo)

How to crash a CoCo 3

From a fresh boot…

CLEAR 16500
WIDTH 40

I have been going through all my OS-9 hard drive images trying to get everything compiled into one place. During this project I ran across a folder called DECB (Disk Extended Color BASIC). It contained the following files:

colours.BAS
contents.txt
DEL.BAK
del.BAS
microwar.txt
new.BAS
reader
copy.asc
reader.asc
reader.BAS
subs.BAS
TEST.DEL
TEST.TXT

I had no recollection of what this was, nor why filenames were in lowercase. That was not normally how files were done from Disk BASIC on a CoCo due to the 32-column screen showing lowercase as inverted video.

The “microwar.txt” was an e-mail response to an inquiry I made to Microware in 1993 about the history of OS-9:

INTERNET# Document Id: UX00f.BUX0039573

Item 6352278 93/08/24 06:03

From: STEVES@MICROWARE.COM@INTERNET# Internet Gateway II

To: COCO-SYSOP Allen C. Huffman

Sub: Re: The History of OS-9

From mcrware!microware.com!steves@uunet.UU.NET Tue Aug 24 17:24:36 1993
Received: from relay1.UU.NET by relay2.geis.com with SMTP
(1.37.109.4
/15.6) id AA23578; Tue, 24 Aug 93 17:24:36 +0100
Received: from spool.uu.net (via LOCALHOST) by relay1.UU.NET with SMTP
(5T.61/UUNET-internet-primary) id AA11760; Tue, 24 Aug 93 12:24:35 -0400
Received: from mcrware.UUCP by uucp2.uu.net with UUCP/RMAIL
(queuweing-rmail) id 122237.10246; Tue, 24 Aug 1993 12:22:37 EDT
Received: from yme by microware.com with SMTP id AA00775
(5.67a8/IDA-1.5 for <coco-sysop@genie.geis.com>); Tue, 24 Aug 1993 10:03:08
-0500
From: Steve Simpson <steves@microware.com>
Received: by yme id <AA00684@yme>; Tue, 24 Aug 93 10:03:04 CDT
Date: Tue, 24 Aug 93 10:03:04 CDT
Message-Id: <9308241503.AA00684@yme>
To: coco-sysop@genie.geis.com
Subject: Re: The History of OS-9

The “Steve” there was Steve “Homer” Simpson, who I would later know when I went to work for Microware two years later. He provide me with a Microware history article, and a Ken Kaplan interview about Microware’s first 15 years. (Note to self: Get this archived somewhere.)

The “TEST.TXT” file was a 300 line text file, obviously created by a program, that was just this:

This is a file of 300 lines or so, and this is line number * 0*...
This is a file of 300 lines or so, and this is line number * 1*...
This is a file of 300 lines or so, and this is line number * 2*...
...snip...
This is a file of 300 lines or so, and this is line number * 298*...
This is a file of 300 lines or so, and this is line number * 299*...
This is a file of 300 lines or so, and this is line number * 300*...

I was a bit confused at the purpose of these two files. Fortunately, “contents.txt” cleared things up a bit.

Jan  '95  #01
Demonstration Issue
1. All About This Program
Allen C. Huffman
INFO

2. REALLY *BIG* FILE
Bob's Big Boy
TEST

3. Microware Information
Microware Staff
MICROWAR

4. Stuff For Sale
Various
FORSALE

5. Useless File
Bob
USELESS

6. Nothing
Dan
NOTHING

7. Something
Bob & Dan
SOMETHIN

8. Movie Reviews
Sis Kehl
MOVIES

9. Spam Recipes
Mr. Cook
SPAMSPAM

F. Another File
Another Writer
ANOTHER

G. Nothin'
Nobody
NOTHING

H. Nothin' Again
Nobody Again
NOTHING

I. More About Flies
Spider-Man
FLYFILE

J. Jump Text
Jumpman Bob
JUMPTEXT

K. KeepThisSecret
Spy
SPYFILE

*. Use Star for This
StarMan
STAR

Seeing my name in there let me know that this was indeed something I was involved in. But what was it? I needed to move those BAS files over to an emulator and take a look.

Fortunately, one of them was already in ASCII – “reader.asc” – and it was indeed a BASIC program that apparently I wrote back in 1995.

0 REM *
1 REM * Text Viewing Program Thingy V1.00 by Allen C. Huffman
2 REM * Copyright (C) 1995 by Sub-Etha Software
3 REM * Written for Terry Simons and the MI&CC Upgrade Diskletter
4 REM *
5 PALETTE0,0:PALETTE8,63:WIDTH80:CLS1

I had zero recollection of writing this, but I remember the Mid-Iowa & Country CoCo Club (MI&CC) and its organizer, Terry Simons. Sub-Etha Software attended their Middle America Fest held in Des Moines in 1993. Somewhere, I am pretty sure I have photos from this even, but they are not in my online CoCoFest photo gallery for some reason.

I could tell this was something I wrote, since that line 5 of doing the background black, foreground white, width 80, CLS1 line was how I started all my CoCo 3 BASIC programs.

A quick scan of this program, which I will include in full, reveals it would read the “contents.txt” file and display a directory of text files (articles) on the disk and let the user select one. It would then load the file and let them read it, with options to go page to page through the file. A text file reader with a menu system – neat!

0 REM *
1 REM * Text Viewing Program Thingy V1.00 by Allen C. Huffman
2 REM * Copyright (C) 1995 by Sub-Etha Software
3 REM * Written for Terry Simons and the MI&CC Upgrade Diskletter
4 REM *
5 PALETTE0,0:PALETTE8,63:WIDTH80:CLS1
10 CLEAR17000:DIMFL$(15,3),A$(200)
50 REM * Read Index File
55 OPEN"I",#1,"contents.txt":LINEINPUT#1,IS$:LINEINPUT#1,SB$:FL=0
60 FORA=0TO3:LINEINPUT#1,FL$(FL,A):NEXT:IFEOF(1)=0THENFL=FL+1:IFFL<30THEN60
65 CLOSE
100 REM * Table of Contents
105 CLS:LOCATE28,0:PRINT"Mid Iowa & Country CoCo":LOCATE40-LEN(IS$)/2,1:PRINTIS$;:LOCATE0,3:ATTR0,7:PRINT:ATTR0,0:LOCATE0,22:ATTR0,7:PRINT:ATTR0,0
110 GOSUB1155:LOCATE35,2:PRINT"Main Menu";:GOSUB1130:LOCATE23,23:PRINT"Select File to View or [Q] to Quit";
115 FORA=0TOFL:LOCATE40*ABS(A>7)+5,(A AND7)*2+5:PRINTFL$(A,0):LOCATE40*ABS(A>7)+23,(A AND7)*2+6:PRINTFL$(A,1):NEXT
120 GOSUB1055:A=0:IFA$="Q"THEN450
125 IFA$=LEFT$(FL$(A,0),1)THENFL$=FL$(A,2):A$=FL$(A,0)+" by "+FL$(A,1):GOTO205ELSEA=A+1:IFA<16THEN125
130 SOUND100,1:GOTO120
200 REM * View a File (FL$)
205 LOCATE40-LEN(A$)/2,2:PRINTA$;:GOSUB1130:LOCATE2,23:PRINT"[UP] Next Page  [DN] Prev Page  [J]ump to Page  [P]rint File  [Q]uit to Menu";:LN=0:
210 GOSUB1105:ONERR GOTO245:OPEN"I",#1,FL$+".TXT":ONERR GOTO
215 LOCATE32,13:ATTR0,0,B:PRINT"Loading File ...":ATTR0,0:MX=0
220 IFEOF(1)=0THENLINEINPUT#1,A$:A$(MX)=LEFT$(A$,65):MX=MX+1:IFMX<200THEN220
225 CLOSE:LOCATE68,2:PRINT"Lines:";MX;:LN=0:LOCATE0,12:PRINT
230 LOCATE0,2:PRINT"Page"INT(LN/18)+1"of"INT(MX/18)+1"  ";:FORA=0TO17:LOCATE8,A+4:IFLN+A<MX THENPRINTA$(LN+A)ELSEPRINT
235 NEXT
240 GOSUB1055:A=INSTR(CHR$(94)+CHR$(10)+"JPQ",A$):IFA<1ORA>5THENSOUND100,1:GOTO240 ELSEONA GOTO255,305,355,405,430
245 FORA=12TO14:LOCATE15,A:PRINT"* File Not Found - Press Any Key for Main Menu *":NEXT:GOSUB1055:GOSUB1105:GOTO110
250 REM * [UP] Next Page
255 IFLN+18<MX THENLN=LN+18
260 GOTO230
300 REM * [DN] Prev Page
305 IFLN-18=>0THENLN=LN-18
310 GOTO230
350 REM * [J]ump to Page
355 LOCATE0,11:PRINT:PRINT:PRINT:LOCATE29,12:PRINT"Jump to Page 1 -"INT(MX/18)+1":";:GOSUB1005:A=VAL(A$)-1:IFA<0ORA>INT(MX/18)THENSOUND100,1:GOTO230ELSELN=A*18:GOTO230
360 IFPG>1THENPG=PG-1
365 GOTO230
400 REM * [P]rint Article
405 LOCATE0,11:PRINT:PRINT:PRINT:LOCATE13,12:PRINT"Ready Printer.  Press [ENTER] to Print or [Q] to Quit";
410 GOSUB1055:IFA$="Q"THEN230ELSEIFA$=CHR$(13)THEN415ELSESOUND100,1:GOTO410
415 REM --- if printer is not online, beep and go back to 201... <- check here
420 A=0
425 PRINT#-2,TAB(8)A$(A):A=A+1:IFA<MX THEN425ELSE230
430 GOTO110
450 REM * Quit
455 CLOSE:CLS:STOP
460 END
1000 REM * Line Input
1005 LINEINPUTA$:RETURN
1050 REM * Inkey$
1055 A$=INKEY$:IFA$=""THEN1055
1060 CH=ASC(A$):IFCH>95THENA$=CHR$(CH-32)
1065 RETURN
1100 REM * Clear Text Area
1105 FORA=4TO21:LOCATE0,A:PRINT:NEXT:RETURN
1125 REM * Clear Bottom Line
1130 LOCATE0,23:PRINTSTRING$(79,32);:RETURN
1150 REM * Clear Top Line (well, third one actually...)
1155 LOCATE0,2:PRINTSTRING$(79,32);:RETURN

I used the Toolshed (new GitHub home) decb command line tool to create a blank 32-track DSK image, and then then copy the “reader.BAS” file over to it. I also copied the “contents.txt” file, since that was needed.

I booted up the Xroar emulator, mounted my new disk image, and loaded the program. When I ran it, it went to a black screen momentarily, then I saw this:

I assumed the file might be corrupted, so I then tried to CLOAD the ASCII file in Xroar. That is a neat feature that lets you “Load” a text file, then when you type CLOAD it simulates loading an ASCII file form tape, using the input text file as that ASCII file.

Same problem.

I visually inspected the program. Maybe there was some EXEC to an assembly routine that needed to loaded before RUNing this BASIC.

Nothing.

Was Xroar defective? I went to the Xroar Online Emulator and tried it there, loading my DSK image through the web page.

Crash.

I then posted to the CoCo e-mail list sharing a Dropbox link to a folder containing these files, as well as the DSK image. I asked if anyone could test it and see if it crashed for them, as well. Michael Kline was the first to respond:

Alan,

I tested all BASIC programmes on a CC3. They all lock up.

Michael

This at least let me know it was not an Xroar-specific issue. But what was this issue?

I experimented with the TRON command to see how far the program would get before locking up. It would print some quick values [0][1][2][3][4][5] before the screen cleared and things crashed, but this time to a blank green screen. The output to the 32-column screen was changing behavior.

I commented out line 5 so it would stay on the 32 column screen, and ran it again. I saw it spew out line numbers, before clearing the screen and printing an “?HP ERROR IN 105”. That is the error you get when you do CoCo 3 40/80 column screen commands on the 32 column screen. From the looks of things, removing the WIDTH80 line allowed it to get to around line 60 or so before one of those commands was used and it errored out.

Why would WIDTH 80 crash a program? I did more experiments. After this error, with the system not locked up, I typed “5 WIDTH 40” just to add a screen width, but no PALLETEs or CLS command.

According to TRON, the program was crashing at WIDTH 40… Huh???

Each time a crash like this happened, the virtual CoCo had to be restarted (power cycle). Just a virtual reset would not work. You might get “OK” back but things were not working.

Very, very odd.

I finally got my program to run by changing the value of the CLEAR command in line 10. (Initially, I deleted the whole line after the WIDTH line just to see what happened, and narrowed it down to something to do with the CLEAR.)

I shared my results on the CoCo list, and William “Lost Wizard” Astle, one of the great minds at understanding how the BASIC ROMs operate, replied with this tidbit:

It won’t be a string space bug – handling that didn’t change in the Coco3.

Have you been running it from the 40 or 80 column screen? If so, that’s probably why. The driver for handling output to the 40/80 column screen doesn’t properly manage the memory map and if the stack ends up too low in memory, it gets swapped out while the 40/80 column screen is mapped in, leading to a system crash. String space and the address parameter to CLEAR are both above the stack.

This crash happens if the stack ends up below $4000 if memory serves.

If you aren’t running from the 40/80 column screen, it may be some other weirdness triggering it.

– William Astle, via the CoCo List

Light has been shedded, and I knew all I would have to do is look up the Super Color BASIC Unraveled book to find a clear and concise explanation of this bug. But, before I got there, William added more details:

The only solution as far as I can tell is do no output on the 40/80 column screen or clear less string space. Given that a lot of the numbers used for CLEAR for string space are effectively random with no real understanding of how big they need to be, it’s entirely possible that 17000 is way more than it needs to be. Something most programmers don’t know is that a string constant in the program that is never modified doesn’t use up any string space so often the CLEAR number is massively larger than it needs to be.

Having the WIDTH before the CLEAR should prevent WIDTH from crashing but any subsequent PRINT, LOCATE, INPUT (from keyboard), or HSTAT probably would crash.

– William Astle, via the CoCo List

My confusion continued, and finally a third response form him added this:

It’s not that straight forward and unravelled doesn’t mention it. I only know because I tripped on it hard back in “the day” and it left me scratching my head for quite a while.

Basically, the stack has to stay above $4000 (the screen gets mapped in the $2000 to $3FFF range) so that would probably put the absolute limit somewhere just under 16K (16384). You’d want 200 bytes or so room for the stack so 16000 would be a nice round number. On the other hand, if you reserve any memory with the second parameter for CLEAR, that number goes down.

Perversely, if you could get the stack to be *below* $2000, it would also not crash, but that means a very small program with no PMODE graphics, probably.

The size of scalar variables, arrays, or program text doesn’t actually matter for this calculation because the screen is not mapped in except when doing I/O on the screen.

– William Astle, via the CoCo List

A bug the Unraveled folks didn’t know about? William stumbled upon it back then, and if this code was a version I tried to run, I must have, as well. But, why would I have left it in this non-working version? I expect I may find a “fixed” version of this program in my Disk BASIC disk archives, eventually. For all I know, maybe I kept this one around as a “what is wrong with this program” example, copying it to my OS-9 hard drive so I could post it on a BBS or online service (or even to the original CoCo List back then).

Hmm, I wonder if the old Princeton CoCo list archives still exist. Maybe I posted about this 30 years ago (1995!) when I was writing this program? (Note to self: Look that up…)

But I digress.

If you CLEAR a big enough number, then do a WIDTH 40 or 80, the CoCo 3 crashes hard. I toyed with that value, and you can get to a spot where it works, then a bit higher and you get some different types of crashes with the screen freaking out in different ways, but all end up the same way: crashed CoCo, must hard-reset/power cycle to recover.

Have you ever run into this bug on your CoCo 3? Please leave a comment with your story…

Until next time…

One more thing…

Oh yeah… Here is what the program looks like when it runs.

Spaces in path names still break stuff in 2025?

Updates:

  • 2025-02-27 – Corrected use of “hard links” to be “symbolic,” per William A. in the comments. Thanks!

NOTE: I am posting this as a plea for help. If you understand this problem, and know of solution, please leave a comment. I would really appreciate some input and clarification on my “understanding” of this issue.

TL:DNR: Symbolic links are a workaround.

The year is 2025, and open source projects can still be broken by having a space in a path name.

According to a robot, “Windows has allowed spaces in filenames and directory names since Windows NT 3.1, which was released in 1993.”

I have not fact checked this. My first PC was a Toshiba laptop I purchased at the end of 1995. (Not counting my DOS-based Tandy 1400LT I had years earlier.) At that point, it was Windows 3.1 that followed the 8.3 filename format that CP/M used.

FILENAME.TXT

It was the late Steve Bjork that convinced me to upgrade to the new Windows 95 when it came out. This upgrade allowed filenames up to 255 characters, if my quick web search is correct. I recall having a DOS C compiler (“Power C” – wow, they still sell this???) and it did not support the long filenames. Windows did provide some level of backwards compatibility by having any long filename still represented by a short name, which would have the first part of the filename then a “~1”, so something like “really long filename.txt” might also exist as “REALLY~1.TXT”.

Side note: There was a quirk with this implementation. Even filenames that could have fit in the 8 characters seemed to get this “~1” added to them. BUT, you could rename those to the normal 8 characters and is till worked. i.e. “filename.txt” would create “FILENA~1.TXT” but you could then “RENAME FILENA~1.TXT FILENAME.TXT” and it would show up as FILENAME.TXT. I actually wrote a C program that would go through the directory and rename any files like this. Fun times. And yikes, that was 30 years ago!?!?!

So basically, for three decades we could have spaces in filenames and directories on Windows.

Unix, back when it started, had short filenames and did not allow spaces initially. But, as long as I have been using it (my first exposure was 1995 on SunOS) I believe it did.

In the late 1980s I began using Microware’s OS-9 for the 6809 (on a Radio Shack Color Computer 3). While it had longer filenames than DOS (28 characters?), it did not allow spaces in filenames or directory names. I am unsure if the modern OS-9000 (renamed to just “OS-9 for x86” or whatever architecture, waybackwhen) has ever updated to allow spaces.

But I digress.

I still run across open source projects that fail if they are built from a path that has a space anywhere in it. For example, if you have this:

/usr/allenh/github downloads/

…and you “git” your project there, the build might break because of that space. Scripts may just see it as “/usr/allenh/github” and fail. This seems to be the case for the NitrOS9 Project, a fantastic effort to recreate OS-9/6809 with tons of enhancements.

From my experience, I think these problems can be solved by simply adding quotes around paths in the build scripts. For example, if you have this:

DISCLAIMER: Just examples. I know about escaping spaces as “\ ” in *nix filesystems, and maybe something like that exists for Windows (let me know in the comment).

SOURCE_PATH=C:\Users\Allen Huffman\Development\Source Code

somecommand -xyz $(SOURCE_PATH$)

…that will fail because it ends up looking like three parameters after the options:

somecommand -xyz [C:\Users\Allen] [Huffman\Development\Source] [Code]

But if the build script “quotes” the file path, like this:

somecommand -xyz "$(SOURCE_PATH$)"

…then that gets passed to the command the same way:

somecommand -xyz "C:\Users\Allen Huffman\Development\Source Code"

And that seems to work.

But, again, this is 2025. I run into projects that fail with spaces in the path multiple times a year.

Just don’t put spaces, duh.

“Hey doctor, it hurts when I do this.”

“Then don’t do that.”

Why not just remove the spaces? In olden days, you were in control of directories because you made them. I came from a “no spaces allowed” OS background so I never used spaces. “SOURCECODE” or, if underscore was allowed, maybe “SOURCE_CODE” to be more readable (but I hate typing two extra keypresses to generate that underscore).

But, Windows may not agree. Once I did a fresh Windows install, and let it do all the defaults (Microsoft account to login, enable OneDrive, etc.) and the path it created had a space in it. Anything that I put in “my” home folder (Documents, etc.) had a space somewhere earlier in the path.

Likewise, on macOS, if you use iCloud, some default directories get links that make them look “normal”:

allenh@Mac Documents % pwd
/Users/allenh/Documents

…but if you decide to make your own directory on your “iCloud Drive”, you see the true long path — which has a space in it!

allenh@Mac Development % pwd
/Users/allenh/Library/Mobile Documents/com~apple~CloudDocs/Others/Development

That “Mobile Documents” path is the cause of so many problems.

My workaround was to simply move these folders outside of my self-created directory and put them into one of the defaults, like “~/Documents/Development”.

Symbolic links, anyone?

On macOS (a Unix-type operating system), and Linux (if such a problem exists there?), you can create symbolic-links to folders. You create a new name and then tell it where it points to.

ln -s /Users/allenh/Library/Mobile\ Documents/com\~apple\~CloudDocs/Others/Development ~/Development-iCloud

Now in my home folder, I have a directory called “Development-iCloud” that has no space in it, but points to the real spot with a space:

allenh@Mac ~ % cd Development-iCloud 
allenh@Mac Development-iCloud % pwd
/Users/allenh/Development-iCloud

Now I can change into that folder and build scripts that were failing will work. Nice.

But what about Windows?

I have not tried it myself, mostly because I didn’t have A.I. to ask for a solution the last time I ran into this on Windows, but there is a “mklink.exe” command that appears similar, and may solve the problem there:

mklink /D "C:\path\to\link" "D:\path\to\actual"

It feels like this workaround should work there.

But is this what developers do? Most smart computer folks I know run away from anything cloud (and for good reason). I have been drinking the Kool-Aid for awhile and love having access to non-private files on all my devices, via syncing on Dropbox (mostly) or iCloud or OneDrive or Google Drive. I use all of them, for different purposes.

This is my workaround, but is there a better way?

Let me know in the comments.

Until then, stay off my lawn.

Color BASIC decimal, hex and octal are not the same?

There is something wonderful about having a poor memory. Whether I knew something before or not, I do not remember it now, so I get the pleasure of “learning something new” even if I previously knew the new thing.

In a reply to my Color BASIC and octal post, Juan Castro mentioned another quirk about how BASIC sees numbers represented as decimals versus hex or octal.

AND, OR, AND NOT demand signed 16-bit integers as input, whereas the &H/&O expressions (and consequantly my &B extension) return UNsigneded integers. That is VERY annoying:

PRINT &H8001 AND &H0007
?FC ERROR
OK

Come the %#&*£ ON!

– Juan Castro

I am unsure about this, since after the parser reads through the code, it turns any hex or octal or decimal value intothe internal 5-byte floating point representation of the value. “A=65535” turns into exactly the same type of variable as “A=&HFFFF”.

AND and OR should deal with them exactly the same way. In Juan’s example, decimal values will generate the same ?FC ERROR. But there is a workaround…

I stumbled upon this when playing around with using AND and OR to set or test bits. My Color BASIC and 16-bits and AND and OR and NOT article explains what I was trying to do, and how I ultimately ended up achieving it.

In Juan’s example, &H8001 is 32769 in decimal. &H0007 is 7. Having the “high bit” (bit 15) set of the first value effectively makes it a negative number:

1000000000000001 = &H8001 (32769)
^ ^
bit15 bit0

Any value with that bit set will not work with AND or OR, regardless if you represented it in decimal, hex or octal. You can go up to &H7FFF (32767) using AND or OR, but past that, you get the ?FC ERROR:

Juan has been working on some BASIC enhancements, adding new features (like a method of representing values in binary — which I would find quite useful). But seeing numbers in binary not work would be even more frustrating:

PRINT &B100000000000000 AND &H1
?FC ERROR

…at least, that is my assumption about what is “&B” binary representation would do.

Here is how to make Juan’s code work:

PRINT (&H8007-65536) AND &H0007
1

Any value that has that high bit set needs to have 65536 subtracted from it, then you get the results you would expect.

But unfortunately, you cannot use AND to test for that high bit to be set ;-) so instead you have to do silly things like this:

V=&H8007
IF V>&H7FFF THEN V=V-65536
PRINT V AND &H0001

And it’s just that easy!

Though, if you print V, you will see it is a negative number, as you might have guessed. If you don’t need to PRINT V, doing something as simple as this will let you AND and/or OR on values that have the high bit set.

Yuck.

“Come the %#&*£ ON!” is right.

Until next time…

Rainbow Check Plus

A followup from my previous post… This box, which appeared in Rainbow magazine, was called Rainbow Check Plus:

Rainbow Magazine checksums

It first appeared in the February 1984 issue, and was even featured on the cover:

The article “Rainbow Check Plus for the CoCo and MC-10” appears on page 21, and was written by H. Allen Curtis. (Why is that name so familiar?) I did not realize it was available for the MC-10 as well. Here is the listing for the CoCo version:

10 CLS:X=256*PEEK(35)+178
20 CLEAR25,X-1
30 X=256*PEEK(35)+178
40 FOR Z=X TOX+77
50 READ Y:W=W+Y:PRINT Z,Y;W
60 POKE Z,Y:NEXT
70 IFW=7985THEN80ELSEPRINT"DATA ERROR":STOP
80 EXEC X:END
90 DATA 182,1,106,167,140,60,134
100 DATA 126,183,1,106,190,1,107
110 DATA 175,140,50,48,140,4,191
120 DATA 1,107,57,129,10,38,38
130 DATA 52,22,79,158,25,230,129
140 DATA 39,12,171,128,171,128
150 DATA 230,132,38,250,48,1,32
160 DATA 240,183,2,222,48,140,14
170 DATA 159,166,166,132,28,254
180 DATA 189,173,198,53,22,126,0
190 DATA 0,135,255,134,40,55
200 DATA 51,52,41,0

But wait … there’s more. As I was looking into this, I learned that “Rainbow Check Plus” was a follow-up to “Rainbow Check” which appeared in January 1983. It seems the original “Rainbow Check” would not catch some key items:

  • Incorrect line numbers. “300 CLS” and “390 CLS” would provide the same check value.
  • Incorrect variables. It would not catch a wrong variable. The example given is that “F” would be the same as “E”.
  • Incorrect command words. SGN or SIN would provide the same checksum.

Now I really wonder what it was doing to generate the numbers, if it wasn’t looking at the actual line data ;-)

The original version appeared on page 95 as part of the “Assembly Corner” column by Dennis L. Lewandoski. The column was called “Let’s End Those Typing Errors Once and For All.” This version appeared in the form of an assembly language program listing, as well as a BASIC loader with DATA statements.

Here is the BASIC program listing for the original 1983 “Rainbow Check” version:

10 CLS:IFPEEK(116)=127 THEN X=32688 ELSE X=16304
20 CLEAR25,X-1
30 IFPEEK(116)=127 THENX=32688 ELSE X=16304
40 FORZ=X TO X+77
50 READY:W=W+Y:PRINTZ,Y;W
60 POKE Z,Y : NEXT
70 IFW=5718 THEN80 ELSE PRINT"DATA ERROR":STOP
80 EXEC X:END
90 DATA 182,1,106,167,141,0,68
100 DATA 134,126,183,1,106,190
110 DATA 1,107,175,141,0,57,48
120 DATA 141,0,4,191,1,107,57
130 DATA 129,10,38,44,52,22,220
140 DATA 27,147,25,142,4,0,141
150 DATA 6,31,152,141,2,32,25
160 DATA 52,2,68,68,68,68
170 DATA 141,4,53,2,132
180 DATA 15,129,9,46,4,139,112
190 DATA 32,2,139,55,167,128,57
200 DATA 53,22,126,0,0

Unfortunately, the assembly was not provided on Rainbow on Tape, so I would have to type it all in by hand.

I suspect I will have to do just that, as well as disassemble the 1984 version and see how both worked, which might explain the limitations of the original.

Until then…

Dragon User magazine and typing in assembly

Over on YouTube, user @ms-ex8em pointed me to the November 1988 issue of Dragon User magazine and a little program that helps you type in machine code program listings accurately.

I recall spending countless hours typing in machine code programs from Rainbow Magazine “back in the day”. These programs would be a few lines of BASIC followed by dozens or hundreds of lines of DATA statements with numbers that represented the bytes of the machine language program.

One such program I specifically remember was Zonx, a cool game with background sound effects. It appeared in the October 1985 issue. You can see what I typed in by checking out page 65. And page 67. And page 68. And page 70. And page 71.

https://colorcomputerarchive.com/repo/Documents/Magazines/Rainbow,%20The/The%20Rainbow%20Vol.%2006%20No.%2003%20-%20October%201986.pdf

And, somehow, I managed to type all of those numbers in and get a working program!

Rainbow did have one thing to help — and perhaps I used it. They had a small program you could run, then as you typed in your program listing, when you got to specific lines you could hit a key and it would spit out a number (a checksum?) and see if it matched their numbers:

Above, you can see what number should be expected when you got to line 150, 310, 440 and so on. After all the code was typed in, the final number it should give you was 238. This required you to type in the program exactly as it appeared including spaces and any other formatting.

It was not optimal, but it was better than nothing.

I also saw some BASIC loaders for machine language that took matters into their own hands, and had built-in checksum values in their DATA statements. For example, they would put a specific amount of numbers on each line, with a checksum of those numbers at the end. Say that amount of numbers was five. A line might look like this:

1500 DATA 1,1,1,1,1,5

In that silly example, you could add up ever five bytes you READ and then compare that to the 6th byte in each line. If it matched, continue. If it didn’t, the loader code would print some kind of message, hopefully indicating what line had a mismatch.

I always appreciated program listings that did that.

Now, back to @ms-ex8em… The code they shared was quite different. You can find it on page 12:

https://colorcomputerarchive.com/repo/Documents/Magazines/Dragon%20User/Dragon%20User%20-%208811%20-%20November%201988.pdf

I will do my best to type it in here, accurately.

10 REM HEX LOADER
20 CLEAR 200,31599
30 INPUT"START";ST
40 INPUT"END";ED
50 FOR J=ST to ED STEP 8
60 PRINT USING"##### : ";J;
70 INPUT A$
80 CS=0
90 FOR K=1 TO LEN(A$)
100 CS=CS+K*VAL("&H"+MID$(A$,K,1))
110 NEXT K
120 INPUT" = ";C
130 IF S<>CS THEN PRINT"CHECKSUM ERROR-TRY AGAIN":SOUND 1,1:GOTO 60
140 FOR K=0 TO 7
150 POKE J+K,VAL("&H"+MID$(K*2+1,2)
160 NEXT K,J

First comment… There appears to be a mistake in line 150. It should have two closing parens at the end of the line.

Now let’s see what this code is doing.

In line 10, the CLEAR reserves memory (so BASIC cannot use it) starting at 31599. This is because the machine language program will load starting at 31600.

In line 40, the user is asked to input the start and end of the program they will be typing in.

In line 50, there is a FOR/NEXT that goes from start to end, stepping by 8. This tells me they expect 8 bytes of data on each line the user types in. The first input should be at 31600, then the next at 31608 and so on.

The user types in the 16 characters (representing 8 hex bytes) shown in the box below. They look like this:

31600 : 8E7B6F9F74Be012B  = 1016

In line 80, a checksum is calculated by adding up the value of each character typed in that line.

In line 120, the user is asked to type in the checksum shown in the data listing.

In line 130, if the number the user typed in (from the data listing) does not match value the program calculated, an error message prints and it goes back to let the user retype the entire line.

If it matched, line 140 will then go through those 16 characters and create the byte value for each of the 8 data bytes and POKE them into memory at the proper place.

This repeats until the end address is reached. At that point, some new assembly language program has been loaded into memory starting at 31600.

Pretty cool!

The problem @ms-ex8em was seeing with this program was a ?TM ERROR. That is most likely showing up in line 150 because of the missing paren. Fix that, then maybe the rest will work ;-)

I thought this was a neat way to enter in machine code. What other neat ways did you see back then?

Comment away…

Recreating the Pac-Man maze in 1993

Many years ago, I played with drawing a 3-D maze under OS-9 on my Radio Shack CoCo 3. That demo is on the NitrOS-9 “Ease of Use” release under the name “semaze“. It lets you wander around a simple line maze:

There is even a map you can bring up with “?”:

As I mentioned years ago on this site, I had played with turning that into an OS-9 version of the classic Phantom Slayer 3-D game on the CoCo 1. I got as far as having my maze with a “phantom” in it that would wander around:

An unfinished CoCo 3 OS-9 3-D maze game inspired by the old “Phantom Slayer” by MED SYSTEMS.

But the oddest version was probably me putting the Pac-Man maze into my 3-D “engine” and then deciding to put dots around it, and make it refresh every half second or so, making it a “real time” game. With a prototype ghost (which appeared just as a large circle) wandering around!

And bringing up the map showed the Pac-Man maze:

In the days before the Internet, the only way I would have been able to recreate this map is if I had access to an accurate home port (I did not), or a picture in a magazine (maybe). I am guessing I based it on some CoCo Pac-Man clone with a fairly accurate maze.

How well did I do? Here is my CoCo version, then the actual arcade game, and the Arduino TV-Out version I was working on a decade ago (very accurate, down to the tiles).

I can see a few errors, like the bottom walls under the power pellets going into the maze an extra tile. And the dots are off. Today, I understand how the Pac-Man maze is laid out with tiles so it would be much easier to recreate my 3-D “DotMaze” game with an accurate map.

Maybe I will.

Color BASIC and octal

Updates:

  • 2025-02-19 – Thanks to a comment from William Astle, the term “decimal” number has replaced my incorrect use of “integer.” And per a comment from James Jones, a clarification that all values you input are still stored internally as the same type of numeric floating point – the parsing converts them all to this floating point representation.

Color BASIC had one type of number you could use: decimal. These are the normal numbers we use every day like 1, 50392 or 42.

A=42
PRINT "A IS";A

When Extended Color BASIC was added, the CoCo accepted the following notations for numeric constants: integer, hexadecimal and octal. (Internally, BASIC converts them all to the same numeric representation of a floating point value.)

Getting Started with Extended Color BASIC describes hex and octal as follows:

Extended Color BASIC lets you use both hexadecimal and octal constants.

Hexadecimal numbers are quantities represented in Base 16 notation, composed of the numerals 0 to 9 and the “numerals” A to F. Hexadecimal constants must be in the range 0 to FFFF, corresponding to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &H, as shown here:

&HA010 &HFE &HDl &HC &H4000

Octal numbers are quantities represented in Base 8 notation, composed of the numerals 0 to 7. Octal constants must be in the range 0 to 177777. The computer stores them as two-byte integers that correspond to the decimal range 0 to 65535.

To indicate that a number is an octal constant, precede it with the symbol &0 or &, as shown here:

&070 &044 U1777 &7170 &17 &01234

The use of “hex” and octal constants is convenient in programs that reference memory locations and contents. For further information, read a book on machine-language programming.

– Getting Started With Extended Color BASIC (p. 195, 1984 revision)

I most likely learned hexadecimal when I was learning assembly language. Today, I use hex values often in C programming. But octal? I do not think I have ever used it for anything. Have you?

I do believe I have seen it used “in the real world.” In the late 1980s (possibly early 1990s) I had a Kawai K1 synthesizer keyboard. It organized its instrument settings (called “patches” in reference to early synthesizers using “patch cables” to route signals do different processors) into two groups of Internal (onboard storage, uppercase “I” and lowercase “I”) and two groups of External (memory card, uppercase “E” and lowercase “e”). Each section had eight patches.

My first commercial CoCo program was a MIDI Librarian that could read the patches from the synthesizer and save them to disk, or load patches from disk into the keyboard. The patch screen in question looked like this:

You will see that each area had four banks (A-D) and each of those had eight patches (1-8). Uppercase “I” was A(1-8), B(1-8), C(1-8) and D(1-8), and lowercase “i” was the same. This was also the same for the External banks.

Thus, octal. I could have used octal in my program — but I do not know if I even realized this was octal at the time. I’d have to think about how I would have even done that. Maybe something like this:

0 'OCTALIN.BAS (2-15-2025)
10 LINE INPUT "BANK (0-7):";B$
20 LINE INPUT "PATCH(0-7):";P$
30 NM=VAL("&O"+B$+P$)
40 PRINT "THAT IS PATCH #";NM

…though I do not recall how the MIDI messages. It could have just been a user interface thing and internally the patches were still 1-whatever.

But I digress.

Juan Castro posted to the Color Computer e-mail list about a bug in the octal routines:

Octal constant (Ex.: &O14 = 12 decimal)

It accepts 8 as a digit. D’oh. Try “PRINT &O18” in a CoCo 1 or CoCo 2.

Without having a CoCo3 at hand to check I’ll wager it patches that bug. All
it has to do is replace a LBHI with a LBHS.

Juan Castro
Enviado do meu Olivetti Programma 101
http://retropolis.com.br

Since an octal value should only be 0-7, a value of 8 is not valid octal.

10 CLS:PRINT"DEC","OCT"
20 FOR A=0 TO 10
30 PRINT A,VAL("&O"+STR$(A))
40 NEXT

This should print 0-7 then error out. Yet…

And is there really no better error than SYNTAX for this type of problem?

And naturally, I had to see what HEX values do. A valid hex digit is 0-9 and A-F, representing 0 to 15. Will it do a syntax error as well if I go past the letter F?

It appears it does not. It seems to bail on the parsing and print them as two variables. Which is a neat trick, since you have to put a space or semicolon between two variables if you want to print them otherwise.

To confirm that is what it is doing, I tried this:

Ah, so it is not treating this as variables “H” and “G”. And I just learned something new (and probably useless).

Something new (and probably useless)…

Integer values are things like 1, 2, or 152032. They are floating point values, so you can also have things like 1.2 or 33.5. Though, not always. Floating point values cannot represent every decimal value accurately, but that’s a story for another article…

Somewhere, someone learned that a decimal (period) by itself would be treated as zero. The fastest way to assign 0 to a variable in Color BASIC is like this:

A=.

Weird, but it works. It seems the parser starts looking for a fractional amount, like “.25” or whatever, so it processes the period and then there is nothing else so the code returns with 0 (the initialization value when the function is called). It is still weird, though.

I found out tonight that the same thing applies to hex. You can do this:

A=&H

…and you get a zero. Try “PRINT &H” to see for yourself.

Of course, I had to try a quick benchmark, sitting in a loop doing something like “Z=.” and another run doing “Z=&H”. 1000 times through with “Z=.” used 140 timer ticks. The “Z=&H” used 154. I guess that is the overhead of parsing two characters instead of one.

But I digress. Again.

I have not looked up what BASIC is doing (see the excellent “BASIC Unravelled” books for the disassembly of the BASIC ROMs), but I suspect the parser starts looking and finds the “&” followed by the “H” and is ready to parse… it then hits an invalid character, so the parsing is over and 0 is there. Then it sees the G, which is not a command so it is treated like a variable.

Using “PRINT” was deceiving. Had I just tried this:

A=&HG

…I would have got what I was expecting:

?SN ERROR

Thanks, Juan, for sharing this. I learned about a bug, and in writing this, discovered another odd thing, which is less odd now that I understand what happened.

Until next time…

Sub-Etha graphical adventures?

Around 93-94, I created a text adventure that featured black and white digitized pictures from the 1992 Atlanta CoCoFest. It was more of a “simulation” than a game — and even called itself a simulation on the splash screen. But, while browsing through the source code, I found there were quite a number of things you could “do” in the game, while the score let you know how much of it you completed.

I also found one from a Chicago CoCoFest, which seems to be complete other than missing the images. Rooms were numbers with the vendor name and description. It was kind of like “playing” one of my old CoCoFest reports. Trippy.

And a weird 3-D first-person Pac-Man game I was working on…

Now that I have Xroar running the current Ease of Use NitrOS-9 build, and have my CoCoSDC “real CoCo” hard drive image mounted as the second drive, I may finally be able to dig through all this stuff and see what else I have.

Like finding I made a Towel V1.05” — after I moved to Iowa! I have no recollection of that. Lots of stuff to get archived and posted online.

Should be fun.

MAZE.BAS for the CoCo

While looking for something completely unrelated, I ended up going through some of my old BBS disks. In addition to my *ALLRAM* tape-based BBS, I worked on several other BBSes that were never completed.

One one of those disks was something called MAZE.BAS. But why would a maze game be on a BBS disk?

Running it showed me this…

The player “P” can move around the maze while the enemy “*” tries to get to you. It uses “A-S” for left and right, and “W-Z” for up and down.

Ah, now I remember. I had learned about VIDTEXT/VIDEOTEXT/whatever having control codes to move the cursor around the screen, so I was going to write a maze game to run online in the BBS. If you had a compatible terminal program, you could play an actual “action” game rather than just some text adventure or simulation.

The numbers at the bottom were diagnostics messages. X/Y and movement direction for Up/Down and Left/Right.

Interesting.

Here is the listing…

0 'PALETTE12,63:PALETTE13,0
9 CLS
10 PRINT" #####
11 PRINT" ########## ##########
12 PRINT" # # #
13 PRINT" ### ###### ####### ###### ###
14 PRINT" # # # #
15 PRINT" # ### ################# ### #
16 PRINT" # # # #
17 PRINT" ####### #### #### #######
18 PRINT" # #
19 PRINT" # ###### # # ###### #
20 PRINT" # # ### # #
21 PRINT" # #### #### #
22 PRINT" ### ####### ###
23 PRINT" #### ####
24 PRINT" ###########
25 MX=15:MY=1:PX=15:PY=13
30 POKE1024+(PY*32+PX),80:POKE1024+(MY*32+MX),96
31 PRINT@512-32,PX;PY;XP;YP,MX;MY;X;Y;
35 X=SGN(PX-MX):Y=SGN(PY-MY):Z=(1024+(MY*32+MX))
36 IFPEEK(Z+(Y*32))=96 THENMY=MY+Y ELSEIFPEEK(Z+Y*32+X)=96 THENMX=MX+X:GOTO39
37 IFPEEK(Z+X)=96 THENMX=MX+X:GOTO39
39 POKE1024+(MY*32+MX),42
40 A$=INKEY$:IFA$=""THEN55
45 IFA$="W"THENYP=-1:XP=0 ELSEIFA$="Z"THENYP=+1:XP=0
50 IFA$="A"THENXP=-1:YP=0 ELSEIFA$="S"THENXP=+1:YP=0
55 IFPEEK(1024+(PY*32+PX)+(32*YP)+XP)=96 THENPOKE(1024+PY*32+PX),96:PX=PX+XP:PY=PY+YP
60 GOTO30
999 GOTO999

Using what I know about BASIC today, I would tackle this in quite a different manner.

Maybe I will, as a benchmark exercise.

Until then…