solo-forth icon indicating copy to clipboard operation
solo-forth copied to clipboard

Standard Forth system for ZX Spectrum 128 and compatible computers, with disk drives.

trafficstars

= Solo Forth :author: Marcos Cruz (programandala.net) :revdate: 2023-10-13 :toc: :linkattrs:

// This file is part of Solo Forth // http://programandala.net/en.program.solo_forth.html

// Last modified: 20231013T2010+0200.

// Description {{{1 == Description

// tag::description[]

Solo Forth is a Forth system for the ZX Spectrum 128 and compatible computers, with disk drives and +3DOS, G+DOS, or TR-DOS.

Solo Forth cannot run on the original ZX Spectrum 48, but could be used to develop programs for it.

Solo Forth can be used as a stand-alone Forth system (either in an emulator or on the real computer), or as part of a cross-development environment in a GNU/Linux operating system (in theory, other type of operating systems could be used as well).

// end::description[]

=== Main features

// tag::mainfeatures[]

  • Fast DTC (Direct Threaded Code) implementation.
  • A kernel as small as possible.
  • Name space in banked memory, separated from code and data space.
  • Easy access to banked memory.
  • Big <<_library,library>> of useful source code.
  • Modular <<_platforms,DOS support>>.
  • Fully documented source code.
  • Detailed documentation.
  • Conform to the http://forth-standard.org[Forth standard,role="external"] (not fully tested yet).

// end::mainfeatures[]

=== Minimum requirements

// XXX REMARK -- These are generic requirements. The manual contains // more details, depending on the DOS.

  • 128 KiB RAM.
  • One double-sided 80-track disk drive (two or three recommended, depending on the DOS).

// tag::name[]

// == Name

// XXX TODO --

// end::name[]

// Motivation, history and current status {{{1 == Motivation, history and current status

// tag::history[]

The motivation behind Solo Forth is double:

  1. I wanted to program the ZX Spectrum with a modern Forth system: In 2015, my http://programandala.net/en.program.abersoft_forth.html[detailed disassembly of ZX Spectrum's Abersoft Forth], a popular tape-based implementation of fig-Forth ported to several 8-bit home computers in the 1980's (and the Forth system I started learning Forth with in 1984), helped me understand the inner working of the fig-Forth model, including its by-design limitations, compared to modern Forths, and discover some bugs of the ZX Spectrum port. At the same time I wrote the http://programandala.net/en.program.afera.html[Afera library] in order to make Abersoft Forth more stable, powerful and comfortable for cross development. The objective was reached but, after a certain point, further improvements weren't feasible without making radical changes in the system. The need for a new Forth system arised: a Forth designed from the start to use disk drives and banked memory, and useful for cross-development.

  2. Nobody had written such a Forth system before: In 2015 there was no disk-based Forth for the ZX Spectrum platform, and the only Forth written for ZX Spectrum 128 (the first model with banked memory) was Lennart Benschop's Forth-83 (1988). But despite being more powerful than fig-Forth, it is still tape-based and keeps the block sources in a RAM disk. Besides, the system is built by metacompilation, what makes it difficult to adapt to disk drives.

The development of Solo Forth started on 2015-05-30, from the disassembled code of Abersoft Forth. Some ideas and code were reused also from the Afera library and from a previous abandoned project called http://programandala.net/en.program.dzx-forth.html[DZX-Forth] (a port of CP/M DX-Forth to ZX Spectrum +3e).

On 2016-03-13 a Git repository was created from the development backups, in order to preserve the evolution of the code from the start, and uploaded to GitHub. On 2020-12-05 the Git repository was converted to https://fossil-scm.org[Fossil,role="external"], keeping http://github.com/programandala-net/solo-forth[GitHub as a mirror,role="external"]. On 2023-04-06 the repository was converted to https://mercurial-scm.org[Mercurial,role="external"], enabling a better interaction with GitHub. On 2023-09-12 the Mercurial repository was https://hg.sr.ht/~programandala_net/solo_forth[published on Sourcehut], keeping GitHub as a mirror.

