Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

TRS-80 Color Computer RCHECK+ in Perl

Jerry Stratton, November 20, 2019

CoCo Terminal profile example: Example of the Color Computer width emulation in vi in macOS Terminal.; Color Computer; CoCo, TRS-80 Color Computer; BASIC; Beginners All-purpose Symbolic Instruction Code; The Rainbow magazine; Mac OS X Terminal

The only text editor I could find that would wrap exactly at 32 characters was vi in the Terminal.

I may be the only person who still enjoys typing in code from old books and magazines, but I do enjoy it, and enough to have written a modern version of those old books, 42 Astoundingly Useful Scripts and Automations for the Macintosh. I recently acquired a TRS-80 Color Computer 2, so I’ve been typing in old code from The Rainbow.

One of the big advantages of The Rainbow over other magazines of its era is the program RCHECK+. It’s a machine-language program that you load into memory before typing the code, and when you press the down arrow, it calculates a very simple checksum from the code you’ve typed.1 The listing in the magazine contains a series of checkpoints, such as this for TRENCH in the July 1986 issue of The Rainbow:


After typing line 7, the checksum should be 208; after typing line 15, it should be 178; and after typing in the entire program, it should be 180.

It turns out that this is a very simple checksum. All it’s doing is adding up the ASCII values of the code in RAM, cycling back to zero after a sum of 255. So the checksum is always from 0 to 255.2

The program is so useful that, even though I would much prefer to type BASIC code on a modern computer in a modern text editor with a modern keyboard, I didn’t.3 The values that RCHECK+ uses are the tokenized values, which means that GOTO is not G plus O plus T plus O, but rather the sum of hex 81 and A5, the tokenization of GOTO. But then I discovered that the decb program from the ToolShed suite can take a text BASIC listing and tokenize it to a standalone file.

Which makes it possible to write rcheck in Perl and run it on a text file created by decb.

There was a lot of trial and error getting this to work. I don’t have the listing for RCHECK+, so I can’t know for sure what the algorithm is. But poking at it on the CoCo by adding, removing, and altering strings, BASIC statements, and line numbers, and watching how the checksum changes, I’m pretty sure I have it. It certainly works on the BASIC code I’ve tested it on so far. But there are no guarantees.

Here’s what it looks like using it:

  • $ ~/bin/rcheck TRENCH.BAS 7 15 20 28 37 51
  • 7: 208
  • 15: 178
  • 20: 102
  • 28: 28
  • 37: 84
  • 51: 224
  • END: 223

Clearly, I went south sometime after line 28.4

You don’t need to give rcheck the checkpoint lines. If you leave them out it will only report the final checksum, which is the behavior of the original rcheck+ in the Rainbow. I find being able to type through a full column without losing the checksums in between very useful, however.

[toggle code]

  • #!/usr/bin/perl
  • # run the Rainbow checksum against a BASIC text file
  • # requires decb to tokenize the BASIC
  • # Jerry Stratton http://www.hoboes.com/Mimsy/hacks/coco/
  • use File::Temp qw/tempfile/;
  • while ($option = shift) {
    • if ($option eq '--debug') {
      • $debug = 1;
    • } elsif ($option eq '--rcheck') {
      • $useOriginalRcheck = 1;
    • } elsif ($option eq '--help') {
      • help();
    • } elsif ($option =~ /^[1-9][0-9]*$/) {
      • $checksumLines{$option} = 1;
    • } elsif (!$basicFile && -f $option) {
      • $basicFile = $option;
    • } else {
      • help("Unknown option $option");
    • }
  • }
  • help("No input file provided.") if !$basicFile;
  • # first, tokenize the BASIC file
  • ($tokenHandle, $tokenFile) = tempfile(UNLINK=>1);
  • `/usr/local/bin/decb copy -b -t "$basicFile" "$tokenFile"`;
  • print `hexdump -C $tokenFile` if $debug;
  • # then read the tokenized file
  • # character zero marks the end of a line, and thus also the beginning of a line
  • open $codeHandle, $tokenFile or die("Can't open $tokenFile: $!");
  • $code = do { local $/; <$codeHandle> };
  • close $codeHandle;
  • # finally, loop through the tokenized code and add up each character
  • $counter = -2;
  • while ($counter < length($code)) {
    • $counter++;
    • #will be zero when $counter is -1
    • $character = substr($code, $counter, 1);
    • $addend = ord($character);
    • #line numbers need to be handled specially
    • #character 0 marks the end of a line
    • if ($addend == 0) {
      • #advance to line number
      • $counter += 3;
      • #calculate line number
      • my $linePartOne = ord(substr($code, $counter, 1));
      • my $linePartTwo = ord(substr($code, $counter+1, 1));
      • $line = $linePartOne*16*16 + $linePartTwo;
      • #use the tokenized line number for the checksum
      • $addend = $linePartOne + $linePartTwo;
      • #advance past the line number
      • $counter +=1;
    • }
    • print "$previousLine:\t", checksum(), "\n" if ($debug || $checksumLines{$previousLine}) && $previousLine ne "" && $line != $previousLine;
    • $sum += $addend;
    • $previousLine = $line;
  • }
  • print "END:\t" if $debug || %checksumLines;
  • print checksum(), "\n";
  • sub help {
    • $message = shift;
    • print "$0 [--debug] [--help] [--rcheck] <BASIC file to checksum> [<line numbers to report>]\n";
    • print "\trcheck: use the original rcheck algorithm instead of rcheck+\n";
    • print "$message\n" if $message;
    • exit;
  • }
  • sub checksum {
    • if ($useOriginalRcheck) {
      • return sprintf('%04X', $counter - 1);
    • } else {
      • return $sum%256;
    • }
  • }
