Monday, February 12, 2018

Z Intepreter Source for CoCo Recovered

In November 2017, The CoCo Crew Podcast interviewed Brian Moriarty. Professor Moriarty (a.k.a. the Professor) was not only an author of several well-known games both at Infocom and elsewhere, but in particular he was the author and maintainer of some of Infocom's Z interpreter software used on a variety of microcomputers. In particular, that includes the Z interpreter software for the Tandy Color Computer. During the interview, the Professor hinted that he might have preserved the source code for that software in some form.

One of our listeners, Carlos Camacho, contacted the Professor in pursuit of that software. This eventually resulted in an email message to the CoCo mailing list indicating that Carlos was in possession of Infocom source code. As of this writing, that sourcecode is now available at the TRS-80 Color Computer Archive website.

(NOTE: What follows should be taken as pursuit of an academic/educational interest and an investigation into a historical aspect of the history of Infocom and the Tandy Color computer. The intellectual property of Infocom belongs to Infocom's legal heirs, and I am not in any way advocating otherwise.)

Preparations to Build

Let's begin by creating a fresh code repository in git and extracting the Infocom source into it:

mkdir coco_infocom
cd coco_infocom/
git init .
unzip ../Infocom\ Adventure\ Games\ Interpreter\ Source\ Code\ \(Infocom\).zip
chmod 644 *
git add *
git commit -m 'Initial commit of pristine CoCo ZIP source from Infocom'

At this point, we are mostly ready to build the code with lwasm or some other assembler. For fun, lets go ahead and try to build the boot track for use with the DOS command:

lwasm -9 -l -f raw -o boot.trk boot.src

That didn't work! Instead we see a bunch of ouput like this:

boot.src(105) : ERROR : Bad opcode
boot.src:00105 ERRM:    DB    $0D

What's going on? Well...unfortunately, many assemblers take some liberties with the naming of pseudo-ops. The assembler used by Infocom does exactly that, and at least lwasm is unsure what to do with a number of those pseudo-ops as they are used in the pristine code from Infocom. In the error shown above, lwasm needs to see ".DB $0D" (or certain other variants) instead of "DB $0D".

Fortunately, some simple transliterations in the source code are sufficient to make lwasm happy. Rather than describe them all here, I have provided a patch that can be applied to your local git tree:

git am lwasm-compat.patch
lwasm -9 -l -f raw -o boot.trk boot.src

You will now see a 597-byte file named boot.trk. The binary data in that file matches what you will find on the boot track of the Infocom diskette images in the Color Computer Archive with the Version C interpreter.

Make Things Easier

Many people do not like typing command lines to use a computer for anything. Even those that don't mind typing a few commands can tire of typing long command lines over and over again. As you can see above, the lwasm command line can be a bit complicated. Serious developers tend to use some sort of build script or a tool like make to control their software builds. To that end, I have provided a patch that adds a Makefile to the repository as well:

git am add-makefile.patch

You will now also see a 5824-byte file named cocozip.img. The binary data in that file matches what you will find on the first several tracks of the Infocom diskette images in the Color Computer Archive with the Version C interpreter.

On to Version D

One of the interestings that I noted in an earlier blog entry is that there are different versions of the Infocom Z interpreter represented among the various Infocom diskette images in the Color Computer Archive. The newly recovered Infocom source matches Version C of the interpreter. But what about the (apparently) later version D?

The ability to build the Version C source and compare the results to the various binaries made a reasonable task out of isolating the differences between the Version C and Version D binaries. I patched the code with the binary differences, then I disassembled those differences to reveal reasonable interpretations of what the original source must have been doing. This was a non-trivial effort, but it is already done! I am making those patches available too:

git am remove-tandy-bit.patch
git am update-to-version-D.patch

Why two different patches? Well, the first patch simply removes the part of the interpreter that sets the "Tandy bit". This little piece of censorship/marketing from Tandy is an interesting historical footnote. Some may choose to apply this single patch but otherwise use the version C interpreter for whatever reason suits them. Others may choose to use version D but otherwise omit that single patch in order to preserve the experience Tandy would have preferred to give them. That change is given its own identity to enable such choices or for further investigation.

The bulk of the version D update is contained in the second patch. With both patches applied, the resulting binaries from the build will match the corresponding bits from those Infocom diskette images in the Color Computer Archive that have the Version D interpreter.

Questions Raised or Answered?

For the record, the Professor seems to have been unaware of the existence of version D of the interpreter. This raises the question of whether version D might have been the work of some lone hacker or whatever. The fact that most of the version D changes seem to be simple features and bug fixes suggests that this is the sort of mundane work that we might expect from a typical software house as it continues to operate its business. That coupled with the several copies of version D in the repository being identical leads me to believe that version D was simply a maintenance update from Infocom.

However, the removal of the "Tandy bit" in version D seems noteworthy. Why would Infocom simply remove this piece of the Z interpreter? Was there some change in the corporate relationship between Infocom and Tandy that made Infocom want to revert this piece of Tandy-specific functionality? Or perhaps that unknown Infocom maintenance programmer was offended by this single bit (literally) of censorship, and simply removed it to soothe his own conscience? We may never know.

Having access to the source for this historic piece of software has been amazing. Interesting code structures and techniques and tantalizing comments abound. Beyond that, I have identified a number of places to make code changes for certain fixes and enhancements, like support for lowercase characters, different text screen dimensions, Drivewire support, etc. I plan to have more patches before long, but CoCoFEST! is'll just have to stay tuned!

Monday, November 20, 2017

Building Infocom Disk Images for CoCo

In the previous posts in this series, I have discussed pairing original Infocom Z interpreter software with new Z code story files in order to enable new interactive fiction games to run on the CoCo. In this post, I intend to tie-up some loose ends and to detail the actual process involved.

Image Issues

The outcome of this whole process will be to build a diskette image. The resulting image can be used as-is in MAME or another emulator, it can be loaded on a real CoCo with a CoCoSDC device or using DriveWire, or it can be used to write an actual physical diskette. Choosing and following the appropriate process for any of the above will be left as an exercise or the reader.

This post will focus on producing what is known as a "JVC" diskette image. In its simplest form, this format is merely a sequential arrangement of sector data arranged sequentially by track, yielding a 161280 byte file representing a single-sided disk with 35 tracks, 18 sectors per track, and 256 bytes per sector. This simple, sequential data layout makes reading and writing specific track data by offset into the disk image very simple.

Filesystem Concerns

The Disk Extended Color BASIC (DECB) code on the CoCo reserves track 17 of the disk for storing the disk's directory. Depending on how a disk is used (i.e. how programs are started), a valid directory may not be required. However, at least some versions of the Infocom Z interpreter rely on being loaded via LOADM and therefore require a valid directory to be present on track 17 of the disk image.

Many CoCo games (including some versions of the Infocom Z interpreter) depend on being started by the DOS command in DECB. The DOS command loads data from track 34 of the disk into a fixed location in memory, checks for a simple signature at the head of that data, and then jumps into the loaded program if the proper signature is found. Care must be taken to preserve the contents of track 34 if use of the DOS command is required to start the game.

Interpreter Differences

I loaded each of the Infocom games from the disk images at the Color Computer Archive. After starting each game, I issued the $VERSION command in order to collect version information from each interpreter. As shown in the table below, at least three interpreter versions were shown to be used by Infocom to package their games for the CoCo!

Result of $VERSION Command by Game
Game Version
CutthroatsCOCO 2 VERSION C
Enchanter, TheCOCO VERSION D
Hitchhiker's Guide to the GalaxyCOCO 2 VERSION C
Lurking Horror, TheCOCO 2 VERSION C
PlanetfallCOCO 2 VERSION C
Sea StalkerVERSION A
SpellbreakerCOCO 2 VERSION C
StationfallCOCO 2 VERSION C
SuspendedVERSION A
WishbringerCOCO 2 VERSION C

Oddly enough, no interpreter found reported anything like "VERSION B". Was a version "B" ever released? What about a version "E" or other later version? Also, if we relate the alphabetical version order to the original release dates of the games above, the release order of the games does not seem to match the version order for the CoCo Z machine interpreters. Were the CoCo versions released in a different order than the original game release order? Or perhaps the diskettes imaged on the Color Computer Archive were purchased in random order over a period of time, while the diskettes sold were sent with whatever version of the CoCo Z machine interpreter was current at the time?

If you have an original Infocom game disk for the CoCo, please boot it up and issue the "$VERSION" command. If you get different results than shown in the table above, then _PLEASE_ let me know in the comments below or however else you may know to reach me!

Given the above, a decision must be made as to which interpreter version to use. The "VERSION A" interpreters are not started via the DOS command, but instead require either the standard "LOADM : EXEC" combo or a BASIC program to do the same. My personal preference for starting via the DOS command and my (baseless?) presumption that higher versions are later and hopefully better (i.e. more features and fewer bugs) causes me to select to use the "COCO VERSION D" interpreter taken from the Ballyhoo disk image.

Command Performance

Starting here, I will presume that you have a "version 3" Z machine story file available called "newgame.z3" and an image of the original Infocom Ballyhoo diskette called "ballyhoo.dsk". So, let's start by using the Toolshed decb command to create a clean disk image called "newgame.dsk":

rm -f newgame.dsk
decb dskini newgame.dsk

Next, copy the Z machine interpreter from Ballyhoo to the new disk image. This is done by copying the first 9216 bytes (i.e. two tracks, eighteen 256-byte sectors each) from one disk image to the other:

dd if=ballyhoo.dsk of=newgame.dsk conv=notrunc bs=1 count=9216

While pillaging the Ballyhoo image, also copy over the boot track code. This is done by copying the contents of track 34 (at byte offset 156672) from one disk image to the other. The size could be as much as an entire track (4608 bytes):

dd if=ballyhoo.dsk of=newgame.dsk conv=notrunc bs=1 \
     count=4608 skip=156672 seek=156672

The final missing piece is the new story file. But there is a problem. While there are now 142848 unused bytes on the new disk image, track 17 (i.e. the directory track) is roughly in the middle of the unused space. So, any story file above a certain size (i.e. exactly 64512 bytes) will need to be written to the disk image in two parts. Given that, two commands are needed to write a large story file:

dd if=newgame.z3 of=newgame.dsk conv=notrunc bs=1 \
     seek=9216 count=64512

dd if=newgame.z3 of=newgame.dsk conv=notrunc bs=1 \
     skip=64512 seek=82944

Mischief Managed

Well, that's about it. The directory track remains empty -- enterprising hacker's could copy the directory track from the original Ballyhoo disk, enabling users to see a LOADM'able BIN file for the game (in case they don't have the DOS command available). Or, the directory track could be modified to show other messages as desired by the hacker. Such directory modifications will also be left as an exercise for the reader.

