vForth 1.5

This is a back-porting of v.Forth 1.5 for NEXTZXOS for:

  • ZX Microdrive



This work is available as-is with no whatsoever warranty. Copying, modifying and distributing this software is allowed provided that the copyright notice is kept.

v.Forth 1.5 - MDR / MGT version

This is the "backporting" to Microdrive and DiSCIPLE MGT versions any improvement I introduced in v.Forth 1.5 NextZXOS version (for the recent ZX Spectrum Next).

MDR : Microdrive version now uses all the eight (8) emulated Microdrive units chained to offer 1778 blocks / screens (889 KBytes).

MGT: DiSCIPLE version uses two disks as usual (#1 for Forth, #2 for Blocks) that offer 1560 blocks / screens (780 KBytes).

In this version 1.5 there are a few deep modifications from previous version 1.413 that make it "deprecated".

At first COLD start, it executes AUTOEXEC definition that in turn should LOAD Screen#11 which contains some useful library utility. You are free to personalize Screen#11 content to launch whatever you need to.

The two versions are compiled from a single source file F15m.f , with the only difference in the content of MGT variable that contains 0 for Microdrive and 1 for DISCiPLE-MGT,

Give a look at https://github.com/mattsteeldue/vforth

Osolete / deprecated version "J" can be found in subdirectory.

vForth 1.413 is the natural evolution of previous 1.3 version. In the latest version, I succeeded to re-compile the whole thing using Forth itself. This Forth is a very simple training programming environment, you can use to experiment how was programming in the 80s.

I am proposing this Forth in many version:

  • MGT Disciple two disks system (#1 for Forth, #2 for Blocks).

  • Tape + Single Microdrive

  • Two Microdrives system (#1 for Forth, #2 for Blocks)

How to start with BLOCKs

Once you enter the Forth prompt is simply "OK" and the input cursor on the next line.

In this system, a disk block is 512 bytes long. It usually contains text or source code, in this case it is divided into 16 lines 32 character each and lines are numbered from 0 to 15. A block stored on disk is usually read and hold in a memory buffer where can modify it and then save or FLUSH it back to the same block number on disk. Blocks are numbered from 1 up to the phisical limit of the diskette.

In general, a block may use more than one disk sector, but on the ZX Spectrum it is easier to have one sector per block. Real Microdrive version has some 170 blocks available; you can reach 254 blocks only using an emulator. Disciple version can use the whole disk (but for the first four tracks) up to 1560 blocks. Maybe in the future I will have the chance to port this system using other filesystems.

At COLD start, Forth vocabulary has the minimum words to keep it alive and I usually begin a Forth session giving a LOAD of a few blocks using:


This command loads some blocks from disk, interprets their contents to compile (i.e. create) some new words in Forth vocabulary. To see the available words in your current vocabulary you can give WORDS to show them in reverse order, from the latest to the oldest.

You can examine or list the content of a block using LIST, for example:


reads block number 3 from disk and keeps its content in a temporary RAM area called buffer. Anytime a buffer is modified, it is marked as updated it will be saved back to disk the first time the same buffer is requested for another block. You can force the rewrite to disk using FLUSH.

Blocks 4, 5 and 6 are reserved and contains the system Error messages. Normally, messages are issued in the form "? msg#nn" provided that WARNING user variable is zero. If you change it using 1 WARNING ! you're telling Forth to start issuing any subsequent error message with full text, for example: "No such line. #3". You can try 3 MESSAGE and see the result: the system has to access the corresponding block to provide the correct message, and if the block isn't already in memory, it has to fetch it from disk. You can check WARNING value using WARNING ? commands.

Blocks starting from 10 provide a very simple line-editor suitable to operate with a single buffer on screen one line at a time. PAD is a dynamic memory zone that collects one line of text, 80 character length that can be used as line-buffer during editing operation.

    • P to put a text line using the sysntax: n PUT xxx ... it replaces the content of line n with the following text until the end of line. There is no way to edit a single line character by character, instead you have to re-type the whole line...

    • S to make space at line n shifting all next lines down by one. Line number 15 is lost, since it is shifted beyond the block border. Syntax n S

    • H to hold the content of line n into PAD text buffer. Syntax n H

    • RE to re-enter line n from PAD. Syntax n RE

    • INS to insert from PAD to line n shifting the rest down. It is equal to the sequence of words S ans RE

    • D to delete line n from current listed block moving the next lines up by one. Line is also copied to PAD. Syntax n D

    • E to erase or fill with blanks line n . Previous content is lost. Syntax n E

    • L to list the current block

    • N to list the next blockand make it the current one.

    • B to list the previous blocki.e. going back by one and and make it the current one.

    • INDEX allows you to display line 0 of several blocks. Syntax first last INDEX for example 4 7 INDEX sends to video the four heading lines of blocks number 4, 5, 6 and 7.

    • EMPTY-BUFFERS fills with blanks all buffers and does not FLUSH. It is useful to start from scratch without spoil the blocks on disk.

These single-letter (or two letters) words acts on a single line of a block whose content is currently hold in a buffer. For example to copy a line across two consecutive blocks you can give 4 H N 6 RE so that is holds line 4 in PAD, lists next block and makes it current, re-enters PADded line to line 6.

In blocks starting from 20 there are some debugging words. The most useful is SEE . This word allows you to inspect the definitions of a word, for example SEE MOD displays some information of the word MOD, its locations and how it is defined. You can see the memory content using addr DUMP.

[ ... ]

MGT DISCiPLE - two diskette version

This version is suitable to be used within an emulator such as ZXSpin or Fuse. The zip file vForth1413-two-diskette.ZIP contains two .IMG files to be inserted in the two disk drivers.

Once GDOS has been loaded via RUN command at reset, you have to load "run" Basic program to start the Forth system, you can load using the following Basic instruction


This "run" program can be renamed somehow to let it "autostart" at RUN boot and it is just a normal "starter". It loads "Forth1413_" that CLEARs memory and loads the machine CODE at address 25600 (=6400h). Then, a small Basic program allows you to enter Forth.

While loading it shows CAT 1 and CAT 2 results, just to be sure you inserted both and to let you the ability to stop it and inspect their contents: there is nothing to hide, I mean.

The last small Basic program has two ways to be executed to enter Forth system after you leave it using BYE:

    • RUN 20 -- to perform a COLD start.

    • RUN -- to perform a WARM start.

Both ways do a GOSUB 80 to allow you to OPEN# anything you need and a CAT 2! before reach Forth prompt: it seems that that CAT 2 is needed to allow the Disciple's hook-code #44 and #45 to work properly and, for now, it is a known bug. No error checking is performed, so if the disk is write protected, nothing is written and no error issued, I plan to fix this though.

Disk 2 contains the blocks. There are 1560 blocks available and this is much more than a microdrive cartridge can hold in theory using an emulator (i.e. 254) and even more than in a real cartridge (i.e. about 170-180). The disk itself has been patched at sector low-level using one of the following Basic utility to pretend we have just one very long text file named "!Blocks" where each sector is a block.

In blocks from 100 to 159 is stored the Forth source code for a "Z80 Assembler" VOCABULARY i.e. a set of WORDS that can be used to create words directly in Assembler. And, in blocks from 160 to 163 there is a Z80N Next Extension Assembler.

In the porting phase from Microdrive to DISCiPLE, I run some hybrid version of this Forth using RealSpectrum 0.98.14 (don't laugh) because is the only emulator I am aware of to not perform a RESET when you switch hardware between these two disk interfaces. This nice feature allowed me to switch between the two hardware configurations without losing the work I've done in each, for example doing LOAD and SAVE between these two mass storage systems. This trick does not always work, but as you can see, I managed to avoid some crucial crash in the more frantic phases of coding.

Disk 1 contains several utility programs. To use them perhaps you have to do a CLEAR USR "A"-1 before you can LOAD them.

      • Tap2Stream allows you to read many arrays one at a time and send their content to a normal OPEN# stream to disk to create an "OPENTYPE" text file. At RUN, it ask for Unit, Filename and Number of chunks and it STOPs at line 999, where you have to positively give a CONTINUE to send these chunks to disk. I wrote it to be able to port to disk any external source code, e.g. the complete source of this Forth: this is already available as "f1413j.f" Forth source file.

      • SectorView groups many piece of code I used to make the second disk to hold the standard Forth BLOCK facility. It has some nice and useful user DEF FN. For example DEF FN x(x$) returns the address of the first character of string x$ and I used it to study how to use machine code to emulate inside the Forth interpreter the Disciple's SAVE @sector utility. As I said, I used some part of this program to patch the first sectors of the disk to fool the system and pretend the disk is full and contains just one OPENTYPE file, the !Blocks file. Really, it is just a placeholder for Basic access, since inside Forth everything is done at track-sector low level.

      • Tap2!Block was used to port the Microdrive version of !Blocks to disk. I used a normal TAP to bridge the porting. There are four ARRAY files (B-1-64, B-65-128, B-129-192, B-193,255) that contain these migrated BLOCKs and inside the Microdrive version cartridge there is the Basic program I used to extract to tape all BLOCKs as these four DATA a$() file and later loaded and saved to the disk using this Basic utility.

      • assemblr.f is the Forth source for the custom Z80 Assembler WORDs used within this Forth system. The same Assembler is available in BLOCKs number 100 to 160 circa, within the Disk 2 as explained above.

      • f1413j.f is the complete Forth source I used to compile this very same Forth system, so in some way this forth is open to be modified whatever way you like or you can imagine.


Tape + Single-microdrive version

This version is suitable to be used within an emulator such as ZXSpin or Fuse. The zip file vForth1413-one-microdrive.ZIP contains one .MDR cartridge file to be inserted in the first Microdrive. To start the Forth system, you have first to insert the Microdirive cartrige, then load the .TAP file.

Once started, a loader ensures you are using microdrive #1, then it loads the Forth CODE and finally loads a small Basic program that provides a very thin layer between Forth and Microdrive. The microdrive cartridge is a peculiar one because I patched it to be able to make available all 254 sectors, using my mdr-cruncher utility.

How to port this Forth to a real cartridge:

As far as I know, seldom anyone owns more than one microdrive unit, so this version is the most common version to be run on a real Sinclair ZX Spectrum system equipped with a ZX Interface I and a ZX Microdrive. To port the .MDR content to a real cartridge one way is to use the "Tap2Blk" utility you can found inside TAP2BLK.TAP: it contains a Basic program that asks you permission to FORMAT a new cartridge, then reads the following character-array files, 32 KBytes each, and copy their contents to the cartridge, via OPEN#4. The program will halt as some point returning "Microdrive full" error message. A real cartridge hardly reaches 90KBytes, then only ~170-180 BLOCKs will be available to Forth. Trying to access any BLOCK beyond that limit will produce a "File not found" error.

Two-microdrives version

The two-microdrives version is suitable to be used within an emulator such as ZXSpin or Fuse.

The zip file vForth1413-two-microdrives.ZIP contains two .MDR cartridge files:

  • M1 in microdrive #1: it contains the Forth environment and some utilities.

  • M2 in microdrive #2: it contains a single text file that fills the whole cartridge and provides a simple BLOCK facility to Forth environment.

To start the Forth system, after reset, give RUN to start the "run" autostart program as usual for ZX Interface I.

Once the loader started, it ensures you had inserted both microdrives cartridges; then it loads the Forth CODE, finally it loads a small Basic program that provides a very simple interface betwen Forth and Microdrives.

#Sinclair #ZX #Spectrum #Next #Forth #MMU #Block #FIG #FIG-Forth