The toolchain I’ve started using for development on the ZX Spectrum is as follows:

  • Visual Studio Code – Editor, with the following extensions:
    • Z80 Assembly 0.0.3 by Imanolea
    • DeZog 1.1.0 by Maziac (this is a renamed update to Z80 Debugger 0.9.1, also by Maziac)
  • ZEsarUX 8.1 – Emulator
  • sjasmplus 1.14.5 – Z80 compiler

Important: If you are running Z80 Debugger 0.9.1 or earlier, Visual Studio Code may prompt you to upgrade to version 0.9.2. This is a non-functional stub that displays a pop-up message requesting you upgrade to DeZog when you try to run/debug your project.

To do this, search for, and install DeZog from the Visual Studio Extensions Marketplace, then disable (or remove) Z80 Debugger. You will also need to make some minor changes to launch.json in the folder .vscode.

Installing and Configuring Visual Studio Code

Download and install Visual Studio Code with all the default settings.

You can optionally select ‘Create a Desktop Icon’ during Step 4.

Configuration Visual Studio Code editor:

  1. Select Command Palette from the Settings cog (bottom left of the Visual Studio Code editor).
  2. From the drop-down, select Preferences: Configure Language Specific Settings
  3. Select Z80 Assembly (z80-asm) from the drop-down list
  4. This will open the settings.json and create a “[z80-asm]” property within it.
  5. Add line 3, 4 and 6 from this example to set the tab behaviour.
	"files.autoSave": "off",
	"editor.insertSpaces": false,
	"editor.detectIndentation": false,
	"[z80-asm]": {
		"editor.tabSize": 8

Installing the DeZog Extension

This extension connects to ZXsarUX via its ZRCP protocol and enables remote debugging of the emulator from within Visual Studio.

  1. Select the Extensions icon on the left-hand side menu bar.
  2. Type in ‘DeZog’ in the search box
  3. Select ‘DeZog’ by Maziac
  4. Click on Install

Installing the Z80 Assembly Extension

This extension provides language support in Visual Studio for Z80 instructions including Intellisense colour coding and autocompletion.

  1. Select the Extensions icon on the left-hand side menu bar.
  2. Type in ‘z80’ in the search box
  3. Select ‘Z80 Assembly’ by Imanolea
  4. Click on Install

Installing and Configuring ZEsarUX

  • Download the latest Windows installer from the website (at time of writing it was
  • Extract the files to a convenient location on your hard-drive.
  • There is no installation – it just runs from this folder.
  • Click on the Application file zesarux within that folder.
  • It will start up with a command line screen, then open up the ZEsarUX emulator window.
    • The authors seem to put a fake error message at the bottom of the command line in Step 1 – this can be ignored if it says ‘just kidding’, or words to that effect.
  • You will probably get a Windows Firewall window first time you start – accept with defaults.
  • Clicking anywhere on the screen, or pressing F5, will bring up the Spectrum 128K style window.
  • This can be access from the PC using the mouse pointer.

Installing sjasmplus

This application compiles Z80 assembly language into a format that the Spectrum understands, typically machine code (a binary executable).

  • Download the executable (i.e. from the releases page
  • Open the ZIP file and copy to a folder on your PC (i.e. C:/Tools/sjasmplus)
  • Add this folder to the Path environment variable in Windows System Properties. Make sure you edit the Path in System Variables, not the one in User Variables for Administrator.
  • You *may* need to restart Windows for the path change to take effect. At the least, you will need to close and re-open any Visual Studio Code instance.
  • Open a command prompt.
  • Type in sjasmplus to test.
  • You should be greeted with the sjasmplus help text output in the command prompt.

Copying and building the source code

Download the latest source code here and follow the build instructions to test your build toolchain

Instructions for installing in MacOS / Linux

Pretty much the same as installing in Windows, with the following exceptions:

  1. ZEsarUX is supplied as a DMG package – open (mount) the package and drag the application file within into the Applications folder.
  2. The assembler sjasmplus will need to be compiled from the source code – extract the ZIP file, open up a terminal window and run the following commands to build and install. It will be added to the path automatically during the make install step.
cd <the extracted zip folder location>
make clean
sudo make install

Support Files

These are more FYI, but may come in handy when configuring your own projects

File: launch.json – Visual Studio Code configuration file for launching the debugger

Important: If you are upgrading from Z80-Debugger, change the type to dezog (line 8) and replace the entries for zhostname and zport with the zrcp section (lines 11-14).

    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit:
    "version": "0.2.0",
    "configurations": [
            "type": "dezog",
            "request": "launch",
            "name": "Z80 Debugger",
            "zrcp": {
                "hostname": "localhost",
                "port": 10000
//          "topOfStack": "Stack_Top",
            "rootFolder": "${fileDirname}",
            "listFiles": [
                  "path": "${fileDirname}/${fileBasenameNoExtension}.lst",
                  "useFiles": true,
                  "asm": "sjasmplus",
                  "mainFile": "${fileDirname}/${fileBasenameNoExtension}.z80"
            "disassemblerArgs": {
                "esxdosRst": true
            "load": "${fileDirname}/${fileBasenameNoExtension}.sna",
            "skipInterrupt": false,
            "startAutomatically": false,
            "preLaunchTask": "sjasmplus"

File: tasks.json – Visual Studio Code configuration file for compiling the source code

    // See
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
            "label": "sjasmplus",
            "type": "shell",
            "command": "sjasmplus", 
            "args": [
            "group": {
                "kind": "build",
                "isDefault": true

Snippet: Compile a SNA file with sjasmplus


Code_Start:	EQU 0x8000
		ORG Code_Start

		include "demo_scroll.z80"

		SAVESNA "Demo/build_scroll_sjasm.sna", Code_Start

Snippet: Compile a SNA file with zasm

#target sna				; use the SNA file template

; The SNA header section
#code HEADER,0,27
		defb    $3f             ; i
        	defw    0               ; hl'
        	defw    0               ; de'
        	defw    0               ; bc'
        	defw    0               ; af'
        	defw    0               ; hl
        	defw    0               ; de
        	defw    0               ; bc
        	defw    0               ; iy
        	defw    0               ; ix
        	defb    0<<2            ; bit 2 = iff2 (iff1 before nmi) 0=di, 1=ei
        	defb    0,0,0           ; r,f,a
        	defw    stackend        ; sp
        	defb    1               ; irpt mode
        	defb    7               ; border color: 0=black ... 7=white

; The slow RAM section and screen memory
#code SLOW_RAM, 0x4000, 0x4000

screen:		defs	0x1800
attrs:		defs	0x0300

; The fast RAM section (top 32K)
#code FAST_RAM, 0x8000, 0x8000

code_start:	EQU	0x8000
		ORG 	code_start

#include "demo_scroll.z80"		; include your code here

stackbot:   defs    0xfe
stackend:   defw    code_start  	; will be popped into pc when the emulator loads the .sna file


Snippet: Compile a TAP file with zasm

This build includes a minimal BASIC loader (encoded in the code) to load the CODE block and execute it (RANDOMIZE USR).

#target tap				; Use the TAP file template

headerflag:     equ     0
dataflag:       equ     0xff
tCLEAR          equ     $FD             ; token CLEAR
tLOAD           equ     $EF             ; token LOAD
tCODE           equ     $AF             ; token CODE
tUSR            equ     $C0             ; token USR
tRANDOMIZE      equ     $F9             ; token RANDOMIZE
tSAVE           equ     $F8             ; token SAVE

; use printer buffer for variables:
#data VARIABLES, 0x5B00, 0x100

; Basic loader, header:
#code PROG_HEADER,0,17,headerflag
        defb    0                       ; Indicates a Basic program
        defb    "mloader   "            ; the block name, 10 bytes long
        defw    variables_end-0         ; length of block = length of basic program plus variables
        defw    10                      ; line number for auto-start, 0x8000 if none
        defw    program_end-0           ; length of the basic program without variables

; Tokenized Basic program:
#code PROG_DATA,0,*,dataflag
; 10 CLEAR 32767
        defb    0,10                    ; line number
        defb    end10-($+1)             ; line length
        defb    0                       ; statement number
        defb    tCLEAR                  ; token CLEAR
        defm    "32767",$0e0000ff7f00   ; number 32767, ascii &amp; internal format ($0e0000llhh00)
end10:  defb    $0d                     ; line end marker
; 20 LOAD "" CODE 32768
        defb    0,20                    ; line number
        defb    end20-($+1)             ; line length
        defb    0                       ; statement number
        defb    tLOAD,'"','"',tCODE     ; token LOAD, 2 quotes, token CODE
        defm    "32768",$0e0000008000   ; number 32768, ascii &amp; internal format ($0e0000llhh00)
end20:  defb    $0d                     ; line end marker
; 30 RANDOMIZE USR 32768
        defb    0,30                    ; line number
        defb    end30-($+1)             ; line length
        defb    0                       ; statement number
        defb    tRANDOMIZE,tUSR         ; token RANDOMIZE, token USR 
        defm    "32768",$0e0000008000   ; number 32768, ascii &amp; internal format ($0e0000llhh00)
end30:  defb    $0d                     ; line end marker
; <-- Basic variables -->
; Machine code block, header:
#code CODE_HEADER,0,17,headerflag
        defb    3                       ; Indicates binary data
        defb    "mcode     "            ; the block name, 10 bytes long
        defw    code_end-code_start     ; length of data block which follows
        defw    code_start              ; default location for the data
        defw    0                       ; unused
; Machine code block, data:
#code CODE_DATA, code_start,*,dataflag

code_start:     equ 0x8000		; where the code is to be located

ORG		code_start

#include "demo_scroll.z80"		; include your code here