Beyond that, there remains a moral issue -- technically, doing the project as described amounts to software piracy. While I doubt that any Infocom lawyers will come knocking on your door, those who feel strongly about the issue may have objections to "borrowing" the Infocom code in this way (or at all). You'll have to resolve that issue for yourself, of course. But if nothing else, this is a fun way to consume exising Interactive Fiction on the CoCo!

Writing a new Z machine interpreter from scratch is not an unreasonable task, even for an old machine like the CoCo. Maybe if some people start consuming Inform content as described above, that will encourage someone to write a more modern Z machine interpreter for the CoCo? Then we could all be happy and our consciences could be free. Who is up for the challenge? Let me know! I'll stay tuned...

Sunday, November 19, 2017

Using Infocom's ZIP on the CoCo

In the previous post, I discussed some background information relating to the system used by Infocom to publish their interactive fiction games across a variety of competing computer systems that existed when their games were commercially viable. Beyond that I suggested that there were tools available which people today can still use to develop games for that same system. Moreover, I hinted that Infocom's own code (i.e. their Z interpreter or "ZIP") could be "borrowed" to enable running those new games on the CoCo. Let's explore those latter options now...

(At the end of that same post, I suggested that you take a look at Michael Sternberg's paper and the video of his KansasFest 2017 presentation on An Apple II Build Chain for Inform. If you have not done so already, then now would be an excellent time for you to check-out that source of information. Much of the information presented there is specific to the Apple II, but I believe that it nevertheless provides a good background for understanding the material presented below.)

Get Informed

Inform is the tool for compiling game descriptions into the form necessary to feed the Z interpreter. Teaching people to program in Inform is well beyond the scope of this blog post, so I will just touch on a few important points and leave the rest as an exercise for the reader...

The first version of Inform appeared in 1993, and versions progressed until a major rewrite in 1996 brought Inform 6. The Inform 6 language is largely procedural with object-oriented features. Inform 7 dates from around 2006 and features a declarative syntax with a high level of domain specificity (i.e. it is highly geared toward interactive fiction). While an Inform 6 compiler is used "under the covers" as a back-end compiler in Inform 7, the two languages are highly diverged and quite different to use.

It so happens that there are different versions of the Z machine interpreter (ZIP). Not surprisingly, the older ZIPs (such as what Infocom used on the CoCo) only support older ZIP standards. It turns-out that the last versions of Inform to effectively support such old ZIPs were somewhere in the Inform 6 range. For writing games to run on the CoCo, use of Inform version 6.1.5 as suggested in Sternberg's paper is recommended.

The point of getting an Inform 6 compiler up and running is to be able to produce story files containing Z code. In some cases these might be found pre-compiled at the Interactive Fiction archive or other sites. In still more cases, example Inform 6 source files might be found for you to compile on your own. Ideally, you will write your own games in Inform 6! But again, teaching you that skill is outside the scope of this blog post. I will suggest that you acquire a copy of the Inform Designer's Manual: 4th Edition, which apparently remains the definitive reference for the language.

Grab the ZIP!

So, the simple nugget of realization that I gleaned from the Sternberg paper was that Infocom wasn't making any use of the filesystem on the Apple II diskettes. So, why would they do things any differently on the CoCo? Applying that nugget of realization along with a hex dump of some Infocom disk images for the CoCo provided the missing information. Each of the Infocom disk images I looked at for the CoCo shared the same data for the boot track and for the initial two tracks on the disk. The data in between those tracks varied with each game, leading me to surmise that copying the boot track and the first two tracks (which I presumed to contain the Z interpreter) to a new disk along with copying a different game's Z machine story file in between would result in a disk that could boot and play that other game.

Continuing with the above theory, I created an image of an empty CoCo disk. I used the Zork I CoCo disk image as a source for it's boot track and its first two tracks (i.e the interpreter). I used the 'dd' command on Linux to retrieve those tracks from the Zork I disk image and to write their data to the appropriate locations on the new disk image. I continued by using the 'dd' command to write a different story file to the space in between the interpreter tracks and the boot track. I then tested the resulting disk image by loading it in MAME and booting it with the 'DOS' command on the emulated CoCo. I was rewarded by seeing the other game start and run.

Admittedly, the above is a bit light on some details. Moreover, there were some complicating facts that arose as I continued to investigate. For example, it turns out that there are at least 3 versions of the Z interpreter for the CoCo.  But that info and a few more details on the above are going to have to wait for now. If you want to learn more, then you will just have to stay tuned... ;-)