Solo Forth is very stable, and it's being used to develop two projects in Forth: http://programandala.net/en.program.nuclear_waste_invaders.html[Nuclear Waste Invaders] and http://programandala.net/en.program.black_flag.html[Black Flag].

// end::history[]

// Platforms {{{1 [#_platforms] == Platforms

// tag::platforms[]

[%autowidth] .Supported platforms |=== | Computer | Disk interface | DOS

| Pentagon 128 | | TR-DOS | Pentagon 512 | | TR-DOS | Pentagon 1024 | | TR-DOS | Scorpion ZS 256 | | TR-DOS | ZX Spectrum 128 | Beta 128 | TR-DOS | ZX Spectrum 128 | Plus D | G+DOS | ZX Spectrum +2 | Beta 128 | TR-DOS | ZX Spectrum +2 | Plus D | G+DOS | ZX Spectrum +2A | (External disk drive) | +3DOS | ZX Spectrum +2B | (External disk drive) | +3DOS | ZX Spectrum +3 | | +3DOS | ZX Spectrum +3e | | +3DOS |===

// end::platforms[]

// Project directories {{{1 [#_tree] == Project directories

// tag::tree[]

// XXX OLD -- This tree was created by tree. The UTF-8 graphic // characters are ruined by htmldoc in the PDF. asciidoctor-pdf // renders it fine, except some descriptions are not aligned.

// .... // . // ├── backgrounds Version background images // ├── bin ZX Spectrum binary files for disk 0 // │   ├── fonts Fonts for the supported screen modes // │   ├── addons Code that is loaded from disk // │ │ because it's not assembled in the library yet // │   └── dos DOS files // ├── disks Disk images // │   ├── gplusdos G+DOS disk images // │   ├── plus3dos +3DOS disk images // │   └── trdos TR-DOS disk images // ├── doc Documentation // ├── make Files used by make to build the system // ├── screenshots Version screenshots // ├── src Sources // │   ├── inc Z80 symbols files // │   ├── lib Library // │   ├── loader BASIC loader for disk 0 // │   ├── addons Code that is loaded from disk // │   └── doc Files used to build the documentation // ├── tmp Temporary files created by make // ├── tools Development and user tools // └── vim Vim files //    ├── ftplugin Filetype plugin // └── syntax Syntax highlighting // ....

// XXX OLD -- A table version is not legible enough.

// [%autowidth] // |=== // | Directory | Description

// | backgrounds | Version background images // | bin | ZX Spectrum binary files for disk 0 // | bin/addons | Code loaded from disk, not assembled in the library yet // | bin/dos | DOS files // | bin/fonts | Fonts for the supported screen modes // | disks | Disk images // | disks/gplusdos | G+DOS disk images // | disks/plus3dos | +3DOS disk images // | disks/trdos | TR-DOS disk images // | doc | Documentation // | make | Files used by make to build the system // | screenshots | Version screenshots // | src | Sources // | src/addons | Code that is loaded from disk // | src/doc | Files used to build the documentation // | src/inc | Z80 symbols // | src/lib | Library // | src/loader | BASIC loader for disk 0 // | tmp | Temporary files created by make // | tools | Development and user tools // | vim | Vim files // | vim/ftplugin | Filetype plugin // | vim/syntax | Syntax highlighting // |===

// XXX OLD -- A list version.

// * backgrounds : Version background images // * bin : ZX Spectrum binary files for disk 0 // - addons : Code loaded from disk, not assembled in the library yet // - dos : DOS files // - fonts : Fonts for the supported screen modes // * disks : Disk images // - gplusdos : G+DOS disk images // - plus3dos : +3DOS disk images // - trdos : TR-DOS disk images // * doc : Documentation // * make : Files used by make to build the system // * screenshots : Version screenshots // * src : Sources // - addons : Code that is loaded from disk // - doc : Files used to build the documentation // - inc : Z80 symbols // - lib : Library // - loader : BASIC loader for disk 0 // * tmp : Temporary files created by make // * tools : Development and user tools // * vim : Vim files // - ftplugin : Filetype plugin // - syntax : Syntax highlighting

