Friday, 12. December 2025

Playing with CP/M – part 1

[This article has been bi-posted to Gemini and the Web]

Earlier this year I wrote an article explaining how to use the CP/M operating system which has been the dominant OS of the 8-bit era of microcomputers. The article was well-received and some commenters asked for more. While I originally had other plans, a lack of time for a bigger project during November made me come back to my leftover notes and turn it into this follow-up. Today we'll go beyond the very basics and look at actually making good use of this fascinating old OS rather than just using CP/M for the sake of it! Well, more precisely we'll do the final preparations to start playing around with CP/M software in the second part.

If you've come here without knowing how to use CP/M, you may want to read the previous article which covers the basics:

(August 2025) A gentle introduction to CP/M

And if you want to know a bit more about the line of operating systems of the CP/M family (the various versions, the multi-user version MP/M or the networking versions), you can have a look at two articles I wrote last year:

(December 2024) A journey into the 8-Bit microcomputing past: Exploring the CP/M operating system - part 1
(December 2024) A journey into the 8-Bit microcomputing past: Exploring the CP/M operating system - part 2

Getting Started

We have (emulated) CP/M up and running as well as a basic grasp of how to work with the OS. So what's next? Historic operating systems are interesting, but CP/M didn't exist as an end in itself, of course. It was meant to enable the user to run programs on the computer, and to do that in a relatively convenient way (providing a filesystem and various utilities). That means the next logical step is to move beyond the core OS and use it to actually do something.

In the previous article, we explored CP/M 2.2, and we're going to stick with it. It's (somewhat) familiar ground now, right? The most pressing limitation that we face if we want to use CP/M is memory. Not only main memory (RAM) is precious (up to 64k), but disk space is scarce, too. With the 250 kilobyte 8" single side, single density (SSSD) disks that were used on most platforms, each drive doesn't exactly provide a lot of space. The z80pack versions of CP/M 1.3 and 1.4 come with only one system floppy while versions 2.2 and 3 come with two. Let's expand on that a little.

We Need More Disk Space

The z80pack emulator comes with a utility to create new disk images, *mkdiskimg*. It's really simple: just execute it and give it a drive letter as the command-line argument, and it will place a new disk image in the current directory. If you run it without arguments (or invalid ones), it will print usage info:

% mkdiskimg
usage: mkdskimg a | b | c | d | i | j | p

Since we want a third floppy for CP/M 2.2, we could simply do this:

% mkdir -p ~/.cpmsim/disks/custom
% cd ~/.cpmsim/disks/custom
% mkdskimg c

The result is a file named 'drivec.dsk' and it's 250k in size. We could also have used 'a' as the argument, then the file would be named 'drivea.dsk'. The fresh disk images would be identical, so it's really only a naming thing - mostly! There's one thing you need to know, though: a - d are meant to produce _floppy disk images_ for CP/M, whereas the other letters generate _hard disk images_. If you choose 'i' or 'j', it will result in an empty 4 *megabyte* HDD image, giving us lots of space (by the standards of the time CP/M was popular) to work with. Finally 'p' is special. It also creates a HDD image, but one for a drive that is a whopping 512 MB in size!

Of course, no drive that large existed back in the day. However that's the limit that was chosen for CP/M 3. Thus the OS can address a maximum of 512 MB on a single HDD and it's actually possible to use such a gigantic image. Keep in mind, though, that this is version 3 only. With version 2.2 we're stuck with the 4 MB drives (which is still a lot better than the 250k floppies).

After we've generated an image for the floppy in drive C, we can generate an HDD image as well and then softlink them to where the emulator script (if you're not using the Ravenports version, adjust the path to your configuration) expects them:

% mkdskimg i
% ln -s ~/.cpmsim/disks/custom/drivec.dsk ~/.cpmsim/disks/drivec.dsk
% ln -s ~/.cpmsim/disks/custom/drivei.dsk ~/.cpmsim/disks/drivei.dsk

Let's fire up CP/M and check if it worked:

% cpm22
A>stat c:
Bytes Remaining On C: 241k
A>stat i:
Bytes Remaining On I: 4048k

Excellent! We've _vastly_ expanded on the available storage capacity (previously the remaining space of floppy a and b combined was less than 180k). If you need even more space, you can create images for d and j. Just don't try to use 4M images for drives a - d, you will still only get 241k usable space.

Putting the Drives to Use