Saturday, November 18, 2017

Building CoCo Games with Inform

Often we see people do retro computing projects that really are only a piece of the puzzle. Such projects include hardware gadgets with cool capabilities but no hardware to use them, or media players with no stash of media content to consume. Hopefully these projects "scatch an itch" for the people doing them, but they often do little for the community other than providing an entertaining read or a cool "look at that" moment.

One type of retro computing project that can be fun and rewarding involves enabling an existing pile of content to be consumed on a computer where it works perfectly well, but where it has never been published. Such a situation presents itself where some game producers of the past had standardized on platforms that presented games on multiple computers using identical source materials. These platforms packaged custom software for each computer with the computer-agnostic game data in order to reach the largest market possible. Sierra On-Line used this sort of strategy with their AGI game engine, and Guillaume Major has exploited that system to add a number of fan-made AGI games to the Color Computer Archive.

Infocom Games

A contemporary of Sierra On-Line, Infocom is often considered as a pioneering company in the "text adventure" or "interactive fiction" genre of games. The lack of graphics in such games probably led to their eventual loss of popularity, but it did make them especially suitable to the sort of "write once, publish anywhere" strategy described above. Not surprisingly, Infocom implemented just this sort of strategy by targeting their game designs at what they called the "Z machine".

By targeting their games to the Z machine, Infocom did not just simplify their own task of releasing to the large variety of machines that were commercially viable in that era. Infocom also enabled their games to be played on any machine to follow, provided only that someone implement a Z machine interpreter for the target machine. Portable code for such interpreters has been available since the mid-1990's, and such interpreters are available for nearly any machine of merit today.

