Author Archives: Allen Huffman

About Allen Huffman

Co-founder of Sub-Etha Software.

CoCo VR

Over the years, there were a number of cool ideas at Sub-Etha Software that I really wish we’d followed through on. Last year, I mentioned some unfinished software projects I uncovered when going through all my old floppies, but there were also a few hardware projects that never made it out of the idea or concept stage…

Reveal VM100 "voice mail" device for PCs.
Reveal VM100 “voice mail” device for PCs.

For instance, once I found a low-cost gadget at Walmart that interfaced a telephone line to a computer. It was controlled by a serial port, and plugged in to the audio in/out ports of a sound card on a PC. It came with software to turn the PC in to an answering machine.

I bought one to hook it up to my CoCo, and had plans to create a simple CoCo answering machine. On a 128K CoCo 3, it would be possible to play a short greeting, and record a short message from the caller then save it out to disk. Sure, the audio quality would have been poor and it would probably be cheaper to just buy an answering machine, but wouldn’t it be fun?

VM100 ready to hook to a CoCo via cassette cable and RS232 pak.
VM100 ready to hook to a CoCo via cassette cable and RS232 pak.
Concept software was witten (in assembly) to record audio from the VM100 (using 1-bit cassette input, or 6-bit joystick input) as well as play back digital audio.
Concept software was witten (in assembly) to record audio from the VM100 (using 1-bit cassette input, or 6-bit joystick input) as well as play back digital audio.

I was even wanting to do touch tone decoding in software and create a simple voice mail system with mailboxes. There was even a plan to create a “telephone adventure game” where a description would be read and the user could make a choice by pressing buttons on their phone. (Years later, the Tellme company did something similar with a version of blackjack you could play over their 1-800-555-TELL demo line. It was so cool, Microsoft bought them!)

Woulda, coulda, shoulda…

I will try to share some more of these “lost” projects in the future, but today I wanted to focus on a virtual reality project I was working on.

VR was a big buzzword in the early 1990s, and many thought it was going to be the next big thing. As we know know, it fizzeled out rather quickly, with Atari, Sega and Nintendo abandoning their home VR products.

The Atari Jaguar VR project was being done in conjunction with Virtuality, the company I previously wrote about that created the VR game I first experienced.

The Sega VR project has a CoCo connection, since one of the launch titles was being worked on by legendary CoCo game programmer Steve Bjork**! I believe this is the game that Bjork was working on: Iron Hammer

Nintendo’s effort eventually came out as the failed Virtual Boy where, instead of wearing an immersive helmet over your eyes, you peered in to a 3-D viewer that remained stationary on a table. Hey, at least they tried!

But I digress…

In the pre-world wide web days, we had things called catalogs which were like paper versions of Amazon.com. One of the catalogs I received always had interesting items often at cheap liquidation prices. One such item was the VictorMaxx Stuntmaster VR helmet. The wiki page claims this was the very first commercial VR helmet made available.

TODO: I need to add a photo of my VR helmet, as soon as I figure out which storage box it is in.

The Stuntmaster wasn’t a real VR helmet, though. It did not provide a stereoscopic display, and did not have any head tracking capability for use with true VR games. Instead, there was an analog dial on one side that connected to a shaft which you clipped to your shoulder. As you turned your head left or right, the shaft would turn the dial, allowing a simulation of left/right head tracking.

You could plug this helmet up to a Sega Genesis game console and then play some games where you held the game controller to play, but used your head to turn left and right. It seems unlikely that this would have worked well with any games not specifically designed for this, but hey, it was the first.

Here is a video of it in all it’s glory:

Me playing Dactyl Nightmare again in 1994.
Virtuality’s Dactyl Nightmare (I am shown here playing it in Dallas in 1994) had a helmet and a hand grip controller that featured a trigger and a thumb button.

When I saw this in the catalog, I immediately ordered one to see if it could be used with the CoCo. My plan was to send CoCo video and audio to the helmet, then wire the left/right control shaft up as a joystick. Taking a nod from the controls of the Dactyl Nightmare arcade VR game I played, I was going to use the two joystick buttons for “walk” and “shoot”. My thought was you could turn your head left or right, then walk in that direction using the button. I guess I was thinking we’d build a special pistol grip controller to work with the helmet.

I had become friends with Vaughn Cato*, who did the original bouncing ball demo when the CoCo 3 first came out. He had been writing routines to do bitmap scaling and such, and I was hoping to use some of this in some CoCo game projects.

Toast 3-D maze engine by Vaugn Cato.
3-D maze engine by Vaughn Cato. It ran under OS-9.

On of the coolest things he created was a 3-D maze engine that drew everything using lines (I guess we would call this a vector engine). It looked similar to Dungeons of Daggorath but you could move through it in all directions, like Wolfenstein 3-D or DOOM did.

I cannot remember why, but for some reason the demo executable was called toast. It would read a small text file that represented the maze, then you could walk through the maze in 3-D. Things never went much further than the demo, but I thought it would work well with the VR helmet as the basis of some kind of VR maze game.

I think I was planning to create something like Phantom Slayer VR (a tribute to the old MED Systems 3-D maze game by Ken Kalish). I certainly know I had worked on this concept before without VR in mind, as well as a 3-D Pac-Man game. The Pac-Man one was interesting, as I got as far as recreating the original Pac-Man maze in 3-D and had it populated with dots you could walk over to “eat.”

Woulda, coulda, shoulda…

I still have the helmet. Who knows . . . maybe some day CoCo VR might still get done, even if there is no longer a supply for helmets to make it a sellable product.

*Vaughn Cato may be the only former CoCo guy to accept an Oscar. He was working with a company doing motion capture and he was on stage to receive a 2005 Technical Achievement Award. That’s quite the trip from a bouncing ball demo on a TRS-80, don’t you think?

**Steve Bjork has also had encounters with movies. If I recall correctly, he was an extra in films like Rollercoaster and The Goonies, as well as working on movie related video games like The Rocketeer and The Mask. Oh, and his CoCo program Audio Spectrum Analyzer appeared in Revenge of the Nerds, and his CoCo Zaxxon program appeared in Friday the 13th Part 4.

Revisiting Virtual Reality from 1993

Everything old is new again… Virtual reality is back and trendy with many predicting it will be “the next big thing.” Again. Today I want to share an article I wrote over 20 years ago when VR was “the next big thing” the first time around.

Me playing Dactyl Nightmare again in 1994.
Me playing Dactyl Nightmare again in 1994 in Dallas, Texas.

But first … Why is VR back again?

