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