Inform Us

Hot on the heels of the portable Z machine interpreters came a Z machine compiler called Inform. This tool allows individuals that want to write interactive fiction games to do so in a way that allows users to consume their games, almost as if the games had been released by Infocom itself years ago. All that is required is a Z machine interpreter. Fortunately for us, the CoCo already happens to have one of those... :-)

The inspiration for this endeavour was a paper presented at KansasFest 2017 by Michael Sternberg, available via his blog in a post entitled An Apple II Build Chain for Inform. I recommend reading his paper and viewing the video from KansasFest (linked from his blog) as background information before continuing to my next post on this subject.

The next post on this topic will provide some technical information and describe the steps necessary to "borrow" the Infocom interpreter from an existing CoCo Infocom game and to make it use a different Z-machine game file. If you have been desperate to demonstrate your skills at writing an interactive fiction game, then this may be the best way for you to get such a game released to the CoCo world. If that sounds good to you, then you had better stay tuned...

Wednesday, September 20, 2017

RetroChallenge Entry -- RC2017/10

Over the years I have participated in RetroChallenge events several times. They are a lot of fun, plus the idea of an organized event helps to provide some discipline to help with motivation for spending time on a silly project.

Organizer vs. Participant

During the past year I have actually taken on the role of organizing the RetroChallenge events. Being the organizer (and judge) certainly counts as participation, but not in the really fun way. Sadly, during the last RetroChallenge event I never got around to actually entering with a real project. Good fun was still had by all, but with all things considered I would prefer to have a project even if (as the judge) I must recuse myself from prize eligibility... ;-)