The simplest way of putting something on our shiny new drive I is, of course, just copying something there. The previous article covered the somewhat quirky syntax of PIP, so let's use it:

A>pip i:=a:bye.com

Another is to create a text file with an editor. CP/M's editor is ED, but it might not exactly meet your expectations. The reason for this is that ED is a _line editor_. It allows you to edit a file with line-based operations---which is rather confusing if you are used to today's editors.

If you're in love with Unix' editor of the same name (which works differently, though!) or you think that it's completely unnecessary to always see the file contents while you edit it (it's in your head, anyways, right?), feel free to explore ED in-depth. I would recommend reading the respective manuals. Should you just be curious what it's like, you can have a look at an older article that I wrote where I try out ED among other things.

I don't mean to say that ED is terrible. In fact I think that it's a surprisingly powerful application. And if you take into consideration that not all CP/M machines had a monitor but might use a so-called hardcopy terminal, a line-oriented editor makes a lot of sense. Always printing out a few dozen lines whenever you make a change, is not practical at all. Still I assume that you're using a monitor and read the output on a screen. And that's where visual editors come into play. They are a game-changer when it comes to convenience and ease of use.

One particularly popular program on CP/M was MicroPro's WordMaster. It was commercial software, so you had to buy it. However the author of the z80pack emulator was kind enough to simply provide it on the first system floppy (thus *massively* lowering the bar to exploring CP/M). Since it's readily available, let's give it a try, shall we?

A>wm i:test.txt

It creates a new file 'test.txt' on drive I. Unlike with ED, you can just type away immediately. When you're done, press ESC which enters command mode (indicated by the asterisk prompt). Type 'e' there to save and end the editing session.

I'm going to edit the file again real quick and make some changes to what I wrote earlier. Now let's check if that worked:

A>type i:test.txt
This is just a simple text file written with WordMaster.
It even has more than one line!
A>type i:test.bak
This is just a simple text file.
But it has more than one line!

As you can see, the editor automatically created a backup (.bak) file when I saved the changes. To close without saving, use 'q' instead of 'e' on the asterisk prompt, BTW.

WM is a topic on its own and would deserve a whole separate article. It has a lot of functionality stuffed into the 11k program and it's not hard to see why it was loved so much back in the day. If you want to use it, it makes sense to learn a couple of basic movement key combinations - for example CTRL + E moves the cursor one line up and CTRL + X moves it one line down. By default the editor is in overwrite mode, so when you start typing, you're replacing what was on that line before.

Strictly speaking, this is all you need to be able to do the most basic editing. It's definitely worth to read the help and pick up some more combinations as they allow for pretty convenient and efficient editing. WM is not half bad! And since it was so popular, a lot of other programs simply used the same movement commands rather than inventing the wheel over and over again (which is a really good idea!).

Sharing Files

This is all nice and fun, but when using a historical system like this, sooner or later you will want to exchange files between the guest and host operating systems. We will explore two different ways of doing this: using native z80pack functionality and with external tools.

The z80pack Way

The z80pack emulator actually has functionality built-in to do this, and it's quite easy to use. On the second system disk, there are the two programs 'r' and 'w' (for _read_ and _write_). The former can copy a file from your host system into the guest OS while the latter writes a file from CP/M to your host OS' filesystem.

For example you could transfer the WordMaster help file from the guest to the host like this:

A>b:w wm.hlp

>

File WM.HLP written to host PC

Of course you have to mind the limitations that apply to filenames---just because "ümlauts totally rule!" is a perfectly acceptable filename on Unix (even though it's gross), don't even think of doing this to poor CP/M. The exchange with the host works in the way that the file written to (or read from) will be in the present working directory (i. e. from where you ran the emulator).

To copy the file 'testfile.txt' from the host system to CP/M, you can do this (provided the file exists in the directory from where you launched the emulator):

I>b:r testfile.txt

>

File TESTFILE.TXT read from host, written to CP/M

Using the CPMTOOLS Utilities

However there's another way of interacting with the CP/M disk images. Just install _cpmtools_ (they are available via Ravenports in case your OS / distribution of choice doesn't package them)!

This set of tools is extremely useful as you continue your journey of exploring CP/M and I highly recommend getting familiar with them. Let's start with the most basic one, _cpmls_. It works like this:

% cpmls ~/.cpmsim/disks/driveb.dsk
0:
bios.hex
bios.z80
boot.hex
boot.z80
bye.asm
bye.com
cls.com
cls.mac
cpm64.sys
r.asm
r.com
reset.asm
reset.com
speed.c
speed.com
survey.com
survey.mac
sysgen.sub
w.asm
w.com

