My own ZX Spectrum emulator written in C# and Avalonia UI. It emulates ZX Spectrum 16K, 48K and classic 128K computers.
This is work in progress, I've been improving it quite a lot recently. However it is stable and usable. It can run most of the games and demos without any problems.
It's a cross-platform emulator that runs on Windows, Linux and macOS. Developed on macOS, so mostly tested on this platform. Needs more testing and feedback on Linux.
This is my hobby project which I always wanted to do. It has been a lot of fun, and quite challenging, too. ZX Spectrum was my first computer and I love it. I am planning to keep it alive since I created it for my own use and I am using it to play games and demos.
It uses several of my own libraries that I created for this project:
- Emulates classic ZX Spectrum 16K, 48K and 128K
- Time Machine: go back in time to continue from there
- Remembers the last state of the emulator
- Supports SNA, SZX, Z80, TAP and TZX file formats (zip is fine, too)
- Tape content browser
- Accurate timings, including contented memory and IO
- Floating bus support
- Multicolor screen effects in games and demos
- ULA+ support
- AY-3-8912 sound chip emulation
- DivMMC emulation
- Adjustable emulator speed
- Debugger
- Keyboard joystick emulation: Kempston, Sinclair, Cursor & Fuller.
- Audio and video recording
- And more features in progress...
Requires .NET 9 in order to build and run the emulator. Grab the latest code from the repository, build and run the emulator:
dotnet build -c Release
dotnet run --project ./src/Spectron
- Passes floatspy v0.33 (RAMSOFT) floating bus test in both 48k and 128k mode
- Passes HALT2INT v3 (Mark Woodmass) test in both 48k and 128k mode
- Passes EIHALT (Mark Woodmass) test in both 48k and 128k mode
- Passes Super HALT Invaders (Mark Woodmass) test
- Passes btime (Jan Bobrowski) test
Test results can be found in the Results directory. Test files can be found in the Tests directory.
I have created my own Z80 CPU emulator library for this project. CPU emulation is quite accurate and supports many undocumented instructions. Memory and IO contention is also supported.
When emulator is closed, it saves the current state of the emulator. The state will be restored when you start the emulator again. This behaviour can be disabled in the settings.
Tape loading is supported for TAP and TZX files (zip is ok). Three loading speeds are supported:
- Normal - loads the tape at normal speed, with border and audio effects,
- Accelerated - loads the tape running emulator at maximum speed,
- Instant - loads the tape instantly into memory. This will skip the tape loading animation and will load the tape instantly. This mode will only work for files that are using standard ROM loaders.
Tape saving is supported for TAP and TZX formats. Two saving speeds are supported:
- Normal - tape is saved at normal speed, with border and audio effects,
- Instant - tape is saved instantly reading the memory.
Tape browser is a feature that allows you to browse the contents of currently loaded or saved tape.
You can browse the blocks, their types and some basic block information.
You can select a block and load it using standard LOAD
command.
Emulator supports saving and loading snapshots in SNA, SZX and Z80 formats (can be inside zip file). It is recommended to use SZX format when saving a snapshot since it is the most robust and supports nearly all features of the emulator.
Multicolor screen effects are supported, as well as border effects. Border size can be adjusted.
Floating bus is emulated and supported by both 48K and 128K modes. Only a handful of games require this feature.
Standard beeper audio is supported, as well as AY audio (mono / stereo ABC or ACB mode). AY is by default enabled in 48K mode, but can be disabled in the settings..
Audio playback is done using Beep which I created for this project since I couldn't find any simple cross-platform audio player that would suit my needs.
Joystick emulation is supported for Kempston, Sinclair, Cursor and Fuller joysticks. External gamepads and joysticks are supported as well. But this has been only tested with few controllers I have. Controller buttons can be mapped to joystick or keyboard keys. Standard keyboard can also be used as a joystick, arrow keys for directions and space for fire.
Note
Not all controllers may work, and compatibility depends on the platform. Experimental feature.
ULA+ mode is supported and can be enabled or disabled in the emulator settings.
DivMMC emulation is supported and can be enabled or disabled in the emulator settings. It is based on esxDOS 0.8.9. You will need to use a disk image with esxDOS files. This can be an image of SD card or compatible disk image: 512 bytes pe sector, MBR partition with FAT16 or FAT32 file system.
You can use RTC.SYS file to enable RTC support. This is not required, but it will enable DivMMC to use RTC clock.
Sample disk images can be found here.
Time Machine is a feature that allows you to go back in time and continue from given time point in the past. The interval and the number of time points can be adjusted in the settings.
Audio and video recording is supported in the emulator. This is experimental feature and may not work on all platforms. You can pause emulator during the recording, however changing emulator settings during the recording may cause unexpected results.
Audio can be recorded to a file in WAV format. The format is PCM 16-bit, 44100 Hz, mono or stereo depending on the current AY mode. No external dependencies are required for audio recording.
Video recording requires FFmpeg to be installed on your system.
Video is generated as MP4 using H.264 codec at 50 FPS. Some video rendering options like scaling, border size can be adjusted in the emulator settings. Raw frame buffer data is used internally during the recording.
Processing of the recorded data starts after the recording is stopped and it can take some time. This is done in a background by converting static frames to a video stream with audio, leveraging FFmpeg.
Debugger is available in the emulator. It is a simple debugger that allows you to inspect the CPU registers, memory and disassembly. You can step through the code, set breakpoints. This is still work in progress.
- Step Over -
F10
ForCALL
,JR cc
,JP cc
,DJNZ
,LDIR
orLDDR
instructions, debugger will try to step over the subroutine. - Step Into -
F11
Debugger will step into the subroutine call or conditional jump. - Step Out -
Shift + F11
Debugger will step out of the subroutine using the current return address on the stack. So this will only work if the value on the stack contains return address.
HELP
- print help informationPRINT [expression]
or? [expression]
- prints a value of the expressionGOTO address
- sets the program counter to the address, equivalent ofPC=address
LIST [address]
- disassembles the code, if no address is provided, it will disassemble the current PCPOKE address,value
- writes a value to the memoryPEEK address
- reads a value from the memoryOUT
port,value` - writes a value to the IO portIN port
- reads a value from the IO portSAVE "filename" [address [,length]]
- saves a memory to a file in binary format starting from the optional address optional lengthR=value
- sets a register value
A B C D E H L F IXH IXL IYH IYL AF BC DE HL IX IY SP PC I R AF' BC' DE' HL'
- Decimal:
16384
- Hexadecimal:
0x4000
or$4000
or4000h
- Binary:
0b1010
or1010b
PRINT HL
GOTO PC
,GOTO 32768
LIST
,LIST 32768
POKE 16384,0x3E
PEEK 16384
OUT 0xFE,$3E
IN 254
SAVE "screen.bin" 16384,6912
A=10h
,IXH=A
HL'=DE
,IX=0x4000
,SP=0x8000
, etc.
Note
All instructions and operands are case insensitive.