88 88 88888888888 88 88 88 88 88 88 88 88 88aaaaa 88 88 88""""" 88 88 88 Y8a. .a8P 88 `"Y8888Y"' 88 Version: 8 I. Introduction This is a traditional Forth system for the "uxn/varvara"[1] virtual computer. "UF" is written in Tal[2] and Forth and provides an interactive text interface and screen editor. The system is not threaded, it compiles to native UXN code, but currently only minimal optimizations are performed. The mapping of Forth source code to VM instructions is nevertheless relatively direct, so performance should be more than sufficient in all but the most speed-critical situations. Cells are 16 bits, the full system uses around 25K of memory, with another 4K needed for screen memory and buffers. II. Building UF To build the .rom files, you need to first assemble the kernel and then use it to generate additional .rom files with more functionality: $ uxnasm kernel.tal kernel.rom ... $ uxncli kernel.rom Additional command line arguments or console input will be redirected to the graphical input prompt and can be used to perform initialization, etc. In the graphical interface the following key sequences have a special meaning ("^" meaning the Control key, "Sh" the Shift key): ^a Jump to beginning of line ^e Jump to end of line ^c Terminate Forth (unless a modified block is open in the editor) ^d Delete next char ^k Kill to end of line or marked region (and write to ".snarf" file) ^u Kill to beginning of line or marked region (and snarf) ^x Copy line or marked region to ".snarf" file ^v, ^y Paste contents of ".snarf" file ^f Find next occurrence of word below cursor ^s Save changes in currently edited block ^l Clear screen (unless in editor) ^g Read digits and jump to indicated block on ENTER (abort on ESC) ^r Read digits and copy current block to new one on ENTER ^m Read digits and move current block to new one on ENTER (and delete the old block) ^ENTER Toggle region mark on/off in editor Sh-Up Recall the last entered line or jump to previous block Sh-Down Jump to next block Sh-Left/Right Jump between code and documentation ("shadow") block The arrow keys have the usual meaning. Pressing ENTER will execute the current line (marked by the cursor). Pressing ^ENTER will toggle "mark" mode, all lines between the start of the mark and the current row are copied and written to a file named ".snarf" in the current directory once you press ENTER or ^x. Pressing the first mouse button will reposition the cursor. Pressing the third button will execute the word below the mouse pointer. Moving the scroll wheel will jump to the previous or next block, when currently editing an unmodified block. File system access is provided by "block" files, where each block is named by a natural number and contains 2496 bytes (39 lines with 64 columns). To edit a block, enter edit The ESC key will exit or enter editing (unless the current block is modified). The bottom row contains counters indicating current row, column, block number, the length of the most recently copied text, the amount of dictionary space left and a marker indicating whether the current block is modified. Blocks can be loaded using `load` and `thru`. Note that block-loading is done by temporarily changing the word for reading user-input (`query`) and takes effect when the current input line has been fully processed. That implies that loading words can not be invoked recursively. You can also edit a block by clicking with button 3 on a string of the form "#nnnn" where "nnnn" is a decimal integer. If a 6 byte file named ".theme" is found in the current directory, then it will be used to initialize the color scheme during startup. The colors are used as follows: #0 background, #1 text, #2 status line text, #3 selection. The current state of the system can be conveniently stored as a .rom file on disk by entering save The saved rom has the exact same state (but with cleared stacks) as when it was created. During startup, the deferred word `boot` is invoked, you can redefine it to replace it with custom startup code. You are also heavily encouraged to consult the source code in "uf.f". IV. Compatibility to other Forths Consult the "GLOSSARY" file for a list of supported Forth words and the extensively commented source files "kernel.tal" and "uf.f" for more information. The dialect implemented in UF is mostly compatible to the Forth 2012 Standard[3]. Notable differences include: - The system is case-sensitive (`Abc` and `abc` name two different words) - `do` and `?do` treat the index and range as unsigned quantities. - Numeric conversion in `<# ... #>` exclusively deals with single cell numbers. - Double-word maths are currently not implemented. - Words that produce boolean results may not always generate -1 (`true`) but some other non-zero value. - Multiple `while` forms in a `begin` ... `repeat` loop are not supported. The dictionary can be inspected with the `words`, `order` and `.vocs` words. To decompile built-in or user words, use `see`. V. The integrated Assembler You can define words containing a simplifed form of Uxntal using the `code` and `end-code` words. Inside such a definition, the following words have a special meaning: BRK INC ... assemble uxn op-instruction " k r add modifier bit to previous instruction $ ( u -- ) pad by number of bytes on stack # ( c -- ) assemble byte literal #" ( x -- ) assemble short literal & ( u -- ) define label , ( u -- ) reference previously defined label as relative branch distance ` ( | -- ) Compile immediate call of Forth word ! ( | -- ) Compile immediate jump to Forth word ? ( | -- ) Compile immediate conditional jump to Forth word Currently only 16 labels can be defined. You can insert absolute references to other Forth words using the sequence `' #"` or by using the syntax ` >1 ) SWP INC SWP ( n+1 x>>1 ) 1 , JMP 2 & POP ( n ) JMP " r end-code VI. Memory Map FFFF +----------------------------+ | Screen buffer | F600 +----------------------------+ | Block load buffer | ec40 +----------------------------+ | | | Unused space | | | +----------------------------+ < `here` | User defined words | +----------------------------+ | Kernel | 0100 +----------------------------+ | Unused | 0000 +----------------------------+ Uf allows up to 4 vocabularies to be active at the same time. You can see the currently available words by executing `words` and inspect the vocabulary stack with `.vocs`. Predefined vocabularies are `forth` (the default), `compiler` (words only available during compilation of colon words), `assembler`, `decompiler` and `editor`. VIII. Uxn VM implementation Issues UF has been tested on SDL uxn[4] and uxn11[5]. In the graphical interface the controller, console and mouse device vectors are modified to receive input events. During evaluation of code the vectors are temporarily cleared and a BRK or machine halt will abort with an error and return to the Forth prompt. If you want to modify any of these vectors permanently, make sure your code does not return to the interactive prompt or use `wait`, which invokes the deferred word `tick`, which you can modify to perform custom processing (the default implementation just blinks the cursor). The graphical system sets the screen size to the default 512x320 resolution which must be supported by the underlying uxn implementation. A number of words are defined to access "varvara" devices, consult the GLOSSARY for more details: System: colors reset clear depth evector Console: cin cout ctype cvector Screen: screensize@ screensize! position pixel auto spritedata sprite svector Audio: sample play adsr volume output Controller: jkey jbutton jvector Mouse: mouse mscroll mstate mvector File: filename filewrite fileappend fileread filedelete Datetime: year month day hour minute second dotw doty isdst Note that the file words only use the first file device (a0). Console input in the graphical interface is redirected to the screen, so the line-length limit of the screen applies here. Input lines that exceed the screen width are silently cut off, with the text preceding the exceeding part being ignored. Due to limitations of the "varvara" file-system interface files loaded with `include` (or `included`) may not exceed the currently available dictionary space divided by two as the file has to be loaded into memory completely before it can be interpreted. Moreover, file-inclusion can not be nested. IX. License This software was written by Felix L. Winkelmann and has been released into the public domain. Do with it whatever you want. X. Contact Information This software will have many bugs and shortcomings. In case you need help, have suggestions or ideas, please do not hesitate to contact the author at felix AT call-with-current-continuation DOT org A git repository can be found at [6], if you want to follow the development of the system more closely. XI. References [1] https://100r.co/site/uxn.html [2] https://wiki.xxiivv.com/site/uxntal.html [3] https://forth-standard.org/ [4] https://git.sr.ht/~rabbits/uxn [5] https://git.sr.ht/~rabbits/uxn11 [6] https://gitlab.com/b2495/uf