1 #+TITLE: Fifth - virtual machine, operating system, programming language
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;}
13 - This program is free software: released under Creative Commons Zero
18 - Homepage: https://svjatoslav.eu
19 - Email: mailto://svjatoslav@svjatoslav.eu
21 - [[https://www.svjatoslav.eu/projects/][Other software projects hosted at svjatoslav.eu]]
23 - [[https://www2.svjatoslav.eu/gitweb/?p=fifth.git;a=snapshot;h=HEAD;sf=tgz][Download latest snapshot in TAR GZ format]]
25 - [[https://www2.svjatoslav.eu/gitweb/?p=fifth.git;a=summary][Browse Git repository online]]
27 - Clone Git repository using command:
28 : git clone https://www2.svjatoslav.eu/git/fifth.git
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.
35 Currently I try to implement those new ideas in the project called
36 [[https://www3.svjatoslav.eu/projects/sixth/][Sixth]].
38 System is built many years ago when I was still using DOS as a primary
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.
47 - [[file:5TH_ET.txt][Example Fifth source file - text editor]]
49 [[file:screenshots/start.png]]
51 Startup screen diplaying Fifth logo and full file list.
53 [[file:screenshots/dictionary.png]]
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.
60 [[file:screenshots/text editor.png]]
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 ).
70 Read more about [[id:0759f3e0-28bb-4901-9e4f-09ef41732173][Fifth distribution directory tree description]].
72 * Fifth distribution directory tree description
74 :ID: 0759f3e0-28bb-4901-9e4f-09ef41732173
76 After downloading and unpacking the ZIP file you shoud get directory
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
85 *imageFile* - files contained within 'disk.raw', just an extracted form.
87 *source* - source files
88 *emulator* - emulator source
91 *disk.raw* - Virtual disk file, has filesystem inside.
92 *emulator.com* - main executable.
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).
105 - 64 KB free RAM below 640KB,
107 - VESA compatible video card.
109 - Beginner level Forth knowledge is recommended.
110 - Lots of enthusiasm.
111 * Numbers representation within Fifth
113 [[file:numbers.png][file:numbers.png]]
115 Because I can define everything, starting from CPU, why not try also
116 alternative and unique number representation ?
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
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 |
134 |------+--------------------------|
136 | -1 | empty sector |
137 | 0 -- | .. pointer to next block |
139 | offset | length | description |
140 |--------+--------+------------------------|
141 | 0 | 4 | extension |
143 | 20 | 4 | entry point |
145 | 28 | 4 | last modification time |
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 < previous entry |
161 |--------+--------+-----------------------|
162 | 4 | 15 | module name string |
163 |--------+--------+-----------------------|
164 | 19 | 1 | entry type |
165 |--------+--------+-----------------------|
166 | 20 | 4 | entry data |
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 |
182 | location | size | description |
183 |----------+--------+-----------------------------|
185 | 1500000 | ~32000 | highlevel Fifth boot code |
186 | 200000h | | core startup messages area |
187 | 5200000 | | end of dynamic memory space |
190 :ID: 9b251eb9-aff6-4025-94bf-25e89e26d54a
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.
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).
206 Maybe one day similar system will run directly on custom silicon chip :)
209 CPU has following registers:
210 | IP | instruction pointer |
211 | DSP | data stack pointer |
212 | RSP | return stack pointer |
215 Virtual CPU, commands (most of them are avaiable as ordinary commands
216 in programming language):
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 |
270 *** kbd@ - read scancode of pressed or released key
272 :ID: 820b1b90-4f4c-4ab1-b49f-9b4a52ea2528
274 Returns 0 if no data available.
275 *** vidput - put image1 into image2, at location x, y
277 :ID: 238e8b03-57b6-424d-bfee-b6bb652cefbc
279 Does clipping, so part of a big image can be mapped into smaller one.
280 *** cmove - copy memory array
282 :ID: 79e1916f-4103-42cc-ac10-bb1ee776ed50
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
288 *** tvidput - put image with transparency support
290 :ID: ab45247c-44c3-464d-9e2a-337f483b4616
295 Put image1 into image2, at location x, y with transparency support
297 Color 255 in source image is treated as transparent.
298 *** charput - draw text character
300 :ID: 4bb479cf-aae0-4128-9868-f016c286a162
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
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.
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) |
322 | else | | ordinary characters, same as in ASCII. |
324 ** Compilation & miscellaneous
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.
332 head <name> ( -- ) compiles new dictionary entry without specifying
336 : <name> ( -- ) creates new code module
337 ; ( -- ) ends module (immideate)
338 ex: : hello ." hi there" ;
340 const <name> ( n -- ) defines new constant.
341 ex: 2147483647 const max
343 :i <name> ( -- ) same as ":" but this module will be executed
344 immideately even in compile mode.
347 create <name> ( -- ) same as "head" , but specify module type as data.
348 ex: create LotoResults 5 , 13 , 52 , 12 , 11 , 3 ,
350 allot ( n -- ) allocate n bytes in dictionary.
351 ex: create MyArray 100 allot
353 " <string>" ( -- ) compile string and its size into core.
354 ex: create Mystring " This is it's contects"
356 str <name> <string>" ( -- ) just shorter way for defining strings.
357 ex: str Mystring This is it's contenc"
359 var <name> ( -- ) define new 32 bit variable.
362 ' <module> ( -- n ) return memory address of given entry.
365 forget <name> ( -- ) erases from RAM given entry and all entries what was
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 * ] ;
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.
383 : run dispver ." running ..." ;
385 : (dispver ." Version 9.99 " ;
386 ' (dispver ' dispver is
388 Now if I type "run" on the screen appears:
389 Version 9.99 running ...
391 asc <char> ( -- ) reads char ascii code and treats it as literal.
393 ex: : BreakLine 30 do asc - emit loop ;
395 : BreakLine 30 do 45 emit loop ;
397 dyninc ( handle -- ) execute code in dynamic memory handle.
398 automatically deallocates it when done.
400 include ( filenumber -- ) execute code in specified file.
402 words ( -- ) display existing blocks in core.
404 bye ( -- ) exit from Fifth
407 Read one byte from input stream.
410 Add one byte "c" to string located at "addr" and updates
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.
418 input stream: """"This is test !"aoeu idh
419 result: This is test !
421 Is useful for breaking text lines into words.
424 So called safe "fkey". Reads data from input stream
425 but converts characters with ASCII codes: 9 13 10
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.
435 Searches whole dictionary for word in "pad". If found,
436 returns it address, if not, returns 0.
439 Execute word located in "pad". Depending on "mode".
441 dta ( addr -- DataAddr )
442 Calculates address of dictionary entry data area, from
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.
450 dadd ( addr length -- )
451 Add to dictionary data located at "addr", with specified
455 Act with number depending on "mode". When interpreting,
460 Add to dictionary data located at "addr"+1 , length is taken
467 Holds input stream parser operation mode.
472 Holds temprorary strings.
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.
480 Pointer to last dictionary word. Each time when new word is
481 compiled or erased by "forget", this pointer is updated.
483 modulechk ( Dstr<filename> -- ) check if module is loaded, if not
486 ne ( entrydata entrytype -- ) Compile new dictionary entry.
487 It's name must be in "pad".
489 ** Conditionals & control flow
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
497 ex: 1 if ." nonzero" else ." zero" then
499 >= ( n1 n2 -- result ) true if (n1 = n2) or (n1 > n2)
500 ex: 5 3 >= if ." first number is greater or equal" then
502 <= ( n1 n2 -- result ) true if (n1 = n2) or (n1 < n2)
503 = ( n1 n2 -- result ) true if n1 = n2
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 ;
511 doexit ( -- ) exit from "do .. loop"
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 ;
519 forexit ( -- ) exit from "for .. loop"
521 until ( -- ) (immideate)
522 "until .. loop" construction. Performs ".." until flag become
523 true. False by default. Top of return stack holds flag.
525 done ( -- ) exit from "until .. loop"
528 ** Disk & file access
530 diskload ( FromDisk ToMem amount -- )
531 Load specified abount of bytes from disk into memory.
533 disksave ( FromMem ToDisk amount -- )
534 save specified abount of bytes from memory into disk.
536 format ( -- ) Erase all files.
538 fsDfilesize@ ( handle -- size )
539 Return size of opened file.
541 fsDcurloc@ ( handle -- location )
542 Return current location in file.
544 fsDupdated@ ( handle -- updated? )
545 Return true if file was updated,
546 ie. write operations occured.
548 fssave ( FromMem DestFileHandle amount -- )
551 fsload ( SrcFileHandle ToMem amount -- )
554 fseof ( handle -- bytesLeft )
555 Return amount of bytes left till end of file.
556 Useful before read operation.
558 fsls ( -- ) List all files and lists (directories,folders)
561 fslsr ( -- ) Same as "fsls" but recursively scans also sub lists.
563 fscl ( DynStrHand -- )
566 fscreate ( DynStrHand -- DescPnt )
567 Create new file or list. Can create multiple lists at once.
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.
574 fsDsave ( DynHand<data> DynStrHand<filename> -- )
575 Create new file and save all data from dynamic memory
578 fsDload ( DynStr<SrcFileName> DynHand<DataDest> -- )
579 Load whole file into dynamic memory block.
581 fsDloadnew ( DynStr<SrcFileName> -- DynHand<DataDest> )
582 Load whole file into new dynamic memory block.
586 dynal ( size -- handle )
587 Allocate dynamic memory block and return it's handle.
590 Deallocate dynamic memory block.
592 dynp ( handle -- addr )
593 Returns pointer to memory where dynamic block
596 dyns ( handle -- size )
597 Returns size of dynamic block.
599 dynresize ( NewSize handle -- )
600 Nondestructively resize dynamic block.
602 dync@ ( addr handle )
603 Read one byte from dynamic block.
605 dync! ( byte addr dynhandle )
606 Write one byte to dynamic block.
609 Read 32 bit number from dynamic block.
610 Address will spacify, whitch number, not byte.
612 dyn! ( 32BitNum addr dynhandle )
613 Write 32 bit number to dynamic block.
614 Address will spacify, whitch number, not byte.
616 dyncon ( size "name" -- )
617 Allocate dynamic block with specified size, and
618 create constant honding its handle.
619 ex: 100 dyncon MyNewBlock
622 Write contenc of dynamic memory block to screen.
626 . ( n -- ) print number on screen
628 d. ( n -- ) print number on screen in decimal
630 ? ( addr -- ) print 32 bit value located at addr.
632 ." <string>" ( -- ) print string into screen. Immideately
634 ex: : greeting ." Hello, World" ;
636 tab. ( -- ) print tabulator
638 calccol ( b g r -- c ) calculate color what best matches given
639 Blue Green & Red values. Values must be in range 0 - 255.
641 imgalloc ( xsize ysize -- imgbuf ) allocate image buffer for
644 imgsize ( imgbuf -- ) print on the screen X & Y size of image
647 point ( x y imgbuf -- addr ) returns memory address for specified
650 pset ( color x y imgbuf -- ) set graphic point
652 boxf ( x1 x2 y1 y2 imgbuf color -- ) draw filled box
654 cls ( imgbuf -- ) clear image buffer
656 setpal ( b g r color -- ) set palette value for specified color.
657 values bust be in size 0 - 63.
659 putchar ( char color x y imgbuf -- ) put graphic character in
660 imagebuffer to specified (x & y) location.
662 scroll ( x y imgbuf -- ) scroll in imgbuf.
664 scrollf ( color x y screen -- ) scroll and fill empty space with
667 at! ( x y -- ) set cursor location
668 curc! ( color -- ) set text color
669 curb! ( solor -- ) set backround color
671 colnorm ( -- ) set text color to normal
672 colneg ( -- ) set text color to negative (selected)
674 dyntype ( dynhandle -- ) display contenc of dynamic memory on screen
675 fsdisp ( file -- ) clear screen, display file, and wait for key
677 type ( addr length -- )
678 Types on the screen string, from memory at addr and
682 Types on the screen string, from memory at "addr"+1
683 length is taken from "addr" .
686 Holds handle of screen buffer.
688 copyscreen ( SrcImgHandle DestImgHandle -- ) copy contenc of source
689 image to destination image. Source and destination images
692 ** Math, memory & stack manipulation
694 off ( n -- ) writes 0 to given address, good for zeroing variable.
696 on ( n -- ) writes -1 (true flag) to given address.
699 2dup ( n1 n2 -- n1 n2 n1 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
708 ex: 12 76 23 11 to32bit result: 186076172
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
713 ex: 186076172 to8bit result: 12 76 23 11
715 mod ( n1 n2 -- reminder ) divide n1 by n2 and returns reminder.
716 ex: 12 5 mod result: 2
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
724 bound? ( low n high -- result ) returns true if n is in the
727 tab ( col -- spaces) calculate amount of spaces to add
728 ta reach next tabulation from given column.
730 count ( addr -- addr+1 n )
731 Useful for returning bytes from constantly incareasing
732 address. Module "type" is nice example.
735 store one byte at memory specified by "h". And incarease
739 store 32 bit number at memory specified by "h". And
742 cmove ( addr1 addr2 n -- )
743 copy "n" amount of bytes from memory at "addr1" to memory
746 rnd ( limit -- result )
747 generates random number in range 0 to "limit"-1.
750 returns absolute value of "n"
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.
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.
762 Both types of strings are stored in the way, where first (0th) byte
763 holds current string length, following bytes are string itself.
772 Dstrlen ( handle -- length )
773 Return string length.
775 c+Dstr ( chr handle -- )
776 Add one byte to end of the string.
778 c+lDstr ( chr handle -- )
779 Add one byte to left side (beginning) of the string.
782 Write contec of string into screen.
784 Dstrsure ( size Dstr -- )
785 Makes sure that at least rquested
786 "size" (amount of characters) is allocated for given
789 Dstr2str ( handle address -- )
790 Copy dyamic string into static memory space.
792 str2Dstr ( address handle -- )
793 Copy static string into dyamic string.
795 Dstr+str ( Dstr addr -- )
796 Add contenc of dynamic string to static string.
798 D" any string" ( -- Dstr )
799 Moves specified string into dynamic string called "defDstr".
801 D> any_string ( -- Dstr )
802 Moves specified string into dynamic string called "defDstr".
803 Space marks end of string!
805 D>2 any_string ( -- Dstr )
806 Moves specified string into dynamic string called "defDstr2".
807 Space marks end of string!
809 Dstr+Dstr ( Dstr1 Dstr2 -- )
810 Adds "Dstr1" to "Dstr2" and places result into "Dstr2".
812 Dstrclear ( Dstr -- )
813 Clears contenc of dynamic string.
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.
822 ex: Dstr Hello, my name is Sven!" message \ creates it
823 message Dstr. \ tests it
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,
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,
835 Dstrlscane ( char Dstr -- loc )
836 Same as "Dstrlscan" buf returns string length+1 as location.
838 Dstrleft ( amo Dstr -- )
839 Only specified amount of characters from left remains
840 in dynamic string. ie. cut right part out.
842 Dstrright ( amo Dstr -- )
843 Only specified amount of characters from right remains
844 in dynamic string. ie. cut left part out.
846 Dstrcutl ( amo Dstr -- )
847 Cut specified amount of characters from left of dynamic
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
862 Allocates empty dynamic string, and places it's handle
866 Reads dynamic string handle from given address and
867 deallocates (frees) it.
871 mystring1 Dv \ allocates string
875 mystring1 Df ; \ deallocates it again when no longer needed.
877 * Dynamically loadable modules
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
888 KBD_FW@ ( -- FSCII ) read pressed key FSCII or FSK, if no keys is
889 are pressed then waits until there is.
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".
930 ** 2D graphic library
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.
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.
949 ** Trigonometry functions
950 *** sin ( a -- result )
952 :ID: 9a66ca9c-eb5f-45aa-8116-71763081f2fb
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.