Cross Assembling on a Commodore 64
These days, the term “cross assembling” means that you use one computing environment to develop applications for different computing environment, like using Windows to make games for a Nintendo, or writing 6502 assembler on a system with an x86 CPU.
For the lack of a better term, I’m using cross compiling to describe a means of programming assembler on a Commodore 64 by writing code on one Commodore 64, then compiling it directly to another Commodore 64 connected to it. This is a technique that I never knew existed. Even after some additional research, none of the fellow Commodore enthusiasts I’ve contacted ever even heard of such a thing since those days, albeit for one, which I’ll mention later.
But first, my story leading up to this discovery…
A few years back, I was sitting on my back porch talking on my HAM radio to other people on a local repeater. These kind of conversations are called a QSO (pronounced “cue-so”). An older gentleman named John popped on the repeater and we started rag chewing for a bit. I never met this guy before. As with any QSO going on, you tend to first talk about the HAM radio hobby. But the conversation later turned to vintage computing, namely the Commodore 64.
Of course, that piqued my interest. John mentioned how back in the day, he would write his own program for almost anything he needed his Commodore 64 to do, rather than buy a program commercially. He was a hobbyist programmer. But the difference was, where most all Commodore 64 hobbyist users would write their programs in BASIC, he would write his exclusively in Assembler. In particular, using the PAL Assembler.
I found it rather fascinating that anyone would use a primarily BASIC computer exclusively in Assembler, but good for him. It’s certainly worthy of praise for him to do so. As the end of our QSO approached, nearly three hours later, John is asking me for my email address. Apparently, he saved all of his original source code from back in the day and archived them to .D64 files. He emailed me ALL of them and said, “They’re yours, I don’t need them anymore, do what you want with them.”
I’m now in possession of unique source code from someone’s personal collection. Around 20 disks worth. These kind of things are coveted in the vintage computing community because it helps paint a picture of how these computers were used back in the day. John’s style was certainly uncommon.
I intend on releasing this source code via GPL, but I’m still going through much of it trying to figure it out. They are stored in a random fashion. It appears John mainly saved his code on disk along with other code, regardless of topic, onto disk until it filled up, then started a new disk for future code. I want to organize them a bit before releasing them.
During the end of the aforementioned QSO, John mentioned how he used two Commodore 64s to develop with, and how he would write code on one Commodore 64 and “send it” directly to another one to test it. I didn’t catch on what he said at that time, and he didn’t make a big deal of the process. John seemed to be a very humble person. He did what he did back in the day on his Commodore 64 for his own needs and really didn’t advertise the “genius” of his methods.
That “remote testing” idea stayed in the back of my mind for the years since that QSO. Last December, I contacted John about it to get more information. He said he forgot a lot of what he did with it. He did mention that he wrote the routines himself that are used to send the code to another Commodore 64. I figured, I can probably reverse engineer his code to discover how it works. His method requires a custom cable to connect the User Ports between two Commodore 64s. I then asked if he remembered how to wire the cable to do so. He did better than that and mailed me his ORIGINAL cable!
Cable in hand, I decided to go to a VC Federation Repair Workshop weekend in January 2017. I wanted to try and use this cable in an environment having other Commodore 64 users, in case I need to pick their brains for knowledge. This is what I discovered about the process…
The cable connects between two Commodore 64s via the User Port. Once that’s established, you pick a Primary computer to do your development on, and the other is the Secondary computer which will receive the compiled code for testing. John created a tiny program which resides in cassette buffer memory that when invoked using a SYS call, puts the Secondary computer in receive mode. Unless the program you’re writing/testing messes with the cassette buffer memory, this code will survive in memory as needed as long as you don’t power off the computer.
On the Primary side, John wrote a small hook which intercepts the compiler output and transmits it to the waiting receiver through the cable. Johns favorite, and only, programming environment was the PAL Assembler. PAL Assembler is very convenient to use. I never knew of it until he told me about it. If I knew about it back in the day, *I* would have done more assembly language programming myself.
PAL Assembler loads from disk to an upper part of RAM, with additional code on a small pocket of RAM near memory address 700. The neat thing about PAL assembler is that you write your code in the BASIC environment. You use line numbers like BASIC, but type in your opcodes instead as you would in any other assembler. This makes it easy to load/save programs as if they were BASIC programs. To invoke the compiler, you simply put
on a line at the top of your program code, then you RUN the program. When the SYS700 line is reached, PAL takes over and treats the rest of your code as assembler and it starts to compile. What John did when he created his compiler hook was to put code at memory address 36658 which then does its magic first and transfers control back to PAL as originally intended.
In a nutshell, to actively use this special developer’s environment, you would have the receive code ready (with a SYS call) in your Secondary Commodore 64 and your source code in your Primary Commodore 64. When you type
on the Secondary computer, it goes into ready-to-receive mode. You then put SYS36658 instead of SYS700 in your source code for PAL. After typing RUN on your Primary computer, the code hooks do their thing by sending compiler output to the Secondary computer instead of out to disk. After the compile is done, you press the space bar on the Secondary computer and your program is there, ready to go. Just RUN it.
The single biggest convenience of this is now you have an interactive developer environment on original hardware. Let’s say you find a bug in your program. Traditionally, you would need to reset your computer, reload the source code, make changes, compile, load and test, over and over. In this remote configuration, you can actively find and work the bugs on the Secondary computer while easily being able to fix your code on the Primary computer, without having to reboot anything. Just go through your bugs, fix them in code, then when you’re ready to test the changes again, SYS319 on the Secondary, RUN on the Primary, and a newly compiled version of your program is ready on the Secondary for additional testing. Meanwhile, you never had to use your disk drive other than to load/save source code, or to save out your final product. Nor did you have to keep resetting your computer to do so.
Granted, this developer setup serves little purpose these days. There are many ways one could do rapid development and testing for the Commodore 64 using modern tools. However, consider the implication in the proper frame of time. Back in the late 80’s we didn’t have the convenience of developing and testing Commodore 64 software through emulation. What John did was rather clever. Only he did this for his own needs and didn’t really make Commodore 64 community aware of this hardware hack until my recent discussion with him. However, there could still be a modern use for it.
When I was demonstrating this at the recent VCF East XII, all of those who showed interest in this setup found it fascinating. Some of them even offered suggestions on current use. One suggestion was to use it for the demoscene, where coders can create their media demos on one machine while sending and testing it on another. Perhaps make that a category for such an event, to code only on original hardware. This could allow coders to invest more time in coding than to waste it trying to compile to disk and running it. Who knows, maybe you have some interesting ideas.