Close

Entry 7: The Virtual Machine

A project log for Aiie! - an embedded Apple //e emulator

A Teensy 4.1 running as an Apple //e

jorj-bauerJorj Bauer 02/20/2017 at 00:210 Comments

(This post refers to git commit 8e155646c9843c095ee4733481913707f49bfe1d.)

This one is kinda big, and I'm going to just give a high-level overview. You can go dig through the weeds yourself, or send me questions that I'll probably ignore for far too long before ignoring you. (Sorry about that, it's not you.)

The virtual machine architecture is broken in half - the virtual and physical pieces. There's the root VM object (vm.h), which ties together the MMU, virtual keyboard, and virtual display.

Then there are the physical interfaces, which aren't as well organized. They exist as globals in globals.cpp:

       FileManager *g_filemanager = NULL;
       PhysicalDisplay *g_display = NULL;
       PhysicalKeyboard *g_keyboard = NULL;
       PhysicalSpeaker *g_speaker = NULL;
       PhysicalPaddles *g_paddles = NULL;

There are the two globals that point to the VM and the virtual CPU:

       Cpu *g_cpu = NULL;
       VM *g_vm = NULL;

And there are two global configuration values that probably belong in some sort of Prefs class:

       int16_t g_volume;
       uint8_t g_displayType;

I've done most of the testing on my Mac, rather than on the device itself - it's easier, faster, and has a full debugger - so there's a Makefile here that will generate an emulator under macOS 10.11.6 with Homebrew and OpenCV installed:

  $ make opencv
  $ ./aiie-opencv /path/to/disk.dsk

As the name implies, this requires that OpenCV is installed and in /usr/local/lib. I've done that with Homebrew like this:

  $ brew install opencv

"Why OpenCV?" you might ask. Well, it's just because I had code from another project lying around that directly manipulated OpenCV bitmap data. It's functional, and the Mac build is only about functional testing (for me). I just needed a window that I could draw in!

A little bit about the file structure: the code is separated in to three subdirectories. There's 'util', which holds the 6502 functional test harness and the script to generate the ROM headers; the 'apple' directory, which contains the Apple //e VM code; and the 'opencv' directory, which holds all of the Mac-specific code. The remainder of the code is splayed out in the project root: the CPU, File manager, base Physical and Virtual object definitions, etc.

When the main program starts - in opencv/aiie.cpp - main() creates the physical and virtual objects (a DummySpeaker, OpenCVFileManager, OpenCVDisplay, openCVPaddles, Cpu, AppleVM, and OpenCVKeyboard); wires them together; and then starts them running.

The 65C02 CPU runs in a dedicated thread (cpu_thread) which executes at least 24 cycles of processor time; calls some maintenance functions to keep the various pieces of virtual hardware working; and then calculates how long it needs to sleep, based on how many CPU cycles really executed and what the clock time was when it started.

It's this sleep that keeps this running at 1023 kHz. Take out the nanosleep() call and this will run flat-out as fast as it can. Which, on modern hardware, is ridiculously fast. And if you want it to run at some other speed - perhaps the 8MHz that the //c could brag about - you'd change CYCLES_PER_SECOND from "1023000UL" to "8184000UL" (or whatever speed you want).

While it's running, the VM will spit out lines of text like this:

hit: 2156381; miss: 0; pct: 0.000000
hit: 4224999; miss: 0; pct: 0.000000
hit: 6233853; miss: 0; pct: 0.000000

If you ever see "miss" become non-zero, it means it's taking too long to run the instructions and isn't sleeping at all. Your hardware is too slow for this implementation, at this speed. (I'd be surprised to see that happen.)

There's no sound here - as you might have guessed from the name "DummySpeaker". And there's no support for the joystick buttons. But everything else works (including joystick position, which is emulated by cursor position within the window).

Next up: time to get it running on the Teensy!

Discussions