Spectrum Next emulator CSpect Set up

As you can see by my site, I have lots and lots of game development and programming experience https://luckyredfish.com/previous-works/, but I have little or none z80 experience. However, having learned many languages over the years I am sure Z80 is going to be a breeze.

As you can see by my site, I have lots and lots of game development and programming experience https://luckyredfish.com/previous-works/, but I have little or no z80 experience. However, having learned many languages over the years I am sure Z80 is going to be a breeze.

Confession time, throughout my coding I will be using windows as the host system, the code that I post will compile on Linux and Mac but you will have to set up your development environment and choose your own editor.

Lets go!

Firstly, we need to set up a development environment to make our coding life as easy as possible, and having missed out on two Spectrum Nexts from eBay I am having to resort to using an emulator for now.

Emulation

You will need the CSpect emulator which can be downloaded from http://dailly.blogspot.com/.

Once downloaded you will need to extract the contents to a folder on your PC and because I do loads of development on different platforms, I like to keep everything for the platform local, therefore in this case I have a SpectrumNext folder on one of my drives and in there I have created a CSpect folder and I have extracted the CSpect zip into that folder.

In the CSpect folder is a “ReadMe.txt” file with further instructions such as the need to install the Open Audio Library (openAl32.dll) which can be downloaded from http://www.zxspectrumnext.online/. Also in the ReadMe.txt it states that you need a SD disk image from the same page under “distribution images”, the emulator will work without it but having the SD image will make your emulator look like the real Spectrum Next including the nice front end menu, the file browser, more code examples, docs, utilities and more.

Me I used the Win32DiskImager to write the image to a USB stick then just copied the contents of the USB to my SpectrumNext/Sd folder as well as copying the files “enNextZX.rom”, “enNxtmmc.rom” and the “cspect-next-XXgb.img” to the CSpect folder as per instructions. 

Now are we ready?

The CSpect folder contains the emulator along with some demos, source codes and the SNASM assembler which is a great assembler, unfortunately it needs more work to enable us to use it with the DeZog remote debugger but more on that below.

So for now to give the emulator a little test, just double click the “beast.bat” or the “parallax.bat” in the CSpect folder to run one of the demos.

Oh and the “mod_player.bat” runs an audio demo and the “NXtel.bat” is like a teletext demo if they are your thing.

You can also start the CSpect emulator from the command line, and for me using -tv switch to remove the horizontal fake TV lines was a must, so in a command prompt window,  navigate to the CSpect folder and start the emulator using the following line remembering to change the XX to match the disk image you downloaded earlier.

“CSpect.exe -w3 -zxnext -nextrom -tv -mmc=.\cspect-next-XXgb.img” 

If these have all gone well and you have seen all the Spectrum Next goodness on your PC monitor, it’s now time to get down to business of setting up your development environment. As mentioned before I like to keep everything local, which means my whole project, including the art, sounds and code, this makes it easier to back up all at once and to easy to find any assets or code.

Therefore, I created a project structure on one of my hard drives like this: –

Tools are normally not related to one particular project and may be shared over multiple projects. Therefore, they have their own folder on the root of the projects folder and contain such things as photoshop scripts, or even c++ utilities written to manipulate binary data, but more on that in later posts.

Notice that none of the paths have spaces in the names, this is to make life easier when creating batch files or reading directory structures in code. And also notice that the Assets folder contains a subfolder Renders etc, as the project develops each of this folder will contain assets and possibly other folders, each with the asset name as just to make it all easy to organize. And in case you are wondering renders in this project does not mean 3D renders although i will be experimenting with that in later posts, at the moment it means final exported, or composited images.

As i mentioned before we will be using the DeZog remote debugger in order to be able to debug from visual studio code and to make that work we can’t use the snasm assembler, therefore we will be using Sjasmplus.

Sjasmplus

Download the Sjasmplus assembler from here:-

 https://github.com/z00m128/sjasmplus  