CoCo Terminal profile (text): Terminal profile for typing in Rainbow magazine code listings, text pane.; Color Computer; CoCo, TRS-80 Color Computer; Mac OS X Terminal

You can create a profile that will set the background and foreground colors.

Save the script as rcheck. You may find my edit script for 42 Astounding Scripts useful for pasting this or any scripts into TextEdit or your favorite text editor.

As you can see, besides requiring that decb be installed on your computer, the only tricky part of the program is detecting where BASIC lines begin. CoCo BASIC uses the null character, character zero, to mark the end of a line. So I have the script look for character zero, grab (and sum) the line number, and then skip ahead to after the line number. This is probably not completely kosher, but it works so far. I’m ignoring two bytes that are probably important.

And, in order to successfully report on the first line, I set the counter to -1. Since there is no character at -1 in any string, it comes out as null, and the script thinks that the very first line is preceded by an end-of-line marker.

In the original RCHECK+, it was critical to verify the checksums every time you reached a checkpoint; it was difficult to see previous checkpoints. You had to delete lines of code. With this program, if you prefer to type in the whole program and then debug, you can do it. Just provide the checkpoints to the script, and then you can type as much as you want. Later, you can go through each checkpoint one at a time fixing any discrepancies in that section.

CoCo Terminal profile (window): Terminal profile for typing in Rainbow magazine code listings, window pane.; Color Computer; CoCo, TRS-80 Color Computer; Mac OS X Terminal

And, more importantly, set the width to the same width as the Color Computer listings in Rainbow.

One of the nice things about such a simple checksum is that the discrepancy is often a clue to what the problem is. Very often, I find that if I’ve checked and double-checked the code and the number still doesn’t match, it is because I left out a character, probably on the last line. Often, this is obvious. There’s a space at the end of a line which is of course invisible in the printed listing, and the checksum is 32 less than what it’s supposed to be.5

In BASIC, of course, the way to check which character is missing is to use CHR$(VALUE) where value is the discrepancy. While typing in TRENCH, I was going crazy thinking I had something wrong with the rcheck script, checking over and over and not finding anything wrong with the code. It was low by 41; because the script can provide the checksum on multiple checkpoints (a distinct advantage over the original RCHECK+), I decided to go ahead to the next checkpoint. It was still 41 low. It was very clear that the problem was not with the script but with my typing.

What is character 41? In Chipmunk BASIC:

  • $ basic
  • Chipmunk BASIC 368b1.07
  • >print chr$(41)
  • )
  • >

The missing character was almost certainly a close parentheses.6 Since I clearly couldn’t be missing a close paren except on the last line—it would have been obvious from the 32-character width—I checked and found the error in less than a minute.

Yes, 32-character width. The other advantage to Rainbow listings is that they were 32-characters wide, and matched exactly7 what should be on screen. This is helpful enough that I emulate it on the Mac by using vi in the Terminal. I’ve created a special Terminal profile for 32-character width typing.

I tried to use my GUI text editors, but they all want to wrap intelligently, that is, at word boundaries. I couldn’t figure out how to tell TextEdit, Textastic, or TextWrangler to simply wrap at the end of the line regardless of word boundaries.

REMEMBER ALSO TO USE CAPS LOCK when typing but TURN IT OFF when done. It will make it a lot easier to find typos if your screen matches exactly what is in Rainbow magazine. But if you leave CAPS LOCK on while in VI’s command mode, the commands you get will not be the commands you expect.

You may also find the “+” key useful for moving to the beginning of the next line in vi. Just using the down arrow will move to the same location in the next line that you are in this line.

The only thing I haven’t figured out how to do is have a better visual or audio cue when the line wraps at 32 characters. When typing directly on the CoCo, the screen is big enough that even while looking at the listing in the magazine I can see the line wrap out of the corner of my eye—the entire screen shifts up one, after all. If I don’t see the shift out of the corner of my eye, I know that I typed too little (or, if the shift happens too soon, I typed too much). This effect is much less pronounced on a modern screen. Having a bell sound when vi wraps a line would be great, but I don’t see how to do it, or even if it’s possible. The problem is exacerbated by vi’s inability to partially scroll the top visible line. If the top line of code takes up four screen lines, then vi will scroll up by four lines. The next word wrap won’t even need to scroll.