I believe it is mostly due to the propagation of powerful pocket computers full of sensors: smartphones.

When the original iPhone was released in 2007, it changed everything. If you look at what a cell phone was before that time, and then what phones are today, you can see a clear jump away from “candy bar” style phones with simple screens and physical keyboards. Today, a modern phone is basically just a high resolution touch screen pocket computer.

Even in the early years, iPhone developers were starting to leverage the sensors inside the device with interesting virtual (or augmented) reality type experiences. I recall a number of early apps that let you hold the iPhone in front of you and then turn around and have the screen respond, as if you were looking through a tiny window in to another place. Today, there are hundreds of such apps for iPhone and Android, with the most famous VR-style experience being Google Cardboard.

When Google created a low-cost VR visor that you could slide your phone in to, they started a huge ball rolling. Now, anyone with a smartphone could easily have a virtual reality helmet. Admittedly, even with the cheap cost of a cardboard visor, most higher end phones today still cost more than the original VR helmets from over 20 years ago, but we already own the phones so why not put them to work?

And if papercraft isn’t your thing, you can buy a plastic VR visor for under $20. Insert your Android or iPhone, load some software, and bingo: instant virtual reality!

But VR wasn’t always this easy or accessible… To appreciate the significance of this, I would like to share an article I wrote back in 1993 that documented my first experience in the world of VR.

Enjoy!


My Trip Into CyberSpace
———————–
by Allen C. Huffman (12/01/93)

The term “Virtual Reality” is new to some of us, and completely unknown to the rest. This term has been used so often in media lately that it’s difficult to know what it is all about. Movies such as Lawnmower Man don’t help clarify things – after all, Science Fiction is just that. Fiction. Today, however, I had the pleasure to experience the real thing and I must say – I’m impressed.

A friend of mine picked me up this morning and we made a three hour drive to Dallas in search of high tech toys. Our search led us to several large electronics superstores where we had a little hands-on fun with some of the hottest video games and gadgets available. We were told about a place not too far away which reportedly had a virtual reality setup. After making a phone call, we discovered this place was a restaurant, bowling alley, pool hall, and arcade all in one. An interesting combination – and one we just had to check out.

A short drive later we were there. Wandering through the dining section we found a pathway leading to the game room. Once there we saw what we had been searching for: Virtuality.

Virtuality is the first commercial attempt at making virtual reality available to the public for entertainment purposes. We found ourselves watching a rather amusing game in progress. There were two platforms side by side. Each one had support beams around it and a “rail” at about waist level. The players had large helmets covering their faces and held a small pushbutton device in their hands. They turned around, pointed up and down, ducked, and just generally acted silly. We noticed two large monitors displaying, apparently, just what each player was “seeing”.

The helmets contained a set of small monitor screens which projected a three dimensional image in front of you. Sensors in the helmet enabled the computer to know where you were looking, and adjust the image accordingly. If you turn your head right, the view pans to the right. If you look up, you see what is above you. Apparently the images were rather convincing, if the actions of the two players was any indication.

It was four dollars for four minutes in a game called Dactyl Nightmare. My associate and I eagerly climbed aboard when it was our chance. The attendant strapped a belt around my waist then gave me a rod to hold. The rod, held like a gun handle, had a trigger on the front and a pushbutton on the top activated with your thumb. The large, awkward helmet was then lowered onto my head and tightened into place. To my surprise, I saw a perfectly clear image of what the large monitors were showing. In front of me I could see a small checkerboarded area with stairs leading down to a large playing area. The square area had stairs leading up on each side, which allowed four starting positions for participants. The center area had an open roof with poles supporting it, and a large doughnut shaped object in the center. While the graphics were bright colored computer shapes floating in space, one could not help but feel like you were standing inside a giant computer world.

A voice came through the stereo headphones in the helmet notifying me that the game was awaiting another player. As soon as my friend was strapped into his setup, the attendant put the game into practice mode. The top thumb button made you “walk” to where you were looking, while the trigger button fired your gun. Gun? Amazingly enough, when I held my arm out in front of me, I saw a computer generated “hand” holding a gun in front of me. If I turned my hand left or right, my virtual arm did the same. Amazing! I tilted my head left and right and the screen moved accordingly. I even turned all the way around and found myself looking at what was behind me.

We took a few moments to walk around. I could hear virtual footsteps as I navigated my way down the stairs and around the poles. “Are you guys ready?” asked the attendant as he activated the real game. A counter appeared at the top of the image at four minutes, counting down. Scores were displayed in either corner. The game was afoot, and I was ready to blast my friend into virtual pieces.

I eased my way around the playfield, turning my head in all directions looking for my target. There he was at the top of one of the side platforms! A computerized person stood there – arms, legs, and a head with facial details and hair. His legs even moved as he came down the stairs. I raised my gun and fired, but missed. The challenge was on. As we chased each other around the playfield shouting “where are you?” back and forth I couldn’t help but notice how real this all felt. Finally, a shot made it’s mark and I saw my target blast into pieces. He was soon back together at the top of his starting platform. The game of chase continued as he shot me and I shot back. After eight shots, a warning flashed on the screen – it was an image of a winged reptile. Looking up into the blackness, a large green creature was sweeping down towards me. I fired up in a panic and saw it disintegrate. My partner wasn’t so fortunate – after his eight shots, the dino picked him up high above the playfield – then dropped him! No harm done, but valuable time wasted.

We had an audience. As I hid behind objects and leaned over and found myself suddenly disembodied by a shot I never saw coming, cheers shouted out. We chased each other some more with some hits but many more misses until the voice warned us “time is running out”. The counter reached zero, and the game was over. As I stood there, completely unaware as to which direction I was facing in the real world, I slowly heard the noises of the surrounding area and realized where I was. The attendant – after what seemed like an eternity – removed my helmet and I found myself staring at a small line of people waiting to take their turns. My friend looked at me and smiled. We stepped down and proceeded to discuss our feelings on what we just experienced. It was very real.

The technology that makes this all possible is not entirely new. The helmet and playing platform were specifically designed for this application, but the computer than ran the show was a specially programmed Commodore Amiga system. The company that produces this “game” packages everything in their own cases (right down to a custom made label on the keyboard) with a CD-ROM drive to hold the program. After it is all put together, it in essence becomes a virtual reality computer system having little to do with the desktop computer that made this all possible. Each pod contains it’s own computer, and up to four can be linked together. Perhaps next time we’ll find a place with all four units available.

