Modern open-source emulator and reverse-engineering project for the Cambridge Z88.
A work-in-progress emulator for the Cambridge Z88 portable computer, written in modern C++17. This project aims to create a clean, well-tested implementation of the Z88 hardware, with a focus on accurately emulating the Z80 CPU and the custom BLINK chip.
This project is in the early stages of development. While not yet a fully functional Z88 emulator, it has a stable core that can execute a significant portion of the Z88's initial boot sequence. It serves as a technical foundation for building a complete and accurate emulation, and we welcome contributors interested in systems programming, emulator development, and retrocomputing.
The project has a solid architectural base but hardware emulation is minimal.
- Core: A
z88corestatic library contains the emulation logic, separating it from the user interface. - CPU: The Z80 core has sufficient instruction coverage to run the initial OZ operating system boot sequence without encountering unknown opcodes. It includes stable support for the
HALTinstruction andIM1interrupts, allowing the OZ scheduler to execute. The core can produce execution traces and state snapshots for debugging. - Memory: A segmented memory model is in place, allowing a ROM to be mapped into the Z80's address space in 16 KiB banks.
- Peripherals:
BLINK,Screen, andKeyboardcomponents exist as placeholder stubs with no functional emulation. - Frontends:
z88emu: An SDL2-based graphical host that provides a window for the LCD.z88headless: A command-line tool for testing and running without video output.
- Testing: The project is configured for CTest, with a foundation for test-driven development.
The immediate goal is to achieve Z80 instruction-set completeness through rigorous testing before emulating the Z88's custom hardware.
The emulator has reached a significant stability milestone:
- OZ Boot Progress: The Z80 core can execute the initial boot sequence of the Z88's OZ operating system without encountering unknown opcodes.
- Interrupt Foundation: A stable foundation for the Z80's
HALTstate andIM1interrupt handling is in place. - Scheduler Alive: The combination of core stability and interrupt handling allows the OZ scheduler to run correctly, which is a critical step toward booting the full OS.
This milestone establishes a solid baseline for implementing the remaining Z80 instruction set and peripheral hardware.
The emulator now successfully:
- Executes the OZ boot sequence without widespread unknown opcode failures
- Handles
HALTandIM1interrupt flow correctly enough to sustain stable execution - Maintains periodic timing interrupts using approximate Z80 T-state accounting
- Supports interrupt tracing, stack tracing, timing diagnostics and hotspot analysis
- Provides BLINK observability tools for reverse engineering hardware behavior
Current bottleneck:
The emulator now appears to be limited primarily by incomplete hardware behavior emulation rather than by core CPU execution correctness. Current investigation focuses on BLINK behavior, timing semantics, scheduler interaction and hardware state expectations from OZ.
This project is currently transitioning from CPU bring-up into hardware-behavior emulation and OZ reverse engineering.
The emulator is composed of several key components:
- Z80 CPU: The central processor. The current implementation is minimal and will be expanded to achieve full instruction set compatibility.
- Memory: The Z80's 64 KiB address space is divided into four 16 KiB segments. Each segment can map to a different bank of ROM or RAM, controlled by the BLINK chip.
- BLINK: The Z88's custom gate-array chip that manages memory paging, the LCD, keyboard scanning, interrupts, and power management. This is the most complex component to emulate accurately.
- ROM: The emulator loads a Z88 ROM file (not included) into memory banks.
- Screen: A 640x64 monochrome LCD. An SDL2-based window is provided, but it does not yet render the Z88's framebuffer.
You will need a C++17 compiler, CMake, and the SDL2 development library.
sudo apt update
sudo apt install build-essential cmake libsdl2-devClone the repository and use CMake to configure and build the project.
# Configure the build
cmake -S . -B build
# Compile the emulator and tools
cmake --build build --parallelTo build the test suite, enable the Z88EMU_BUILD_TESTS option:
cmake -S . -B build -DZ88EMU_BUILD_TESTS=ON
cmake --build build --parallelA Z88 ROM file is not included in this repository due to copyright. You must provide your own.
Run the SDL2-based emulator, passing the path to a Z88 ROM file.
./build/z88emu /path/to/your/Z88.romThe headless tool is suitable for automated runs, performance measurement, and debugging.
./build/z88headless /path/to/your/Z88.romExecute the CTest suite from the build directory.
cd build && ctest --output-on-failureAdvanced tracing features are planned to aid development. The z88headless tool is targeted to produce detailed execution summaries for regression testing.
Planned z88headless summary output:
Executed instructions: N
Last PC: 0x0000
Last SP: 0x0000
Last opcode: 0x00
Unknown opcodes: N
Future work will add command-line flags like --trace and --trace-unknown for more granular logging.
The high-level roadmap is structured in phases. See ROADMAP.md for more detail.
- Strict CPU Foundation: Achieve a high degree of Z80 instruction accuracy with a comprehensive test suite.
- Z80 Completeness: Implement the full Z80 instruction set, including undocumented features and accurate flag handling.
- Z88 Hardware Emulation: Implement the BLINK chip, memory banking, LCD controller, and keyboard matrix.
- OZ Boot Milestone: Reach the point where the Z88's operating system (OZ) successfully boots.
- Usability: Add features like save states, persistent RAM, and debugger tools.
We follow a test-driven, incremental development philosophy.
- Small, Focused Changes: Development proceeds via small, self-contained tasks.
- Test-Driven: Every hardware feature or CPU instruction must be accompanied by tests.
- Continuous Integration: The
mainbranch is kept stable via GitHub Actions. - Clarity Over Premature Optimization: Code should be clean, modern C++, and easy to understand.
Contributions are welcome. Please see docs/DEVELOPMENT_QUEUE.md for workflow details and available tasks.