Unzip it into a folder named “sjasmplus” again within in the SpectrumNext folder, we will make use of it in a while as we need some other bits and bobs first.

DeZog

Now we have a compiler now we just need a debugger, and for this we will use DeZog. In Visual Studio Code simply install “DeZog” (maziac.dezog) from the Marketplace.

For those that are interested here is the dev page!

https://github.com/maziac/DeZog

All can be installed from the market place. Also to connect CSpect to the DeZog debugger via a socket you will need the DeZog plug in for CSpect this can be found here

https://github.com/maziac/DeZogPlugin

Unzip and drop the “DeZogPlugin.dll.config” and the “DeZogPlugin.dll” into the root folder of CSpect!

And while you are in the marketplace, there are other extensions that are not required to work with DeZog, but may help your coding experience.

asm-code-lens: Z80 assembler syntax highlighting completions, references, jump to label, renaming

z80-unit-tests: an extension to start/debug unit tests from a graphical UI

onatm.open-in-new-window: VS Code explorer context menu extension to open any path in a new window

z80-instruction-set: shows the opcode, affected flags and a description on hovering over a Z80 instruction.

z80-asm-meter calculates timings for selected instructions!

qiaojie.binary-viewer to view any open file as binary

The Code

As for the programming, my source files will be kept in a folder called “Source” again within the project folder, with the compiled results being placed in the “Output” folder and the project files being kept in the root of the project.

For this project I will be using Visual Studio Code as the Integrated Development Environment (IDE) which by the way is pronounced I D E and not ‘ide’ like I heard on you tube a short time ago.

While we are on the subject of programming I have noticed that some developers write multiple lines of z80 code on a single line, that is not my style, as my style is to try and comment my code as much as possible and to make it easy to read a year later when I want to make changes, therefore my code will be each line equals one instruction.

You can get Visual Studio Code from here https://code.visualstudio.com/

Once you have downloaded and installed Visual Studio Code, open your project folder from the File Menu by selecting Open Folder, then choose your project folder in my case it is located at

 F:\SpectrumNext\Projects\MyGameName 

but yours may be different. You should now see your project folder and its subfolders and files on the left-hand side of Visual Studio Code.

Now pressing ctrl + shift + B will build your code, however because we do not have any code of projects set up this will bring up the build menu at the top, so from this menu select “no build tasks to run …”and then select “Others …” at the bottom of that menu.

This will create a new build task file for your project from the default template, creating a new tasks.json looking like this:-

{
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
                {
                        "label": "echo",
                        "type": "shell",
                        "command": "echo Hello",
                        "problemMatcher": [],
                        "group": {
                                "kind": "build",
                                "isDefault": true
                        }
                }
        ]
}

Unfortunately Microsoft do not program on the Spectrum next so their template is not what we need, but that’s easily fixed.

