It’s time to stop talkin’ and start walkin’ …

Disk initialisation

As mentioned in the previous article, the last step is about getting the virtual disk in flash formatted and set up correctly.

But instead of uploading all the disk blocks manually (and figuring out where exactly), I’m going to let the emulator itself do the work. So the plan is to embed the contents of the system track as data inside the emulator app, and then if flash memory does not yet have a valid disk image, to initialise flash and copy the data. Here is the corresponding code:

    ie (disk.valid())
        disk.init();
    else {
        disk.init(true);
        
        // write boot loader and system to tracks 0..1
        int pos = 0;
        for (uint32_t off = 0; off < sizeof rom; off += 128)
            disk.writeSector(pos++, rom + off);

        // write 16 empty directory sectors to track 2
        uint8_t buf [128];
        memset(buf, 0xE5, sizeof buf);
        for (int i = 0; i < 16; ++i)
            disk.writeSector(26*2 + i, buf);
    }

Creating an image for the system tracks is relatively easy. Assuming all the Z80 code has been assembled properly (I used z80asm, which works on MacOS and Linux), then we’ll end up with a couple of data files. For convenience, they are also in the code repository:

These three binaries need to be turned into a C header file and stored as data inside the emulator. The trick is to first convert the binary data to a C data definition, using xxd:

cd code-z80
cat boot.com bdos22.com bios.com | xxd -i >../common-z80/rom-cpm.h

… and then include that file as const data (i.e. in flash) in the emulator with these lines:

const uint8_t rom [] = {
#include "rom-cpm.h"
};

That’s it. All the pieces have been worked out (I spent a lot of time testing it all, of course). The complete project for this “CP/M on F407” implementation can be found here.

The first power-up

Let’s connect the board, fire up the terminal emulator for access to the serial console, and upload the system to the Black F407 board (using pio run -t upload, as always).

Drum roll … here’s what appears on the serial console:

initialising internal flash

[JeeLabs Retro Z80]

64K CP/M Version 2.2

A>

Yeay - we have launched CP/M, running on a virtual Z80 inside a 32-bit ARM F407 µC!

In case you’re wondering:

And as everyone over a certain age knows: when you see “A>”, you type “dir”, of course!

A>dir
No file
A>

Haha. There’s obviously not much to see, since we don’t have any files or programs yet. Still, here’s a quick check that CP/M files work, using some of its built-in commands:

A>save 10 blah.dat
A>dir
A: BLAH     DAT
A>era blah.*
A>dir
No file
A>

References