Updated documentation.
[fifth.git] / doc / index.org
1 #+TITLE: Fifth - virtual machine, operating system, programming language
2
3 -----
4 - [[http://www2.svjatoslav.eu/gitweb/?p=fifth.git;a=snapshot;h=HEAD;sf=tgz][download latest snapshot]]
5
6 - This program is free software; you can redistribute it and/or modify it under
7   the terms of version 3 of the [[https://www.gnu.org/licenses/lgpl.html][GNU Lesser General Public License]] or later as
8   published by the Free Software Foundation.
9
10 - Program author:
11   - Svjatoslav Agejenko
12   - Homepage: http://svjatoslav.eu
13   - Email: mailto://svjatoslav@svjatoslav.eu
14
15 - [[http://www.svjatoslav.eu/programs.jsp][other applications hosted at svjatoslav.eu]]
16
17 * (document settings) :noexport:
18 ** use dark style for TWBS-HTML exporter
19 #+HTML_HEAD: <link href="https://bootswatch.com/4/darkly/bootstrap.min.css" rel="stylesheet">
20 #+HTML_HEAD: <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
21 #+HTML_HEAD: <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>"
22 #+HTML_HEAD: <style type="text/css">
23 #+HTML_HEAD:   footer {background-color: #111 !important;}
24 #+HTML_HEAD:   pre {background-color: #111; color: #ccc;}
25 #+HTML_HEAD: </style>
26
27 * !Project deprecated!
28 Current implementation does not support object oriented
29 programming. While working on Fifth I got lots of cool new ideas that
30 require reimplementation of everything.
31
32 Currently I try to implement those new ideas in the project called
33 [[http://www2.svjatoslav.eu/gitbrowse/sixth/doc/index.html][Sixth]]
34
35 System is built many years ago when I was still using DOS as a primary
36 operating system.
37 * Introduction
38 Fifth is programming lanquage & operating system, running on [[emulator.html][virtual
39 CPU]], with custom instruction set. It is much like Charles Chunk
40 Moore's Forth, it also uses stack architecture, and many commands are
41 similar. Basically I got familiar with concepts of Forth, and being
42 inspired created my own system.
43
44 - [[file:5TH_ET.txt][Example Fifth source file - text editor]]
45 ** screenshots
46 - [[file:screenshots/start.png]]
47   - Startup screen diplaying Fifth logo and full file list.
48
49 - [[file:screenshots/dictionary.png]]
50   - Sample words defined. Most of the words are commands that can be
51     executed interactively from command line or from file. When
52     executed they can be selectively compiled or interpreted.
53
54 - [[file:screenshots/text editor.png]]
55   - Built in text editor.
56
57 * Installation
58 Just unpack all files, witout altering original directory structure,
59 somewhere in your hard disk. For example: C:\MISC\FIFTH\....  To run
60 fifth you need minimally just 2 files.  emulator itself ( EMULATOR.EXE
61 or EMULATOR.COM ), and virtual disk file ( DISK.RAW ).
62
63 Read more about [[files.txt][distribution directory layout]]
64 * Fifth distribution directory tree description
65 After downloading and unpacking the ZIP file you shoud get directory
66 tree similar to this:
67
68 #+BEGIN_VERSE
69 [DOC]                   - Fifth documentation
70   [commands]            - documentation on Fifth built-in commands
71   [modules]             - documentation on additional commands, realized as loadable modules
72   [shots]               - Fifth screenshots
73
74 [imageFile]             - files contained within 'disk.raw', just an extracted form.
75
76 [source]                - source files
77   [emulator]            - emulator source
78   [util]                - utilites
79
80 disk.raw                - Virtual disk file, has filesystem inside.
81 emulator.com            - main executable.
82 #+END_VERSE
83
84 * Software/Hardware/Human requirements
85 ** Software
86 - MS-DOS 6.22, with HIMEM.SYS loaded.
87 - Mouse driver if you have a mouse.
88 - Does work only when CPU is in real mode.
89 - To recompile ASM sources I used FASM (Flat Assembler).
90 - I ran QBasic utilities on QB 4.5 .
91 - VESA support by BIOS, or external driver (UNIVBE).
92 ** Hardware
93 - Minimum CPU 386.
94 - 64 KB free RAM below 640KB,
95 - 2 MB of free XMS.
96 - VESA compatible video card.
97 ** Human
98 - Beginner level Forth knowledge is recommended.
99 - Lots of enthusiasm.
100 * Numbers representation within Fifth
101
102 [[file:numbers.png][file:numbers.png]]
103
104 Because I can define everything, starting from CPU, why not try also
105 alternative and unique number representation ?
106
107 Fifth uses its hexdecimal number representation as primary. Numbers
108 shape is formed by dividing a square into four parts. And manipulating
109 their color (black or white).
110 * Disk file map, and it's data structures
111 Core and high-level boot code is stored outside of the filesystem to
112 allow easy access to it, at early booting time, when filesystem is not
113 yet initialized.
114 ** disk allocation
115 | offset | length | description          |
116 |--------+--------+----------------------|
117 | 0      | ~4 Kb  | Fifth core           |
118 | 4 Kb   | ~32Kb  | high-level boot code |
119 | 37 Kb  | ~65Kb  | FAT                  |
120 | 101Kb  | ~16MB  | filesystem data area |
121 ** FAT entry format:
122 | code | meaning                  |
123 |------+--------------------------|
124 |   -2 | last sector              |
125 |   -1 | empty sector             |
126 | 0 -- | .. pointer to next block |
127 ** file entry format
128 | offset | length | description            |
129 |--------+--------+------------------------|
130 |      0 |      4 | extension              |
131 |      4 |     16 | name                   |
132 |     20 |      4 | entry point            |
133 |     24 |      4 | size                   |
134 |     28 |      4 | last modification time |
135 * Core architecture
136 Fifth core is simply some amount of already compiled into machine code
137 and linked together modules (entries in other words). In compilation
138 process modules is compiled one by one and simply stored on top of
139 already existing and growing core. Separately from core is kept
140 dictionary, this is special list that contain names of compiled
141 modules, variables etc. and they locations in core. Constants use
142 dictionary space only. Random word can be removed from dictionary at
143 any time. Currently dictionary can contain at most 1000 entries.
144 ** Dictionary entry format
145 | offset | length | description           |
146 |--------+--------+-----------------------|
147 |      0 |      4 | 0 &lt; previous entry |
148 |        |        | 0 = last              |
149 |        |        | -1 = empty            |
150 |--------+--------+-----------------------|
151 |      4 |     15 | module name string    |
152 |--------+--------+-----------------------|
153 |     19 |      1 | entry type            |
154 |--------+--------+-----------------------|
155 |     20 |      4 | entry data            |
156
157 Core headers as linked list of module names make up something like
158 dictionary.  When some entry address is needed compiler can quickly
159 run through headers backwards and find needed entry.
160 ** Possible module types
161 | type | description    | "execute" action           |
162 |------+----------------+----------------------------|
163 |    0 | data           | compile "num" instruction  |
164 |      |                | with address to module     |
165 |------+----------------+----------------------------|
166 |    1 | submodule      | compile "call" instruction |
167 |      |                | with address to module     |
168 |------+----------------+----------------------------|
169 |    2 | imm. submodule | immediately call to module |
170 ** Memory map (average)
171 |   <loc> | <size> | <desc>                      |
172 |---------+--------+-----------------------------|
173 |       0 | ~4096  | core                        |
174 | 1500000 | ~32000 | highlevel Fifth boot code   |
175 | 200000h |        | core startup messages area  |
176 | 5200000 |        | end of dynamic memory space |
177 * Virtual machine
178 Using CPU emulator slows it down but I shouldn't now think too mutch
179 about, and waste my time on batteling with problems whitch results on
180 complex design of PC hardware. Also it allows me to use existing DOS
181 and resident drivers services in real mode. So I don't need to deal
182 with hardware too mutch. It also allows me to use all free XMS for
183 flat code & data storage.
184
185 Current emulator emulates 1 CPU. It has 2 stacks, ~50 instructions,
186 and 4GB flat address space (theoretically).  I'm not sure that DOS
187 6.22 that I currently prefer can handle more than 64 MB of RAM. While
188 I tried to keep instructionset simple, I was forced to put in lot of
189 complex instructions to make it's performance acceptable on
190 emulator. On actual silicon ~20 instructions is enaugh (I think).
191
192 Maybe one day similar system will run directly on custom silicon chip :)
193
194
195 CPU has following registers:
196 | IP  | instruction pointer  |
197 | DSP | data stack pointer   |
198 | RSP | return stack pointer |
199
200 Virtual CPU, commands (most of them are avaiable as ordinary commands
201 in programming lanquage):
202
203 #+BEGIN_VERSE
204
205 code    mnemonic        description
206
207 0       nop                     does notheing
208 1       halt            halt CPU ( return to DOS on emulator )
209
210 2       kbd@            ( -- c ) read scancode of pressed or released key.
211                                 Returns 0, if no data avaiable.
212 3       num <dword>     ( -- n ) put immidiate number into datastack
213
214 4       jmp <dword>     jump to specified code
215 5       call <dword>jump to specified code, save return address to
216                                 return stack.
217
218 6       1+                      ( n -- n+1 )
219 7       1-                      ( n -- n-1 )
220
221 8       dup                     ( n -- n n ) duplicate top of data stack
222 9       drop            ( n -- ) drop last element in data stack
223
224 10      if <dword>      ( n -- ) jump to addr if top element was 0
225 11      ret                     jump to code, specified in return stack.
226
227 12      c@                      ( addr -- n ) read byte from memory at specified address
228 13      c!                      ( n addr -- ) store byte to specified memory
229
230 14      push            ( DSTK -> RSTK ) move top of datastack to returnstack
231 15      pop                     ( RSTK -> DSTK ) move top of returnstack to datastack
232
233 16      <unused>
234 17      rot                     ( n1 n2 n3 -- n2 n3 n1) rotate stack elements
235
236 18      disk@           ( FromDiskSect ToMem -- ) read 1KB from disk into RAM
237 19      disk!           ( FromMem ToDiskSect -- ) write 1KB to disk
238
239 20      @                       ( addr -- n ) read 32 bit number from memory
240 21      !                       ( n addr -- ) store 32 bit number to memory
241
242 22      over            ( n1 n2 -- n1 n2 n1 ) self explaining ...
243 23      swap            ( n1 n2 -- n2 n1 ) -,,-
244
245 24      +                       ( n1 n2 -- n1+n2 ) -,,-
246 25      -                       ( n1 n2 -- n1-n2 ) -,,-
247
248 26      *                       ( n1 n2 -- n1*n2 ) -,,-
249 27      /                       ( n1 n2 -- n1/n2 ) -,,-
250
251 28      >                       ( n1 n2 -- result ) is true when n1 > n2
252 29      <                       ( n1 n2 -- result ) is true when n1 < n2
253
254 30      not                     ( n1 -- not_n1 ) logical not
255 31      i                       ( -- n ) copies top of return stack into datastack
256
257 32      cprt@           ( addr -- n ) read one byte from hardware port
258 33      cprt!           ( n addr -- ) store one byte to hardware port
259
260 34      i2                      ( -- n ) like "i" but takes socond top stack element.
261 35      i3                      ( -- n ) like "i" but takes third top stack element.
262
263 36      shl                     ( n amount -- n ) left bit shift
264 37      shr                     ( n amount -- n ) right bit shift
265
266 38      or                      ( n1 n2 -- n ) logical or
267 39      xor                     ( n1 n2 -- n ) exclusive logical or
268
269 40      vidmap          ( addr -- ) copy memory from "addr" to video memory.
270
271 41      mouse@          ( -- x y button ) read mouse coordinates & buttons
272
273 42      vidput          ( addr1 addr2 x y -- ) put image1 into image2, at
274                                 location x, y. Does clipping, so part of a big image
275                                 can be mapped into smaller one.
276
277 43      cmove           ( addr1 addr2 amount ) move memory from addr1 to addr2
278                                 if addr1 is greater than addr2 then count address
279                                 foward while moving, elseway starts from end and
280                                 counts backwards, so no data loss will occure on
281                                 overlapping.
282
283 44      cfill           ( c addr amount -- ) fill memory starting at "addr"
284                                 with "c" bytes.
285
286 45      tvidput         ( addr1 addr2 x y -- ) same as "vidput" but treats
287                                 color 255 in source image as transparent.
288
289 46      depth           ( -- depth ) returns current depth of data stack.
290
291 47      charput         ( colorfg colorbg addrsrc addrdest x y )
292                                 draw character to image buffer located at "addrdest"
293                                 to specified x & y location. Decodes 8 bytes from
294                                 source to bits, used to draw character.
295 #+END_VERSE
296
297 * Fifth source format
298 Fifth uses a different character table and codes than ASCII (still
299 almost similar). I call it FSCII (Fifth Standard Code for Information
300 Interchange) for example space character is not 32 but 255 instead.  I
301 plan to use mainly HEX numbers, and create new characters to represent
302 numeric values. So typical nemric characters "0123..."  is treated
303 like ordinary letters.
304 ** FSCII
305
306 |    DEC | HEX   | function                               |
307 |--------+-------+----------------------------------------|
308 | 0 - 15 | 0 - F | HEX numbers                            |
309 |    252 | FC    | backspace                              |
310 |    253 | FD    | tabulator (TAB)                        |
311 |    254 | FE    | carriage return (CR)                   |
312 |    255 | FF    | space                                  |
313 |   else |       | ordinary characters, same as in ASCII. |
314 * Fifth commands
315 ** Compilation & miscellaneous
316 #+BEGIN_VERSE
317 init    module  ( -- )
318                 First module, control is passed to on startup. Contains
319                 initialization routines. Also it is the last core module.
320                 All new modules on top of it comes as result of executing
321                 external source files.
322
323 head <name>     ( -- )  compiles new dictionary entry without specifying
324                 new module type.
325                 ex: head myentry
326
327 : <name>        ( -- )  creates new code module
328 ;               ( -- )  ends module (immideate)
329                 ex: : hello ." hi there" ;
330
331 const <name>    ( n -- ) defines new constant.
332                 ex: 2147483647 const max
333
334 :i <name>       ( -- ) same as ":" but this module will be executed
335                 immideately even in compile mode.
336                 ex: :i ( 41 scan ;
337
338 create <name>   ( -- ) same as "head" , but specify module type as data.
339                 ex: create LotoResults 5 , 13 , 52 , 12 , 11 , 3 ,
340
341 allot           ( n -- ) allocate n bytes in dictionary.
342                 ex: create MyArray 100 allot
343
344 " <string>"     ( -- ) compile string and its size into core.
345                 ex: create Mystring " This is it's contects"
346
347 str <name> <string>" ( -- ) just shorter way for defining strings.
348                 ex: str Mystring This is it's contenc"
349
350 var <name>      ( -- ) define new 32 bit variable.
351                 ex: var result
352
353 ' <module>      ( -- n ) return memory address of given entry.
354                 ex: ' init
355
356 forget <name>   ( -- ) erases from RAM given entry and all entries what was
357                 defined after it.
358                 ex: forget myprog
359
360 [               ( -- )  set interpret mode (immideate)
361 ]               ( n -- ) set compile mode and compile top stack element
362                 in as literal. Together [ .... ] cobination provides good
363                 way to compute some values only once, at compile time,
364                 rather than every time while program is running.
365                 ex: : calculate - [ 4 MyConst1 + MyConst2 * ] ;
366
367 defer <name>    ( -- ) creates new module, with jump instruction.
368                 Later address where to jump can be modified by "is" command.
369                 This provides method of foward referencing. So you can use
370                 modules what not jet exist.
371 is              ( address1 address2 -- ) address1 - where to jump, address2 -
372                 address of module created by defer command.
373                 ex:     defer dispver
374                         : run dispver ." running ..." ;
375                                ... whatever ...
376                         : (dispver ." Version 9.99 " ;
377                         ' (dispver ' dispver is
378
379                 Now if I type "run" on the screen appears:
380                         Version 9.99 running ...
381
382 asc <char>      ( -- ) reads char ascii code and treats it as literal.
383                 (immideate)
384                 ex: : BreakLine 30 do asc - emit loop ;
385                                  same as:
386                     : BreakLine 30 do    45 emit loop ;
387
388 dyninc          ( handle -- ) execute code in dynamic memory handle.
389                 automatically deallocates it when done.
390
391 include         ( filenumber -- ) execute code in specified file.
392
393 words           ( -- ) display existing blocks in core.
394
395 bye             ( -- ) exit from Fifth
396
397 fkey            ( -- c )
398                 Read one byte from input stream.
399
400 sadd            ( c addr -- )
401                 Add one byte "c" to string located at "addr" and updates
402                 string length.
403
404 scan            ( c -- )
405                 Read input stream and store it to  pad   until it finds  c  .
406                 It ignores all "c" bytes until it finds any non "c" byte.
407                 in other words:
408                                 c  is:  "
409                          input stream:  """"This is test !"aoeu idh
410                                result:  This is test !
411
412                 Is useful for breaking text lines into words.
413
414 skey            ( -- c )
415                 So called safe "fkey". Reads data from input stream
416                 but converts characters with ASCII codes: 9 13 10
417                 to spaces.
418
419 str=str?        ( adr1 adr2 -- result )
420                 Compares string at "adr1" with string at "adr2", returns
421                 true flag if they are equal or false if they are not.
422                 true = -1
423                 false = 0
424
425 find            ( -- addr )
426                 Searches whole dictionary for word in "pad". If found,
427                 returns it address, if not, returns 0.
428
429 execute         ( -- )
430                 Execute word located in "pad". Depending on "mode".
431
432 dta             ( addr -- DataAddr )
433                 Calculates address of dictionary entry data area, from
434                 entry point.
435
436 2num            ( -- num result )
437                 Attempt to convert string located in "pad" into numeric
438                 value. If succeed returns number and true as result.
439                 If not, returns whatever and false as result.
440
441 dadd            ( addr length -- )
442                 Add to dictionary data located at "addr", with specified
443                 length.
444
445 lit             ( n -- )
446                 Act with number depending on "mode". When interpreting,
447                 leaves it in stack.
448
449
450 incmod          ( addr -- )
451                 Add to dictionary data located at "addr"+1 , length is taken
452                 from "addr".
453
454 here            ( -- n )
455                 return "h" contents.
456
457 mode    var     8 bit
458                 Holds input stream parser operation mode.
459                 0 = interpreting
460                 1 = compiling
461
462 pad     var     128 bytes
463                 Holds temprorary strings.
464
465 h       var     32 bit
466                 Pointer to free byte in memory, always at the end of the
467                 dictionary. Each time when something is stored
468                 by "c," command, pointer is incareased.
469
470 lp      var     32 bit
471                 Pointer to last dictionary word. Each time when new word is
472                 compiled or erased by "forget", this pointer is updated.
473
474 modulechk       ( Dstr<filename> -- ) check if module is loaded, if not
475                 immideately load it.
476
477 ne              ( entrydata entrytype -- ) Compile new dictionary entry.
478                 It's name must be in "pad".
479 #+END_VERSE
480 ** Conditionals & control flow
481 #+BEGIN_VERSE
482 if              ( flag -- )   (immideate)
483                 "if 1.. else 2.. then" or
484                 "if 1.. then" construction. Conditional execution.
485                 Performs "1.." if "flag" was true,
486                 elseway performs "2.." if exist. Execution continues after
487                 word "then".
488                 ex: 1 if ." nonzero" else ." zero" then
489
490 >=              ( n1 n2 -- result ) true if (n1 = n2) or (n1 > n2)
491                 ex: 5 3 >= if ." first number is greater or equal" then
492
493 <=              ( n1 n2 -- result ) true if (n1 = n2) or (n1 < n2)
494 =               ( n1 n2 -- result ) true if n1 = n2
495
496 do              ( count -- )  (immideate)
497                 "do .. loop" construction. Performs ".." "count" times.
498                 In every step "count" is decareased until it is 0.
499                 ex: : test 5 do i .d loop ;
500                 result: 4 3 2 1 0
501
502 doexit         ( -- ) exit from "do .. loop"
503
504 for             ( count top -- )   (immideate)
505                 "for .. loop" construction. Performs ".." (top - count)  times.
506                 In every step "count" is incareased until it reaches "top" .
507                 ex: : test 4 10 for i .d loop ;
508                 result: 4 5 6 7 8 9
509
510 forexit         ( -- ) exit from "for .. loop"
511
512 until           ( -- )  (immideate)
513                 "until .. loop" construction. Performs ".." until flag become
514                 true. False by default. Top of return stack holds flag.
515
516 done            ( -- ) exit from "until .. loop"
517
518 #+END_VERSE
519 ** Disk & file access
520 #+BEGIN_VERSE
521 diskload ( FromDisk ToMem amount -- )
522                 Load specified abount of bytes from disk into memory.
523
524 disksave ( FromMem ToDisk amount -- )
525                 save specified abount of bytes from memory into disk.
526
527 format ( -- )   Erase all files.
528
529 fsDfilesize@ ( handle -- size )
530                 Return size of opened file.
531
532 fsDcurloc@ ( handle -- location )
533                 Return current location in file.
534
535 fsDupdated@ ( handle -- updated? )
536                 Return true if file was updated,
537                 ie. write operations occured.
538
539 fssave ( FromMem DestFileHandle amount -- )
540                 Save data to file.
541
542 fsload ( SrcFileHandle ToMem amount -- )
543                 Load data from file.
544
545 fseof ( handle -- bytesLeft )
546                 Return amount of bytes left till end of file.
547                 Useful before read operation.
548
549 fsls ( -- )     List all files and lists (directories,folders)
550                 in current path.
551
552 fslsr ( -- )    Same as "fsls" but recursively scans also sub lists.
553
554 fscl ( DynStrHand -- )
555                 Change list (path)
556
557 fscreate ( DynStrHand -- DescPnt )
558                 Create new file or list. Can create multiple lists at once.
559                 ex: when creating:
560                     "\listGAMES\listSTRATEGY\listSIMWORLD\5th-runme"
561                 and only "\listGAMES\" already exist, then
562                 "listSTRATEGY" and "listSIMWORLD" lists will be created,
563                 and empty file "5th-runme" placed in there.
564
565 fsDsave ( DynHand<data> DynStrHand<filename> -- )
566                 Create new file and save all data from dynamic memory
567                 block to it.
568
569 fsDload ( DynStr<SrcFileName> DynHand<DataDest> -- )
570                 Load whole file into dynamic memory block.
571
572 fsDloadnew ( DynStr<SrcFileName> -- DynHand<DataDest> )
573                 Load whole file into new dynamic memory block.
574 #+END_VERSE
575 ** Dynamic memory
576 #+BEGIN_VERSE
577 dynal ( size -- handle )
578                 Allocate dynamic memory block and return it's handle.
579
580 dynde ( handle -- )
581                 Deallocate dynamic memory block.
582
583 dynp ( handle -- addr )
584                 Returns pointer to memory where dynamic block
585                 data begins.
586
587 dyns ( handle -- size )
588                 Returns size of dynamic block.
589
590 dynresize ( NewSize handle -- )
591                 Nondestructively resize dynamic block.
592
593 dync@ ( addr handle )
594                 Read one byte from dynamic block.
595
596 dync! ( byte addr dynhandle )
597                 Write one byte to dynamic block.
598
599 dyn@ ( addr handle )
600                 Read 32 bit number from dynamic block.
601                 Address will spacify, whitch number, not byte.
602
603 dyn! ( 32BitNum addr dynhandle )
604                 Write 32 bit number to dynamic block.
605                 Address will spacify, whitch number, not byte.
606
607 dyncon ( size "name" -- )
608                 Allocate dynamic block with specified size, and
609                 create constant honding its handle.
610                 ex: 100 dyncon MyNewBlock
611
612 dyn. ( handle -- )
613                 Write contenc of dynamic memory block to screen.
614 #+END_VERSE
615 ** Graphics and text
616 #+BEGIN_VERSE
617 .               ( n -- ) print number on screen
618
619 d.              ( n -- ) print number on screen in decimal
620
621 ?               ( addr -- ) print 32 bit value located at addr.
622
623 ." <string>"    ( -- ) print string into screen. Immideately
624                 compiles.
625                 ex: : greeting ." Hello, World" ;
626
627 tab.            ( -- ) print tabulator
628
629 calccol         ( b g r -- c ) calculate color what best matches given
630                 Blue Green & Red values. Values must be in range 0 - 255.
631
632 imgalloc        ( xsize ysize -- imgbuf ) allocate image buffer for
633                 specified size.
634
635 imgsize         ( imgbuf -- ) print on the screen X & Y size of image
636                 buffer.
637
638 point           ( x y imgbuf -- addr ) returns memory address for specified
639                 pixel.
640
641 pset            ( color x y imgbuf -- ) set graphic point
642
643 boxf            ( x1 x2 y1 y2 imgbuf color -- ) draw filled box
644
645 cls             ( imgbuf -- ) clear image buffer
646
647 setpal          ( b g r color -- ) set palette value for specified color.
648                 values bust be in size 0 - 63.
649
650 putchar         ( char color x y imgbuf -- ) put graphic character in
651                 imagebuffer to specified (x & y) location.
652
653 scroll          ( x y imgbuf -- ) scroll in imgbuf.
654
655 scrollf         ( color x y screen -- )  scroll and fill empty space with
656                 given color.
657
658 at!             ( x y -- ) set cursor location
659 curc!           ( color -- ) set text color
660 curb!           ( solor -- ) set backround color
661
662 colnorm         ( -- ) set text color to normal
663 colneg          ( -- ) set text color to negative (selected)
664
665 dyntype         ( dynhandle -- ) display contenc of dynamic memory on screen
666 fsdisp          ( file -- ) clear screen, display file, and wait for key
667
668 type            ( addr length -- )
669                 Types on the screen string, from memory at  addr  and
670                 specified length.
671
672 write           ( addr -- )
673                 Types on the screen string, from memory at "addr"+1
674                 length is taken from "addr" .
675
676 screen  const   32 bit
677                 Holds handle of screen buffer.
678
679 copyscreen      ( SrcImgHandle DestImgHandle -- ) copy contenc of source
680                 image to destination image. Source and destination images
681                 must have same size.
682 #+END_VERSE
683 ** Math, memory & stack manipulation
684 #+BEGIN_VERSE
685 off             ( n -- ) writes 0 to given address, good for zeroing variable.
686                 ex: MyVariable off
687 on              ( n -- ) writes -1 (true flag) to given address.
688                 ex: MyVariable on
689
690 2dup            ( n1 n2 -- n1 n2 n1 n2 )
691 2drop           ( n1 n2 -- )
692 nip             ( n1 n2 -- n2 )
693 neg             ( n1 -- -n1 ) negotiate
694 bit@            ( n bit -- result ) return specified bit from n.
695                 ex: 38 2 bit@   (result will be 1)
696 to32bit         ( n1 n2 n3 n4 -- n32 ) treat 4 last stack elements as bytes
697                 and unite them into 32 bit dword. Most significant byte
698                 on top.
699                 ex: 12 76 23 11 to32bit   result: 186076172
700
701 to8bit          ( n32 -- n1 n2 n3 n4 ) break 32 bit number into 4 bytes.
702                 Useful if you need to send 32 bit numbers thru 8 bit COM
703                 port.
704                 ex: 186076172 to8bit   result: 12 76 23 11
705
706 mod             ( n1 n2 -- reminder ) divide n1 by n2 and returns reminder.
707                 ex: 12 5 mod   result: 2
708
709 bound           ( low n high -- n ) check if n is in given bounds,
710                 if not then incarease/decarease it to match bounds.
711                 ex: 5 80 15 bound    result: 15
712                     5 10 15 bound    result: 10
713                     5 -10 15 bound   result: 5
714
715 bound?          ( low n high -- result ) returns true if n is in the
716                 given bounds.
717
718 tab             ( col -- spaces) calculate amount of spaces to add
719                 ta reach next tabulation from given column.
720
721 count           ( addr -- addr+1 n )
722                 Useful for returning bytes from constantly incareasing
723                 address. Module "type" is nice example.
724
725 c,              ( n -- )
726                 store one byte at memory specified by "h". And incarease
727                 "h" by 1.
728
729 ,               ( n -- )
730                 store 32 bit number at memory specified by "h". And
731                 incarease "h" by 4.
732
733 cmove           ( addr1 addr2 n -- )
734                 copy "n" amount of bytes from memory at "addr1" to memory
735                 at "addr2".
736
737 rnd             ( limit -- result )
738                 generates random number in range 0 to "limit"-1.
739
740 abs             ( n -- |n| )
741                 returns absolute value of "n"
742 #+END_VERSE
743 ** Dynamic & static strings
744 Fifth supports both static and dynamic strings. Static strings must
745 have predefined space reserved, and string mustn't exceed this
746 length. They manipulation is faster. But they use more memory. Static
747 string memory address is used to refer to the string.
748
749 Dynamic strings can have at any time length form 0 to 0FFh, They take
750 up only memory they currently need. They are held in dynamic memory
751 blocks, so dynamic block handle is used to refer to this string.
752
753 Both types of strings are stored in the way, where first (0th) byte
754 holds current string length, following bytes are string itself.
755
756
757 #+BEGIN_VERSE
758 Dynamic:
759
760 Dstral ( -- handle )
761                 Allocate new string.
762
763 Dstrlen ( handle -- length )
764                 Return string length.
765
766 c+Dstr ( chr handle -- )
767                 Add one byte to end of the string.
768
769 c+lDstr ( chr handle -- )
770                 Add one byte to left side (beginning) of the string.
771
772 Dstr. ( handle -- )
773                 Write contec of string into screen.
774
775 Dstrsure ( size Dstr -- )
776                 Makes sure that at least rquested
777                 "size" (amount of characters) is allocated for given
778                 dynamic string.
779
780 Dstr2str ( handle address -- )
781                 Copy dyamic string into static memory space.
782
783 str2Dstr ( address handle -- )
784                 Copy static string into dyamic string.
785
786 Dstr+str ( Dstr addr -- )
787                 Add contenc of dynamic string to static string.
788
789 D" any string" ( -- Dstr )
790                 Moves specified string into dynamic string called "defDstr".
791
792 D> any_string ( -- Dstr )
793                 Moves specified string into dynamic string called "defDstr".
794                 Space marks end of string!
795
796 D>2 any_string ( -- Dstr )
797                 Moves specified string into dynamic string called "defDstr2".
798                 Space marks end of string!
799
800 Dstr+Dstr ( Dstr1 Dstr2 -- )
801                 Adds "Dstr1" to "Dstr2" and places result into "Dstr2".
802
803 Dstrclear ( Dstr -- )
804                 Clears contenc of dynamic string.
805
806 Dstr2Dstr ( Dstr1 Dstr2 -- )
807                 Moves "Dstr1" to "Dstr2".
808 Dstr ( data" name -- )
809                 Creates new dynamic string and moves specified data into it.
810                 Then creates new constant with given "name" holding created
811                 dynamic string handle.
812
813                 ex: Dstr Hello, my name is Sven!" message      \ creates it
814                     message Dstr.                              \ tests it
815
816 Dstrlscan ( char Dstr -- loc )
817                 Searches dynamic string for "char", from left to right,
818                 returns first found "char" location in string, or 0,
819                 if not found.
820
821 Dstrrscan ( char Dstr -- loc )
822                 Searches dynamic string for "char", from right to left,
823                 returns first found "char" location in string, or 0,
824                 if not found.
825
826 Dstrlscane ( char Dstr -- loc )
827                 Same as "Dstrlscan" buf returns string length+1 as location.
828 ÿ
829 Dstrleft ( amo Dstr -- )
830                 Only specified amount of characters from left remains
831                 in dynamic string. ie. cut right part out.
832
833 Dstrright ( amo Dstr -- )
834                 Only specified amount of characters from right remains
835                 in dynamic string. ie. cut left part out.
836
837 Dstrcutl ( amo Dstr -- )
838                 Cut specified amount of characters from left of dynamic
839                 string out.
840
841 Dstrsp ( char Dstr1 Dstr2 -- )
842                 Separate dynamic string in Dstr1 into two parts,
843                 using "char" as separator. First part will be stored in
844                 "Dstr2", second part in "Dstr1".
845                 ex: asc \                               \ ..separator
846                     D> listF\listLIB\5TH_DRVMOUSE       \ ..separate from
847                     defDstr2                            \ ..place result in
848                     Dstrsp              \ separation command
849                     defDstr Dstr.       \ will be: listLIB\5TH_DRVMOUSE
850                     defDstr2 Dstr.      \ will be: listF
851
852 Dv ( addr -- )
853                 Allocates empty dynamic string, and places it's handle
854                 into given address.
855
856 Df ( addr -- )
857                 Reads dynamic string handle from given address and
858                 deallocates (frees) it.
859
860 ex:     var mystring1
861         : testmodule
862         mystring1 Dv            \ allocates string
863
864                 <whatever>
865
866         mystring1 Df ;          \ deallocates it again when no longer needed.
867 #+END_VERSE
868 * Dynamically loadable modules
869 ** Keyboard driver
870 #+BEGIN_VERSE
871
872 KBD_@           ( -- code ) get scancodes for pressed keys from keyboard.
873 KBD_down?       ( key -- result ) check is key with specified scancode
874                 currently pressed down.
875 KBD_SC2FSCII    ( code -- FSCII ) convert key scancode into FSCII code,
876                 or in FSK (Fifth standard keycode).
877 KBD_F@          ( -- FSCII ) read pressed key FSCII or FSK, returns -1 if no
878                 keys are pressed.
879 KBD_FW@         ( -- FSCII ) read pressed key FSCII or FSK, if no keys is
880                 are pressed then waits until there is.
881
882                 FSK
883                 ---
884 In HEX.
885
886 FC      backspace
887 FD      TAB
888 FE      enter
889 FF      space
890
891 400     ESC
892 401 ... F1 ...
893 410     up
894 411     right
895 412     down
896 413     left
897 414     INS
898 415     DEL
899 416     home
900 417     end
901 418     PG/UP
902 419     PG/DN
903 #+END_VERSE
904 ** Mouse driver
905 #+BEGIN_VERSE
906 mousex  var     Mouse x coordinate.
907 mousey  var     Mouse y coordinate.
908 mousekeyl var   Mouse left key.
909 mousekeym var   Mouse middle key.
910 mousekeyr var   Mouse right key.
911 mousec  var     Display current mouse coordinates in top left part of screen,
912                 if true. (good for debugging)
913 mousepointer var  Image buffer, holding current mouse pointer.
914 mouseadd        ( ModuleAddr x1 x2 y1 y2 -- ) Add specified area on screen,
915                 into mause click buffer. If any mouse button is clicked on
916                 that area, module at "ModuleAddr" will be executed.
917 mousebe var     Amount of buffer elements.
918 mousedo         ( -- ) Updates mouse coordinates and keys. Parse mouse
919                 click buffer, and draw mouse cursor to "screen".
920 #+END_VERSE
921 ** 2D graphic library
922 #+BEGIN_VERSE
923 lineh           ( color len x y imgbuf -- ) draws horisontal line
924                 from X,Y coordinates to right, with specified length.
925 linev           ( color len x y imgbuf -- ) draws vertical line
926                 down, from coordinates X,Y, with specified length.
927 box             ( color x2 x1 y2 y1 imgbuf -- ) draws rectangular
928                 box. x2 bust be >= x1, y2 must be >= y1.
929                         x1,y1-----------+
930                           |             |
931                           |             |
932                           +-----------x2,y2
933
934 flipv           ( imgbuf -- ) flip image vertically.
935 imgcoltrans     ( ImgBuf Color ToColor -- ) Translate all pixels in
936                 specified image with "Color" into "ToColor".
937 imgfill         ( color x y imgbuf -- ) Fill image region starting at location
938                 X & Y with specified color.
939 #+END_VERSE
940 ** Trigonometry functions
941 #+BEGIN_VERSE
942 sin             ( a -- result ) return sinus from given angle "a",
943                 360ø is 2000. So 1000 represents 180ø angle.
944                 Result will be in range -10'000 to 10'000, instead of ñ1.
945
946 cos             ( a -- result ) return cosinus from given angle.
947                 Parameters are like in "sin" function.
948 #+END_VERSE