December 11, 2019: I’ve added an option to run the original rcheck instead of the far better rcheck+. The rcheck+ algorithm is a real, if primitive, checksum. The original rcheck just checked how much RAM the typed program was using. This wouldn’t pick up many errors that didn’t already get picked up by just watching when the cursor flipped to a new line.

Use --rcheck to run the original rcheck on a file.

  • $ ~/bin/rcheck ENRAK.BAS 70 140 290 390 580 680 870 1100 1260 1360 1510 1610 1720 1830 --rcheck
  • 70: 0426
  • 140: 076F
  • END: 07AF

As you can see, the original used hexadecimal totals, and the number always rises.

In response to TRS-80 Color Computer Programming Tools: The TRS-80 Color Computer was a fascinating implementation of the 6809 computer chip, and was, from the Color Computer 1 through 3, possibly the longest-running of the old-school personal computers.

November 11, 2020: New, improved rcheck+ for Rainbow Magazine code
ON L GOSUB: The TRS-80 Color Computer’s Extended Color BASIC requires spaces between variable letters and THEN, GOTO, or (as in this example) GOSUB.; Color Computer; CoCo, TRS-80 Color Computer; BASIC; Beginners All-purpose Symbolic Instruction Code

This, from Le Lutin in the July 1987 Rainbow, was a very annoying and time-consuming error to debug just using rcheck. It was obvious once brought into Xroar.

I’ve added a few new features to the rcheck script to make it more useful for typing in code from The Rainbow.

--debugprovide a hexdump of the tokenized BASIC file
--rcheckuse the original rcheck rather than rcheck+
--shift <x>shift all checksums by x
--verboseshow checksums for all lines
[xxx]show checksum for line xxx
[xxx:yyy]verify line xxx against expected checksum yyy
[:yyy]verify checksum yyy at the end of the code

rcheck+ for macOS (Zip file, 2.5 KB)

The big, important change is that you can now specify the expected checksums on the command line. You can continue to use rcheck as before, and its behavior will not change. But if you add “:yyy” to a line number, it uses “yyy” as the expected checksum. For the final line, you can use simply “:yyy” or “yyy”.

  • ~/bin/rcheck MEMOCARD.BAS 130:15 210:170 320:9 :167
  • 130: 15
  • 210: 152 238 (-18); possibly a 4 where there should be an F?
  • 320: 247 238 (-18)
  • END: 149 238 (-18)

When a checksum does not match the expected checksum, the script shows the difference. This is extremely helpful, because often merely knowing that the checksum is off by, say, 32, tells you what the likely problem is—a missing or extra space, or an incorrectly-cased letter. In fact, some errors are common enough that I’ve put a check for them in the script, as you can see in the example.

  • The dash is right next to the equals on my keyboard, so that’s a common mistake.
  • I’ve no idea why I often type 4 where I should type F, but I do.
  • Ditto with typing a dash instead of an equals sign.
  • Also, very commonly spaces will not be obvious and so will not be typed when they appear in a remark, especially when they appear (I suspect) at the end of a remark.
  • Multiples of 32 can be the result of case issues, since the difference between upper and lower case characters is 32 in ASCII, or multiple missing/extra spaces.
  • Every once in a while, not only can’t I find the supposed error, but the very next block of code is also off—by the inverse of the amount the previous block was off. I suspect that these are typos in the Rainbow checksum block.
  1. I considered providing a similar program for Astounding Scripts, but the advantage of modern scripting languages over BASIC—their readability—also makes it more difficult to ensure that typists use exactly the same characters, especially spaces and tabs, as in the original.

  2. And, importantly, order of values didn’t matter. This is not as bad as it could be because if you transpose letters in a BASIC keyword, the value of the keyword changes. But I had a vicious problem with Vicious Vic in the July 19867 issue because I mistyped the variable MN as NM. The rcheck algorithm reported the correct checksum, but the program failed until I was able to hand-trace the code to figure out why the it was trying to get a CHR$ of a negative number.

  3. Ed Snider’s CoCo SDC combined with the decb program makes it easy to copy files via SD card between modern computers and CoCos.

  4. And you may find the aligntabs script from 42 Astoundingly Useful Scripts and Automations for the Macintosh useful for aligning the numbers. Just pipe it through: ~/bin/rcheck TRENCH.BAS 7 15 20 28 37 51 | aligntabs.

  5. Or, if the author had the habit of adding spaces to the end of lines, a multiple of 32. It’s important to remember that the difference between upper and lower case—or reverse text in the case of Color Computer programs—is also 32. Reverse case is often used to emphasize some text. And sometimes in obscure locations such as comments.

  6. The same method, using CHR$(), would work in Extended Color BASIC itself, either on a real CoCo or in an emulator such as XRoar.

  7. Barring strange printer artifacts such as replacing reverse text with lowercase. I think the up arrow printed differently as well, though I may be misremembering the Model I.

  1. Rainbow BASIC preflight ->