Wednesday, October 28, 2026

Giving plm09 a spin!

There is a decent chance that you have never really heard of PL/M. Even if you are as old as I am, this one might have slipped by you. The truth is, it really is a bit before my time. I first heard of PL/M about the time that the CP/M sources started to become publicly available, and even then the complaint was that there would be no way to compile much of the source anymore. PL/M had been nearly forgotten by the mid-90's, even by those of us who were already interested in retrocomputing. But do not worry! This post will (or may?) get you started!


 Everyone has this on their bookshelf, right? ;-)

Hello, world!

 Or, at least something similar? An example program or two that output some text. Unlike many/most languages, PL/M lacks any form of standard I/O. Instead, that exercise is mostly left "for the reader". That is to say that rather than simply including a language feature for writing a string of text for output, the programmer must format any such string internally, and output each character sequentially. Fortunately the plm09 runtime provides PUTCH and PUTDEC procedures to simplify the actual output tasks, so let's look at an example that makes use of those:

 /* hello.plm */
HELLO: DO;
PUTCH: PROCEDURE (C) EXTERNAL; DECLARE C BYTE; END PUTCH;
PUTDEC: PROCEDURE (N) EXTERNAL; DECLARE N ADDRESS; END PUTDEC;
DECLARE I BYTE;
I = 1;
DO WHILE I <= 5;
    CALL PUTDEC(I * I);
    I = I + 1;
END;
CALL PUTCH('!');
END HELLO;

Here we see a DO WHILE loop which counts to 5 while calling PUTDEC to print each value to the output. PUTCH is used at the end to pring a final '!' character.

I used the following Makefile to execute the build procedures and to run the result:

 PLM09_SHARE = /usr/share/plm09

PLMC = plmc
LWASM = lwasm -9
SIM6809 = sim6809

%.asm: %.plm
    $(PLMC) -o $@ $<

%.s19: %.asm
    $(LWASM) -f srec -I $(PLM09_SHARE)/runtime -I $(PLM09_SHARE)/runtime/sim -o $@ $<

%: %.s19
    $(SIM6809) $<

With the program save in "hello.plm", a simple 'make hello' is sufficient to run the binary to see the result below:

 sim6809 hello.s19
1
4
9
16
25
!

Let's try one more example!

 /* sum.plm */
SUM: DO;
PUTDEC: PROCEDURE (N) EXTERNAL; DECLARE N ADDRESS; END PUTDEC;
DECLARE I BYTE, TOTAL ADDRESS;
TOTAL = 0;
I = 1;
DO WHILE I <= 10;
    TOTAL = TOTAL + I;
    I = I + 1;
END;
CALL PUTDEC (TOTAL);
END SUM;

This program similarly uses a DO WHILE loop to count to 10, this time keeping the sum of each iterated value in TOTAL. Finally PUTDEC is used to output TOTAL at the end. Typing 'make sum' will yield the following output:

 sim6809 sum.s19
55

Simple enough... What can you do with plm09?

Tuesday, October 27, 2026

An old dog learns a new-ish trick?

For those that aren't aware, I retired from Red Hat earlier this year. I was there for almost 22 years, most of which were both pleasant and rewarding for me. The exceptions were the final 2 or 3 years, during which I was constantly a bit annoyed by the dogged pressures from upper management to integrate AI into my workflow even when I saw no place for it or I judged that there was little or no value in doing so for my particular tasks or duties. Since regaining full mastery of how my skills are utilized and how my time is spent, I have continued to be aware of the growing use and influence of AI tools in my areas of interest both professionally and in the retrocomputing hobby.

Over time I  developed a nagging feeling that my overall lack of interest in AI tools was leaving me with an experiential gap which was separating me from my peers. I began to consult various friends from my professional life and collecting their advice and opinions on how best to make use of AI tools, particularly the well-known Claude Code. Since hands-on learning tends to yield the best results, I decided that I should pick a hobby-related project to use for my learning experience. All that and a reasonable token allowance allowed me to produce1 a Linux-based compiler for the PL/M programming language which targets the Motorola 6809 processor.

