The computer above has helped me learn programming and play many video games throughout my childhood. It is a Romanian ZX Spectrum clone called Cobra, and was built by my uncle. It features a keyboard superior to both Spectrum and Spectrum+'s. A small Romanian-made TV ("Sport" model) served as the monitor. Programs were loaded from cassette tape through a Russian-made player.
I decided to emulate it and thus zxian was born.
zxian is a ZX Spectrum emulator written in C, using SDL2 for graphics, input/output, and audio. As with my other projects, the source is available for download. I built it with Visual Studio Community 2019 (with C++ core features installed).
I hadn't coded in C in a while and it was very enjoyable. After several years of projects mostly in assembly language, C feels like a smarter assembly language, with really useful macros. I considered C++, but found no benefit from object orientation for this project, so I wrote in pure C.
zxian v1 emulator (for Windows)
- unzip anywhere and run zxian.exe. The included readme file has more information.
zxian v1 source
- load the solution file in Visual Studio to build zxian yourself.
zxian supports the popular Kempston joystick, which is mapped to the arrow keys, with the left control key acting as fire.
As of this version, only SNA format snapshots are supported. zxian is completely command-line driven. If started with no arguments, it will simply boot into Sinclair BASIC.
Development began with a 50Hz (the Spectrum was made in Britain) timer-invoked routine which read memory and drew pixels following Spectrum's questionable video memory layout. This was followed by writing the functionality for reading Z80 instruction opcodes, with support for all of Z80's opcode prefixes.
Then came seveal weeks of microcode development, where each Z80 instruction was implemented and tested. The Z80 CPU manual was a good resource for findings details on how each instruction behaved, what flags it affected, etc.
There is a large number of undocumented Z80 instructions, which I also implemented.
This was followed by support for interrupts and ZX Spectrum-specific areas such as hardware ports.
Seeing the image above was a great milestone.
I think that one difficulty with emulator development is that you have access to low-level tests (you can manually test each instruction individually) and to high-level tests (the Sinclair ROM, or a game) - but not much in between.
This means that you keep testing at a very low level, as you progress, but can only hope that when everything has been written, the ROM (or game) boots and works.
I enjoyed developing the sound capability of zxian, because I hadn't done anything like that before. While the SDL2 library abstracts the audio hardware of the host computer, it still requires a constant stream of data (audio samples) to function. The difficulty is that these samples have to be provided in real time.
The challenge I faced was that the Z80 CPU finishes a video frame's worth (20ms) of computation in much less time than the 20ms. Additionally, how much real time the Z80 actually needs varies from host computer to host computer, and is therefore unknown and unreliable.
However, the amount of CPU clock cycles (or tstates) that the Z80 is allowed to perform during each 20ms interval is constant, irrespective of the host machine. That specific amount of clock cycles might be performed in 9ms on one host computer, and in 5ms on a much faster host computer.
My solution was to sample the state of the speaker at fixed clock cycle intervals during the Z80's active time and write them to a buffer, such that 20ms's worth of Z80 CPU time yielded 20ms worth of real-time audio data.
Conversely, the SDL audio layer read from a second buffer, which was full of audio samples accumulated during the last video frame (20ms).
At the end of each video frame, the two buffers are swapped - the read buffer becomes the write buffer and vice-versa.