// XXX OLD -- A description list version.

// [horizontal] // backgrounds :: Version background images // bin :: ZX Spectrum binary files for disk 0 // bin/addons :: Code loaded from disk, not assembled in the library yet // bin/dos :: DOS files // bin/fonts :: Fonts for the supported screen modes // disks :: Disk images // disks/gplusdos :: G+DOS disk images // disks/plus3dos :: +3DOS disk images // disks/trdos :: TR-DOS disk images // doc :: Documentation // make :: Files used by make to build the system // screenshots :: Version screenshots // src :: Sources // src/addons :: Code that is loaded from disk // src/doc :: Files used to build the documentation // src/inc :: Z80 symbols // src/lib :: Library // src/loader :: BASIC loader for disk 0 // tmp :: Temporary files created by make // tools :: Development and user tools // vim :: Vim files // vim/ftplugin :: Filetype plugin // vim/syntax :: Syntax highlighting

[cols="12,14,54"] |=== | Directory | Subdirectory | Description

| backgrounds | | Version background images | bin | | ZX Spectrum binary files for disk 0 | bin | addons | Code loaded from disk, not assembled in the library yet | bin | dos | DOS files | bin | fonts | Fonts for the supported screen modes | disks | | Disk images | disks | gplusdos | G+DOS disk images | disks | plus3dos | +3DOS disk images | disks | trdos | TR-DOS disk images | doc | | Manuals in DocBook, EPUB, HTML and PDF | make | | Files used by make to build the system | screenshots | | Version screenshots | src | | Sources | src | addons | Code to be loaded from disk. Not used yet. | src | doc | Files used to build the documentation | src | inc | Z80 symbols | src | lib | Library | src | loader | BASIC loader for disk 0 | tmp | | Temporary files created by make | tools | | Development and user tools | vim | | Vim files | vim | ftplugin | Filetype plugin | vim | syntax | Syntax highlighting |===

// end::tree[]

// Disks {{{1 == Disks

The directory of the <<_tree,directory tree>> contains the disk images:

.... disks//disk_0_boot. disks//disk_1_library.* disks//disk_2_programs. disks//disk_3_workbench. ....

The subdirectory and the filename extension of every DOS are the following:

[cols="6,11,18"] .DOS subdirectories and disk image filename extensions |=== | DOS | Subdirectory | Filename extension

| +3DOS | plus3dos | dsk | G+DOS | gplusdos | mgt | TR-DOS | trdos | trd |===

// How to run {{{1 [#_run] == How to run

// tag::attributes[]

:diskdriveformat: Make sure its disk drives are
configured as double-sided and 80-track in the emulator.

// end::attributes[]

// In +3DOS {{{2 [#_run_plus3dos] === In +3DOS

// On ZX Spectrum +3/+3e {{{3 ==== On ZX Spectrum +3/+3e

// tag::run_plus3[]

// XXX REMARK -- A problem with Asciidoctor makes the rendering of the // ZX Spectrum +3e link text fail. It seems the error condition has to // do with a combination of "+" be at start of a new line, and the // presence of the link attribute. The result is the "+3e" part is // omited. Using {sp} to prevent the text from being splitted // fixes the problem.