Why A PL/M Compiler?

For some time I have had an interest in programming tools for retro computing targets, but there is really no community need for yet another assembler or even another C compiler. Programming Language for Microcomputers (PL/M) is a high(-ish) level systems programming language originally conceived to support early microprocessors from Intel. This role yielded a language which reminds me quite a bit of C, but without the decades of accumulated baggage and expectations. IMHO, the language maps reasonably well to the capabilities of my favorite vintage CPU, the 6809. Hopefully the availability of this language will be welcomed by the existing communities of 6809 users, particularly that surrounding  the Tandy Color Computer.

Working With Claude

The collected advice from everyone came down to two points: a) be specific about the desired outcome without specifying how to achieve it;  and b) treat the AI like one would treat an intern (i.e. someone skilled and competent, but distracted and inexperienced). With that advice in mind, I gave Claude the following prompt:

Project goal is a Linux-based compiler for a minimal version of the PL/M language which outputs 6809 assembly language compatible with the lwasm  assembler toolchain.

After that, Claude asked a handful of clarifying questions. This included some specifics to help define what a "minimal verion of the PL/M language" meant, and some other minor clarifications. After a little time burning tokens, Claude showed me what it had for a plan and asked me to approve it. Initially I asked Claude to allow me to approve each change, but soon I was comfortable enough to let it proceed in automatic mode. I asked Claude to generate PDF documentation for the main binaries and to keep both the docs and the Claude.md file up-to-date with each subsequent change to the project.

How Did Claude Do?

I admit to having been extremely skeptical about what Claude would produce. Early experiences with various AI tools had been embarassingly disappointing, so I anticipated something that would at best mimic the assigned task. But instead, I was pleasantly surprised. Claude produced both a tool that compiles PL/M source code down to 6809 assembly language and a command-line 6809 simulator capable of running 6809 binaries which is used to run all of the compiler tests which Claude produced as part of its development process. Claude also built a system to provide runtime support for different machine targets, including the Tandy Color Computer and an example target for a user to customize for other targets. At my prompting, Claude provided targets for OS-9 and FLEX as well as the simon6809, the kswitchit 6809 kit, and Grant Searle's 6809 design. I have had limited opportunity to toy with the results so far, but so far I am quite pleased. Claude was even able to produce an RPM file suitable for Fedora!

Where Are The Results?

The git tree for the resulting PL/M compiler for 6809 is here:

https://github.com/retrotinker/plm09
 The PDF documenting the compiler is available here:

https://github.com/retrotinker/plm09/blob/master/docs/plmc.pdf 

And the PDF documenting the simulator is here:

https://github.com/retrotinker/plm09/blob/master/docs/sim6809.pdf 

Finally, Fedora users can use the RPM here:

plm09-0.3.3-1.fc44.x86_64.rpm 

Conclusion 

So, there you have it! I believe this tool is suitable for play/testing by retro computing enthusiasts with an interest in PL/M and/or the Motorola 6809, particularly if that enthusiast has a Tandy Color Computer, or one of the other supported targets. Someone suitably skilled and motivated could even extend the example runtime support for their own custom target. Finally, Fedora users can use my pre-built RPM for their own testing.

Please do give the tool a try and let me know what you think, or if you find any problems! I look forward to hearing from you in the comments!


1 I think "produce" is the correct term. I wrote essentially none of the actual code, but merely specified what I wanted from Claude and any additional changes which I wanted along the way. ↩

Sunday, July 10, 2022

Recovering VTL-09

 A few months ago, a retrocomputing post from David Wiens caught my attention. The post indicated that David was looking for some assistance in recovering an old piece of 6809 assembly language software that he had keyed-in from a listing in a book. The software in question was a 6809 port of Very Tiny Language, an early, small, higher-level-than-assembly programming language with published source code. Even after verifying the accuracy of his transcription of the VTL-09 source, David was having trouble getting the assemblers available to him to build the VTL-09 source into anything useful.


