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