1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;; based on AberSoft FIG-Forth v1.1A
4 ;; restored & partially rewritten by Ketmar
5 ;; distribution terms: GNU GPL v3
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 ;; excuse me my English, i'm not a native speaker
10 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 ;; the code has to be optimized!!!
12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15 ;; set this to 0 to save ~700 bytes
19 ;; those words are of little use
20 USE_EXT_BLOCK_WORDS EQU 0
22 ;; waste ~350 bytes for textual error messages?
23 USE_TEXT_ERROR_MESSAGES EQU 1
26 USE_EXT_LAST_KEY EQU 0
28 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37 ;; bit 5: SMUDGE flag (=1: word definition isn't finished)
38 ;; bit 6: IMMEDIATE flag (=1: true)
40 ;; the last byte of the name always has bit 7 set
42 ;; for CODE words: cfa points to the body
43 ;; for FORTH words: cfa points to "_doforth"
44 ;; for CONST words: cfa points to "_doconst"
45 ;; for VAR words: cfa points to "_dovar"
46 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
51 ;; BC: address interpreter insrtuction pointer
53 ;; IY: used by ROM, do not change
54 ;; all other regs are free
57 ;; data stack: machine stask (PUSH/POP)
58 ;; exec stack: address with f_curRP (last item)
59 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
63 ;; start address: #6000
66 jp run_0 ;; DO NOT CHANGE THIS TO JR!
74 ; save byte at #C000 for 48K
85 out (c),a ;; now #C000 should be the screen page #5
86 ld (#C000),a ;; trash it
88 out (c),a ;; and go back (just in case) %-)
90 ld (hl),0 ;; so it won't be visible
91 or a ;; now check if we really trashed the scrren
114 ;;;;;;;;;;;;;;; VARIABLES
120 ;; it grows to to lower addresses (to 0), just as the data stack
121 ;; currently it's address is hardcoded
122 f_curRP: defw #D7AE ;; ???
124 ;; address of the first "user" variable (def: run_cold-64)
125 f_userBASE: defw forth_default_user_area ;; was:#D7B0
131 defw #FFE0 ;; S0: starting SP. SP grows to addr #0000; was #D600
133 defw #F800 ;; R0: starting RP. RP grows to addr #0000; was #D7AE
136 ;; WARNING! keep in sync with `FORTH_USER` and `COLD`!
138 defw 1 ;; WARNING -- if we have no messages text, 1 is the same as 0
139 defw latest_byte ;; FENCE
140 defw latest_byte ;; DP
141 defw forth_voc_link ;; VOC-LINK
142 f_userDEF_size equ $-f_userDEF
143 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
145 ;;; address interpreter
166 ;;; end of address interpreter
169 $FORTH_CONST (.NEXT) i_next
170 $FORTH_CONST (.PUSHHL) i_pushhl
171 $FORTH_CONST (.PUSHDEHL) i_pushde
172 $FORTH_CONST (@CUR-RP) f_curRP
173 $FORTH_CONST (@CUR-BASE) f_userBASE
174 $FORTH_CONST (LAST-7FFD) f_cur7FFD
186 $FORTH_END_CODE_WORD LIT
188 $FORTH_CODE_WORD EXECUTE
193 $FORTH_END_CODE_WORD EXECUTE
195 $FORTH_CODE_WORD BRANCH XBRANCH
200 ;; original code for relative RBRANCH
213 $FORTH_END_CODE_WORD BRANCH
215 $FORTH_CODE_WORD 0BRANCH XBRANCH
225 $FORTH_END_CODE_WORD 0BRANCH
227 $FORTH_CODE_WORD TBRANCH XBRANCH
234 $FORTH_END_CODE_WORD TBRANCH
236 $FORTH_CODE_WORD (LOOP) XBRANCH
273 $FORTH_END_CODE_WORD (LOOP)
275 $FORTH_CODE_WORD (+LOOP) XBRANCH
279 $FORTH_END_CODE_WORD (+LOOP)
281 $FORTH_CODE_WORD (DO)
283 ;; ( limit start -- )
284 ;; loops from start to limit-1
301 $FORTH_END_CODE_WORD (DO)
313 $FORTH_END_CODE_WORD I
323 $FORTH_END_CODE_WORD I'
332 jr fword_loadrp_itick
333 $FORTH_END_CODE_WORD J
342 $FORTH_END_CODE_WORD J'
344 ;; DO/LOOP will stop on the next iteration
345 $FORTH_CODE_WORD LEAVE
357 $FORTH_END_CODE_WORD LEAVE
360 $FORTH_CODE_WORD DIGIT
362 ;; ( c base -- n2 true ) ok case
363 ;; ( c base -- false ) error case
367 ;; k8: allow lowercased chars
386 ld hl,0 ;; k8: just in case of invalid base
388 $FORTH_END_CODE_WORD DIGIT
391 $FORTH_CODE_WORD (FIND)
393 ;; ( addr l addr2 -- pfa b tf ok)
394 ;; ( addr l addr2 -- ff bad)
442 $FORTH_END_CODE_WORD (FIND)
445 $FORTH_CODE_WORD ENCLOSE
447 ;; ( addr delimeter -- addr w_start_ofs w_end_ofs next_scan_ofs )
448 pop de ;; E=delimeter
457 ;; here: E=word len; A=delim; HL=addr
466 push de ;; store # of delimiters before the word
468 ld d,a ;; D=delimiter
469 ;; check for "end of buffer" (#0)
474 ;; oops... no more blondies on the island
477 push de ;; store full length
480 push de ;; store position of the next char to scan
483 ;; here: E=word len; D=delim; HL=addr
485 ;; now collect the word itself
490 jr z,enclose2 ;; word ends?
491 ;; no, check "end of buffer"
496 ;; oops... no more blondies on the island
498 push de ;; store full length
499 push de ;; store position of the next char to scan (???)
504 push de ;; store full length
506 push de ;; store position of the next char to scan
508 $FORTH_END_CODE_WORD ENCLOSE
510 include "math_bitop.zas"
511 include "math_compare.zas"
512 include "math_basic.zas"
513 include "math_misc.zas"
514 include "math_hlev.zas"
516 include "main_stackops.zas"
517 include "main_memops.zas"
519 $FORTH_CODE_WORD FORTH-WORD?
536 $FORTH_END_CODE_WORD FORTH-WORD?
538 ;; check if BREAK is pressed
539 $FORTH_CODE_WORD ?BREAK
542 call #1F54 ;; uses only A
547 $FORTH_END_CODE_WORD ?BREAK
549 include "main_hldef.zas"
551 ;;;;;;;;;;;;;; some speedup constants
568 $FORTH_END_WORD +ORIGIN
570 ;; offsets to some COLD values
571 $FORTH_CONST (COLD-INIT-SP) f_initSP
572 $FORTH_CONST (COLD-INIT-RP) f_initRP
573 $FORTH_CONST (COLD-TIBPTR) f_tibptr
575 ;; these ones will be inited by COLD with the predefined values
579 $FORTH_USER WIDTH #0C
580 $FORTH_USER WARNING #0E
581 $FORTH_USER FENCE #10
583 $FORTH_USER VOC-LINK #14
584 ;; these ones will not be inited by COLD
587 fuserofs_readonly equ #1A
588 $FORTH_USER READ-ONLY #1A
590 ;; OFFSET is the offset for BLOCK operation
591 ;; i.e. actual block number will be n+OFFSET
592 $FORTH_USER OFFSET #1E
593 $FORTH_USER CONTEXT #20
594 $FORTH_USER CURRENT #22
595 $FORTH_USER STATE #24
603 $FORTH_USER SHOW-HIDDEN #32
604 fuserofs_showhidden equ #32
605 ;; new var for TLOAD: if not zero, we're loading from a disk file
606 ;;$FORTH_USER TLOAD-Y #34
608 forth_default_user_size equ #40
609 forth_default_user_area defs #40,0
612 ;; 6x8 printing driver
613 include "main_emit6.zas"
614 include "main_key6.zas"
616 $FORTH_CODE_WORD (HANG)
620 $FORTH_END_CODE_WORD (HANG)
625 ;;;; return to BASIC?
633 $FORTH_END_CODE_WORD BYE
635 $FORTH_CODE_WORD 128K?
641 $FORTH_END_CODE_WORD 128K?
643 $FORTH_CODE_WORD 48K?
650 $FORTH_END_CODE_WORD 48K?
654 (.") ~\n48K/128K dsFORTH v0.0.2\n~
655 (.") ~original version: \x7F Abersoft, 1983\n~
656 (.") ~modifications by Ketmar//Invisible Vector\n~
657 ;; (.") ~distribution terms: GNU GPL\n~
659 $FORTH_END_WORD .CREDITZ
662 ;; ;eave the address of the next available dictionary location
673 SP@ RP@ UMIN BL - DP @ U< 0BRANCH allot0
674 (.") ~ALLOT: out of memory!\n~ ;;"
679 $FORTH_END_WORD ALLOT
696 ;; ( addr1 n -- addr2 )
699 OVER + LIT 127 OVER C@ <
702 $FORTH_END_WORD TRAVERSE
709 $FORTH_END_WORD LATEST
726 LIT 5 - -1 TRAVERSE ;S
732 1 TRAVERSE LIT 5 + ;S
751 $FORTH_END_WORD ?ERROR
756 STATE @ 0= LIT 17 ?ERROR ;S
757 $FORTH_END_WORD ?COMP
762 STATE @ LIT 18 ?ERROR ;S
763 $FORTH_END_WORD ?EXEC
769 $FORTH_END_WORD ?PAIRS
774 SP@ CSP @ - LIT 20 ?ERROR ;S
780 BLK @ 0= LIT 22 ?ERROR ;S
781 $FORTH_END_WORD ?LOADING
786 ?COMP R> DUP 2+ >R @ , ;S
787 $FORTH_END_WORD COMPILE
804 LATEST LIT #20 TOGGLE ;S
805 $FORTH_END_WORD SMUDGE
817 $FORTH_END_WORD BINARY
823 $FORTH_END_WORD DECIMAL
829 $FORTH_END_WORD COUNT
831 $FORTH_WORD -TRAILING
833 ;; ( addr n1 -- addr n2 )
836 OVER OVER + 1- C@ BL - 0BRANCH ntrailing1
837 LEAVE BRANCH ntrailing2
843 $FORTH_END_WORD -TRAILING
849 R@ COUNT dup 1+ R> + >R TYPE ;S
850 $FORTH_END_WORD (.") ;;"
852 $FORTH_WORD ." IMM ;;"
855 LIT 34 STATE @ 0BRANCH dotq0
857 WORD C@ 1+ ALLOT BRANCH dotq1
862 $FORTH_END_WORD ." ;;"
864 $FORTH_CODE_WORD (") ;;"
876 $FORTH_END_CODE_WORD (") ;;"
878 $FORTH_WORD " IMM ;;"
881 ;; compile string into the current definition
882 ;; or place it at PAD (depends of current STATE)
883 LIT 34 STATE @ 0BRANCH dots0
885 WORD C@ 1+ ALLOT BRANCH dots1
890 $FORTH_END_WORD " ;;"
892 include "main_editstr.zas"
897 1- (EDITSTR-MAXLEN) ! (EDITSTR-ADDR) !
898 (EDITSTR-LEN) 0! (EDITSTR-cp) 0!
900 $FORTH_END_WORD EXPECT
905 TIB @ LIT 80 EXPECT IN 0! ;S
906 $FORTH_END_WORD QUERY
908 ;; ~ will be changed to char with code 0 by ZASM
909 ;; this word will be called by INTERPRET
910 ;; when it meets the end of line marker (0x00)
911 ;; zwb: break INTERPRET
912 ;; zw2: continue INTERPRETING
913 $FORTH_WORD ~ IMM ;; #0
916 ;;TLOAD-Y @ 0BRANCH zwx
918 FREADLN 0BRANCH zwx1 ;; no more lines
919 DROP TIB ! IN 0! BRANCH zw2
923 LIT f_tibptr @ DUP 0! TIB ! IN 0!
928 1 BLK +! IN 0! BLK @ b/SCR 1- AND 0= 0BRANCH zw0
947 ;; read next word from the input stream
948 ;; place it at HERE as the counted string
951 ;; ( delimeter -- here )
952 BLK @ 0BRANCH word0 ;; not LOADing?
953 BLK @ BLOCK BRANCH word1 ;; else -- load block and get its address
958 ;; ENCLOSE: ( addr delimeter -- addr w_start_ofs w_end_ofs next_scan_ofs )
961 IN +! ;; ( addr w_start_ofs w_end_ofs )
962 OVER - ;; ( addr w_start_ofs w_len )
963 DUP >R HERE C! ;; length stored; ( addr w_start_ofs | w_len )
970 ;; ( d1 addrl -- d2 addr2 )
971 ;; converts from (addrl+1)
973 1+ DUP >R C@ BASE @ DIGIT 0BRANCH xnumber2
974 SWAP BASE @ U* DROP ROT BASE @ U* D+ DPL @ 1+ 0BRANCH xnumber1
980 $FORTH_END_WORD (NUMBER)
985 ;; sets DPL if decimal point was found
986 0 0 ROT DUP 1+ C@ LIT 45 = DUP >R + -1
988 DPL ! (NUMBER) DUP C@ BL - 0BRANCH number1
989 DUP C@ LIT 46 - 0 ?ERROR 0
992 DROP R> 0BRANCH number2
996 $FORTH_END_WORD NUMBER
999 ;; read next word from the input stream
1000 ;; search it in the dictionary
1003 ;; ( -- pfa b tf ok)
1005 BL WORD CONTEXT @ @ (FIND)
1006 DUP 0= 0BRANCH nfind0
1007 DROP HERE LATEST (FIND)
1010 $FORTH_END_WORD -FIND
1016 $FORTH_END_WORD (ABORT)
1018 $FORTH_WORD (ERROR-STOP)
1023 LIT f_tibptr @ TIB !
1025 $FORTH_END_WORD (ERROR-STOP)
1032 WARNING @ 0< 0BRANCH error0
1035 HERE COUNT TYPE (.") ~? ~ ;;"
1037 SP! BLK @ -DUP 0BRANCH error1
1040 LIT f_tibptr @ TIB !
1042 $FORTH_END_WORD ERROR
1048 DUP PFA LFA OVER - PAD SWAP CMOVE
1049 PAD COUNT LIT 31 AND 2DUP + 1- DUP @ LIT #FF7F AND SWAP !
1053 $FORTH_WORD [COMPILE] IMM
1056 -FIND 0= 0 ?ERROR DROP CFA , ;S
1057 $FORTH_END_WORD [COMPILE]
1059 $FORTH_WORD LITERAL IMM
1062 STATE @ 0BRANCH literal0
1066 $FORTH_END_WORD LITERAL
1068 $FORTH_WORD DLITERAL IMM
1071 STATE @ 0BRANCH dliteral0
1072 SWAP LITERAL LITERAL
1075 $FORTH_END_WORD DLITERAL
1080 ;; check for stack underflow
1081 SP@ S0 @ SWAP U< 1 ?ERROR
1082 ;; check for stack overflow
1083 ;; SP@ HERE LIT 128 + U< LIT 7 ?ERROR
1093 $FORTH_END_WORD ?STACK
1096 $FORTH_WORD ([0pfx])
1100 BASE @ >R SWAP BASE !
1101 0 0 ROT (NUMBER) ;; ( d2 addr2 )
1103 HERE COUNT ;; (d2 addr2 here+1 count )
1104 NROT ;; (d2 count addr2 here+1 )
1105 - ;; (d2 count diff )
1111 $FORTH_END_WORD ([0pfx])
1113 $FORTH_WORD [0x] IMM
1118 $FORTH_END_WORD [0x]
1120 $FORTH_WORD [0b] IMM
1125 $FORTH_END_WORD [0b]
1127 $FORTH_WORD [0o] IMM
1132 $FORTH_END_WORD [0o]
1134 $FORTH_WORD [CHAR] IMM
1137 BL WORD COUNT 0= LIT 42 ?ERROR
1140 $FORTH_END_WORD [CHAR]
1143 $FORTH_WORD INTERPRET
1146 -FIND 0BRANCH interpret3
1147 STATE @ < 0BRANCH interpret1
1148 CFA , BRANCH interpret5 ;;OLD: BRANCH interpret2
1152 ?STACK BRANCH interpret0 ;;OLD: BRANCH interpret6
1154 HERE NUMBER DPL @ 1+ 0BRANCH interpret4
1155 DLITERAL BRANCH interpret5
1162 $FORTH_END_WORD INTERPRET
1164 $FORTH_WORD IMMEDIATE
1167 LATEST LIT #40 TOGGLE ;S
1168 $FORTH_END_WORD IMMEDIATE
1170 $FORTH_WORD DEFINITIONS
1173 CONTEXT @ CURRENT ! ;S
1174 $FORTH_END_WORD DEFINITIONS
1182 ;;FIXME: NOT PROPERLY TESTED!
1186 BLK @ 0BRANCH cmt_eol_tib
1187 BLK @ BLOCK BRANCH cmt_eol_main ;; else -- load block and get its address
1192 IN @ + ;; ( staddr curaddr )
1197 DUP 0BRANCH cmt_eol_done
1199 DUP CHCR = TBRANCH cmt_eol_done
1200 DUP CHLF = TBRANCH cmt_eol_done
1206 ;;DEBUG: SPACE DUP U. CR
1220 RP! CR QUERY INTERPRET STATE @ 0= 0BRANCH quit1
1224 $FORTH_END_WORD QUIT
1233 FORTH DEFINITIONS QUIT
1234 $FORTH_END_WORD ABORT
1240 ;; 8 1 16384 TR-SREAD
1244 $FORTH_END_WORD WARM
1250 FIRST BUF-USE ! FIRST BUF-PREV ! DR0
1251 ;; the first USER is at f_userBASE+6
1252 LIT f_userDEF LIT f_userBASE @ LIT 6 + LIT f_userDEF_size CMOVE
1254 LIT f_userBASE @ LIT fuserofs_readonly + 0! ;; READ-ONLY
1255 LIT f_userBASE @ LIT fuserofs_showhidden + 0! ;; SHOW-HIDDEN
1256 LIT latest_word LIT forth_voc_latest !
1257 LIT f_cur7FFD C@ LIT #7FFD OUTP
1259 $FORTH_END_WORD COLD
1262 IF USE_TEXT_ERROR_MESSAGES
1263 forth_error_msg_table:
1267 defc "Dictionary full"
1269 defc "Incorrect address mode"
1271 defc "Is not unique"
1273 defc "RAM disc range"
1277 defc "Load from page 0"
1279 defc "Compilation only"
1281 defc "Execution only"
1283 defc "Conditionals not paired"
1285 defc "Definition not finished"
1287 defc "In protected dictionary"
1289 defc "Use only when loading"
1291 defc "Off current editing screen"
1293 defc "Declare vocabulary"
1295 defc "Word expected"
1298 ;; show warning message
1302 ;; message #0 is "word?" show no warning text
1303 -DUP 0BRANCH message_done
1304 ;; show warning text?
1305 WARNING @ 0BRANCH message_simple
1306 ;; show message line
1307 ;; k8: nope; use built-in text instead
1308 ;; 4 OFFSET @ b/SCR / - .LINE SPACE
1310 LIT forth_error_msg_table
1313 COUNT -DUP 0BRANCH message_loop_done
1314 ;; ( tbl msgid | num )
1315 R@ = 0BRANCH message_loop_skip
1325 BASE @ DECIMAL SWAP . BASE !
1328 $FORTH_END_WORD MESSAGE
1332 ;; show warning message
1336 ;; message #0 is "word?" show no warning text
1337 -DUP 0BRANCH message_done
1339 BASE @ DECIMAL SWAP . BASE !
1342 $FORTH_END_WORD MESSAGE
1350 -FIND 0= 0 ?ERROR DROP LITERAL ;S
1353 include "main_ctrl.zas"
1355 include "main_nprint.zas"
1360 ;; $FORTH_END_WORD ?
1362 include "main_vlist.zas"
1364 ;; read next word from the input stream
1365 ;; place it at PAD as the counted string
1370 WORD PAD C/L 1+ CMOVE ;S
1371 $FORTH_END_WORD TEXT
1377 $FORTH_END_WORD SIZE
1382 SP@ RP@ UMIN BL - HERE - ;S
1383 $FORTH_END_WORD FREE
1389 CURRENT @ CONTEXT @ - LIT 24 ?ERROR
1390 ' DUP FENCE @ U< LIT 21 ?ERROR
1391 DUP NFA DP ! LFA @ CURRENT @ ! ;S
1392 $FORTH_END_WORD FORGET
1396 $FORTH_DOES FORTH voc_does IMM
1401 defw latest_word ;; voc latest
1403 defw 0 ;; prev voc-link
1405 $FORTH_WORD VOCABULARY
1408 <BUILDS LIT #A081 , CURRENT @ CFA , HERE VOC-LINK @ , VOC-LINK ! DOES>
1411 $FORTH_END_WORD VOCABULARY
1420 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1421 ;; buffers, blocks, etc...
1422 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1423 include "main_trdos.zas"
1424 include "main_blocks.zas"
1425 include "ext_textfile.zas"
1426 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1427 ;; end of buffers, blocks, etc...
1428 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1430 include "ext_gfxlo.zas"
1431 include "ext_gfxhi.zas"
1432 include "ext_dump.zas"
1434 ;;;;;;;;;;;;;;;;;;;; INSERT YOUR WORDS BELOW ;;;;;;;;;;;;;;;;;;;;
1437 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1439 ;;!!!!!! THIS LABEL SHOULD BE JUST BEFORE THE LAST DEFINED WORD
1441 ;;!!!!!! DO NOT REMOVE THIS WORD! THE SYSTEM USES IT
1446 $FORTH_END_WORD NOOP
1448 latest_byte: defw 666