Within the past several years I had come across VTL and identified it as a likely source of some future retro-computing entertainment for me, either based on the original 6800 sources or through my own 6809 port of the code to the Tandy Color Computer. I was familiar with David as a notable person from the Color Computer's past, and we had already interviewed him for episode 46 of The CoCo Crew Podcast. David is a nice fellow, and clearly our interests here overlap! So, not long ago I finally got around to poking at his VTL-09 sources to see if I could get them assembling correctly. A short afternoon of some simple reformatting and such gave me a VTL-09 source file that LWASM would digest with only a minimal amount of "scaffolded" code. I sent David an email, describing what I had been doing and  including an updated version of the VTL-09 source file.

David was working with original, native assemblers for OS-9 and FLEX, each with its own inherent requirements and quirks. After a little back-n-forth we found a source combination that would assemble for both of us. After adding some requisite code for I/O routines specific to each of our environments, we were rewarded with the initial "OK" prompt from the VTL command processor. The illusion of entering commands was available! But alas, there was no obvious execution of any commands or program entry. On my local version, attempting to enter a program only resulted in a crash... :-(

I have attempted to find any remaining translation (or transcription) errors, but nothing so far has produced any meaningful success. I believe David was going to attempt starting over by passing the original 6800 sources directly to a 6809 assembler -- this should be possible if the assembler is in "6800 compatible" mode. But I suspect that the real problem (at least in my case) is that the original source assumed it would be running in a very different environment than what I have available. For example, at least one of the ORG statements puts a large chunk of variables into low memory. I think there may need to be at least a bit of code refactoring to get any version of VTL running on anything other than a duplicate of what the previous authors were using all those years ago.

Refactoring the code may yet be fun to do. But so far, I have found it difficult to trace how the command parser code (and even just the tokenizer) is supposed to work. There are some unusual redirections in the control flow and some non-obvious coding practices at play. Hopefully my interests, my patience, and perhaps my vacation time will align properly to get more work done on this before too long. Perhaps? Well, I can still dream... :-)

I am sorry to disappoint everyone with a "to be continued" sine die. But that's really all I've got in the retrocomputing realm at the moment. I suppose that I am still recovering from the troubles we've all faced over the past few years. Somehow, all that time effectively shut in the house just left me more behind on my retro projects than ever! At least this little VTL detour gave me  something enjoyable to pursue.

Hopefully I can pull other things together and get back to VTL-09 before too long...wish me luck?


Thursday, October 1, 2020

Something New

It has been a while since I have written anything here. Between some manufactured antagonism in the CoCo world and the COVID-19 affair in the real world, my capacity for fun has been zapped for months. I do not want to claim to have been "depressed", solely because I do not want to belittle the experiences of those who regularly struggle with such issues. But, I have been feeling the weight of the world for some time.

Starting Something

I have been lamenting that I do not have a current retrocomputing project in progress. Even without a lot of dedicated time, an open project can be an invitation to steal away for a few moments here and there to try some experiment or to implement some new feature or another. But I often find that starting a project from nothing can be an ordeal. Perhaps I am just averse to building a string of unfinished projects? But for whatever reason, I have had trouble getting started on much of anything for some time.

I have a few ideas for CoCo projects -- mostly games. But what type of game? What sort of game mechanics? What graphics resolutions? Do I target the CoCo3? Or is the base CoCo and its various clones good enough? Should I make use of any specific hardware or controllers? Will the game be a demonstration of my skill and prowess as a 6809 programmer? Or just something fun to do? So many questions!!

Boilerplate

With my lingering indecision and looming depression, I still have no CoCo project to which I am committed. Still, I feel the need to get something underway. For now, I have decided to start with something simple. Using some older projects for boilerplate code, I will start experimenting. I have a couple of directions to explore and experiments to try. I am hoping that I will at least learn something in the process, and maybe something will spark.