// XXX REMARK -- This tag does not include the title, because this is // the only entry for +3DOS, and the computers are mentioned in item // 1:

  1. Run a ZX Spectrum emulator and select a ZX Spectrum +3 (or http://www.worldofspectrum.org/zxplus3e/[ZX Spectrum{sp}+3e,role="external"]). {diskdriveformat}
  2. “Insert” the disk image file <disks/plus3dos/disk_0_boot.dsk> as disk 'A'.
  3. Choose “Loader” from the computer start menu. Solo Forth will be loaded from disk.

// end::run_plus3[]

// In G+DOS {{{2 [#_run_gplusdos] === In G+DOS

// On ZX Spectrum 128/+2 with the Plus D interface {{{3 ==== On ZX Spectrum 128/+2 with the Plus D interface

// tag::run_128_with_plusd[]

// XXX REMARK -- This tag does not include the title, because this is // the only entry for +3DOS, and the computers are mentioned in item // 1:

  1. Run a ZX Spectrum emulator and select a ZX Spectrum 128 (or ZX Spectrum +2) with the Plus D disk interface. {diskdriveformat}
  2. “Insert” the disk image file <disks/gplusdos/disk_0_boot.mgt> as disk 1 of the Plus D disk interface.
  3. Choose "128 BASIC" from the computer start menu.
  4. Type run in BASIC. G+DOS will be loaded from disk, and Solo Forth as well.

// end::run_128_with_plusd[]

// In TR-DOS {{{2 [#_run_trdos] === In TR-DOS

// tag::trdos_disk_drives[]

[IMPORTANT]

[#trdosdiskdrives] The TR-DOS version of Solo Forth uses numbers as disk drive identifiers (the same numbers TR-DOS uses internally) instead of the letters used by the TR-DOS BASIC interface:

.TR-DOS disk drive identifiers |=== | Drive | In TR-DOS | In Solo Forth

| 1st | A | 0 | 2nd | B | 1 | 3rd | C | 2 | 4th | D | 3 |===

// end::trdos_disk_drives[]

// tag::run_pentagon[]

// On Pentagon 128 {{{3 ==== On Pentagon 128

  1. Run a ZX Spectrum emulator and select a Pentagon 128. {diskdriveformat}
  2. “Insert” the disk image file <disks/trdos/disk_0_boot.128.trd> as disk 'A'.
  3. Choose “TR-DOS” from the computer start menu. This will enter the TR-DOS command line{blank}footnote:trdoscli[The TR-DOS command line uses keyboard tokens, like the ZX Spectrum 48, but commands typed in 'L' cursor mode will be recognized as well, as on the ZX Spectrum 128 editor. In order to get the 'L' cursor mode you can type a quote (Symbol Shift + 'P') or press 'E' to get keyword REM. When the DOS command is typed in full, the quote or the REM must be removed from the start of the line before pressing 'Enter'.].
  4. Press the 'R' key to get the RUN command and press the Enter key. Solo Forth will be loaded from disk.

// On Pentagon 512 {{{3 ==== On Pentagon 512

  1. Run a ZX Spectrum emulator and select a Pentagon 512. {diskdriveformat}
  2. “Insert” the disk image file <disks/trdos/disk_0_boot.pentagon_512.trd> as disk 'A'.
  3. Choose "128k menu"footnote:pentagonboot[In theory, choosing option “TR-DOS” from the system service menu should work. But it seems it depends on a specific version of TR-DOS. This alternative method is longer, but it works with the TR-DOS 5.03 ROM.] from the computer start menu (the reset service menu). This will enter a ZX Spectrum 128 style menu. Choose “TR-DOS”. This will enter the TR-DOS command line{blank}footnote:trdoscli[].
  4. Press the 'R' key to get the RUN command and press the Enter key. Solo Forth will be loaded from disk.

// On Pentagon 1024 {{{3 ==== On Pentagon 1024

  1. Run a ZX Spectrum emulator and select a Pentagon 1024. {diskdriveformat}
  2. “Insert” the disk image file <disks/trdos/disk_0_boot.pentagon_1024.trd> as disk 'A'.
  3. Choose "128k menu"footnote:pentagonboot[] from the computer start menu (the reset service menu). This will enter a ZX Spectrum 128 style menu. Choose “TR-DOS”. This will enter the TR-DOS command line{blank}footnote:trdoscli[].
  4. Press the 'R' key to get the RUN command and press the Enter key. Solo Forth will be loaded from disk.

// end::run_pentagon[]

// tag::run_scorpion[]

// On Scorpion ZS 256 {{{3 ==== On Scorpion ZS 256

  1. Run a ZX Spectrum emulator and select a Scorpion ZS 256. {diskdriveformat}
  2. “Insert” the disk image file <disks/trdos/disk_0_boot.scorpion_zs_256.trd> as disk 'A'.
  3. Choose "128 TR-DOS" from the computer start menu. Solo Forth will be loaded from disk.

// end::run_scorpion[]

// tag::run_128_with_betadisk[]

// On ZX Spectrum 128/+2 with the Beta 128 interface {{{3 ==== On ZX Spectrum 128/+2 with the Beta 128 interface

  1. Run a ZX Spectrum emulator and select a ZX Spectrum 128 (or ZX Spectrum +2) with the Beta 128 interface. {diskdriveformat}
  2. “Insert” the disk image file <disks/trdos/disk_0_boot.128.trd> as disk A of the Beta 128 interface.
  3. Choose "128 BASIC" from the computer start menu.
  4. Type randomize usr 15616 in BASIC (or just run usr15616 to save seven keystrokes). This will enter the TR-DOS command line{blank}footnote:trdoscli[].
  5. Press the 'R' key to get the RUN command and press the Enter key. Solo Forth will be loaded from disk.

// end::run_128_with_betadisk[]

// How to use the library {{{1 [#_library] == How to use the library

// In +3DOS {{{2 === In +3DOS

// tag::library_on_plus3dos[]

// XXX TODO -- is set-drive needed?

  1. <<_run_plus3dos,Run Solo Forth>>.
  2. “Insert” the file <disks/plus3dos/disk_1_library.dsk> as disk B. 'b' set-drive throw to make drive 'B' the current one.
  3. Type 1 load to load block 1 from the library disk. By convention, block 0 cannot be loaded (it is used for comments), and block 1 is used as a loader. In Solo Forth, block 1 contains 2 load, in order to load the need tool from block 2.
  4. Type need name, were “name” is the name of the word or tool you want to load from the library.

// end::library_on_plus3dos[]

// In G+DOS {{{2 === In G+DOS

// tag::library_on_gplusdos[]

  1. <<_run_gplusdos,Run Solo Forth>>.
  2. “Insert” the file <disks/gplusdos/disk_1_library.mgt> as disk 2 of the Plus D disk interface. Type 2 set-drive throw to make drive 2 the current one.
  3. Type 1 load to load block 1 from the library disk. By convention, block 0 cannot be loaded (it is used for comments), and block 1 is used as a loader. In Solo Forth, block 1 contains 2 load, in order to load the need tool from block 2.
  4. Type need name, were “name” is the name of the word or tool you want to load from the library.

// end::library_on_gplusdos[]

// In TR-DOS {{{2 === In TR-DOS

// tag::library_on_trdos[]

  1. <<_run_trdos,Run Solo Forth>>.

  2. “Insert” the file <disks/trdos/disk_1a_library.trd> into the first disk drive (called A in TR-DOS and 0 in Solo Forth), and the file <disks/trdos/disk_1b_library.trd> into the second disk drive (called B in TR-DOS and 1 in Solo Forth).

-- Notice that the library is split into two disks because the maximun capacity of a TR-DOS disk is only 640 KiB.

Also remember in Solo Forth the <<trdosdiskdrives,TR-DOS disk drive identifiers>> are numbers 0..3 instead of letters A..D.

  1. Type 1 load to load block 1 from the first library disk. By convention, block 0 cannot be loaded (it is used for comments), and block 1 is used as a loader. In Solo Forth, block 1 contains 2 load, in order to load the need tool from block 2.

  2. Type need 2-block-drives to load and execute the word 2-block-drives from the library, setting the first two drives as block drives in their normal order.

  3. Type need name, were “name” is the name of the word or tool you want to load from the library.

// end::library_on_trdos[]

// Documentation {{{1 == Documentation

The directory contains one version of the manual for every supported DOS, EPUB, HTML and PDF formats. The manuals are built automatically from the sources and other files. At the moment they contain a description of the Forth system, the basic information required to use it and a complete glossary with cross references.