Now, you may wonder just how realistic this all was. It felt real. While the images I saw were certainly computer pictures and could NOT be mistaken for anything we see in the “real” world, the feeling of being there was very convincing. You didn’t “walk” with your legs, and you couldn’t touch anything, but the way the world responded to my commands was stunning. The best part is that this is a first generation example of this type of arcade virtual reality. One can only imagine what the next “game” will be like.

So, if you ever get the chance to check out a Virtuality setup, do it. The money was well spent and the brief four minutes felt like an eternity. It was well worth the three hour drive. (By the way, the final score was three to three so we’re going back soon for a rematch!) What a way to start the new year…


That was in 1993 and, as you can tell, I was blown away. Here is a TV program I found on YouTube that featured the above mentioned game (or at least a version of it):

I actually found a number of clips on YouTube featuring this old hardware (some as recently as 2014, as folks have kept the machines running – I guess it’s retro VR now?). I have even read about a modern remake of the game for Oculus Rift:

But back to the 90’s…

I had completely forgotten this until I found a photo last night (included at the top of this article), but I apparently got to play Dactyl Nightmare a second time, about a year later (also in Dallas, quite possibly in the same Dave & Busters). But Dactyl Nightmare wasn’t my only experience with VR. I also got to try a “next generation” version, this time thanks to Disney.

During a 1995 vacation to Walt Disney World, my father and I watched an Imaigneering presentation about Disney VR. They brought a few audience members up on stage and let them try out a new Aladdin’s flying carpet VR game they were developing. It was a very interesting presentation, and the graphics had gotten much better in the two years since I played Virtuality’s Dactyl Nightmare.

Disney's Aladdin-themed VR game at Disneyland in 1996.
Disney’s Aladdin-themed VR game at Disneyland in 1996.

A year later, that VR experiment showed up as a $5 video game at the Disneyland Tomorrowland Starcade. I got to play it there in 1996 and took one tiny 320×240 photo with my first generation Epson PhotoPC digital camera.

The Disney approach had you sitting on a motorcycle-style seat, rather than standing, and you were steering the flying carpet with handles. It was really more of a flight simulator (or flying motorcycle simulator). The game itself involved collecting coins while flying over Agrabah (as seen in the 1992 animated movie Aladdin). The Disney touch was occasional encounters with animated characters that would talk to you during the game.

I don’t know what happened to all of Disney’s work in VR, but I do know that some of this technology ended up as playable games at DisneyQuest in Florida when it opened a few years later. At the time, Disney had big plans for building similar virtual theme parks across the country, but that never happened.

Note: I don’t know if this was the original name, but It appears the game was called Aladdin’s Magic Carpet Ride when it made it’s way to DisneyQuest. Websites I have found show a photo that is very similar to the installation at Disneyland, though I expect it was a bit upgraded since the descriptions I read mention effects that were not part of the prototype presentation at Epcot or installed at Disneyland’s arcade.

Second Note: Had Disney gone through with building Disney’s America theme park in the early 1990s, one of the proposed attractions was a parachute experience that would have made use of VR helmets. (I once read that a version of this was going to be installed at an ESPN Zone somewhere, but I don’t know if that ever happened.) With all the research and investment in to VR, it looks like they saw big potential in the technology if it had caught on.

My third (and so far, final) arcade VR experience was with a second generation Virtuality pod at an arcade somewhere (I keep thinking it was in Canada) running Missile Command VR. Although the graphics were improved, I didn’t find the game itself as immersive as running around those checkboarded platforms being chased by pterodactyls. (Missile Command VR was planned to be released for the Atari Jaguar VR add-on, but when that failed to happen, the game was released as Missile Command 3-D as a normal TV screen game.)

Sadly, the VR fad of the early 90’s ended quickly. Although upcoming offerings like Oculus Rift look promising, who knows how advanced things would be today if it VR had caught on the first time and been in continual development for the past two decades.

Next time … a look at our CoCo VR project that almost was!

My first programs!

Allen's first computer programs for the VIC-20.
Allen’s first computer programs for the VIC-20.

Tonight, I made an amazing discovery. I finally located a cigar box full of cassettes tapes containing VIC-20 programs I wrote in 1982 (when I was just 13 years old). I am eager to see what is on them!

Amazingly, not only where the games I remember writing here, but also a number of others I had completely forgotten about (and some I am not sure what they were). The list of programs I wrote includes:

  1. Brick Layer – likely a Surround type game (like TRON light cycles, which was not out yet).
  2. Factory TNT – the tape just calls it TNT, though. This was a Kaboom “catch the falling bombs” game.
  3. Gold Grabber – ???
  4. Meteor Clash – maybe this is the one I have been calling Meteor Storm all these years. If so, it’s a side scrolling spaceship dodging game.
  5. Sky-Ape-Er – a Donkey Kong style platform game, based on one I purchased and knew I could write better.
  6. Space Shot – ???
  7. Thick Brush – likely a drawing program.

I am very excited to see what these programs were. I also have (very faded) thermal printouts of some of them, though I don’t think I could scan them and OCR them or even read them enough to type them in these days.

Off to find a VIC-20 emulator, and figure out how to digitize these tapes and get them loaded in to it…

Sky-Ape-Er Lives!

Update: I managed to load a few files so far, but most have errors. But, I found two versions of Sky-Ape-Er!

This must have been an early prototype.
This must have been an early prototype.
Pinwheels where the original enemy. For some reason.
Pinwheels where the original enemy. For some reason.
Later versions had instructions!
Later versions had instructions!
The graphics were more Kong-like here. Sorta.
The graphics were more Kong-like here. Sorta.

iCade Mobile controller for $5 on Amazon

I just used some points I earned on Swagbucks to order a discontinued iCade Mobile controller for less than $5 (with Amazon Prime shipping). Currently, the price has gone up to $9, but either way, it’s a deal if you want an iCade circuit to mess with:

Yes. It's pink. Pink was cheaper.
Yes. It’s pink. Pink was cheaper.

iCade Game Controller (Pink) – Amazon link

I chose the pink one because it was a buck less than the other color. Of course, now it’s going to seem mean to dissect something that “cute.”

The iCade devices, which I have written about before, started out as an April Fool’s joke at Think Geek in 2010. They act like a Bluetooth (or USB) keyboard and some games were written to interpret certain key presses as joystick buttons. Ever since iOS 7, Apple has added official support for game pads so the iCade format is pretty much dead. Still, there are a ton of old apps (over 100) that still support iCade (including Atari’s Greatest Hits and a few other retro emulators).

I plan to dissect mine and use it inside a cheap arcade-style joystick I have, thus allowing me to have something like a Tankstick for iOS (for games that support it), without having to spend any money. I am especially interested in using it for Pinball Arcade and plan to add some buttons on the sides to act as flipper buttons.