What is my entry?

Friends and fans alike will know of my fondness for the Tandy Color Computer. Part of the CoCo's history is a precursor machine known as the TRS-80 VIDEOTEX terminal. This machine was not much different than a "TV typewriter" with a built-in modem. However, the VIDEOTEX terminal had a similar appearance to the CoCo and it shared the same basic chipset as the CoCo. Nevertheless, little is known about this CoCo progenitor today.

I just so happen to have two examples of this type of machine. For my project, I intend to do some reverse engineering of the system, hopefully producing at least a "block diagram" schematic and/or basic "memory map". If things go really well, then I might even attempt to throw together a new machine emulation for MAME. Or if nothing else, maybe I can hack together a replacement ROM for the machine? Oh, the possibilities...

Does that sound interesting to you? Then I guess you'll have to stay tuned...

UPDATE: 18 November 2017

Well...too sick, lame, and/or lazy to do much for RC2017/10. Hopefully I can revisit this project before too long! As always, stay tuned...

Tuesday, August 15, 2017

CoCo3 programs on a cartridge too?

Not long after the previous article, someone asked me about making the ROM cartridge loading technique work on a BASIC program written specifically for the CoCo3. Although the issue hadn't occurred to me before that, I immediately suspected that the existing technique would not work in that situation. A little experimentation revealed that to be true...

