So I’m building a Spectrum emulation. Having done a 6502, I thought it would be fun to do something different and try to document it along the way. I’m a bit late getting going since the actual work has already progressed quite a way.
I want to build a functional emulator for the ZX Spectrum. The Spectrum was an eight bit microcomputer based on the Z80 microprocessor and was very popular in the mid eighties in the UK. I had previously written a Commodore PET emulation and wanted to see if the skills and techniques I learned there could be transferred to something else. The ultimate aim is for the emulator to be able to run at least some of the popular games that were available, like Jet Set Willy or Manic Miner.
As with the PET emulator, outright performance is not a high priority. The Spectrum had a Z80A which ran at 3.5MHz (in the Speccy – it could go up to 4MHz) and it’s easy, using modern technology to beat that. My PET emulation runs at 75MHz with very little program level optimisation. This is, however, a problem in that a lot of software of the era depends on precise timing and breaks if it is going too fast.
Before You Start
Certain tools are obviously necessary. First, decide your platform and language: I’m going with Swift running on macOS. This is because I am familiar with the tools and I really enjoy programming in Swift, to be honest. There are certain downsides to Swift: at one point I found my PET emulation was spending approximately 30% of its time doing retains and releases for Swift’s memory management. I got that down quite a bit, but it took some effort. However, as I said, speed is not a primary factor. If it was, I’d be using C. So the Spectrum emulation is being developed using Apple’s Xcode and Swift 3.1 (currently).
An assembler is also essential. I like to implement instructions by building a test case for the instruction and then writing the code to make the test case pass. For this, an assembler is not essential but is useful. If you generate the opcodes by using somebody else’s assembler, it’s an independent confirmation you got the opcode right. As a cautionary tale, using zexdoc (see below) I came across an unimplemented opcode 0xed 0x42. I looked it up and found it was reti. I implemented a test and the instruction decoding. The test passed but zexdoc went into an infinite loop. Had I used an assembler to generate the test, I would have found that reti is 0x4d and the 0x42 was meant to be sbc.
Source code control is a necessity for any project. I’m using git even though it is a pile of crap. Unfortunately, git is becoming ubiquitous thanks to the god Linus inventing it. “Git is shit” is an apt motto for it. However, SourceTree from Atlassian makes it passably usable.
Finally, somebody wrote a Z80 test suite in Z80 called zexdoc and an alternative called zexall that runs a series of tests on your emulation to make sure it conforms to the behaviour of a real Z80. The difference between the two is that zexdoc only tests documented instructions and flags, zexall tests everything. If you pass zexall, you are the same as a real Z80.