I just thought I’d share this, since it’s cheaper to buy this and gut it than to get a cheap Arduino Leonardo type device to hook up via USB adapter cables like my Atari joystick project.

If you get one and hack it in to something, let me know. I’d love to see what you come up with.

P.S. Since 4/15/2014, I have earned over $1419 in Amazon gift cards (and PayPal cash)! Sign up using my link and I get credit: http://swagbucks.com/refer/allenhuffman (Ask me for the tip/howto doc.)

sizeof() matters

Updates:

  • 2016/02/29 – Per a comment by James, I corrected my statement that sizeof() is a macro. It is not. It is a keyword. My bad.

In C, the sizeof() macro can be used to determine the size of a variable type or structure. For instance, if you need to know the size of an “int” on your system, you can use sizeof(int). If you have a variable like “int i;” or “long i;”, you can also use sizeof(i).

On the Arduino, an int is 16-bits:


void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.print("sizeof(int) is ");
Serial.println(sizeof(int));
}

void loop() {
// put your main code here, to run repeatedly:
}

On the Arduino, that produces:

sizeof(int) is 2

On a Windows system, an int is 32-bits:


int main()
{
printf("sizeof(int) is %dn", sizeof(int));

return EXIT_SUCCESS;
}

That displays:

sizeof(int) is 4

Note: sizeof() is not a library function. It is a macro C keyword that is handled by the C preprocessor during compile time. It will be replaced with the number representing the size the same way a #define replaces the define in the source code. At least, I think that’s what it does.

You should avoid making any assumptions about the size of data types beyond what the C standard tells you. For example, an “int” should be “at least 16-bit”. Thus, even a PC compiler could have chosen to make an “int” be 16-bits instead of 32.

A better way to use data types was added in the C99 specification, where you can include stdint.h and then request specific types of variables:


uint8_t unsignedByte;

uint16_t unsignedWord;

int32_t signed32bit;

But I digress.

The point of this article was to mention that you can also use sizeof() on strings IF they are known to the compiler at compile time. You can, of course, get the size of a pointer:


char *ptr;

printf("sizeof(ptr) is %dn", sizeof(ptr));

Depending on the size of a pointer on your system  (16-bits on the Arduino, 32 on the PC), you will get back 2 or 4 (or 8 if it’s a 64-bit pointer, I suppose).

And the pointer is still the same size regardless of what it points to. You still get the same size even if you had something like this:


char *msgPtr = "This is my message.";

printf("sizeof(msgPtr) is %dn", sizeof(msgPtr));

But, if you had declared that string as an array of characters, rather than a pointer to a character, you get something different because the compiler knows a bit about what you are pointing to:


char msgArray[] = "This is my message.";

printf("sizeof(msgArray) is %dn", sizeof(msgArray));

There, you see the compiler actually substitutes the size of the array of characters:

sizeof(msgArray) is 20

This is an instance where using “char *ptr =” is different than “char ptr[] = ” even though, ultimately, they both are pointers to some memory location where those characters exist.

At work, I ran across a bunch of test code that did this:


const char    PROMPT[] = "Shell: ";
const uint8_t PROMPT_LEN = 7;

const char    LOGIN[] = "Login: ";
const uint8_t LOGIN_LEN = 7;

Those strings would be used elsewhere, and the length needed to be known by some write()-type function. Counting bytes in a quotes string and keeping that number updated sounds like work, so instead they could have used the sizeof() macro. Since it returns the size of the array (including the NIL zero byte at the end), they’d need to subtract one like this:


const char    PROMPT[] = "Shell: ";
const uint8_t PROMPT_LEN = sizeof(PROMPT)-1;

const char    LOGIN[] = "Login: ";
const uint8_t LOGIN_LEN = sizeof(LOGIN)-1;

At compile time, the size of the character array is known, and the compiler substitutes that length where the “sizeof()” macro is. If the string is changed, that value also changes (at compile time).

Of course, since we are using NIL terminated strings, you could also just use the strlen() function. But, that is more for strings of unknown length, and it runs code that counts every character until the NIL zero, which is wasted CPU use and code space if you don’t actually need to do that.

My optimization tip for today is: If you are using hard coded constant strings, and you need to know the size of them, declare them as C arrays (not a pointer to the string) and use the sizeof() macro as a constant. Use strlen() only for times when the compiler cannot know the size of the character array (dynamic strings or things being passed in to a function from the outside).

Speaking of that … as long as the compiler can “see” where the array is declared, sizeof() will work. But if you had something like this:


void showSize(char *ptr)
{
printf("showSize - sizeof(ptr) = %dn", sizeof(ptr));
}

int main()
{
const char    LOGIN[] = "Login: ";

showSize(LOGIN);

return EXIT_SUCCESS;
}

…that will not work. By the time you pass in just a “pointer to” the array, all the compiler sees (inside that showSize function) is a pointer, and thus can only tell you the size of the pointer, and not what it points to.

As you see, this tip is of limited use, but I think it is still neat and a potential way to save some CPU cycles and program space bytes from time to time. Since I have worked on a number of Arduino Sketches that have gotten too big to fit (also on some TI MSP430 projects), small tricks like this can make a very big difference in getting something to fit or not fit.

sizeof() can matter :-)

Building safer C string functions, part 1

Updates:

  • 2025-02-13 – fixing code formatting that WordPress messed up at some point.

In an earlier series, I discussed some easy ways to prevent buffer overrun problems when doing copies of C strings. As part of this, I created a few of my own implementations for things like strncpy() and strnlen(). Much of what I did as a workaround could be simplified if we had a smarter string concatenate function, so today I’d like to present one.

Fixing strncat

The max-limited string copy (strncpy) works well enough to prevent buffer overruns when copying strings, but the max-limited string concatenate (strncat) does not. It only limits how many characters it copies from the source buffer, without any regard to how much room is left in the destination buffer. (Is this of any use?)

We can do better.

The first thing strcat has to do is look at the destination buffer and seek to the end of whatever null terminated C string is there. Since it is already doing this work, it would be easy for it to limit how many characters it copies based on being told the maximum size of the destination buffer (as opposed to strncat, which limits based on a maximum size of the source buffer).

I am envisioning a function that looks like strncat(), but the max number passed in is for the destination buffer. Thus, if I try to append a string of 10 characters to a buffer that can hold up to 40 characters, I’d just append with a value of 40, and the function would check how much is already in the buffer and do the math for me. Because math is hard.