Wish me luck!?!?!

 

Wednesday, March 6, 2019

RC2019/03 -- All About The Data

My project for RC2019/03 is to write a chip tune player for the Tandy Color Computer (CoCo) that utilizes the SN76489 chip on the Game Master Cartridge (GMC). This is not a tool for creation but a utility for consumption. So, what will it consume?

VGM Files


The VGM file format is capable of representing audio intended for a variety of audio devices, most of which are generally in the category of programmable sound generators. Information about which chips are supported by a given VGM file is encoded in that VGM file. A quick glance at the format specification reveals lots of details about decoding such files. At the very least, supporting VGM files only for the SN76489 will require not only ignoring much of this information, but also knowing which bits of information can be safely ignored. Moreover, part of the information in a VGM file for the SN76489 indicates not only the proper rate for updating register values but also the input clock rate used to calibrate those register values.

Writing a tool merely to simplify a VGM file's data for playback would be worthy of it's own RetroChallenge project! Fortunately for me, someone has already provided a tool which does exactly that -- vgm-convertor is a "Python script for processing SN76489 PSG based VGM files". Along with being able to adjust the SN76489 data not only for different clock input values (including the 4 MHz used by both the BBC Micro and the GMC) but also for several different playback rates (including both 50 and 60 Hz), vgm-convertor is able to output a "raw" data format that is very easy to parse for playback. At least for now, processing VGM files with vgm-convertor will be a requirement for users of this CoCo chiptune player.

Simple Playback


Let's walk through my ROM-based player to get a feel for the overall task at hand. The program starts with some simple housekeeping (e.g. relocating the stack, setting-up interrupts, and clearing the screen), and then it silences the SN76489 tone and noise channels. (These default to being active when the power is applied to the chip, so it makes sense to turn them off.) The program then enables sound output from the cartridge to play through the CoCo. Finally, the program copies part of itself from ROM to RAM. (The copy from ROM to RAM is necessary since the program allows for music data to cross ROM bank boundaries. If the program is executing from ROM when a bank switch occurs, then the program would disappear from the address space and cause a crash.)

This program has to know in advance how many songs are represented in the song data that is part of the program. That number is used to control a loop in which each song is played in sequence. For each song, the title and author information is retrieved from the song data and displayed on the CoCo screen while the song is played. The remaining song data for each song defines the sequence of tone and noise channel settings, which are read from the song data and written to the SN76489 during the timing defined by the horizontal sync interrupt period. The only other notable bit of the program is the bounds checking done after each read of song data. This is used to determine when to switch to the next ROM bank.

This program has been used for a number of small demonstrations of the audio capabilities of the GMC, most notably at CoCoFEST! and on a variety of YouTube videos.

Assessment


As it stands the software described is sufficient to allow me to download a VGM file, to convert it for use on the GMC, and to build a ROM image that will play the song in question. This works fine for demonstrating the hardware, but it is a bit tedious for chiptune enjoyment. Processing VGM files with vgm-convertor may be a necessity, but building and using ROM images for every song or small group of songs is too awkward for normal use.

Instead I want to write something for the CoCo to load song data from a diskette (or diskette image). The file handling might be done in BASIC, or maybe not. The player will need to be modified to match the file handling and it might benefit from other feature additions (e.g. fast-forward and rewind). If you have any other suggestions, then feel free to offer them in the comments below.

So, still interested in where this is going? If so, then you will definitely need to stay tuned...

Tuesday, March 5, 2019

RC2019/03 -- Getting Started

It's RetroChallenge time once again! In fact, we are already five days into the contest, and I still haven't posted a "start" entry. I reckon it is time to fix that... 

Project Description 


I'm going to work on a Tandy Color Computer (CoCo) project that enables the use of the CoCo's Game Master Cartridge hardware as a means for playing a variety of "chiptunes". That sounds simple enough, but let me break it down a bit further.