What's The Deal?

I knew that the CoCo3 had a more complicated boot process than its predecessors. The CoCo3 boot-up involves copying code from ROM to RAM, patching some existing BASIC routines, and adding some new ones designed to take advantage of CoCo3 hardware enhancements. I also knew that to preserve some compatibility with the original CoCo and the CoCo2, ROM cartridge programs were given an environment that looked much more like those earlier machines. In other words, the ROM cartridge environment doesn't get access to the CoCo3 extensions to BASIC. So, a BASIC program written specifically for the CoCo3 won't work with the ROM cartridge environment as our existing technique would try to use it.

Finding The Solution

Understanding the CoCo3 boot process requires some understanding of the actual code in the CoCo3 ROMs. This could be done the hard way, manipulating the CoCo3 registers to expose the actual ROM contents, dumping those contents, then analyzing them with f9dasm or some other disassembler. In this case, however, that work has already been done for us in the Unravelled Series. Referring to Super Extended Basic Unravelled II gives a good disassembly of the code in question and some useful commentary as well.

I had never had cause to look so closely at the CoCo3 boot sequence. I was confused and believed that the Color BASIC and Extended BASIC ROMs in the CoCo3 were essentially untouched from the CoCo and CoCo2 equivalents, and that the CoCo3 ROM got control in a chained fashion similar to how Disk Extended BASIC gets control from Extended Color BASIC. This misunderstanding led to some initial puzzlement until I was able to clear-up the situation in my mind.

In reality, there are some changes to the original Color BASIC and Extended BASIC ROMs that are actually burned into the hardware, as detailed by Super Extended Basic Unravelled II. Among these changes, the startup code is changed to transfer control to the CoCo3 ROM early in the boot process. This code then copies the BASIC ROM contents to RAM and patches the code as required for the CoCo3. After this is done, the patched ROM code (now in RAM) is entered and BASIC initializes itself. Late in this process the cartridge autostart sequence is enabled. When the cartridge autostart is detected, then the CoCo3 re-enables the ROMs and jumps to the code at the start of the cartridge.

The point here is easy to miss -- the CoCo3 has already initialized itself, including copying its patched BASIC code to RAM. But then it purposefully turns-off access to the RAM with the patched code in favor of accessing the ROM with the more-or-less original CoCo2 BASIC. It's no wonder that CoCo3 BASIC programs won't run!

As an experiment, I hacked-together a simple BASIC-in-a-cart program that would run and then exit. From there I verified that by default, I could not access CoCo3-specific BASIC commands (e.g. HSCREEN). But if I executed the POKE to turn-off the ROMs and re-enable the RAM first, I could access the CoCo3 BASIC commands with no problem!

New Loader

So now we must consider modifications to the "loader" program. My first thought was to add the equivalent of the required POKE as an assembly language instruction in the program. But that won't work -- since the loader is executing from ROM, swapping-out the ROM for whatever is in RAM at the same address after the swap will almost certainly cause the CPU to do something weird, foolish, or just wrong. What we really need is a way to execute the POKE after the "loader" has already executed, but before the BASIC program is RUN...