Here is what it might look like:

char * strncatdst( char * destination, const char * source, size_t num )
{
    size_t len;
    size_t left;

    // Step 1 - find out how much data is in the destination buffer.
    len = strlen( destination );

    // If string len is longer than we want...
    if (len > num)
    {
        // ...limit the len to be the max num.
        len = num;
    }

    // len comes back with how much is in the buffer or maxed to num.

    // Step 2 - find out how much room is left
    left = num - len;

    // Step 3 - copy up to a null, or until we hit the max size.
    // We always copy one less because strncat() adds an extra null.
    strncat( destination, source, left-1 );

    // Return destination pointer, because C says so.
    return destination;
}

This demonstrates a simple way to make a custom version of strncat() by using other standard C library functions. It could be used like this:

#define BUFSIZE 20

int main()
{
    char buffer[BUFSIZE];
    char *string = "This is a long string";

    // Put an initial string in the buffer.
    strcpy(buffer, "new:");

    // Using our own strncatdst() function:
    strncatdst(buffer, string, BUFSIZE );

    printf("buffer = '%s'\n", buffer);

    return EXIT_SUCCESS;
}

Of course, we probably want to use a safer strcpy() as well, so going back to an earlier article I wrote, I should have done this:

// Put an initial string in the buffer.
strncpy(buffer, "new:", BUFSIZE-1);
buffer[BUFSIZE-1] = '';

// Using our own strncatdst() function:
strncatdst(buffer, string, BUFSIZE );

printf("buffer = '%s'n", buffer);

Even though I know I am only copying four characters (“new:”) there, I might not be sure of the length if I was copying in some string that was created somewhere else, or if I (or someone) changed that string to something longer without thinking about the buffer size.

Fixing strncpy

strncpy() could also use a bit more work because it does not put in a null terminator (required for C strings) if the string being copied is as long (or longer) as the max length specified.

Let’s see if we can make an improved strncpy() that handles the null terminator:

char * strncpynull( char * destination, const char * source, size_t num )
{
    // Step 1 - copy up to 1 less than num characters.
    strncpy( destination, source, num-1 );

    // Step 2 - make sure there is null terminator, in case num reached.
    destination[num-1] = '\0';

    return destination;
}

As you can see, this is just a wrapper for the standard strncpy() library function that adds a final null just in case the string is that long.

Now we can use it like this:

strncpynull(buffer, "This is a really long string.", BUFSIZE);

printf("buffer = '%s'n", buffer);

…and it will make sure it trims long strings to to len-1, and adds a null terminator (which standard strncpy does not do).

Is it fixed yet?

These two functions should protect us against string buffer overruns, provided we know the size of the destination buffer.

However, by calling existing library functions, we are adding extra overhead. If those functions are highly optimized and very well done, this may still be more efficient than doing them yourself (and it is certainly easier to leverage existing functions rather than rolling your own). However, there are still a few potential issues that bother me.

For instance, for my strncatdst() function, the first thing I do is use strlen() to get the length of the string. It does this by starting at the first byte of the destination buffer and walking through it until it finds a null character. If this was a corrupt pointer, it might find itself walking through bogus memory until it happens to find a zero, potentially crashing the program from a memory access exception (if the operating system has such).

It is also not efficient because, after strlen(), the standard strncat() is used, and internally, it also must start with the first character in the destination buffer and walk through all the bytes until it finds a null (or the max num is reached), to know where it can start appending the source string. If we were doing this to a buffer containing a large 1K string, it would be walking through that 1K twice!

We can do better than that. Let’s see if we can create versions of these functions that do not use the existing C library functions.

Fixing strlen

First, recall my proposal for a version of strlen() that has a limit since there is no such strnlen() function as part of the ANSI-C standard library:

size_t strnlen( const char * str, size_t num )
{
    size_t len;

    len = strlen(str);

    // If string len is longer than we want...
    if (len > num)
    {
        // ...limit the len to be the max num.
        len = num;
    }

    // Return actual len, or max len.
    return len;
}

From the caller’s perspective, that seems fine, but this won’t actually solve the problem — it only hides it, and is still calling strlen() internally.

For this one, we really do need to create our own version so we can prevent it from scanning through 1K of memory if we know the string we expect to find should never be that long.

size_t strnlen2( const char * str, size_t num )
{
    size_t len;

    len = 0;

    while(len < num)
    {
        if (str[len]=='\0') break;
        len++;
    }

    return len;
}

This function will now stop counting at a value you specify. The original version I created used strlen() so it would count endlessly until it found a 0 before returning and having that value (if too big) clipped to the num passed in. This seems to be better for those chances when we are passed a bad pointer. (Not that that EVER happens, right?) It’s just not as efficient as it could be, so we’ll address that later.

Next, let’s use that code inside a new strncatdst() function:

char * strncatdst2( char * destination, const char * source, size_t num )
{
    size_t len;
    size_t index;

    // Step 1 - find out how much data is in the destination buffer.
    // This is basically the strnlen2() code, above.
    len = 0;

    while(len < num)
    {
        if (destination[len]=='\0') break;
        len++;
    }

    // len comes back with how much is in the buffer or maxed to num.

    // Step 2 - copy characters until we are out of room.
    index = 0;

    while(len < num)
    {
        destination[len] = source[index];
        if (source[index]=='\0') break;
        len++;
        index++;
    }

    // Step 3 - make sure string is null terminated. We really only
    // need to do this is len==num, but the overhead of adding the
    // check is probably more than just always doing it.
    if (len == num)
    {
        destination[num-1] = '\0';
    }

    // Return destination pointer, because C says so.
    return destination;
}

Now we can append short or long strings to a destination buffer, and ensure we never copy more than the size of that buffer, including a null terminator we will add if needed.

Next is a version of strncpynull() that does not use library functions. I previously shared a simple strncpy() implementation to demonstrate what it did (padding short strings with nulls). Using that as a reference, we have:

char * strncpynull2( char * destination, const char * source, size_t num )
{
    size_t index;

    // Step 1 - copy up to 1 less than num characters.
    index = 0;

    while(index < num-1) // One less, to leave room for null.
    {
        if (source[index]=='\0') break; // Exit the for loop.
        destination[index] = source[index];
        index++;
    }

    // Here we have copied 'index' characters.

    // If less than num, fill the rest with nulls.
    while(index < num)
    {
        destination[index] = '\0';
        index++;
    }

    return destination;
}

Now we have our own free-standing enhanced versions of strncpy(), strncat() and strnlen().

We should probably look at optimizing them so they are less stupid!