I designed the Game Master Cartridge (GMC) hardware _specifically_ to be a platform for distributing games on cartridge. This would seem to solve the "chicken and egg" problem of having a game require an audio hardware upgrade, since that exact upgrade is provided in the same hardware package as the game that uses it. Alas, some in the CoCo community are averse to distributing software on cartridge due to (IMHO exaggerated) concerns about cost (as if there is no cost to an independent "sound card" or no advantage to pairing the hardware with the software on cartridge)...

I have been somewhat reluctant to promote the GMC as a stand-along sound card technology. This has primarily been due to the GMC's reliance on the inherently "slot based" addressing associated with the ^SCS signal on the expansion bus. My opinion is that a properly independent sound card should use a fully decoded address like the Orchestra-90, Speech/Sound Pak, Deluxe RS-232 Pak, and other CoCo add-on cards. Nevertheless, contemporary alternatives for CoCo audio hardware (e.g. CoCoPSG and the MegaMiniMPI) have chosen to rely on ^SCS-based addressing. So, why shouldn't I? What is good for the goose is good for the gander! 

Where Things Stand 


Dozens of GMC cards are already in the hands of the public, having been sold to "developers" either as kits or pre-assembled. Dozens more will soon be made available in the form of "Fahrfall: Master Edition" cartridges that can also be used as a sound card by other software. This project is intended to illustrate how to make use of this hardware on a CoCo and to provide an extra resource that adds value to those cartridges.

Many people will want to make noises with their GMC using the built-in BASIC on the CoCo. Even those using assembly language or some other programming environment will benefit from some simple examples of how to setup the cartridge and how to drive it. In fact, some time ago I made BASIC sources available to that effect. I have also published a video, demonstrating the use of those programs.




Chiptunes that target the SN76489 on the GMC are commonly available. These seem to be concentrated in the Video Game Music (VGM) format, but your mileage may vary. At it's core, VGM represents music as a timed sequence of register value and is relatively simple to handle as input data for a music player. In fact, I have already demonstrated a player which embeds VGM data into a ROM image.




What remains is to implement something with more flexibility, such as the ability to load music files from a diskette. Some concessions to "ease of use" may be appropriate as well.

Want to see where I take this project this month? Well, then I guess you will just have to stay tuned...

Friday, September 7, 2018

ASL/LSL -- more defense of the obvious...

In the previous post, I explained the difference of intent between "logical" and "arithmetic" shift operations in assembly language. I also demonstrated that for two's complement binary numbers, the bitwise effects of logical-shift-left and arithmetic-shift-left are actually identical. This makes the choice to implement a single physical instruction that covers both operations a completely legitimate option, which explains why that choice was made for x86, Z80, MIPS, ARM, SPARC, RCA1802, CP1610, and of course the various Motorola 68xx CPUs.

The previous post would seem to be an unnecessary defense of the obvious truth, except that it was a response to a statement made on a podcast by someone operating in a teaching capacity. Random statements are easy to ignore, but authoritative claims can pollute conversations for long afterward. So, I posted my correction in hopes of clearing the air. Alas, so far all indications are that the errant speaker remains unabashed. Given the situation, perhaps a bit more discussion is in order?

Overflow Example

It is important to consider what happens when values grow beyond the capacity of a single byte to store them. An arithmetic-shift-left is a multiplication by a factor of two, and there are only so many bits in a byte. Let's look at a couple of examples...

First, let's look at a 16-bit value, say the equivalent of decimal 32. The values in the A and B registers are shown below. The states of the Carry and oVerflow flags are unknown at the start of the example, but they will be shown in the indicated places as the example continues below.

          A Reg.   B Reg.   C   V
          ------   ------   -   -
         00000000 00100000  X   X

We will now perform a left-shift operation across the 16-bit value held in the A and B registers. This must be done 8 bits at a time, therefore two instructions are used. Since we are shifting left, we must first shift from B (with the highest bit of B going to the Carry flag) and then rotate into A (with the value of the Carry flag rotated into the lowest bit of A).


