This page contains software for the ZX Spectrum Next, written and shared by former Crash magazine Tech Tipster Simon N Goodwin.
The files on this page may be freely distributed on a non-commercial basis so long as the author's name Simon N Goodwin is acknowledged and a link to this page is included with any redistribution.
Please contact Simon if you have any comments or changes to these programs which you would like to share. Click here for Simon N Goodwin's home page and contact information.
Nextramon.bas - a NextBASIC disassembler and memory monitor, capable of disassembling all the Z80N instructions including Nextras, Floating point calculator (FPC) language codes, Sinclair reports and Interface 1, GDOS and Unidos hook codes. Memory areas can also be displayed as text, hex or decimal.
This is a major update and bugfix for Spectramon, a Z80 disassembler written in ZX BASIC first published in ZX Computing magazine. Simon wrote the original on his new Spectrum in 1982, in a three-day marathon attempt to get to grips with keyword entry and adapt from TRS-80 BASIC.
The original program was documented and listed in the April/May and June/July 1983 issues of ZX Computing, and later sold on cassette by Argus Press Software. Just for good measure, Argus also ran it, over nine pages, in the Spring 1984 issue of Personal Software magazine. An extended version for Sam Coupe appeared in issue 33 of the Sam Supplement disc magazine.
The Next version is faster (though still not as fast as a disassembler written well in machine code - select 24 MHz clock speed or type RUN AT 3 before running it, to take full advantage of the Next's optional CPU acceleration). It still gives nonsensical results, like any disassembler, if you disassemble memory that does not contain valid Z80 code. You can avoid this by checking with the A or N options. Adresses may be entered in decimal or hex - add a H suffix if the hex address contains no letters, to avoid ambiguity.
Nextramon automatically switches between Z80N and FPC machine language byte encodings after a RST 56 instruction which switches the Spectrum to expect FPC code, but sometimes FPC code is entered directly via a branch from other FPC code. The F option allows you to start disassembly in FPC mode, whereas D defaults to Z80N instructions. FPC code is extensively used in the original Spectrum ROM and generated code from ZX compilers that support Sinclair's five-byte floating point format. The rendering of embedded floating-point constants in FPC code is still a bit ragged - please let Simon know if you find problems with this, or (better still) fixes!
Nextramon uses Timex 2068 hires mode for a 64-column display. It supports the Alphacom and ZX printers, and possibly other printers which are compatible with NextBASIC. Once again, I recommend you run this with your Next accelerated to 24 MHz as it's written in BASIC and so quite slow at the original Spectrum clock rate.
This program was written from scratch for Next, though informed by similar structured programs written in QL SuperBASIC, so it exercises many of the features that set NextBASIC apart from ZX BASIC. There are some potentially useful and re-usable PROCs in the program, so here's the NextBASIC source text of the MGT reader in case you'd like to see inside and pick up ideas, even if you've not got any MGT disc images to recover.
The program starts by using the Next file browser to help you locate a disc image for unpacking. The filename should have the extension .DSK unless you modify line 1116 to let through a different file extension, such as .MGT if you have your disc images named that way. MGT disk images are usually 800K long and always a multiple of 200K (for relatively rare single-sided or 40 track drives), but .browse doesn't yet allow filtering of files by size though in this case it's a much stronger hint of the contents than however the filename ends. There are some test commands to load disc images directly by name, in the previous commented-out lines starting REM PROC ReadDir.
The first couple of PROCs are at the start of the program for speed, though they don't use any GO TO or GO SUB instructions. PROC CopyBlock calls the subsequent GetSector repeatedly to read each sector of a file inside the disc image into the 510 byte string g$ so it can be displayed (if it's ASCII - expect errors if it contains undisplayable characters interpreted by PRINT as ZX BASIC control codes) and copied to the output file (in any case). MGT sectors are the standard 512 bytes long but the last two characters are not file data but the track and sector number of the following chunk of file data. Track numbers over 127 refer to the second side of the disc (for disks of over 400K) and a pair of zeros mark the end of the file.
Whatever address you chose, the byte immediately *after* your data must be POKEable, though its original value is restored on exit from the PROC. This is because NextBASIC lacks a command or function to input an arbitrary sequence of bytes, so I had to use INPUT .. LINE to fetch characters and that requires its 'input' to be terminated by a newline, CHR$ 13. If this terminator cannot be POKEd, probably because you're trying to read from ROM, the PROC stops with the message "Something's ROM". Otherwise it opens the NextBASIC "m" (memory) channel and reads as many 'lines' from the specified address range as it must to get past any newline characters that happen to be in the data, which could be anything, not necessarily text. There's a simpler PROC POKESTR defined at line 2600 but recent improvements allow Next to POKE strings as well as numbers (or strings of numbers) so that's only useful as an example, which again uses the nifty "m" channel. Serves me right for suggesting the POKE improvements to Garry in 2019! The 16-bit memory Fn d() and PROC DPOKE are likewise obsolescent now NextBASIC has DPEEK etc, but still work.
Right after that, PROC UPPER$ has standard ZX BASIC internals and just converts its argument into a string with UPPER-CASE characters in place of any lower-case ones. To make a similar PROC LOWER$, substitute "Z" and "A" for "z" and "a" in line 2665 and add rather than subtract 32 in the next line.
Sinclair allocated space for details of a file, such as array names, code addresses or BASIC variable offsets, in the tape header or microdrive directory but Amstrad's CP/M adaptation for the Plus Three scrapped that approach and introduced a 128 byte data block at the start of every ZX-standard file - DATA arrays, programs and variables, CODE or SCREEN$. It's mostly empty but 128 is the original CP/M sector size so the minimum amount of data it's easy to skip over in a CP/M file. But this does mean there's an extra byte, at offset 13 in the data prefix, for files more than 64K long, which Sinclair didn't consider. The PROC SetHead creates an Amstrad-style header, also required for ZX files in ZXNextOS, and copies in the filetype and up to three words of ZX file details, as documented in the Sinclair manuals.
This PROC will be useful to anyone else bringing ZX files onto Next and expecting to load them later with the LOAD or MERGE commands. But it is not fully structured despite the parameters and LOCALs, as it has some external dependencies like the variables plus3header and headLen which tell it where to compile the header, and the flag file which is non-zero if the header is to be written to file stream #5 after compilation. It also clobbers two of Next's fast integer variables, c% and s%, which can't be declared LOCAL. Various cryptic messages appear if the expected setup is not found. One neat trick in this PROC is the way it uses BANK 2 ERASE to clear 120 bytes to zero in one statement, though this will need adjustment if plus3header does not point at memory bank 2, addresses 49152 to 65535 - hence the sanity checks.
For speed, PROC ReadDir uses the dot command .extract to read entire 5K tracks of disc data into memory in one statement. It then calls PROC UnPack to decode each 256 byte disc directory entry, most of which is a bitmap identifying the sectors allocated to the file, though not their order. UnPack extracts vital parts of the directory data into seven BASIC arrays, with one entry per file in each array. PROC SortDir then sorts the names in f$ and corresponding elements in the arrays a(), b(), s(), t(), x() and z() into ascending alphabetical order, using a Shell sort, which is much faster than a slightly simpler bubblesort but doesn't require recursion, which is still problematic in Next BASIC. This nicely structured PROC (apart from the hard-wired array names it uses) fell foul of a new BASIC bug in the day 0 update so one of the REPEAT loops has had to be commented out and replaced with an olde-worlde IF test and pair of GO TOs; various other failed workarounds are commented out. The same bug and mitigation appears in PROC SelectFile.
PROC UnPack can identify and label 20 file types, including the four standard ZX ones and extensions added by SAM, UniDOS and BetaDOS. It strips off the 'hidden' and 'protected' flags in the MGT directory and sets limit to the number of files found, to speed up the sorting. Various diagnostic and test routines appear from line 3000 in the listing. These include StrTest for the string peeks and pokes, WordTest for the 16-bit ones, MDevTest for the memory channel and - probably the most useful - PROC GetHead which opens any file and looks for a Plus3DOS header at the start and extracts and displays key information from it, if found.