/maple-2

An Apple ][ emulator written in Rust

Primary LanguageRust

An Apple // emulator in Rust

Introduction

Maple // is an Apple ][ emulator written in Rust. It was initially inspired by my Kotlin Apple ][ emulator but diverged quite a bit after a while and by now, it supports a lot of additional features (double hi resolution, write, etc...).

Maple // has a specific focus on being developer friendly by exposing a lot of internal details on the emulation, e.g.

  • A convenient file picker view that lets you quickly insert disks in the drives of your choice
  • Support for disk formats (dsk, woz) and hard drive / SmartPort (hdv). Try the Total Replay image!
  • A Nibble view that shows you the raw nibbles contained on the current track
  • A track map showing you which tracks are standard (green dot) and non standard (red dot)
  • A disk view, so you can visualize the head as it moves across the disk
  • A debugger

Building and running

$ cargo run -r

Protected disks

As of this writing, Maple-2 boots the following protected woz disks:

  • Basic protections
    • Bouncing Kamungas
    • Commando
    • Planetfall
    • Rescue Raiders
    • Sammy Lightfoot
  • Cross track sync
    • Blazing Paddles
    • Take 1
    • Hard Hat Mack
    • Marble Madness
  • Half Tracks
    • The Bilestoad
  • More advanced protections
    • Dino Eggs
    • Crisis Mountain
    • Miner 2049er II
  • Fake bits
    • The Print Shop Companion
  • Data latch protection
    • First Math Adventures - Understanding Word Problems
  • Bit timing
    • Border Zone
  • Spiradisc and quarter tracks
    • Frogger
    • Craze Maze Construction Set
  • Ultimate protection
    • Prince of Persia (E7 + RWTS18)

Gallery

Text (40 columns) Text (80 columns)
King's Quest (DHGR) Airheart (DHGR)
Disks view Debugger view
Nibbles view Drive view
Total Replay (hard drive) Prince of Persia
Aztec Apple Galaxian
The Black Cauldron Bouncing Kamungas
Conan Ultima V

Documentation

When you launch Maple // for the first time, you will have to select a folder that contains Apple ][ disk images (.woz and .dsk). This directory will be read recursively. After this, select the disks of your choice, place them in the drive 1 or 2, and press the Reboot button.

Views

Disks

Once you have selected a directory, all the disks found in that directory and below will be displayed in that window. Just press "Drive 1" or "Drive 2" to insert that disk in the drive. You can use the filtering box on the side to narrow down the disk you're looking for.

Nibbles

This view shows you what was found on the disk. It's made of two parts:

  • At the top, the map of all the tracks (quarter tracks really) shown either in green (standard track) or yellow (non-standard track, most likely protected). A "." indicates an empty track (will return random bits). You can click on any of these tracks to take a look at its nibbles
  • Below is the actual buffer of bits, corrected to show you nibbles. Maple // will attempt to locate the markers for address and data in order to facilitate identifying where these tracks start. This will only produce highlighted results for standard markers (D5 AA 96 / DE AA and D5 AA AD/DE AA).

Drive

THis view shows you a graphical representation of the travels of the disk drive. It is updated in real time as the disk drive reads more tracks.

It's a great way to visualize copy protections in action. For a regular, unprotected disk, you would expect to only see white dots. As soon as you see orange (half tracks) or red (quarter tracks) show up on this graph, it means you are dealing with a protected disk.

Tests

cargo test will run Klaus' functional suite for the 6502, which guarantees that the emulation is "mostly" correct. Additionally, my Kotlin emulator boots a few Apple ][ games that use precise cycle timing for their protection, so I'm reasonably confident the cycle counting is correct as well, including the handling of page crossing and "branch taken", but there are no tests for cycle counting.

This code is pretty rigid right now, it needs to add some kind of listener support for the memory reads and writes in order to be usable in an emulator, but this should be pretty trivial to add.

Harte's processor tests

The harte/ directory contains a TUI runner for Tom Harte's 6502 tests:

cd harte
cargo run --release
harte.mp4

Developer note

I made the graphical back-end as agnostic as I could since there are so many Rust crates that let you display pixels on the screen, and as a proof of concept, I experimented with two different graphical backends: iced (which is the current Maple // GUI/graphics library) and minifb). Here is what the experiment looks like:

emulator-minifb.mp4