#zx-spectrum #zx-spectrum-emulator #8-bit #retro #ay-3-8910 #file-format

spectrusty

SPECTRUSTY is a library for building highly customizable emulators of the ZX Spectrum computer series and clones

7 unstable releases

0.4.0 Dec 18, 2022
0.3.3 Dec 2, 2022
0.3.2 Jan 20, 2021
0.3.0 Nov 19, 2020
0.1.0 Sep 21, 2020

#76 in Emulators

Download history 1/week @ 2024-02-20 12/week @ 2024-02-27 2/week @ 2024-03-05 4/week @ 2024-03-12 80/week @ 2024-03-19

99 downloads per month
Used in 2 crates

LGPL-3.0-or-later

740KB
15K SLoC

S P E C T R U S T Y

Crate Docs Build Status Minimum rustc version License

What's this & Why?

There are plenty of ZX Spectrum emulators, a large portion of them are open-source, some very advanced, most are done just for fun. But except some examples of Z80 CPU emulators, each of the ones I've seen is a complete program, with code that is not easy to build upon or port to another system. Most that I found is written in C, a lot of them in Java, and even some in javascript.

The notable example is Free Unix Spectrum Emulator written in C with pleasantly readable code. The components of the emulator are nicely separated, with high cohesion but unfortunately, here and there sprinkled with a vast range of global variables. However, I can imagine that with sufficient patience and skill you can build successful projects upon such a foundation.

SPECTRUSTY was built from scratch, partly for fun, but also as a Rust abstraction testing facility. I needed some theme to dive deep into the Rust OO model for educational purposes, and have chosen ZX Spectrum because it's such a simple machine thoroughly reverse-engineered and documented. It was also the first computer that I've owned. From the start, the goal was not to build a complete emulator program, but rather a library, upon which you can relatively easy build emulators that suit your particular needs.

In this library, every component is a separate entity that doesn't know anything about the world and realizes its purpose via trait interfaces. Most of the structs are defined with generic parameters that can be substituted by the complementary components which complete or extend their base functionality.

To create your emulator with SPECTRUSTY first, you need to choose the components you need, then choose the way to glue them together, and then realize their functions via trait methods.

Caveats

Because of the heavy use of polymorphism and static dispatching the separate code is being created due to monomorphisation for every set of spectrum chipset, device set, and the CPU. This may result in a rather large output code if you want all these sets to be available at run time. On the other hand, the produced code is quite efficient.

How To

Because the best way to learn new things is by example, I invite you to see the tutorial.

Several examples of what can be built with SPECTRUSTY can be also found in the examples directory, provided as separate crates.

Contribution and feedback

Because of ZX Spectrum's popularity, there is a lot of technical information available from various sources. On the other hand, the certainty of the information has been deluded because some of the resources are contradicting each other. Unfortunately, my access to the real hardware is very limited - I'm a proud owner of a single TC2048, that is still working today. If you'd find something that is being emulated incorrectly, please don't hesitate to submit an issue.

Features

Below you'll find the featured facilities of the library and its roadmap.

CPU

The Zilog's Z80 CPU emulation is performed via a separate z80emu crate that can emulate NMOS, CMOS, and BM1 variants of the CPU.

Core chipset models

The video and contention timings for the Sinclair/Amstrad machines are thoroughly tested and at least match those of the Fuse emulator. The SCLD implementation has no separate timings implemented yet, so for now it can borrow the timings from Sinclair models.

  • - Ferranti ULA (Uncommitted Logic Array) for Sinclair ZX Spectrum 16k/48k (PAL and NTSC timings).
  • - Ferranti ULA 128 for Sinclair ZX Spectrum 128k/+2.
  • - Amstrad Gate Array for ZX Spectrum +2A/+3.
  • - (partial) SCLD by NCR Corporation for Timex TC2048/TC2068/TS2068 series (uses Ferrant ULA's contention at the moment).
  • - ULAplus screen and color modes (including grayscale) as an enhancement wrapper for other chipsets.
  • - Chloe for ZX Spectrum SE (272kB RAM).
  • - Russian Pentagon and Scorpion models.
  • - Slovak's Didaktik series.
  • - Polish Elwro 800 Junior (if I ever find some serious specs).

Emulated chipsets' original bugs and features

  • - "Slow" memory contention.
  • - Partial port decoding as on original machines.
  • - Floating bus when read an unused port on Ferranti ULA chipsets.
  • - Keyboard issue (2/3/none/scld) on ULA port read - determines the EAR IN bit value when there is no tape signal.
  • - EAR/MIC output allows for sound emulation from both sources.
  • - Ferranti ULA "snow" bug interference - when the register I is set to a contended page (see Robocop 3 on 128k model or Vectron). However the exact timings of the RFSH influence on the interference is not currently known, so it is an approximation. The bug emulation also does not hang Spectrum as on real machines.
  • - Early/late timing schemes.
  • - I/O port contention matches that of the Fuse emulator. Most of the emulators assume port read/write is performed at the last IO cycle - T4, however the IO_IORQ signal of Z80 is active between T1 and T4 and Fuse port read/write is timestamped at T1. This is especially important for exact emulation of border effects.
  • - Reads from port 0x7ffd cause a crash on ULA 128 as its HAL10H8 chip does not distinguish between reads and writes to this port, resulting in a floating data bus being used to set the paging registers.

Emulated peripherals

  • - Tape signal interface as a pulse iterator (input and output).
  • - AY-3-8910 sound processor and generic I/O A and B ports (for 128k / Melodik / FullerBox / Timex).
  • - 128k RS-232 port as an AY-3-8910 port attachement.
  • - 128k keypad as an AY-3-8910 port attachement.
  • - +2A/+3 centronics port.
  • - Interface 1 ROM extension.
  • - Interface 1 - microdrives (including IN 0 bug).
  • - Interface 1 - RS232.
  • - Interface 1 - ZX-NET (with the real time UDP packet encapsulation!).
  • - Joysticks: Kempston, Fuller, Sinclair, Cursor.
  • - Kempston mouse.
  • - +3 floppy disk drive
  • - other floppy drive systems (TR-DOS, DiSCIPLE, +D, FDD 3000, ...)

File formats

  • - .SNA format loader/saver
  • - .Z80 v1/2/3 format loader/saver
  • - .SLT
  • - .SZX
  • - .TAP format reader/writer, pulse encoder/decoder
  • - .TZX format reader/writer, pulse encoder/decoder
  • - .PZX format reader/writer, pulse encoder/decoder
  • - .RZX format reader/writer, recorder/player
  • - .MDR microdrive format reader/writer, filesystem browser
  • - .SCR format loader/saver
  • - .ZXP format loader/saver
  • - .AY player format parser

Rust Version Requirements

This version of spectrusty requires Rustc version 1.59 or greater due to dependent crates usage of Rust 2021 Edition and other API stabilized in this version.

The SPECTRUSTY library is available under the terms of the GNU LGPL version 3 or later.

Examples, tests, and benchmarks are available under the terms of the GNU GPL version 3 or later.

ROM files found in the resources directory are made available under different terms.

Dependencies

~1–35MB
~508K SLoC