To be continued…

C strcat, strcpy and armageddon, part 6

See also: part 1, part 2, part 3, part 4, part 5 and part 6.

Updates:

  • 3/3/2016 – Updated note about the problem with strlen(), referencing the discussion in part 5, and the solution in the summary.

And now, a simple one-page summary of how to make copying/appending C strings safer and hopefully avoid potential buffer overrun crashes (or other problems).

Copying Strings

Instead of using strcpy(), which does absolutely no checking to see if it’s copying more data than the destination buffer can hold, use strncpy() to limit how much can be copied. If the max amount is copied, strncpy() will not null terminate the destination, so you need to do that yourself.

#define BUFSIZE 30 // size of desination buffer

char buffer[BUFSIZE] = { 0 }; // Initialize buffer with zeros.
char *longString = "Copy this long string to the buffer.";
char *shortString = "Short string.";

// Instead of strcpy(buffer, shortString), do this:
// Copy up to max buffer size-1 (leaving room for a null).
// In case of max-sized string, make sure to null terminate. 
strncpy( buffer, shortString, BUFSIZE-1 );
buffer[BUFSIZE-1] = '\0';

printf( "Buffer: '%s'\n", buffer );

// Instead of strcpy(buffer, longString), do this:

// Copy up to max buffer size-1 (leaving room for a null).
// In case of max-sized string, make sure to null terminate. 
strncpy( buffer, longString, BUFSIZE-1 );
buffer[BUFSIZE-1] = '\0';

printf( "Buffer: '%s'\n", buffer );

That should produce the following output:

Buffer: 'Short string.'
Buffer: 'Copy this long string to the '

Appending Strings

Instead of using strcat() to append a string to an existing string buffer, use strncat() and some math to not copy more than the buffer can hold (counting how many characters are already in it). NOTE: As mentioned in part 5, the use of strlen() is still a point of failure so this is actually NOT a reliable fix.

#define BUFSIZE 30 // size of destination buffer

char buffer[BUFSIZE] = { 0 }; // Initialize buffer with zeros.
char *string1 = "Buffer start.";
char *string2 = "This is what we will be appending.";

printf( "Initial buffer  : '%s'\n", buffer );

// Let's put something in the buffer to demonstrate.
// In case of max-sized string, make sure to null terminate. 
strncpy( buffer, string1, BUFSIZE-1 );
buffer[BUFSIZE-1] = '\0';

printf( "Copied buffer   : '%s'\n", buffer );

// Instead of strcat(buffer, string2), do this:

// Let's "safely" append something to the buffer.
strncat( buffer, string2, BUFSIZE-strlen(buffer)-1 );
// NOTE: strlen() can cause a failure if the original buffer
// was already bad with too much data. We need an strnlen()
// but no such function exists in ANSI-C. See the followup
// article for a "roll your own" set of functions to solve this.
//strncat( buffer, string2, BUFSIZE-strnlen(buffer, BUFSIZE)-1);

printf( "Appended buffer: '%s'\n", buffer );

This should produce the following output:

Initial buffer : ''
Copied buffer : 'Buffer start.'
Appended buffer: 'Buffer start.This is what we '

Comparing Strings

And, instead of using strcmp() to compare strings, use strncmp() so you can set the maximum string size expected.

#define FIRSTNAME_SIZE 20

char firstName[FIRSTNAME_SIZE] = {0}; // Initialize with zeros.

...

// Instead of strcmp(buffer, firstname), do this:

