With this new subversion I ventured to split the dictionary in two parts: name-space and code-space. We use higher 8k-RAM pages fitted at MMU7 to keep the linked list of definitions names, while the actual compiled code is stored in lower memory as usual.
This way, there is much more memory available for real programs, say two times more, no more fear in create long-name definitions and HEAP facility still available.
Since the core is now less than 7.5 KBytes, I deem possible convert the whole thing into a DOT-COMMAND.
Improved GRAPHICS.f with some definitios now coded in machine code, in particular the ones that handle LAYER 2
Interrupt-driven MOUSE using hardware sprite is now available as point-n-click interface.
Registers DE now hold the Return Stack Pointer: this produces an overall speed boost of +30%
Release of 1.52 version. From this version vForth has a standard VARIABLE behavior. This should preserve any previous code written using the old behavior, but care must be taken to verify any old syntax. PDF documentation has reached 100 pages, this is quite an achievement.
This build introduces REMOUNT definition: now to copy a file to SD Card you don't need to switch to Basic anymore. You can even change the Screens/BLOCKs file used. There is a new "Large file EDitor" LED that uses all RAM available to edit very large text files, 85 characters per line. It comes along with some new CAT" definitions to inspect directory content.
I've also introduced a GRAPHICS.f library that can be loaded via NEEDS GRAPHICS and makes available PLOT, DRAW-LINE and CIRCLE for most of Graphic-Modes available using LAYERxy words. This GRAPHICS libary is a valuable piece of code that is a good example of vector-call via DEFER and IS along with the use of DOES> to create very compact and fast code.
Now, there are two distinct Basic Loader to better handle the two flavors Direct vs Indirect Threaded.
Release of 1.51 version. From this version vForth is a "direct-thread" instead of an "indirect-thread" Forth system. It brings a overall 25% speed improvement. Any Low-Level definition saves two bytes, but any non Low-Level definitions needs one additional byte because CFA does not contain an address anymore, instead CFA contains the real machine-code to be executed. For non Low-level definitions CFA is a three byte instruction "CALL aaaa" to the ;CODE part routine that handles that kind of definition.
Some definitions have been speed-improved and space-improved using alternate registers: REG! REG@ FILL +ORIGIN P! P@ 2! DNEGATE D+ CMOVE> CMOVE (COMPARE)
Re-introducing Floating-Point Option Library (experimental but useful) available via NEEDS FLOATING : This is a simple interface to the ZX Spectrum "standard ROM" Floating-Pointer routine (RST $28).
In this version I'm trying to make more "standard" this Forth so ;S becomes EXIT and S->D becomes S>D, but for backward compatibility both ;S and S->D are available via NEEDS. There is an improved LEAVE that now really jumps off the DO-LOOP structure, that before now it just set the loop-limit to current index.
Quasi-standard Test Suite (https://forth-standard.org/standard/testsuite) is quite reliable now: try NEEDS TESTING and INCLUDE test/core-tests.f
An INTERRUPT vocabulary that provide some IM 2 Interrupt Service Routine (ISR) and I've tested to move a couple of sprite (Screen # 412 and https://www.youtube.com/watch?v=gRZfHnZ7eDQ )
In addition to inc/ now NEEDS searches lib/ too.
Introducing NEEDS definition and the corresponding inc/ including directory. ( Reading source file via OPEN# stream is now deemed obsolete ).
Now it is possible to recompile the whole system via 10 LOAD: the process takes about five minutes, and then to make the new version permanent, you have to save it from Basic using GOTO 9991.
Everything is moved in C:/tools/vForth to avoid future collisions with C:/forth.
Introducing example game "Chomp" in blocks 600-670. It's a PacMan style: Once AUTOEXEC completes its LOAD, give 600 LOAD, then GAME. Cursor keys (or Cursor Joystick maybe) It's a work-in-progress though. See
I am going to use Using Visual Studio Code with some "Next extension", and create a new project to produce the same code of Forth itself: This opens the way to change the Forth's core in a more effective way.
.
Introducing F_GETLINE and first version of INCLUDE definition. Introducing also SOURCE-ID user variable to keep track of nested calls to INCLUDE definition. This - and this is a real big leap - allows interpreting any source file.
Introducing a new Full-Screen Editor available at startup or after AUTOEXEC. See Screens 190-196 whiel Line-Editor is moved to Screens 90-95.
Renamed IN into >IN to be more ANS compliant and defined DEFER, at last. Changed STRING" into ," in Forth Inc. style.
AUTOEXEC now loads Screen # 11. This frees the first 3 Screen for any other purpose.
Attached block-system file !Blocks64.bin has become integral part of this Forth system, since many features come along with it.
Documentation upgraded and revised.
Removed a subtle bug: DO ... +LOOP structure with negative step that crosses the 0 boundary behaves in a buggy way. The bug is in (LOOP) definition that does a JP C instead of a JP M.
Now the following words are available: M_P3DOS F_SYNC F_OPEN F_CLOSE F_READ F_WRITE F_SEEK that use RST 8 calls for NextZXOS interaction, fast and neat indeed since there is no more need for BANK paging during DOSCALL.
Screens/Blocks system doesn't need OPEN# from Basic anymore, instead Block's file is opened during COLD or WARM and closed during BYE.
Now CREATE is more ISO compliant and a new MARKER definition is now available.
Also, a better compiled strings are now available to create string to hold a filename. Still, an USE definition is lacking, ... la prochaine fois.
ASSEMBLER vocabulary doesn't occupy Dictionary space anymore, instead it uses some HEAP VOCABULARY extending what I am already doing with HEAP STRINGs.
Introduction of LAYER 1,2 graphic resolution, this now allows screen size 1024 bytes, twice than previous releases. KEY cursor must be displayed via software-loop instead of "flash" attribute (which is no more using LAYER 1,2). Continuing studying POINTER address for heap memory via MMU7 and experimenting with ASSEMBLER vocabulary on MMU7 page. This is the first step into Next's Hardware: hopefully next will be sprites.
Improvement in DOSCALL to allow A register to be passed along. To interact with Next's hardware there are new definitions: REG@ and REG! Same thing to better interact with higher RAM: MMU7@ and MMU7!
Implemented a heap-based string S" storage system using FAR on MMU7 with a fair stable version of POINTER. for "Heap Memory Management" to store counted-string, i.e. strings 255 bytes in length. I put in Screens #80-85 some of these definitions.
IX register now holds NEXT address: this makes inner-interpreter 2 T-states faster than before and many Library Screens had to be checked to be IX-compliant and some definitions that used IX as temporary register. Introducing RECURSE in core dictionary and a faster LOAD from external text source file by disabling echoing to video.
In this this release: CHOMP2.F source, a simple "pacman" style game written in Forth that explores how to use Heap Memory to store data.
Today, I'm presenting two version of the same software:
Forth_15e_20200808 : is the latest version that frees top 8K RAM ( E000h-FFFFh hence "e") to exploit MMU7 for memory-paging.
Forth_15a_20200721 : is the same version as above, without any MMU memory-pagin.
In this build I've resolved the memory limitation of the previous build (where I had to put everything under C000h thus giving up almost 16K of room)
Now, I put buffers and stacks to the extreme border of the memory, then the map is as follow:
FFFF P_RAMT Phisical ramtop
FF58 LIMIT @ First byte outside Forth, i.e. UDG area.
F94C FIRST @ First buffer : there are 3 buffers available (at F94Eh, FB52h, FD56h)
F8E2-F930 User variables area
F8E0 R0 @ RP location when return stack is empty
RP@ Return-Stack grows downward: it can hold 80 entries
F840 S0 @ SP location when stack is empty
SP SP@ Current Calculator Stack-pointer: Stack grows downward
... at COLD start there are 27384 bytes of ROOM
HERE Forth Vocabulary grows upward
6400 0 +ORIGIN Entry point for Warm Start using Basic USR 25600.
62FF RAMTOP Set from Basic loader.
You can check it out for yourself with
SP@ HEX U.
The core of this Forth implementation takes slightly above 8K of memory: This allows room for 27384 bytes free for FORTH Vocabulary.
Also, there are 3 word to move these 3 entities around: MOVE-SP , MOVE-RP, MOVE-LIMIT. These words change the location in Origin area so that they resist to COLD course. To make the move permanent, you have to re-save the code file to disk manually from Basic, with something like SAVE "forth1413n.bin" CODE A,B where A and B can be calculated from Forth itself giving :
A := 0 +ORIGIN U. ( normally 25600)
B := HERE 0 +ORIGIN - U. ( in this build 8841 bytes )
On April 27th 2020, I received my ZX Spectrum Next (Accelerated) and immediately tried to port my Forth to the Next environment. The purpose was to make Screens / BLOCKs system available using ZxNextOS APIs.
Having done it in the past for ZX Microdrive and MGT Disciple floppy diskette I really thought it was worth give a try on ZxNextOs: Well, I did it and this is the first version that is stable enough to be published here.
Screens are stored in a file inside the SD card called "!Blocks.txt" 8 MBytes long and it can hold 16.384 Screens (while MGT can hold 1.560 and Microdrive 254 only). In this implementation a Screen is equivalent to a BLOCK.
Among the other things, I implemented an ASSEMBLER vocabulary with Z80N extension op-codes with custom notation as explained here.
You can download the zip file available in this page and unzip it in your ZX-Next SD C:/tools/vForth directory.
To load the Forth system from Next Basic or Browser you have to change to C:/tools/vForth directory and load the Basic program loader.
Forth1413_.bas (the one with the trailing underscore)
Once loaded you will land on this welcome screen.
To exit to Basic you can give BYE .
To re-enter Forth from Basic you can give a simple RUN that uses the USR Warm start entry-point.
You can force an USR Cold start using a RUN 20 instead.
Once you enter this Forth system, the prompt is simply "Ok" with a flashing input cursor on the next line.
In this system, a Screen/Block is 512 bytes long. It can contain text and source code ,in this case it is divided into 16 lines 32 character each and lines are numbered from 0 to 15. Maybe in the future I will be able to build a 1024 Screen long version.
Each Screen is stored on disk inside the text file !Blocks.txt and is read and hold in a memory buffer where you can modify it and then save it back to the same position in the file !Blocks.txt. Screens are numbered from 1 up to the physical limit of the file, 16383 in this implementation.
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 important Screens using:
13 LOAD
This command loads some other Screens 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 BREAK the listing at any point. You can examine or list the content of a block using LIST, for example:
13 LIST
When buffer is modified, it is marked as updated so the screen it contains will be saved back to disk the next time the same buffer is requested for another screen. You can force the rewrite to disk of all updated buffers using FLUSH.
Screens #4, #5 and #6 are reserved and contains the Forth system Error messages. Messages are issued in the form "? msg#nn" when 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.
Screens 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 Screen 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 screen
N to list the next screen and make it the current one.
B to list the previous screen i.e. going back by one and and make it the current one. Beware: this word prevents you to type the hex number B, use 0B instead...
INDEX allows you to display line 0 of several screens. Syntax first last INDEX for example 4 7 INDEX sends to video the four heading lines of screens # 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 disk.
These single-letter (or two letters) words acts on a single line of a Screen 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 Screens 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.
In addition to LOAD from screen, you can LOAD from a "negative" screen number and this makes the Forth interpreter to accept text coming from the stream # having the absolute value of that "negative number". For example, giving
-12 LOAD
it will read and compile from the stream you opened beforehand from Basic using OPEN#12.
This stream can be attached to a text file somewhere on the SD; in this case text lines must not exeed 80 characters wide. This is a fair improvement compared to the 32 characters limitation of the current Screen & Block facility.
This is how I cross-compiled the whole thing in Forth itself.
The complete source of this Forth system is available under ./SRC/ directory.
All disk access are done using the following three DOS API:
DOS_SET_POSITION ($0136) Set file pointer for random access
DOS_READ ($0112) Read bytes into memory
DOS_WRITE ($0115) Write bytes from memory