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