We need to modify the tasks.json first, which is is a simple change for the assembler and its arguments, but we all know you will just copy and paste the whole thing, so here are the new contents of the tasks.json file :-

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
                {
    // use the sjasmplus assembler
            "label": "sjasmplus",
            "type": "shell",
    // the command to the assembler and its path has changed
    // and the argument to create a listing file is added
            "command": "F:\SpectrumNext\sjasmplus\sjasmplus.exe", 
            "args": [
                "--lst=${fileDirname}/${fileBasenameNoExtension}.lst",
                "${file}"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

Next, we need something to compile, so make a file called borders.asm in your Source folder and copy and paste this code into it.

This is my first z80 ever.

// as pointed out by Peter Ped Helcmanovsky, the OPT switches 
// must be indented so please copy this comment as well, which will
// have the correct formatting, also click the Raw button to get plain ascii.
// no copyright patricia dot curtis at luckyredfish.com


                OPT     --zxnext    
                DEVICE  ZXSPECTRUMNEXT                               // tell the assembler we want it for Spectrum Next
                ORG     0x8000
StackEnd:
                ds      127 
StackStart:     db      0        
//              org StackStart
StartAddress   
MainLoop:       ld      a,0                     // black border
                out     ($fe),a        

// Here DE counts down and D and E are OR-ed to check if the loop has completed.

                ld      de,1000                 // loop for 1000 times just wasting cycles
Loop1:          dec     de                      // take 1 off the 1000
                ld      a,d                     // move it to a register we can or with
                or      e                       // or with e to set the flags
                jp      nz,Loop1 

                ld      a,1                    // change this for different colours
                out     ($fe),a         
                
// do another loop wasting more cycles , this time larger band                
                ld      de,2000
Loop2:          dec     de
                ld      a,d
                or      e
                jp      nz,Loop2
// do the whole thing black and blue again and again
                jp      MainLoop
//end start 
// now we save the compiled file so we can either run it or debug it

                SAVENEX OPEN "Output\\borders.nex", StartAddress
                SAVENEX CORE 3, 0, 0                                // Next core 3.0.0 required as minimum
                SAVENEX CFG  0
                SAVENEX AUTO
                SAVENEX CLOSE   

Launch.json

The last part now is the launcher, so make a new file in the root of your project called launch.json and paste this code into it.

{
        "version": "0.2.0",
        "configurations": [
            {
                "type": "dezog",
                "request": "launch",
                "name": "Z80 Debugger",                
                "remoteType": "cspect",      
	// connect to the CSpect emulator via TCIP          
                "cspect": 
                {
                        "hostname": "localhost",
                        "port": 11000
                },
	// for when my next arrives i hope this works
                "zxnext": 
                {
                        "baudrate": 230400,
                        "port": "/dev/tty.usbserial"
                },
                "rootFolder": "${fileDirname}",
                "listFiles": [
                  {
                      "path": "${fileDirname}/${fileBasenameNoExtension}.lst",
                      "useFiles": true,
                      "asm": "F:\\SpectrumNext\\sjasmplus\\sjasmplus.exe",
                      "mainFile": "${fileDirname}/${fileBasenameNoExtension}.asm"
                  }
                ],
                "disassemblerArgs": {
                    "esxdosRst": true
                },
                "load": "Output/${fileBasenameNoExtension}.nex",
                "skipInterrupt": false,
                "startAutomatically": false
            }
        ]
    }

Alexey Glider has pointed out some changes, which I can not test at the present with my set up so please check the comments for his changes!

Yay, that was a bit long wasnt it, but hey, so now you should just have to open the CSpect emulator, and this time with the -remote switch set, remembering to change the XX for your image size.

CSpect.exe -w3 -zxnext -nextrom -tv -16bit -s28 -remote -mmc=.\cspect-next-XXgb.img

Then with the borders.asm file selected (focused and clicked on), then press ctrl+shift+B to build your code and then either click run or press ctrl+shift+d to open the debugger menu and then press the little green arrow start debugging your code.

Part two can be found here

Please let me know how you get on!

29 thoughts on “Spectrum Next emulator CSpect Set up”

  1. Hi it just doesnt work for me, get floating comma errors and the border asm is just black and white no opcode colours and when I try to build code it says no project

  2. Thanks, excellent guide. I had a problem with Cspect not working with the command line version of the code you gave, despite all the batch files working. I have to run it in full screen otherwise it (Cspect) just hangs – tried all sorts of other options like -60 -vsync, etc but only fullscreen works for me. e.g. remove -w3 and add -fullscreen and it works.

    Any ideas? It would be nice to not have to be full screen, but at least it works, and thats great so thanks again.

  3. Dear Patricia,

    you write:
    Launch.json
    The last part now is the launcher, so make a new file in the root of your project called launch.json and paste this code into it.
    -> Should this Launch.json goto:
    \SpectrumNext\Projects\NameOfProject\Launch.json
    or goto:
    \SpectrumNext\Projects\NameOfProject\Source\Launch.json
    ?

    Also I get problem: “Trailing comma”, “startLineNumber”: 35, “startColumn”: 40,

    Cheers,

    Luzie

    1. Hi Luzie
      The trailing comer can be removed as you can see the prelaunch task is commented out which is why there is a trailing comer, thanks for the heads up I will make the edits today. As for the location, I have found that I have had to move things about when I wanted to change up the project, the launch.json and the tasks.json live in a .vscode folder mine looks like this now.

      F:\SpectrumNext\Projects\NameOfGame
      F:\SpectrumNext\Projects\NameOfGame\Assets
      F:\SpectrumNext\Projects\NameOfGame\Output
      F:\SpectrumNext\Projects\NameOfGame\Source
      F:\SpectrumNext\Projects\NameOfGame\Source\.vscode
      F:\SpectrumNext\Projects\NameOfGame\Source\.vscode\launch.json
      F:\SpectrumNext\Projects\NameOfGame\Source\.vscode\tasks.json

      I hope this helps

      1. Hi. Building now works, but it seems to me the .vscode-Folder defaults/should be direct under Project-Folder, so I use:
        F:\SpectrumNext\Projects\NameOfGame
        F:\SpectrumNext\Projects\NameOfGame\.vscode
        F:\SpectrumNext\Projects\NameOfGame\vscode\launch.json
        F:\SpectrumNext\Projects\NameOfGame\.vscode\tasks.json
        F:\SpectrumNext\Projects\NameOfGame\Assets
        F:\SpectrumNext\Projects\NameOfGame\Output
        F:\SpectrumNext\Projects\NameOfGame\Source

  4. Another question:
    Where´s “the code” to inject NameOfGame.Nex into the .mmc-File or put it “remotely” into CSpect? I yet add this NameOfGame.nex manually into the .mmc-File, than start CSpect and start the NameOfGame.nex from Next´s browser.

  5. Great tutorial. Thank you.

    I believe that the fastest and easiest way of doing 16 bit loops in Z80 is using DJNZ (inner loop) + JP NZ (outer loop).

  6. Hi! Thank for the best tutorial.
    Please fix an error in ‘launch.json’. Must be: “asm”: “sjasmplus” (assembler name, not the full path to the exe-file).
    Otherwise, the debugger does not load the source file and labels from it. Instead, it decompiles the executable file with auto-generated labels into the .tmp directory and debug it but not source file.

  7. And one more fix:

    After changing the value of “acm” breakpoints will stop working. To make them work again, you need to change in launch.json:

    “path”: “${relativeFileDirname}/${fileBasenameNoExtension}.list”
    “mainFile”: “${relativeFileDirname}/${fileBasenameNoExtension}.asm”

    1. I have added your response to the main article suggesting people check your comments, I would have made the changes however i can not test it, how I have my set up at the moment, but awesome job and many thanks.

  8. I am glad to help.
    I would also move the generation of lst files outside the ./src directory (e.g. to ./output or ./build) to keep the sources “clean”.

  9. Thank you. It worked smoothly :). One mistake I did was to put DeZog dll to a wrong directory. Not the cspect one I ran with -remote option. But I resolved it finally.

  10. Hey just wanted to thank you for posting this up. Whilst not perfect i was able to get this up and running with a few alterations and I can have a proper play around. I think the tools have changed their required arguments, but it wasn’t too difficult to get it up and running following the error messages 🙂

    Rich

  11. I’ve got this working against v 2 of dezog and cspect 2.13

    Launch.json like this:
    {
    // Use IntelliSense to learn about possible attributes. //cspect
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    “version”: “0.2.0”,
    “configurations”:
    [
    {
    “type”: “dezog”,
    “request”: “launch”,
    “name”: “Z80 Debugger”,
    “remoteType”: “cspect”,
    “cspect”:
    {
    “hostname”: “localhost”,
    “port”: 11000
    },

    “rootFolder”: “${fileDirname}”,
    “sjasmplus”: [
    {
    “srcDirs”: [
    “D:/nextdev/Projects/platformer/Source/”
    ],
    “path”: “D:/nextdev/Projects/platformer/Output/test.sld”,
    “mainFile”: “D:/nextdev/Projects/platformer/Source/test.asm”
    }
    ],

    “disassemblerArgs”:
    {
    “esxdosRst”: true
    },
    “load”: “D:/nextdev/Projects/platformer/Output/test.nex”,
    “startAutomatically”: false,
    }
    ]
    }

    Tasks.json like this:

    {
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    “version”: “2.0.0”,
    “tasks”:
    [

    {
    “label”: “sjasmplus”,
    “type”: “shell”,
    “command”: “D:\\NextDev\\sjasmplus\\sjasmplus.exe”,
    “args”:
    [
    “–sld=D:/NextDev/Projects/platformer/Output/test.sld”,
    “–zxnext”,
    “–lst=D:/NextDev/Projects/platformer/Output/test.list”,
    “–fullpath”,
    “D:/NextDev/Projects/platformer/Source\\test.asm”
    ],
    “group”:
    {
    “kind”: “build”,
    “isDefault”: true
    }
    }
    ]
    }

    Hope that’s some help 🙂

  12. Outstanding post but I was wanting to know if you could write a litte more on this topic? I’d be very grateful if you could elaborate a little bit further. Cheers!

  13. Hi!
    Great post – noticed it’s a few years old now, so maybe development has moved on.

    But… I got as far as assembling, all good… but when I debug and press the little green button, I get a dialog generated by Visual Studio Code that says
    “Error during parsing of the list/sld file(s). ‘d:/SpectrumNext/sjasmplus/sjasmplus.exe’: SLD data version not found.”

    I have absolutely no clue what that means! Any ideas?

    / Boz.

    1. do you use the “–sld” switch on sjasmplus ?

      Here is my tasks.json and launch.json for tx-1696 I hope this helps!

      {
      // See https://go.microsoft.com/fwlink/?LinkId=733558
      // for the documentation about the tasks.json format //”–syntax=f”,
      “version”: “2.0.0”,
      “tasks”:
      [
      {

      “label”: “sjasmplus”,
      “type”: “shell”,
      “command”: “F:\\sjasmplus\\sjasmplus.exe”,
      “args”:
      [
      “–fullpath”,
      “–sld”,
      “–zxnext”,
      “–nologo”, //”–syntax=f”,
      “–lst=${workspaceFolder}\\main.sdl”,
      “${workspaceFolder}\\main.asm”
      ],
      “group”:
      {
      “kind”: “build”,
      “isDefault”: true
      }
      },
      {
      “label”: “run mdl”,
      “type”: “shell”,
      “command”: “java -jar mdl.jar

      -po -dialect “,
      “group”: “build”,
      “problemMatcher”: {
      “applyTo”: “allDocuments”,
      “fileLocation”: [
      “autoDetect”,
      “${workspaceFolder}”
      ],
      “pattern”: [
      {
      “regexp”: “^(\\w+): (.+) in (.+)#([0-9]+): (.+)$”,
      “file”: 3,
      “line”: 4,
      “severity”: 1,
      “message”: 5,
      “code”: 2
      }
      ]
      },
      “presentation”: {
      “echo”: false,
      “focus”: false,
      “panel”: “shared”,
      “showReuseMessage”: false,
      “clear”: true,
      “revealProblems”: “onProblem”
      }

      }
      ]
      }

      and my launch.json

      {
      // Use IntelliSense to learn about possible attributes. //cspect
      // Hover to view descriptions of existing attributes.
      // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
      “version”: “0.2.0”,
      “configurations”:
      [

      //————————————————————————–
      //
      // on the the real spectrum next with the register window
      //
      //————————————————————————–
      {
      “type”: “dezog”,
      “request”: “launch”,
      “name”: “On Next with registers”,
      “remoteType”: “zxnext”,
      “zxnext”:
      {
      “baudrate”: 921600,
      “serial”: “COM8″,
      //”timeout”: 2
      },
      “sjasmplus”:
      [
      {
      “useFiles”: true,
      “asm”: “sjasmplus”,
      “path”: “${workspaceFolder}\\main.sld.txt”, //list”,
      “mainFile”: “${relativeFileDirname}/main.asm”,
      “cwd”: “${workspaceFolder}”,
      }
      ],
      “disassemblerArgs”:
      {
      “esxdosRst”: true,
      “numberOfLines”: 40,
      },
      “load”: “F:\\Projects\\Komodo\\Build\\main.nex”,
      //”skipInterrupt”: false,
      “startAutomatically”: true,
      “history”:
      {
      “reverseDebugInstructionCount”: 10000,
      “codeCoverageEnabled”: true
      },
      “commandsAfterLaunch”:
      [
      “-rmv”,
      // “-LOGPOINT enable”,
      ],
      “rootFolder”: “${fileDirname}”,
      //”topOfStack”: “StackStart”,
      “smallValuesMaximum”: 513,
      “tmpDir”: “.tmp”
      },

      //————————————————————————–
      //
      // on the the real spectrum next
      //
      //————————————————————————–

      {
      “type”: “dezog”,
      “request”: “launch”,
      “name”: “On Next”,
      “remoteType”: “zxnext”,
      “zxnext”:
      {
      “baudrate”: 921600,
      “serial”: “COM8”,
      “timeout”: 2
      },
      “sjasmplus”:
      [
      {
      “useFiles”: true,
      “asm”: “sjasmplus”,
      “path”: “${workspaceFolder}\\main.sld.txt”, //list”,
      “mainFile”: “${relativeFileDirname}/main.asm”,
      “cwd”: “${workspaceFolder}”,
      }
      ],
      “disassemblerArgs”:
      {
      “esxdosRst”: true,
      “numberOfLines”: 40,
      },
      “load”: “F:\\Projects\\Komodo\\Build\\main.nex”,
      //”skipInterrupt”: false,
      “startAutomatically”: true,
      “history”:
      {
      “reverseDebugInstructionCount”: 10000,
      “codeCoverageEnabled”: true
      },
      // “commandsAfterLaunch”:
      // [
      // “-LOGPOINT enable”,
      // ],
      “rootFolder”: “${fileDirname}”,
      //”topOfStack”: “StackStart”,
      “smallValuesMaximum”: 513,
      “tmpDir”: “.tmp”
      },

      //————————————————————————–
      //
      // on the c spect emulator
      //
      //————————————————————————–

      {
      “type”: “dezog”,
      “request”: “launch”,
      “name”: “On CSpect”,
      “remoteType”: “cspect”,
      “zxnext”:
      {
      “hostname”: “localhost”,
      “port”: 11000
      },
      “sjasmplus”:
      [
      {
      “useFiles”: true,
      “asm”: “sjasmplus”,
      “path”: “${workspaceFolder}\\main.sld.txt”, //list”,
      “mainFile”: “${relativeFileDirname}/main.asm”,
      “cwd”: “${workspaceFolder}” //,
      }
      ],
      “disassemblerArgs”:
      {
      “esxdosRst”: true,
      “numberOfLines”: 40,
      },
      “load”: “F:\\Projects\\Komodo\\Build\\main.nex”,
      //”skipInterrupt”: false,
      “startAutomatically”: true,
      “history”:
      {
      “reverseDebugInstructionCount”: 10000,
      //”codeCoverageEnabled”: true
      },
      “commandsAfterLaunch”:
      [
      // “-LOGPOINT enable”,
      ],
      “rootFolder”: “c:\\Tx-1696″, //${fileDirname}”,
      //”topOfStack”: “StackStart”,
      “smallValuesMaximum”: 513,
      “tmpDir”: “.tmp”
      }
      ]
      }

Leave a Reply to Alexey Glider Cancel reply

Your email address will not be published. Required fields are marked *