As you can see, it lists all the files that are in _user area 0_. The command supports some switches which can for example change how the file listing is formatted. For example use '-d' to get CP/M-like output:

% cpmls -d ~/.cpmsim/disks/driveb.dsk
BOOT HEX : BYE ASM : CLS MAC : SURVEY MAC
R ASM : CLS COM : BOOT Z80 : W ASM
RESET ASM : BYE COM : SYSGEN SUB : BIOS HEX
CPM64 SYS : SPEED C : BIOS Z80 : SPEED COM
SURVEY COM : R COM : RESET COM : W COM

Have a look at the manpage (all of cpmtools' manpages are excellent!) to find out what other options are available and try them out to find the one you like best. Of course it's also possible to to limit the results (mind the quotes - it's a pattern for cpmls, we don't want shell globbing for the current directory!):

% cpmls ~/.cpmsim/disks/driveb.dsk '*.asm'
0:
bye.asm
r.asm
reset.asm
w.asm

But there's one more thing that needs to be mentioned. You need to mind the _type of disk_ your accessing. Here's an example without it:

% cpmls ~/.cpmsim/disks/drivei.dsk

Why is there no output? Haven't we copied BYE.COM and created a text file on that drive? Yes, we have. But the problem is that this is not a standard 250k floppy image but a 4MB HDD one. CP/M's disk format is pretty primitive. For example, it doesn't record the type or layout information! Therefore there's nothing that the _cpmls_ tool could detect there. Which in turn means that whenever you're using a non-standard image type, you have to specify it.

CPMTOOLS and Disk Formats

To find out which ones the program knows about, have a look at "${prefix}/share/diskdefs" as the manual suggests. If you do and you're shocked that it contains almost 150 (!) disk definitions - well, these were the days when that technology was still new. It was much later that vendors eventually settled on standards. In the chaotic time before that, every vendor simply created their own format (or multiple formats if only one would have been too easy!).

Let's try again, this time with specifying the right disk format:

% cpmls -f 4mb-hd ~/.cpmsim/disks/drivei.dsk
0:
bye.com
test.bak
test.txt

That looks much better, doesn't it?

The cpmtools utilities can do more than just list files contained in images, though. You can for example remove files in an image right from your Unix host's shell:

% cpmrm -f 4mb-hd ~/.cpmsim/disks/drivei.dsk '*.bak'

The command returns silently. So did it work?

% cpmls -f 4mb-hd ~/.cpmsim/disks/drivei.dsk
0:
bye.com
test.txt

Yes, it did! But even better, there's also _cpmcp_ which can be used to copy files to or from CP/M disk images. We can for example copy the BYE transient to the /tmp directory on the host machine like this:

% cpmcp -f 4mb-hd ~/.cpmsim/disks/drivei.dsk 0:bye.com /tmp

As you can see, this supports user areas. This means we can copy something onto a CP/M disk and into a specific user area without first having to get PIP there! The utility involves some checks, so as expected, trying to copy a file over that has an invalid filename by CP/M's standards, results in this:

% cpmcp -f 4mb-hd ~/.cpmsim/disks/drivei.dsk edelib___std.log 1:
cpmcp: can not create 01edelib___std: illegal CP/M filename

What however does work is changing the name:

% cpmcp -f 4mb-hd ~/.cpmsim/disks/drivei.dsk edelib___std.log 1:edelib.log

Let's check that to make sure it worked:

A>i:
I>user 1
I>dir
I: EDELIB LOG

Indeed! That's pretty nice. When using _cpmcp_ for text files, though, you usually want to use the '-t' switch. It's used to convert text files between the conventions of CP/M and Unix. Otherwise your line breaks might not work as intended.

There are some more programs among cpmtools that allow for setting CP/M 3's file attributes, creating new disk images (more flexible than z80pack's _mkdskimg_) and even a simple fsck for CP/M filesystems.

Conclusion

This article covered working with disk images as well as how to transfer files between your Unix-like host system and the emulated CP/M system. This is necessary to be able to eventually run software that doesn't come distributed with the z80pack emulator. It also touched on using WordMaster for a more user-friendly editor.

What's Next?

In the next part we'll finally take a look at some more CP/M software and even play some games.

BACK TO NEUNIX INDEX