if (strncmp( buffer, firstName, FIRSTNAME_SIZE ) == 0)
{
  ...

Follow these three simple steps and you will greatly reduce your chance of a buffer overrun that could cause unexpected problems.

Look for an upcoming article that will expand on this with replacement functions you can use to make things easier and more efficient.

C strcat, strcpy and armageddon, part 5

See also: part 1, part 2, part 3, part 4, part 5 and part 6.

In our quest to find the safest (or at least a safer) way to copy or append strings, we have been discussing the C library functions strncpy() and strncat(). In the previous installment I mentioned there is a potential problem. That problem is with strlen(), which we are using for strncat() to determine how much data is already in the destination buffer:

// Create full name by starting with first name...
strncpy( fullName, firstName, FULLNAME_SIZE-1 );
fullName[FULLNAME_SIZE-1] = '';

// ...then appending a space...
strncat( fullName, " ", FULLNAME_SIZE-strlen(fullname)-1 );

// ...then appending the last name.
strncat( fullName, lastName, FULLNAME_SIZE-strlen(fullName)-1 );

We are assuming that the length of the data in the buffer is never greater than what the buffer can hold. But what if, somehow, the existing string was too large? If strlen(fullName) was larger than FULLNAME_SIZE, the math would break. Let’s say FULLNAME_SIZE is 20, but the string copied there was 25 (a buffer overrun):

FULLNAME_SIZE-strlen(fullName)-1

…is 20-25-1 which is -6 which means:

strncat( fullName, " ", -6 ); // error!

I would think that strncat() should fail because it is being passed a negative number for the count, but that third parameter is of type size_t, which, according to the cplusplus.com page, is:

Unsigned integral type
Alias of one of the fundamental unsigned integer types.It is a type able to represent the size of any object in bytes: size_t is the type returned by the sizeof operator and is widely used in the standard library to represent sizes and counts.

Unsigned numbers can only be positive (0 and up), while signed numbers can be negative or positive. If you pass in a -1 as an unsigned value, it will actually look like a huge positive number. (For signed numbers, one of the bits is used to indicate if it is positive or negative. If you use an 8-bit value, that can represent the unsigned values of 0-255, or the signed values of -128 to 127).

Thus, because of bad math, strncat() will operate as it was instructed, thinking the limit is some huge number.

Gotcha.

What we really need is a version or strlen() that stops counting when it his a maximuim size (like a strnlen() call). If we did, we could also give it the limit of our buffer:

FULLNAME_SIZE-strnlen(fullName, FULLNAME_SIZE)-1

That way, strnlen() would never return anything greater than FULLNAME_SIZE, so if it didn’t find a null (0) terminator before that character, it would just return the max. Thus, the above example would be 20-20-1 which is… -1.

Crap.

We would have to treat strnlen() the same way we do the other calls, and subtract one from it (a 40 character max buffer would return 39, always leaving room for an extra null terminator):

FULLNAME_SIZE-strnlen(fullName, FULLNAME_SIZE-1)-1

That would give us 20-19-1 which is 0, and passing in a 0 to strncat() should fail, not appending anything.

Problem solved.

Unfortunately, the ANSI-C standard has no such function (though some do offer it as a non-standard function). This means to be safe in these situations, you would have to create our own strnlen() function. A simple wrapper to the existing strnlen() should work:

// Return the length of the string, or num,
// whichever is smaller.
size_t strnlen( const char * str, size_t num )
{
    size_t len;

    len = strlen(str);

    // If string len is longer than we want...
    if (len > num)
    {
        // ...limit the len to be the max num.
    len = num;
    }

    // Return actual len, or max len.
    return len;
}

Problem actually solved.

This may seem to be a very unlikely error, but maybe you have a function written to deal with a buffer up up to 40 characters, but the caller was creating one that could hold up to 60. They might have a string there longer than you expect, so when you go to append (thinking 40 is the max) there might already be a longer string there.

This type of problem can be quite common when using code from other libraries or projects.

Or, perhaps someone properly used the buffer size, but used strncpy() and it filled it up without a null terminator to stop strlen(). Ah! This seems like a much more common issue.

Pity my proposed strnlen() is still potentially inefficient (and could even cause a crash). Do you see why? I guess we will have to fix that, too.

In the next part, I will summarize all of this on one simple “better practices” page for dealing with string copies or appends.

See you then…

C strcat, strcpy and armageddon, part 4

See also: part 1, part 2, part 3, part 4, part 5 and part 6.

The story so far . . . String copies can be made much safer by using strncpy() instead of strcpy(). strncpy() will take up slightly more code space than strcpy() and may be slower.

Now let’s move on to appending strings with strcat() (“string concatenate”). From the very-useful cplusplus.com website:

  • strcat( char *destination, const char *source ) – Concatenate strings. Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.

As an example of normal use, perhaps you want to take two string buffers that contain a first and last name, and put them together and make a full name string buffer:

char firstName[40];
char lastName[40];
char fullName[81]; // firstName + space + lastName

// Load first name.
strcpy( firstName, "Zaphod" );

// Load last name.
strcpy( lastName, "Beeblebrox" );

// Create full name by starting with first name...
strcpy( fullName, firstName );

// ...then appending a space...
strcat( fullName, " " );

// ...then appending the last name.
strcat( fullName, lastName );

The fullName buffer looks like this:

// strcpy( fullName, firstName )
+---+---+---+---+---+---+---+---+---+---+---+---+-...
| Z | a | p | h | o | d | 0 |   |   |   |   |   | ...
+---+---+---+---+---+---+---+---+---+---+---+---+-...

// strcat( fullName, " " );
+---+---+---+---+---+---+---+---+---+---+---+---+-...
| Z | a | p | h | o | d |   | 0 |   |   |   |   | ...
+---+---+---+---+---+---+---+---+---+---+---+---+-...

// strcat( fullName, lastName )
+---+---+---+---+---+---+---+---+---+---+---+---+-...
| Z | a | p | h | o | d |   | B | e | e | b | l | ...
+---+---+---+---+---+---+---+---+---+---+---+---+-...

Hopefully you get the idea.

In this simple example, we are controlling the length of the name strings being copied in. We know that fullName can hold 81 bytes, so we know firstName and lastName plus the space in between must be less than 81 bytes long to avoid overflowing the fullName buffer.

In a perfect world, that is fine.  But in a perfect world, we would never need any error checking. Let’s just pretend the world isn’t perfect and do this the safe(r) way.

Just like strcpy() has strncpy(), strcat() also has a safer version. It is called strncat():

  • char * strncat ( char * destination, const char * source, size_t num ) – Append characters from string. Appends the first num characters of source to destination, plus a terminating null-character.

    If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.

For strncat(), num specifies how many characters of the source to append to the destination buffer. If you know the destination buffer (fullName, in this example) is 81 characters (because it is, in this example), you might think you could just do this:

strncat( fullName, firstName, 81 );

While you can do that, that would be wrong. The num count only controls how many characters are appended — it does not have anything to do with the count of how many characters are already in the destination buffer. For example, say fullName already has a 6 character firstName copied to it:

+---+---+---+---+---+---+---+---+--...--+---+---+---+
| Z | a | p | h | o | d | 0 |   |  ...  |   |   |   | <- fullName
+---+---+---+---+---+---+---+---+--...--+---+---+---+

If fullname is able to hold 81 characters, and already contains “Zaphod” (6 characters, not counting the null), the maximum size of a string we could append would be 75 (81-6) characters. Remember that the null (0) character just marks the end of a C string, and gets overwritten by the next strcat() data.

This means what we really want is:

strncat( fullName, firstName, 75 );

Or do we? Actually, there’s another difference with strncat() versus strncpy(), and it was clearly stated in the function description:

Appends the first num characters of source to destination, plus a terminating null-character.

strncat() always appends the null (0) character, meaning if you gave it a long source string and told it to append up to 10 characters, it would append 10 characters plus the null (0) character. Thus, that 75 could actually append 76 characters! We have to always subtract one to avoid a buffer overrun.

// Copy up to 74 characters + null to the 81 character
// fullName buffer which already contains 6 characters.
strncat( fullName, firstName, 74 );

But hard-coding the numbers like that isn’t possible if we don’t know how many characters are already in the destination buffer. Instead, we can use some other C string calls to determine that and then do some math.

strlen() will return a count of how many characters are in a string buffer. It counts up to the first null (0) it finds. Thus, strlen(fullName) would return 6 (“Zaphod”). If we know the full size of the buffer, we can use strlen() to determine what is already there, and then simply subtract to know how many free bytes the buffer has. And since strncat() always adds a null, we subtract 1:

strncat( fullName, firstName, 81-strlen(fullName)-1 );

This is getting messy, but that is the basic way to ensure that strcat() doesn’t append too much data. Let’s update the original example a bit more:

#define FIRSTNAME_SIZE 40
#define LASTNAME_SIZE  40
// firstName + space + lastName
#define FULLANME_SIZE  FIRSTNAME_SIZE + 1 + LASTNAME_SIZE

char firstName[FIRSTNAME_SIZE];
char lastName[LASTNAME_SIZE];
char fullName[FULLNAME_SIZE]; 

// Load first name.
strncpy( firstName, "Zaphod", FIRSTNAME_SIZE-1 );
firstName[FIRSTNAME_SIZE-1] = '\0';

// Load last name.
strncpy( lastName, "Beeblebrox", LASTNAME_SIZE-1 );
lastName[LASTNAME_SIZE-1] = '\0';

// Create full name by starting with first name...
strncpy( fullName, firstName, FULLNAME_SIZE-1 );
fullName[FULLNAME_SIZE-1] = '\0';

// ...then appending a space...
strncat( fullName, " ", FULLNAME_SIZE-strlen(fullname)-1 );

// ...then appending the last name.
strncat( fullName, lastName, FULLNAME_SIZE-strlen(fullName)-1 );

So much extra code, but necessary to avoid a potential buffer overrun if the string being appended was passed in from another function where you don’t know the length.

Now we have a “safe” string append that can’t possibly write past the end of the destination buffer (fullName). If the string is too long, it just stops and puts a null there, truncating the string.

If every string copy is done using strncpy() to assure the destination buffer is never overran, and if every string append is done using strncat() with checks to limit how many characters can be appended, you practically eliminate the chance that a buffer overrun could occur and corrupt or crash your program.

However… If I were writing code to run a nuclear reactor, I might still take some extra steps to make sure the data I am using is valid.

Next time, we will look at a problem with this code. (Hint: What if something is wrong with the initial buffer that you are trying to append to?)

Until then…

64K TRS-80 CoCo memory test

Updates:

  • 2016/1/19 – Added reference to earlier article about more memory for BASIC (and an excerpt about why BASIC is that way). Also added reference to Juan’s comment on improving the program. Added link to Facebook CoCo group.
  • 2016/9/2 – Removed a duplicate line in the 2nd listing. Maybe fixed a typo or two.
On startup, a cassette-based CoCo has 24871 bytes available for BASIC.

Recently, Richard Ivey became the latest person in the Facebook TRS-80 / Color Computer group to ask how to tell if an old Radio Shack Color Computer had 64K without opening the case. The problem has to do with backwards compatibility. When the original Radio Shack TRS-80 Color Computer was released in 1980, it was sold as either a 4K or 16K system. Later, a 32K model would be available, and the Microsoft COLOR BASIC would give about 24K of free memory (with the rest of the memory used by the video display, cassette buffers, BASIC input buffer, etc.).

Update: See this earlier article about getting more memory for BASIC. Here is an excerpt:

64K NOTE: The reason BASIC memory is the same for 32K and 64K is due to legacy designs. The 6809 processor can only address 16-bits of memory space (64K). The BASIC ROMs started in memory at $8000 (32768, the 32K halfway mark). This allowed the first 32K to be RAM for programs, and the upper 32K was for BASIC ROM, Extended BASIC ROM, Disk BASIC ROM and Program Pak ROMs. Early CoCo hackers figured out how to piggy-pack 32K RAM chips to get 64K RAM in a CoCo, but by default that RAM was “hidden” under the ROM address space. In assembly language, you could map out the ROMs and access the full 64K of RAM. But, since a BASIC program needed the BASIC ROMs, only the first 32K was available.

When 64K upgraded became available, the original BASIC would still only report about 24K free since it had never been modified to make use of the extra memory. Thus, typing “PRINT MEM” on a 32K CoCo 1 shows the same thing it does on a 512K (or greater) CoCo 3.

So how do you tell? One easy way is to just try to load a program or game that requires 64K and see if it works. But, if all you have is the CoCo, there is a short program you could type in to test. (NOTE: See a better listing later in this article.)

10 READ A$:IF A$="X" THEN END
20 POKE 20000+N,VAL("&H"+A$)
30 N=N+1:GOTO 10
40 DATA 34,01,1A,50,10,8E,80,00
50 DATA B7,FF,DE,EC,A4,AE,22,EE
60 DATA 24,B7,FF,DF,ED,A1,AF,A1
70 DATA EF,A1,10,8C,FE,FC,25,E8
80 DATA 10,8C,FF,00,24,0C,B7,FF
90 DATA DE,EC,A4,B7,FF,DF,ED,A1
100 DATA 20,EE,35,01,39
110 DATA X

Thanks to Juan Castro for passing this along. I reformatted it so no line would be longer than the 32 column screen, hoping it makes it a bit easier to type in (though it does make the program longer, needing more, shorter lines).

On a 64K CoCo, this program will copy the ROMs to RAM and then switch in to all-RAM mode. RUN it, then type EXEC 20000 to execute it.
On a 64K CoCo, this program will copy the ROMs to RAM and then switch in to all-RAM mode. RUN it, then type EXEC 20000 to execute it.

I believe this is the classic “ROM TO RAM” (or ROM2RAM) program that appeared somewhere in Rainbow magazine back probably around 1983. Basically, it places the system in to 64K mode (where memory addresses &H0000 to &HFFFF are all RAM) and copies the COLOR BASIC and, if installed, the EXTENDED and DISK BASIC ROMs in to that upper 64K so the system can still work.

If you type this in on a CoCo 1 or 2, then RUN it, it loads a small machine language program in starting ad memory address 20000. After this, you can type “EXEC 20000” to execute that machine language program. If you typed it in correctly, it should just return to BASIC and nothing should seem any different.

But, at this point (if it worked), the BASIC ROM is now in RAM, which means you can POKE to those memory locations and make changes.

Juan suggests an easy hack of changing where the prompt “OK” appears. He says:

Now try POKE &HABEF,89 — OK should become OY.

It worked for me in the Xroar emulator (configuration to emulated a 64K CoCo 2):

The BASIC "OK" prompt is changed to read "OY" (after placing the 64K CoCo in to all-RAM mode).
The BASIC “OK” prompt is changed to read “OY” (after placing the 64K CoCo in to all-RAM mode).

Thus, if you can run this program without it crashing, and that POKE works to change something formerly in ROM, your CoCo is operating in all-RAM mode and must have more than 32K.

In the future, I will have to track down a simpler way to test for 64K. Until then, happy typing…

Update: In the comments, Juan suggested making the following changes, so the program will execute the machine language program for you:

10 READ A$:IF A$=”X” THEN 35
20 POKE 20000+N,VAL("&H"+A$)
30 N=N+1:GOTO 10
35 EXEC 20000:POKE &HABEF,89:END
40 DATA 34,01,1A,50,10,8E,80,00
50 DATA B7,FF,DE,EC,A4,AE,22,EE
60 DATA 24,B7,FF,DF,ED,A1,AF,A1
70 DATA EF,A1,10,8C,FE,FC,25,E8
80 DATA 10,8C,FF,00,24,0C,B7,FF
90 DATA DE,EC,A4,B7,FF,DF,ED,A1
100 DATA 20,EE,35,01,39
110 DATA X

With those changes, now all you have to do is type RUN and it will load the machine language program, execute it (to copy ROM in to RAM), then poke the “OK” prompt to say “OY”. Thanks, Juan!