RCA's MicroDOS for the CDP1802

When someone at the COSMAC Elf list noticed a diskette for the PL/M compiler for the 1802 on eBay, I was surprised that no one mentioned anything about the diskette (and Manual!) for the MicroDOS operating system. That certainly had information critical to making the PLM compiler work. I placed a token bid just in case no one else did.

After winning that bid (I also won a diskette for the BASIC1 interpreter/compiler. Not because I had any particular interest in it but I did want a disk to try out first before working on the high value one.) I then had the task of extracting the data. Fortunately, the manual had enough detail on the file system so that this wasn't too difficult. The worst problem was that my 3.5"/5.25" combo floppy drive had stopped working. I don't blame it since I hadn't used it in years. Luckily I located a cheap replacement quickly.

RCA's MicroDOS uses a 3.5" drive but it was a very early version so does not use the format typical of PCs. Instead it is single sided, double density, 70 tracks (same spacing as 80 track disks or this wouldn't work), 512 bytes/sector, and 9 sectors/track. The Linux fdutils package provides a handy tool (setfdprm) for changing the floppy drive parameters. The Linux tool dd would be the easiest way to grab the data but it encountered errors before completing the task. ddrescue was able to get more but still died before reading the entire diskette. Which wasn't a disaster because neither diskette was close to being full.


I scanned the manual and converted it to a pdf file which now can be found at bitsavers.

File Transfer


The next step was interpreting the file system so that individual files could be extracted. While it is possible to do this by hand, that would be tedious and error prone, so I wrote microdosread to automate the task. Which is useful later for getting other files.

This transfers all of the files found on the MicroDOS file system and makes no effort to prevent overwriting existing files. Use with care.

The program only has one option and that enables adjusting the length of binary files that don't use all of the final sector. If you want to see the cruft in that unused area, don't enable this option.


While the disk includes enough tools to support program development, the editor is primitive and better suited to the teletypewriter era from which it came. I would vastly prefer to use a better editor (Emacs) which means that I need some way to transfer files.

My first attempt at this failed because it turns out that MicroDOS uses a hashing function when deciding where to put directory entries. Put one where it isn't expecting it and it will never be found. Tedious searching through a disassembled listing of MicroDOS eventually revealed the hashing function. It simply added the characters in the file name with the twist being that it was an add with carry.

microdoswrite writes a single file and if there is already a file with the same name it will fail. Because of the simple way that I search for a spot to put the file this could fail due to there not being a large enough contiguous block of free space.

If you try to write a file to a disk image that is currently in use by the simulator, there could be trouble. File locking is used to detect this situation. If microdoswrite finds that the target image is locked, it asks the user if it should proceed. If yes, the sync() is called first to force buffered data out to the physical drive. This may not solve all problems.

It would be nice to have something a bit more like cpmtools but that is too much work for my tastes. These work well enough for now.

Text Files

MicroDOS uses a single carriage return as the end of line separator but it will work fine with a DOS style carriage return-line feed. Linux includes a number of programs to convert files with mac2unix being the one to change from MicroDOS to Linux. MicroDOS uses ^S (0x13) to terminate text files which can be easily added in emacs using the ^Q command.


MicroDOS requires that the RCA utility program UT71 (some sources say UT70) be present. This provides basic monitor functions so that you can examine and change the contents of memory. It also provides routines to read, write, and boot from the floppy disk drive. Fortunately there was a complete listing in the appendix of the manual. I used OCR on that to produce a machine readable version. UT71 is written for the ASM8 assembler (included on the MicroDOS disk) and is not compatible with anything else. I converted the text so that it could be assembled with the A18 cross assembler.

With that in hand it was time to try and make it run. I didn't have any hardware that would work although I do have enough parts to make something. A simulation seemed like the easiest path.

Running UT71 and MicroDOS

UT71 and MicroDOS have fairly simple hardware requirements. Besides the CDP1802 it requires 62K of SRAM, 2K of ROM located at 0x8000, a CDP1854 UART, and a CDP18S651 floppy disk controller. That last one is the hard part as the closest thing I have seen to one is a bare board. No schematics, just a block diagram.

But the IC used is the ubiquitous uPD765. That or a compatible chip is used in every IBM PC compatible. At least until they dropped floppy disk support. So with a little design effort it should be possible to create a functional simulation.

1802 Simulator for UT71 and MicroDOS

Since I have created a simulator for an old OS before (CP/M-68K) I figured this couldn't be too difficult...

I was fortunate to find an existing CDP1802 simulator written in C that was perfect for the task. It was written by Harold Rabbie and targeted at supporting a Forth system. I removed most of that support because I wasn't using it.


I modified how memory was handled to simulate the required 62K of SRAM with 2K of ROM at 0x8000. UT71 is loaded there during startup from an Intel hex format file. Of course almost any code could be loaded there instead.


