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]]
50 - Startup screen diplaying Fifth logo and full file list.
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.
57 - [[file:screenshots/text editor.png]]
58 - Built in text editor.
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 ).
66 Read more about [[id:0759f3e0-28bb-4901-9e4f-09ef41732173][Fifth distribution directory tree description]].
68 * Fifth distribution directory tree description
70 :ID: 0759f3e0-28bb-4901-9e4f-09ef41732173
72 After downloading and unpacking the ZIP file you shoud get directory
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
81 [imageFile] - files contained within 'disk.raw', just an extracted form.
83 [source] - source files
84 [emulator] - emulator source
87 disk.raw - Virtual disk file, has filesystem inside.
88 emulator.com - main executable.
91 * Software/Hardware/Human requirements
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).
101 - 64 KB free RAM below 640KB,
103 - VESA compatible video card.
105 - Beginner level Forth knowledge is recommended.
106 - Lots of enthusiasm.
107 * Numbers representation within Fifth
109 [[file:numbers.png][file:numbers.png]]
111 Because I can define everything, starting from CPU, why not try also
112 alternative and unique number representation ?
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
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 |
130 |------+--------------------------|
132 | -1 | empty sector |
133 | 0 -- | .. pointer to next block |
135 | offset | length | description |
136 |--------+--------+------------------------|
137 | 0 | 4 | extension |
139 | 20 | 4 | entry point |
141 | 28 | 4 | last modification time |
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 < previous entry |
157 |--------+--------+-----------------------|
158 | 4 | 15 | module name string |
159 |--------+--------+-----------------------|
160 | 19 | 1 | entry type |
161 |--------+--------+-----------------------|
162 | 20 | 4 | entry data |
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 |---------+--------+-----------------------------|
181 | 1500000 | ~32000 | highlevel Fifth boot code |
182 | 200000h | | core startup messages area |
183 | 5200000 | | end of dynamic memory space |
186 :ID: 9b251eb9-aff6-4025-94bf-25e89e26d54a
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.
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).
202 Maybe one day similar system will run directly on custom silicon chip :)
205 CPU has following registers:
206 | IP | instruction pointer |
207 | DSP | data stack pointer |
208 | RSP | return stack pointer |
210 Virtual CPU, commands (most of them are avaiable as ordinary commands
211 in programming lanquage):
215 code mnemonic description
218 1 halt halt CPU ( return to DOS on emulator )
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
224 4 jmp <dword> jump to specified code
225 5 call <dword>jump to specified code, save return address to
231 8 dup ( n -- n n ) duplicate top of data stack
232 9 drop ( n -- ) drop last element in data stack
234 10 if <dword> ( n -- ) jump to addr if top element was 0
235 11 ret jump to code, specified in return stack.
237 12 c@ ( addr -- n ) read byte from memory at specified address
238 13 c! ( n addr -- ) store byte to specified memory
240 14 push ( DSTK -> RSTK ) move top of datastack to returnstack
241 15 pop ( RSTK -> DSTK ) move top of returnstack to datastack
244 17 rot ( n1 n2 n3 -- n2 n3 n1) rotate stack elements
246 18 disk@ ( FromDiskSect ToMem -- ) read 1KB from disk into RAM
247 19 disk! ( FromMem ToDiskSect -- ) write 1KB to disk
249 20 @ ( addr -- n ) read 32 bit number from memory
250 21 ! ( n addr -- ) store 32 bit number to memory
252 22 over ( n1 n2 -- n1 n2 n1 ) self explaining ...
253 23 swap ( n1 n2 -- n2 n1 ) -,,-
255 24 + ( n1 n2 -- n1+n2 ) -,,-
256 25 - ( n1 n2 -- n1-n2 ) -,,-
258 26 * ( n1 n2 -- n1*n2 ) -,,-
259 27 / ( n1 n2 -- n1/n2 ) -,,-
261 28 > ( n1 n2 -- result ) is true when n1 > n2
262 29 < ( n1 n2 -- result ) is true when n1 < n2
264 30 not ( n1 -- not_n1 ) logical not
265 31 i ( -- n ) copies top of return stack into datastack
267 32 cprt@ ( addr -- n ) read one byte from hardware port
268 33 cprt! ( n addr -- ) store one byte to hardware port
270 34 i2 ( -- n ) like "i" but takes socond top stack element.
271 35 i3 ( -- n ) like "i" but takes third top stack element.
273 36 shl ( n amount -- n ) left bit shift
274 37 shr ( n amount -- n ) right bit shift
276 38 or ( n1 n2 -- n ) logical or
277 39 xor ( n1 n2 -- n ) exclusive logical or
279 40 vidmap ( addr -- ) copy memory from "addr" to video memory.
281 41 mouse@ ( -- x y button ) read mouse coordinates & buttons
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.
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
293 44 cfill ( c addr amount -- ) fill memory starting at "addr"
296 45 tvidput ( addr1 addr2 x y -- ) same as "vidput" but treats
297 color 255 in source image as transparent.
299 46 depth ( -- depth ) returns current depth of data stack.
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.
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.
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) |
323 | else | | ordinary characters, same as in ASCII. |
325 ** Compilation & miscellaneous
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.
333 head <name> ( -- ) compiles new dictionary entry without specifying
337 : <name> ( -- ) creates new code module
338 ; ( -- ) ends module (immideate)
339 ex: : hello ." hi there" ;
341 const <name> ( n -- ) defines new constant.
342 ex: 2147483647 const max
344 :i <name> ( -- ) same as ":" but this module will be executed
345 immideately even in compile mode.
348 create <name> ( -- ) same as "head" , but specify module type as data.
349 ex: create LotoResults 5 , 13 , 52 , 12 , 11 , 3 ,
351 allot ( n -- ) allocate n bytes in dictionary.
352 ex: create MyArray 100 allot
354 " <string>" ( -- ) compile string and its size into core.
355 ex: create Mystring " This is it's contects"
357 str <name> <string>" ( -- ) just shorter way for defining strings.
358 ex: str Mystring This is it's contenc"
360 var <name> ( -- ) define new 32 bit variable.
363 ' <module> ( -- n ) return memory address of given entry.
366 forget <name> ( -- ) erases from RAM given entry and all entries what was
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 * ] ;
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.
384 : run dispver ." running ..." ;
386 : (dispver ." Version 9.99 " ;
387 ' (dispver ' dispver is
389 Now if I type "run" on the screen appears:
390 Version 9.99 running ...
392 asc <char> ( -- ) reads char ascii code and treats it as literal.
394 ex: : BreakLine 30 do asc - emit loop ;
396 : BreakLine 30 do 45 emit loop ;
398 dyninc ( handle -- ) execute code in dynamic memory handle.
399 automatically deallocates it when done.
401 include ( filenumber -- ) execute code in specified file.
403 words ( -- ) display existing blocks in core.
405 bye ( -- ) exit from Fifth
408 Read one byte from input stream.
411 Add one byte "c" to string located at "addr" and updates
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.
419 input stream: """"This is test !"aoeu idh
420 result: This is test !
422 Is useful for breaking text lines into words.
425 So called safe "fkey". Reads data from input stream
426 but converts characters with ASCII codes: 9 13 10
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.
436 Searches whole dictionary for word in "pad". If found,
437 returns it address, if not, returns 0.
440 Execute word located in "pad". Depending on "mode".
442 dta ( addr -- DataAddr )
443 Calculates address of dictionary entry data area, from
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.
451 dadd ( addr length -- )
452 Add to dictionary data located at "addr", with specified
456 Act with number depending on "mode". When interpreting,
461 Add to dictionary data located at "addr"+1 , length is taken
468 Holds input stream parser operation mode.
473 Holds temprorary strings.
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.
481 Pointer to last dictionary word. Each time when new word is
482 compiled or erased by "forget", this pointer is updated.
484 modulechk ( Dstr<filename> -- ) check if module is loaded, if not
487 ne ( entrydata entrytype -- ) Compile new dictionary entry.
488 It's name must be in "pad".
490 ** Conditionals & control flow
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
498 ex: 1 if ." nonzero" else ." zero" then
500 >= ( n1 n2 -- result ) true if (n1 = n2) or (n1 > n2)
501 ex: 5 3 >= if ." first number is greater or equal" then
503 <= ( n1 n2 -- result ) true if (n1 = n2) or (n1 < n2)
504 = ( n1 n2 -- result ) true if n1 = n2
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 ;
512 doexit ( -- ) exit from "do .. loop"
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 ;
520 forexit ( -- ) exit from "for .. loop"
522 until ( -- ) (immideate)
523 "until .. loop" construction. Performs ".." until flag become
524 true. False by default. Top of return stack holds flag.
526 done ( -- ) exit from "until .. loop"
529 ** Disk & file access
531 diskload ( FromDisk ToMem amount -- )
532 Load specified abount of bytes from disk into memory.
534 disksave ( FromMem ToDisk amount -- )
535 save specified abount of bytes from memory into disk.
537 format ( -- ) Erase all files.
539 fsDfilesize@ ( handle -- size )
540 Return size of opened file.
542 fsDcurloc@ ( handle -- location )
543 Return current location in file.
545 fsDupdated@ ( handle -- updated? )
546 Return true if file was updated,
547 ie. write operations occured.
549 fssave ( FromMem DestFileHandle amount -- )
552 fsload ( SrcFileHandle ToMem amount -- )
555 fseof ( handle -- bytesLeft )
556 Return amount of bytes left till end of file.
557 Useful before read operation.
559 fsls ( -- ) List all files and lists (directories,folders)
562 fslsr ( -- ) Same as "fsls" but recursively scans also sub lists.
564 fscl ( DynStrHand -- )
567 fscreate ( DynStrHand -- DescPnt )
568 Create new file or list. Can create multiple lists at once.
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.
575 fsDsave ( DynHand<data> DynStrHand<filename> -- )
576 Create new file and save all data from dynamic memory
579 fsDload ( DynStr<SrcFileName> DynHand<DataDest> -- )
580 Load whole file into dynamic memory block.
582 fsDloadnew ( DynStr<SrcFileName> -- DynHand<DataDest> )
583 Load whole file into new dynamic memory block.
587 dynal ( size -- handle )
588 Allocate dynamic memory block and return it's handle.
591 Deallocate dynamic memory block.
593 dynp ( handle -- addr )
594 Returns pointer to memory where dynamic block
597 dyns ( handle -- size )
598 Returns size of dynamic block.
600 dynresize ( NewSize handle -- )
601 Nondestructively resize dynamic block.
603 dync@ ( addr handle )
604 Read one byte from dynamic block.
606 dync! ( byte addr dynhandle )
607 Write one byte to dynamic block.
610 Read 32 bit number from dynamic block.
611 Address will spacify, whitch number, not byte.
613 dyn! ( 32BitNum addr dynhandle )
614 Write 32 bit number to dynamic block.
615 Address will spacify, whitch number, not byte.
617 dyncon ( size "name" -- )
618 Allocate dynamic block with specified size, and
619 create constant honding its handle.
620 ex: 100 dyncon MyNewBlock
623 Write contenc of dynamic memory block to screen.
627 . ( n -- ) print number on screen
629 d. ( n -- ) print number on screen in decimal
631 ? ( addr -- ) print 32 bit value located at addr.
633 ." <string>" ( -- ) print string into screen. Immideately
635 ex: : greeting ." Hello, World" ;
637 tab. ( -- ) print tabulator
639 calccol ( b g r -- c ) calculate color what best matches given
640 Blue Green & Red values. Values must be in range 0 - 255.
642 imgalloc ( xsize ysize -- imgbuf ) allocate image buffer for
645 imgsize ( imgbuf -- ) print on the screen X & Y size of image
648 point ( x y imgbuf -- addr ) returns memory address for specified
651 pset ( color x y imgbuf -- ) set graphic point
653 boxf ( x1 x2 y1 y2 imgbuf color -- ) draw filled box
655 cls ( imgbuf -- ) clear image buffer
657 setpal ( b g r color -- ) set palette value for specified color.
658 values bust be in size 0 - 63.
660 putchar ( char color x y imgbuf -- ) put graphic character in
661 imagebuffer to specified (x & y) location.
663 scroll ( x y imgbuf -- ) scroll in imgbuf.
665 scrollf ( color x y screen -- ) scroll and fill empty space with
668 at! ( x y -- ) set cursor location
669 curc! ( color -- ) set text color
670 curb! ( solor -- ) set backround color
672 colnorm ( -- ) set text color to normal
673 colneg ( -- ) set text color to negative (selected)
675 dyntype ( dynhandle -- ) display contenc of dynamic memory on screen
676 fsdisp ( file -- ) clear screen, display file, and wait for key
678 type ( addr length -- )
679 Types on the screen string, from memory at addr and
683 Types on the screen string, from memory at "addr"+1
684 length is taken from "addr" .
687 Holds handle of screen buffer.
689 copyscreen ( SrcImgHandle DestImgHandle -- ) copy contenc of source
690 image to destination image. Source and destination images
693 ** Math, memory & stack manipulation
695 off ( n -- ) writes 0 to given address, good for zeroing variable.
697 on ( n -- ) writes -1 (true flag) to given address.
700 2dup ( n1 n2 -- n1 n2 n1 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
709 ex: 12 76 23 11 to32bit result: 186076172
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
714 ex: 186076172 to8bit result: 12 76 23 11
716 mod ( n1 n2 -- reminder ) divide n1 by n2 and returns reminder.
717 ex: 12 5 mod result: 2
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
725 bound? ( low n high -- result ) returns true if n is in the
728 tab ( col -- spaces) calculate amount of spaces to add
729 ta reach next tabulation from given column.
731 count ( addr -- addr+1 n )
732 Useful for returning bytes from constantly incareasing
733 address. Module "type" is nice example.
736 store one byte at memory specified by "h". And incarease
740 store 32 bit number at memory specified by "h". And
743 cmove ( addr1 addr2 n -- )
744 copy "n" amount of bytes from memory at "addr1" to memory
747 rnd ( limit -- result )
748 generates random number in range 0 to "limit"-1.
751 returns absolute value of "n"
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.
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.
763 Both types of strings are stored in the way, where first (0th) byte
764 holds current string length, following bytes are string itself.
773 Dstrlen ( handle -- length )
774 Return string length.
776 c+Dstr ( chr handle -- )
777 Add one byte to end of the string.
779 c+lDstr ( chr handle -- )
780 Add one byte to left side (beginning) of the string.
783 Write contec of string into screen.
785 Dstrsure ( size Dstr -- )
786 Makes sure that at least rquested
787 "size" (amount of characters) is allocated for given
790 Dstr2str ( handle address -- )
791 Copy dyamic string into static memory space.
793 str2Dstr ( address handle -- )
794 Copy static string into dyamic string.
796 Dstr+str ( Dstr addr -- )
797 Add contenc of dynamic string to static string.
799 D" any string" ( -- Dstr )
800 Moves specified string into dynamic string called "defDstr".
802 D> any_string ( -- Dstr )
803 Moves specified string into dynamic string called "defDstr".
804 Space marks end of string!
806 D>2 any_string ( -- Dstr )
807 Moves specified string into dynamic string called "defDstr2".
808 Space marks end of string!
810 Dstr+Dstr ( Dstr1 Dstr2 -- )
811 Adds "Dstr1" to "Dstr2" and places result into "Dstr2".
813 Dstrclear ( Dstr -- )
814 Clears contenc of dynamic string.
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.
823 ex: Dstr Hello, my name is Sven!" message \ creates it
824 message Dstr. \ tests it
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,
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,
836 Dstrlscane ( char Dstr -- loc )
837 Same as "Dstrlscan" buf returns string length+1 as location.
839 Dstrleft ( amo Dstr -- )
840 Only specified amount of characters from left remains
841 in dynamic string. ie. cut right part out.
843 Dstrright ( amo Dstr -- )
844 Only specified amount of characters from right remains
845 in dynamic string. ie. cut left part out.
847 Dstrcutl ( amo Dstr -- )
848 Cut specified amount of characters from left of dynamic
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
863 Allocates empty dynamic string, and places it's handle
867 Reads dynamic string handle from given address and
868 deallocates (frees) it.
872 mystring1 Dv \ allocates string
876 mystring1 Df ; \ deallocates it again when no longer needed.
878 * Dynamically loadable modules
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
889 KBD_FW@ ( -- FSCII ) read pressed key FSCII or FSK, if no keys is
890 are pressed then waits until there is.
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".
931 ** 2D graphic library
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.
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.
950 ** Trigonometry functions
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.
956 cos ( a -- result ) return cosinus from given angle.
957 Parameters are like in "sin" function.