ASLB --> 00000000 01000000  0   0
ROLA --> 00000000 01000000  0   0

The value is exactly as expected: instead of 10 zeros, a single 1, and 5 more zeros, we now have 9 zeros, a single 1, and 6 more zeros. The left most bit (i.e. bit 7) in B was a zero, so now the Carry flag is zero. The two's complement sign of B was unchanged, so the oVerflow flag was zero after each of the two instructions.

Let's do another round!

ASLB --> 00000000 10000000  0   1

Here again, the leftmost bit (i.e. bit 7) in B was a zero, so now the Carry flag remains zero. Also, we see that the two's complement sign of B changes, which causes the oVerflow bit to be set. If we were confined to signed, 8-bit numbers then we could check for the V flag here and then branch to some error handling code. But since we are dealing with a 16-bit value we just continue the operation we already started.


ROLA --> 00000000 10000000  0   0

With the Carry flag as zero, the ROLA shifts the bits in A to the left and rotates the zero from Carry into the rightmost bit.

Let's try one more round...

ASLB --> 00000000 00000000  1   1

Now the leftmost bit in B was a one, so the Carry flag becomes a one. The two's complement sign of B changed, so the oVerflow flag is also a one. Again, if we were dealing with an 8-bit number then we could branch to some error handling code at this point. But since we are dealing with a 16-bit value...

ROLA --> 00000001 00000000  0   0

...we continue with the ROLA. This instruction again shifts the bits in A to the left, but in this case a one is rotated from Carry into the rightmost bit.

Hopefully the above demonstrates that while the arithmetic-left-shift may seem to do funny things at first glance when viewed only in terms of an 8-bit number, the truth is that a) the behavior is advantageous when dealing with 16-bit (or larger) numbers; and b) the flags indicate when the 8-bit results become problematic and therefore the flags can be used for handlilng those situations as required.

But...you may ask about negative numbers! Let's try another (hopefully less verbose) example. Let's start with the equivalent of decimal - 96:


          A Reg.   B Reg.   C   V
          ------   ------   -   -
         11111111 10100000  X   X
ASLB --> 11111111 01000000  1   1
ROLA --> 11111111 01000000  1   0
ASLB --> 11111111 10000000  0   1
ROLA --> 11111110 10000000  1   0

Unsurprisingly, after two ASLB/ROLA combinations (i.e. two left shifts within a 16-bit value) then the -96 value has become -384 (i.e. "4 time -96"). Also, please note that the oVerflow bit is always clear after the final rotate instruction in these examples. The value of the V bit after the first ASLB instruction is irrelevant for the overall 16-bit value being computed. Obviously this behavior is only guaranteed if proper two's complement encoding is observed across an entire 16-bit value.


Multiplication or Addition

So it seems reasonable to demand that if an arithmetic shift to the left is equivalent to multiplication by two, then the result of such an operation should be the same as the result of adding the starting value to itself:

          A Reg.                      A Reg.
         --------                    --------
         00001000                    00001000
ASLA --> 00010000        ADDA #8 --> 00010000

Another example, this time with a negative value:

          A Reg.                      A Reg.
         --------                    --------
         11000000                    11000000
ASLA --> 10000000    ADDA #(-64) --> 10000000

I'll stop here because to be honest, it is tiresome to continue thinking-up examples that are interesting enough to be worth typing. ASL as implemented on the 6809 "just works". Anyone that still needs convincing is either being dishonest or just plainly doesn't understand two's complement binary math.

That's Enough

As if the first blog post wasn't already too much time wasted on such a stupid controversy, I've now burnt another one. My original hope was that by illustrating the mathematical facts involved, we might avoid spreading misinformation among those in the retrocomputing community that were honestly trying to learn something about assembly language for the 6809. Consequently, the facts have been presented, demonstrated, and even illustrated across two different postings to this blog.

If you want to learn the truth, it's all here for you. Really, there isn't much more to say...keep hope alive!