The CDP1854 was simple because the UT71 code doesn't do much with it. It writes a value to the control register that can be ignored and only checks the status register to see if data is available or that it can transmit. (It turns out that some of the MicroDOS programs, COPY in particular, also check EF3 which is connected to serial data in. Checking to see if the user is pressing the break key to get the programs attention.

To keep things simple reading the status register returns a fixed value (0x81) that indicates data is available and data can be sent. Writing data is also simple. Reading data is trickier. On a Linux machine console I/O is normally in "cooked" mode where the OS provides line editing and buffering. This isn't required here because UT71 is doing that. So the termios group of functions is used to set the console to raw mode. Some signals are caught so that the terminal settings can be restored before exiting.

Another way to go which may be required depending on the particular program being run is to test to see if a character is available before returning a data available flag. This tends to result in the process just spinning its wheels doing nothing but checking for a character. Lots of CPU cycles are wasted.

Processing of ^C is kept as usual and this is the only way to terminate the simulation apart from the usual ways to kill a process.

I run this in an xterm which handles the output quite well. One thing that might cause trouble for other terminal emulators is that UT71 always outputs NULL characters (0x00) after a carriage return. This is to allow slow devices like the ASR33 to perform that operation. Otherwise there is no telling where the next character will be printed.


This required the most work. Creating a high fidelity simulation of the floppy disk controller and disk would be a lot of work. Work that would be mostly wasted. So I did just enough to keep UT71 happy. As an example, read and write commands return seven bytes of status information. But UT71 only ever examines the first byte. So anything can be returned for the remaining status. This makes status handling a lot simpler.

There is a FORMAT command on the system disk which presumably sends a format command to the uPD765. I have not implemented that because it is completely useless in a simulation. The equivalent is: "dd of=blank.img if=/dev/null bs=1K count=315". That will create a nice empty disk image to work with. I did that once and then ran the MicroDOS SYSGEN command on it. Now when I need a new blank disk image I just copy this.


The command line interface to my version of 1802sim is pretty simple. I added a "-r" option which causes execution to start at address 0x8000 rather than 0x0000. This is like the RNU signal that causes execution to start at the UT71 ROM.

You can mount up to four MicroDOS file systems using "-a disk.img" (the other three use "-b", "-c", and "-d"). The first image ("-a") must be a MicroDOS system disk with a copy of the operating system at the correct location if you want to wun MicroDOS. The other disks are optional. There is no capability to unmount a disk image and mount another while the simulator is running.

The final command line argument is the filename of the Intel hex format listing to be loaded. The code will be loaded at the addresses specified in the file but for MicroDOS to work, this must be a copy of UT71 loaded at 0x8000.

There are a few miscellaneous command line options:

The version number is new to this release. There is also a fix to the code that loads the Intel hex file that causes trouble if the data records are not strictly in address order.

A typical command line is: "./1802sim -r -a microdos.img -b work.img ut71.hex"


I compiled these on a Fedora Linux system. I have heard of trouble on some Ubuntu systems that seems to be caused by compiler settings. Mine uses a default of "-std=gnu11" while Ubuntu is complaining of things not following the C99 standard. I have no idea why any current compiler would default to that.

Using MicroDOS

There are a couple of assembly source files on the distribution disk. This is required because of the nature of the programs.

CDSBIN.CM takes an ASCII/HEX file and converts it to a binary file suitable for loading for execution by MicroDOS. The ASCII/HEX file is a very different take on assembler output. Rather than have separate listing and object output formats, you just get a listing. CDSBIN.CM reads that lising and extracts the hex bytes generated by ASM8. These are loaded into memory at the locations stated in the listing.

Normally CDSBIN.CM is loaded to an address in upper memory. If you want to create some other program to run there, an updated version of CDSBIN.CM for example, CDSBIN.SR must be altered to run at some other non-conflicting address.

This brings up another problem: what if you want to create a new image to program into an EPROM to replace UT71? CDSBIN.CM will try to write it to that location but because it is ROM, it will fail. So CDSBIN.SR must be edited so that it will create the binary image somewhere else.

disk drives

While MicroDOS nominally supports up to four disk drives and I included the ability to mount four file systems, RCA only delivered systems with two drives. So some things may not work well with the extra two drives. Some may ignore them completely. ASM8 for example normally works with drives 0 and 1. Assemble source on drive 0 and the list is produced on drive 1. Source on drive 1 results in a listing on drive 0. Those are defaults that can be overridden.

There are some hints in the MicroDOS code that suggest that at least some of it was produced by a compiler. A dumb compiler by modern standards. I can't think of any reason why a programmer would load an immediate value and then shift it left four times. A dumb compiler just might do that sort of thing.


Everything is here.


The disk image for the RCA BASIC interpreter and compiler for MicroDOS is included. The manual can be found here. At least for now.


As a bonus I have included fig-FORTH source. The original version of this was meant to be assembled using an RCA assembler which can be done yet again.

Another Way

After I published this the author of Emma used it to add MicroDos support. So if you prefer a fancier Windows based system rather than this simple command line Linux approach, that is for you.