BASADR  EQU     7680

        ORG     49152
        STA     113
        STD     114
        JSR     47452      SET UP PARAMETERS FOR BASIC
        LDA     #53        RESTORE INTERRUPTS
        STA     65283      THAT ARE
        LDA     #5         DISABLED ON
        STA     65315      CARTRIDGE AUTO START
        STY     25         SAVE IT IN BASIC START
        STA     ,Y+        TRANSFER BYTE TO BASIC RAM
        CMPB    #3         IS THERE 3 CONSECUTIVE ZERO'S?
        STA     ,Y+        TRANSFER BYTE TO BASIC RAM
        STY     29         SAVE VAR START AT END OF TEXT
        STY     31         SAVE ARRAY START AT END OF VAR/TEXT
        LDD     #$504f     LOAD CHARS "PO"
        STD     ,x++
        LDD     #$4b45     LOAD CHARS "KE"
        STD     ,x++
        LDD     #$2648     LOAD CHARS "&H"
        STD     ,x++
        LDD     #$4646     LOAD CHARS "FF"
        STD     ,x++
        LDD     #$4446     LOAD CHARS "DF"
        STD     ,x++
        LDD     #$2c30     LOAD CHARS ",0"
        STD     ,x++
        LDA     #$3a       LOAD CHAR ":"
        STA     ,x+
        LDD     #21077     LOAD LETTERS "RU"
        STD     ,X++
        LDD     #19968     LOAD "N" AND END
        STD     ,X++

        LDB     #17        INDICATE 17 CHARACTERS
        STA     112        SET CONSOLE IN BUFFER FLAG
        LDX     #732       POINT TO LINE INPUT BUFFER
        JMP     44159      START MAIN BASIC LOOP
        FCB     $00


As you can see, the solution is a bit clever -- just add the POKE to the same line of BASIC input that causes the program to RUN! Aside from that, the process is the same as described in the earlier blog post -- enter the BASIC program, save the in-memory image of the program to emulated cassette, extract the file, append it to the assembled "loader" program above, burn it to an EPROM, and use that in a cartridge. I used Robert Gault's PALETTE.BAS program as a test subject for the technique described, and it works perfectly for me.

For now, I'll leave the actual BASIC conversion work as an exercise for the reader. Perhaps in the future I will seek permission to post converted versions of PALETTE.BAS or some other BASIC programs, along with pre-assembled "loader" images both for the CoCo/CoCo2 and the CoCo3. If you want to see that, then for now you'll just have to stay tuned...

Friday, August 4, 2017

Color BASIC Program On A Cartridge?

Wow! It's been a while since I posted on this blog. I guess the podcast has been keeping me busy, among other things. Anyway, I'm back for now so let's talk about something cool and retro... :-)

Games On Cartridge

Those of you familiar with my Fahrfall project will recall that I ultimately packaged Fahrfall as a ROM cartridge, one of the available mechanisms for distributing software for the Tandy Color Computer (aka CoCo). I even went so far as to produce silicon molds and to cast cartridge cases made of plastic resin for that project. For me, no other means of distributing software seems as cool and "retro" as using a ROM cartridge, and I am very pleased with the results of that project. Nevertheless, producing resin cast plastic cartridges was not without its problems.

3D-printed plastic projects are 'all the rage' these days, but 3D-printing still has plenty of its own problems: filament is expensive, surfaces usually have visible texture marks, the layered construction often leads to "delamination" and other structural problems, and printing times are so long that bulk production runs become at least impractical. With these issues in mind, some time ago I partnered with Boisy Pitre and Mike Rowen to produce injection-molded cartridge cases for the CoCo. These cases are beautiful, strong, and despite considerable setup costs fairly cheap in large quantities.

Having produced a large number of cartridge cases, my partners and I have explored a variety of ways to market them to the community. My preferred approach is to wrap cases around software releases, and I have done so with Fahrfall and a number of other titles both from myself and from others. To date all of these titles have been written either in assembly language or C, resulting in machine language programs running directly from ROM on the CoCo. But many CoCo authors are skilled in Color BASIC (Extended or otherwise).

BASIC Games Too!

Ultimately, ROM is just another storage medium. So, it should come as no surprise that a BASIC program could be distributed on a ROM cartridge as well. No version of Color BASIC supports loading programs from ROM, so a little trickery is required to make the CoCo aware of the program stored in ROM. So, what has to be done?

Long ago there was a web page called "Paul D's CoCo Pages". This was nearly lost after Yahoo bought GeoCities, but fortunately an archive exists. The page in question describes a technique for loading a BASIC program from a ROM cartridge. Boisy and I had also sought advice from Robert Gault on this topic, and he proposed a technique that was substantially the same. I had some trouble replicating the procedure described on the "Paul D" page, but below I'll summarize what worked for me.

Extraction Procedure

Start with loading the BASIC program on the CoCo. Then you will need to determine the start and end of the RAM used to store the actual BASIC program itself in memory:


Now you will need to save that as a memory image (i.e. not as a normal BASIC program). Here I will presume that one is using an emulator and capturing the CSAVEM to a file called cartprog.cas:


Now on the machine running the CoCo emulator, we will use the cecb comand from the Toolshed project to extract the binary image file of the CoCo's memory:

cecb copy -2 -b cartprog.cas,CARTPROG cartprog

Building the ROM Image

The Color BASIC ROM will jump to the beginning of cartridge ROM as part of the machine's initialization. We need to put some machine code there to do the job of loading the BASIC program. The assembly language program I am using for this task is shown below. It is based upon the loader program shown on the original "Paul D" page, but with some minor changes to suit my way of working:

BASADR  EQU    7680

        ORG    49152

        STA    113
        STD    114
        JSR    47452      SET UP PARAMETERS FOR BASIC
        LDA    #53        RESTORE INTERRUPTS
        STA    65283      THAT ARE
        LDA    #52        DISABLED ON
        STA    65315      CARTRIDGE AUTO START
        STY    25         SAVE IT IN BASIC START
        STA    ,Y+        TRANSFER BYTE TO BASIC RAM
        CMPB   #3         IS THERE 3 CONSECUTIVE ZERO'S?
        STA    ,Y+        TRANSFER BYTE TO BASIC RAM

        STY    29         SAVE VAR START AT END OF TEXT
        LDD    #21077     LOAD LETTERS "RU"
        STD    ,X++
        LDD    #19968     LOAD "N" AND END
        STD    ,X++
        LDB    #4         INDICATE 4 CHARACTERS
        STA    112        SET CONSOLE IN BUFFER FLAG
        LDX    #732       POINT TO LINE INPUT BUFFER
        JMP    44159      START MAIN BASIC LOOP
        FCB    $00

This program is assembled and a "raw" format image is produced, called "loader"...

lwasm -9 -l -f raw -o loader loader.asm

The BASIC program image "cartprog" is concatenated with "loader" to produce the data for programming into the cartridge ROM:

cat loader cartprog > eprom.dat # DOS/Windows command differs

How Does It Work?

Once the auto-start cartridge is detected, Color BASIC transfers control to the loader program listed above. The "loader" program performs some simple initializations for the Color BASIC interpreter before proceeding to copy the BASIC program to the CoCo's program memory. This includes setting the start address of the BASIC program.

The "loader" program starts reading from the location labeled BASLOD. There it will read the value zero as shown, and it will write it to the location defined by BASADR. After the first zero, "loader" continues with the next location which will correspond to the first value from "cartprog". The sequence of reading and writing byte-by-byte continues until 3 consecutive zeroes are read. This corresponds to the end of the BASIC program. (The original "Paul D" version looks for 4 zeroes, but AFAICT that is incorrect.) At this point, the end address of the BASIC program (and the end addresses for BASIC variables and arrays) is set for the Color BASIC interpreter.

Finally, the "loader" program manipulates the keyboard input buffer used by Color BASIC in order to force a "RUN" command to be executed immediately. Then, control is transferred to the Color BASIC interpreter and the loaded BASIC program is now executed.

So, there it is -- a BASIC program loaded from a ROM cartridge on a Tandy Color Computer. Now Color BASIC programmers can publish their programs on ROM cartridge, with all of the prestige, durability, and collector value that entails. That includes ROM cartridges with extra hardware, like my CoCo Games Master Cartridge. But that is another story -- you'll just have to stay tuned!