From a7ef2d0e64f36a779e98e559e134fc76bd66cef1 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 14 Mar 2022 23:38:10 +0100 Subject: [PATCH 01/21] Delete obsolete preptest.fb/fth, replaced by testprep.fb/fth --- 8086/msdos/tests/preptest.fb | 1 - 8086/msdos/tests/preptest.fth | 38 ----------------------------------- 2 files changed, 39 deletions(-) delete mode 100644 8086/msdos/tests/preptest.fb delete mode 100644 8086/msdos/tests/preptest.fth diff --git a/8086/msdos/tests/preptest.fb b/8086/msdos/tests/preptest.fb deleted file mode 100644 index dd70b90..0000000 --- a/8086/msdos/tests/preptest.fb +++ /dev/null @@ -1 +0,0 @@ -\ include file to bundle what test-*.fth need phz 30jan22\ on top of kernel.com \ loadscreen to prepare kernel.com for test-*.fth phz 31jan22 include multi.vid \ include asm.fb \ include extend.fb : arguments ( n -- ) depth 1- > Error" too few params" ; : blank ( addr count -- ) bl fill ; include dos.fb include include.fb include log2file.fb \ No newline at end of file diff --git a/8086/msdos/tests/preptest.fth b/8086/msdos/tests/preptest.fth deleted file mode 100644 index 7d0e4bc..0000000 --- a/8086/msdos/tests/preptest.fth +++ /dev/null @@ -1,38 +0,0 @@ - -\ *** Block No. 0, Hexblock 0 - -\ include file to bundle what test-*.fth need phz 30jan22 -\ on top of kernel.com - - - - - - - - - - - - - - - -\ *** Block No. 1, Hexblock 1 - -\ loadscreen to prepare kernel.com for test-*.fth phz 31jan22 - - include multi.vid -\ include asm.fb -\ include extend.fb - - : arguments ( n -- ) - depth 1- > Error" too few params" ; - : blank ( addr count -- ) bl fill ; - - include dos.fb - include include.fb - include log2file.fb - - - From 9c2a76189473de3e93ee04e19e5e9cae90c9220f Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 15 Mar 2022 00:39:21 +0100 Subject: [PATCH 02/21] Migrate .fth include into v4th.com kernel; adapt test-min.log rule --- 8086/msdos/Makefile | 4 +- 8086/msdos/src/mk-v4th.fth | 2 + 8086/msdos/src/vf86core.fth | 3 +- 8086/msdos/src/vf86file.fth | 108 +++++++++++++++++++++++++++++++++++ 8086/msdos/tests/logprep.fth | 5 ++ 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 8086/msdos/src/vf86file.fth create mode 100644 8086/msdos/tests/logprep.fth diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 8e346d8..b5ac5cc 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -25,7 +25,7 @@ metafile.com: v4thfile.com src/meta.fb src/mk-meta.fth tests/log2file.fb grep -F 'Metacompiler saved as metafile.com' metafile.log v4th.com: metafile.com src/meta.fb src/mk-v4th.fth \ - src/vf86core.fth src/vf86dos.fth + src/vf86core.fth src/vf86dos.fth src/vf86file.fth rm -f v4th.com V4TH.COM OUTPUT.LOG FORTHPATH="f:\\;f:\\src;f:\\tests" ./emulator/run-in-dosbox.sh \ metafile.com "include mk-v4th.fth" @@ -73,7 +73,7 @@ test-min.log: \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) rm -f dosfiles/OUTPUT.LOG (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ - "include testprep.fb include test-min.fth") + "include logprep.fth include test-min.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ diff --git a/8086/msdos/src/mk-v4th.fth b/8086/msdos/src/mk-v4th.fth index b89a973..9fc6f4e 100644 --- a/8086/msdos/src/mk-v4th.fth +++ b/8086/msdos/src/mk-v4th.fth @@ -20,6 +20,8 @@ \ &112 &146 thru \ MS-DOS interface include vf86dos.fth + include vf86file.fth + : forth-83 ; \ last word in Dictionary 0 ' limit >body ! $DFF6 s0 ! $E77C r0 ! diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index e614835..9a8285e 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -819,8 +819,9 @@ Label domove I W cmp moveup CS ?] \ input strings ks 23 dez 87 + $84 Constant /tib Variable #tib #tib off - Variable >tib here >tib ! $50 allot + Variable >tib here >tib ! /tib allot Variable >in >in off Variable blk blk off Variable span span off diff --git a/8086/msdos/src/vf86file.fth b/8086/msdos/src/vf86file.fth new file mode 100644 index 0000000..2d8f0b1 --- /dev/null +++ b/8086/msdos/src/vf86file.fth @@ -0,0 +1,108 @@ + + variable tibeof tibeof off + + : eolf? ( c -- f ) + \ f=-1: not yet eol; store c and continue + \ f=0: eol but not yet eof; return line and flag continue + \ f=1: eof: return line and flag eof + tibeof off + dup #lf = IF drop 0 exit THEN + -1 = IF tibeof on 1 ELSE -1 THEN ; + + + + +\ *** Block No. 3, Hexblock 3 + +\ incfile incpos inc-fgetc phz 06feb22 + + variable incfile + variable incpos 2 allot + + : inc-fgetc ( -- c ) + incfile @ f.handle @ 0= IF + incpos 2@ incfile @ fseek THEN + incfile @ fgetc + incpos 2@ 1. d+ incpos 2! ; + + + + + + + +\ *** Block No. 4, Hexblock 4 + +\ freadline probe-for-fb phz 06feb22 + + : freadline ( -- eof ) + tib /tib bounds DO + inc-fgetc dup eolf? under 0< IF I c! ELSE drop THEN + 0< 0= IF I tib - #tib ! ENDLOOP tibeof @ exit THEN + LOOP /tib #tib ! + ." warning: line exteeds max " /tib . cr + ." extra chars ignored" cr + BEGIN inc-fgetc eolf? 1+ UNTIL tibeof @ ; + +| : probe-for-fb ( -- flag ) + \ probes whether current file looks like a block file + /tib 2+ 0 DO isfile@ fgetc #lf = IF ENDLOOP false exit THEN + LOOP true ; + + +\ *** Block No. 5, Hexblock 5 + +\ save/restoretib phz 16jan22 + + $50 constant /stash + create stash[ /stash allot here constant ]stash + variable stash> stash[ stash> ! + + : savetib ( -- n ) + #tib @ >in @ - dup stash> @ + ]stash u> + abort" tib stash overflow" >r + tib >in @ + stash> @ r@ cmove + r@ stash> +! r> ; + + : restoretib ( n -- ) + dup >r negate stash> +! stash> @ tib r@ cmove + r> #tib ! >in off ; + + +\ *** Block No. 6, Hexblock 6 + +\ interpret-via-tib include phz 06feb22 + + : interpret-via-tib + BEGIN freadline >r .status >in off interpret + r> UNTIL ; + + : include ( -- ) + pushfile use cr file? + probe-for-fb isfile@ freset IF 1 load close exit THEN + incfile push isfile@ incfile ! + incpos push incpos off incpos 2+ dup push off + savetib >r interpret-via-tib close r> restoretib ; + + : (stashquit stash[ stash> ! (quit ; + : stashrestore ['] (stashquit IS 'quit ; + ' stashrestore IS 'restart + +\ *** Block No. 7, Hexblock 7 + +\ \ phz 25feb22 + + : \ blk @ IF >in @ negate c/l mod >in +! + ELSE #tib @ >in ! THEN ; immediate + +\ : \needs have 0=exit +\ blk @ IF >in @ negate c/l mod >in +! +\ ELSE #tib @ >in ! THEN ; + + + + + + + + diff --git a/8086/msdos/tests/logprep.fth b/8086/msdos/tests/logprep.fth new file mode 100644 index 0000000..44c7a6e --- /dev/null +++ b/8086/msdos/tests/logprep.fth @@ -0,0 +1,5 @@ + + include extend.fb + include multi.vid + include dos.fb + include log2file.fb From 54c3d25af5043ad46e1e51abeae9a08691292ee3 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Thu, 17 Mar 2022 22:14:27 +0100 Subject: [PATCH 03/21] Fix wrong automatic make variable in test golden file concat rules --- 6502/C64/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/6502/C64/Makefile b/6502/C64/Makefile index 3b76b96..7f71ff8 100644 --- a/6502/C64/Makefile +++ b/6502/C64/Makefile @@ -162,31 +162,31 @@ emulator/sdcard.img: emulator/sdcard.sfdisk test-v4thblk-c64.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double block report-blk) - cat $? > $@ + cat $^ > $@ test-v4th-c64.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double report-noblk) - cat $? > $@ + cat $^ > $@ test-v4thblk-c16+.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double block report-blk) - cat $? > $@ + cat $^ > $@ test-v4th-c16+.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double report-noblk) - cat $? > $@ + cat $^ > $@ test-v4thblk-c16-.golden: $(patsubst %, tests/golden/%.golden, \ prelim core) - cat $? > $@ + cat $^ > $@ test-v4th-c16-.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double report-noblk) - cat $? > $@ + cat $^ > $@ test-v4th-x16.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreext double report-noblk) - cat $? > $@ + cat $^ > $@ # Rules for building Forth binaries on top of the plain vanilla # c64-volksforth83. From 41cecebbfa81346fb4eed9f5b5283b4ff442d8a5 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Thu, 17 Mar 2022 22:18:14 +0100 Subject: [PATCH 04/21] Add make rules for "std" test for v4th.com, i.e. all tests except the block tests. Now that v4th.com has a 132 char TIB, it can process the other tests, some of which have a few lines longer than 80 chars. --- 8086/msdos/Makefile | 18 +++++++++++++----- 8086/msdos/tests/{double.fth => doubltst.fth} | 0 8086/msdos/tests/golden/coreext.golden | 6 +++--- 8086/msdos/tests/golden/coreplus.golden | 2 +- .../golden/{double.golden => doubltst.golden} | 2 +- 8086/msdos/tests/test-std.fth | 11 +++++++++-- 6 files changed, 27 insertions(+), 12 deletions(-) rename 8086/msdos/tests/{double.fth => doubltst.fth} (100%) rename 8086/msdos/tests/golden/{double.golden => doubltst.golden} (50%) diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index b5ac5cc..01e6242 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -6,7 +6,7 @@ fbfiles_uppercase = $(wildcard src/*.FB tests/*.FB) fthfiles_caseconverted = $(patsubst %.fb, %.fth, \ $(shell ../../tools/echo-tolower.py $(fbfiles_uppercase))) -test: incltest.result logtest.result test-min.result \ +test: incltest.result logtest.result test-min.result test-std.result \ incltest-volks4th.result test-volks4th-min.result fth: $(fthfiles) $(fthfiles_caseconverted) @@ -76,6 +76,14 @@ test-min.log: \ "include logprep.fth include test-min.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ +test-std.log: \ + $(patsubst %, dosfiles/%, v4th.com $(prepsrcs)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ + "include logprep.fth include test-std.fth") + dos2unix -n dosfiles/OUTPUT.LOG $@ + incltest-volks4th.log: v4thfile.com tests/log2file.fb tests/incltest.fth rm -f OUTPUT.LOG @@ -95,15 +103,15 @@ run-editor: volks4th.com emulator/run-in-dosbox.sh test-min.golden: $(patsubst %, tests/golden/%.golden, prelim core) - cat $? > $@ + cat $^ > $@ test-std.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) - cat $? > $@ + prelim core coreplus coreext doubltst report-noblk) + cat $^ > $@ test-volks4th-min.golden: $(patsubst %, tests/golden/%.golden, \ volks4th-prelim core) - cat $? > $@ + cat $^ > $@ %.golden: tests/golden/%.golden diff --git a/8086/msdos/tests/double.fth b/8086/msdos/tests/doubltst.fth similarity index 100% rename from 8086/msdos/tests/double.fth rename to 8086/msdos/tests/doubltst.fth diff --git a/8086/msdos/tests/golden/coreext.golden b/8086/msdos/tests/golden/coreext.golden index ddf90a8..4b81e2d 100644 --- a/8086/msdos/tests/golden/coreext.golden +++ b/8086/msdos/tests/golden/coreext.golden @@ -1,9 +1,9 @@ -utilities.fth ?DEFTEST1 exists +UTIL.FTH ?DEFTEST1 exists Test utilities loaded -errorreport.fth -coreexttest.fth************** +ERRORREP.FTH +COREEXT.FTH ************** Output from .( You should see -9876: -9876 diff --git a/8086/msdos/tests/golden/coreplus.golden b/8086/msdos/tests/golden/coreplus.golden index b6ea7aa..0c3fde5 100644 --- a/8086/msdos/tests/golden/coreplus.golden +++ b/8086/msdos/tests/golden/coreplus.golden @@ -1,5 +1,5 @@ -COREPLUS.FTH******** +COREPLUS.FTH ******** You should see 2345: 2345 ***** End of additional Core tests diff --git a/8086/msdos/tests/golden/double.golden b/8086/msdos/tests/golden/doubltst.golden similarity index 50% rename from 8086/msdos/tests/golden/double.golden rename to 8086/msdos/tests/golden/doubltst.golden index ad02caf..146428f 100644 --- a/8086/msdos/tests/golden/double.golden +++ b/8086/msdos/tests/golden/doubltst.golden @@ -1,3 +1,3 @@ -doubletest.fth***************** +DOUBLTST.FTH ***************** End of Double-Number word tests diff --git a/8086/msdos/tests/test-std.fth b/8086/msdos/tests/test-std.fth index 97bb1fb..baaea50 100644 --- a/8086/msdos/tests/test-std.fth +++ b/8086/msdos/tests/test-std.fth @@ -1,11 +1,15 @@ +\ : .blk|tib +\ blk @ ?dup IF ." Blk " u. ?cr exit THEN +\ incfile @ IF tib #tib @ cr type THEN ; + include log2file.fth logopen output.log include ans-shim.fth : \vf [compile] \ ; immediate -include prelimtest.fth +include prelim.fth include tester.fth \ 1 verbose ! include core.fr @@ -15,7 +19,10 @@ include util.fth include errorrep.fth include coreext.fth -include double.fth + +\ ' .blk|tib Is .status + +include doubltst.fth REPORT-ERRORS From 432048b8446ddbcb518b07fb99665f8d7e628990 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Thu, 17 Mar 2022 23:02:31 +0100 Subject: [PATCH 05/21] Move TIB-capable line comment \ into core code. --- 8086/msdos/src/vf86core.fth | 3 ++- 8086/msdos/src/vf86file.fth | 19 ------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index 9a8285e..4ed0186 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -997,7 +997,8 @@ swap ]? C >in #) add : ( Ascii ) parse 2drop ; immediate : .( Ascii ) parse type ; immediate - : \ >in @ negate c/l mod >in +! ; immediate + : \ blk @ IF >in @ negate c/l mod >in +! + ELSE #tib @ >in ! THEN ; immediate : \\ b/blk >in ! ; immediate : have ( -- f ) name find nip 0<> ; immediate : \needs have 0=exit [compile] \ ; diff --git a/8086/msdos/src/vf86file.fth b/8086/msdos/src/vf86file.fth index 2d8f0b1..d0dfa04 100644 --- a/8086/msdos/src/vf86file.fth +++ b/8086/msdos/src/vf86file.fth @@ -87,22 +87,3 @@ : (stashquit stash[ stash> ! (quit ; : stashrestore ['] (stashquit IS 'quit ; ' stashrestore IS 'restart - -\ *** Block No. 7, Hexblock 7 - -\ \ phz 25feb22 - - : \ blk @ IF >in @ negate c/l mod >in +! - ELSE #tib @ >in ! THEN ; immediate - -\ : \needs have 0=exit -\ blk @ IF >in @ negate c/l mod >in +! -\ ELSE #tib @ >in ! THEN ; - - - - - - - - From 483be768c18448d33f6c405a01ce7ff5c9b03ced Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Thu, 17 Mar 2022 23:44:31 +0100 Subject: [PATCH 06/21] Remove commented-out coreplus.fth from test-min.fth (it has lines >80char and cannot be run by the original volks4th.com. --- 8086/msdos/tests/test-min.fth | 1 - 1 file changed, 1 deletion(-) diff --git a/8086/msdos/tests/test-min.fth b/8086/msdos/tests/test-min.fth index b78ff86..68071f9 100644 --- a/8086/msdos/tests/test-min.fth +++ b/8086/msdos/tests/test-min.fth @@ -10,6 +10,5 @@ include tester.fth \ 1 verbose ! include core.fr -\ include coreplus.fth logclose From 620cfae9139087d3d3553419186f2a7ba4dccdf4 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sat, 19 Mar 2022 22:05:42 +0100 Subject: [PATCH 07/21] Extract main part of buffer and block code from vf86core.fth --- 8086/msdos/Makefile | 2 +- 8086/msdos/src/vf86bufs.fth | 171 ++++++++++++++++++++++++++++++++++++ 8086/msdos/src/vf86core.fth | 169 +---------------------------------- 3 files changed, 173 insertions(+), 169 deletions(-) create mode 100644 8086/msdos/src/vf86bufs.fth diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 01e6242..3d447a0 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -25,7 +25,7 @@ metafile.com: v4thfile.com src/meta.fb src/mk-meta.fth tests/log2file.fb grep -F 'Metacompiler saved as metafile.com' metafile.log v4th.com: metafile.com src/meta.fb src/mk-v4th.fth \ - src/vf86core.fth src/vf86dos.fth src/vf86file.fth + src/vf86core.fth src/vf86dos.fth src/vf86file.fth src/vf86bufs.fth rm -f v4th.com V4TH.COM OUTPUT.LOG FORTHPATH="f:\\;f:\\src;f:\\tests" ./emulator/run-in-dosbox.sh \ metafile.com "include mk-v4th.fth" diff --git a/8086/msdos/src/vf86bufs.fth b/8086/msdos/src/vf86bufs.fth new file mode 100644 index 0000000..1361b46 --- /dev/null +++ b/8086/msdos/src/vf86bufs.fth @@ -0,0 +1,171 @@ + +\ *** Block No. 90, Hexblock 5a + +\ Struktur der Blockpuffer ks 04 jul 87 + +\ 0 : link zum naechsten Puffer +\ 2 : file 0 = direct access +\ -1 = leer, +\ sonst adresse eines file control blocks +\ 4 : blocknummer +\ 6 : statusflags Vorzeichenbit kennzeichnet update +\ 8 : Data ... 1 Kb ... + + + + + + + + +\ *** Block No. 91, Hexblock 5b + +\ buffer mechanism ks 04 okt 87 + + Variable isfile isfile off \ addr of file control block + Variable fromfile fromfile off \ fcb in kopieroperationen + + Variable prev prev off \ Listhead +| Variable buffers buffers off \ Semaphor + + $408 Constant b/buf \ physikalische Groesse + $400 Constant b/blk \ bytes/block + + Defer r/w \ physikalischer Diskzugriff + Variable error# error# off \ Nummer des letzten Fehlers + Defer ?diskerror \ Fehlerbehandlung + + + +\ *** Block No. 92, Hexblock 5c + +\ (core? ks 28 mai 87 + + Code (core? ( blk file -- dataaddr / blk file ) + A pop A push D D or 0= ?[ u' offset U D) A add ]? + prev #) W mov 2 W D) D cmp 0= + ?[ 4 W D) A cmp 0= + ?[ 8 W D) D lea A pop ' exit @ # jmp ]? ]? + [[ [[ W ) C mov C C or 0= ?[ Next ]? + C W xchg 4 W D) A cmp 0= ?] 2 W D) D cmp 0= ?] + W ) A mov prev #) D mov D W ) mov W prev #) mov + 8 W D) D lea C W mov A W ) mov A pop + ' exit @ # jmp + end-code + + + + +\ *** Block No. 93, Hexblock 5d + +\ (core? ks 31 oct 86 + +\ | : this? ( blk file bufadr -- flag ) +\ dup 4+ @ swap 2+ @ d= ; + +\ .( (core?: offset is handled differently in code! ) + +\ | : (core? ( blk file -- dataaddr / blk file ) +\ BEGIN over offset @ + over prev @ this? +\ IF rdrop 2drop prev @ 8 + exit THEN +\ 2dup >r offset @ + >r prev @ +\ BEGIN dup @ ?dup 0= IF rdrop rdrop drop exit THEN +\ dup r> r> 2dup >r >r rot this? 0= +\ WHILE nip REPEAT +\ dup @ rot ! prev @ over ! prev ! rdrop rdrop +\ REPEAT ; + +\ *** Block No. 94, Hexblock 5e + +\ backup emptybuf readblk ks 23 jul 87 + +| : backup ( bufaddr -- ) dup 6+ @ 0< + IF 2+ dup @ 1+ \ buffer empty if file = -1 + IF BEGIN dup 6+ over 2+ @ 2 pick @ 0 r/w + WHILE 1 ?diskerror REPEAT + THEN 4+ dup @ $7FFF and over ! THEN + drop ; + + : emptybuf ( bufaddr -- ) 2+ dup on 4+ off ; + +| : readblk ( blk file addr -- blk file addr ) + dup emptybuf >r + BEGIN 2dup 0= offset @ and + + over r@ 8 + -rot 1 r/w + WHILE 2 ?diskerror REPEAT r> ; + +\ *** Block No. 95, Hexblock 5f + +\ take mark updates? full? core? ks 04 jul 87 + +| : take ( -- bufaddr) prev + BEGIN dup @ WHILE @ dup 2+ @ -1 = UNTIL + buffers lock dup backup ; + +| : mark ( blk file bufaddr -- blk file ) 2+ >r + 2dup r@ ! over 0= offset @ and + r@ 2+ ! + r> 4+ off buffers unlock ; + +| : updates? ( -- bufaddr / flag) + prev BEGIN @ dup WHILE dup 6+ @ 0< UNTIL ; + + : core? ( blk file -- addr /false ) (core? 2drop false ; + + + +\ *** Block No. 96, Hexblock 60 + +\ block & buffer manipulation ks 01 okt 87 + + : (buffer ( blk file -- addr ) + BEGIN (core? take mark REPEAT ; + + : (block ( blk file -- addr ) + BEGIN (core? take readblk mark REPEAT ; + + Code isfile@ ( -- addr ) + D push isfile #) D mov Next end-code +\ : isfile@ ( -- addr ) isfile @ ; + + : buffer ( blk -- addr ) isfile@ (buffer ; + + : block ( blk -- addr ) isfile@ (block ; + + +\ *** Block No. 97, Hexblock 61 + +\ block & buffer manipulation ks 02 okt 87 + + : update $80 prev @ 6+ 1+ ( Byte-Order! ) c! ; + + : save-buffers buffers lock + BEGIN updates? ?dup WHILE backup REPEAT buffers unlock ; + + : empty-buffers buffers lock prev + BEGIN @ ?dup WHILE dup emptybuf REPEAT buffers unlock ; + + : flush file-link + BEGIN @ ?dup WHILE dup fclose REPEAT + save-buffers empty-buffers ; + + + + +\ *** Block No. 98, Hexblock 62 + +\ Allocating buffers ks 31 oct 86 + $10000 Constant limit Variable first + + : allotbuffer ( -- ) + first @ r0 @ - b/buf 2+ u< ?exit + b/buf negate first +! first @ dup emptybuf + prev @ over ! prev ! ; + + : freebuffer ( -- ) first @ limit b/buf - u< + IF first @ backup prev + BEGIN dup @ first @ - WHILE @ REPEAT + first @ @ swap ! b/buf first +! THEN ; + + : all-buffers BEGIN first @ allotbuffer first @ = UNTIL ; + +| : init-buffers prev off limit first ! all-buffers ; diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index 4ed0186..eeaf857 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -1633,176 +1633,9 @@ Target Forth also definitions end-code $E9 4 * >label >taskINT -\ *** Block No. 90, Hexblock 5a -\ Struktur der Blockpuffer ks 04 jul 87 + include vf86bufs.fth -\ 0 : link zum naechsten Puffer -\ 2 : file 0 = direct access -\ -1 = leer, -\ sonst adresse eines file control blocks -\ 4 : blocknummer -\ 6 : statusflags Vorzeichenbit kennzeichnet update -\ 8 : Data ... 1 Kb ... - - - - - - - - -\ *** Block No. 91, Hexblock 5b - -\ buffer mechanism ks 04 okt 87 - - Variable isfile isfile off \ addr of file control block - Variable fromfile fromfile off \ fcb in kopieroperationen - - Variable prev prev off \ Listhead -| Variable buffers buffers off \ Semaphor - - $408 Constant b/buf \ physikalische Groesse - $400 Constant b/blk \ bytes/block - - Defer r/w \ physikalischer Diskzugriff - Variable error# error# off \ Nummer des letzten Fehlers - Defer ?diskerror \ Fehlerbehandlung - - - -\ *** Block No. 92, Hexblock 5c - -\ (core? ks 28 mai 87 - - Code (core? ( blk file -- dataaddr / blk file ) - A pop A push D D or 0= ?[ u' offset U D) A add ]? - prev #) W mov 2 W D) D cmp 0= - ?[ 4 W D) A cmp 0= - ?[ 8 W D) D lea A pop ' exit @ # jmp ]? ]? - [[ [[ W ) C mov C C or 0= ?[ Next ]? - C W xchg 4 W D) A cmp 0= ?] 2 W D) D cmp 0= ?] - W ) A mov prev #) D mov D W ) mov W prev #) mov - 8 W D) D lea C W mov A W ) mov A pop - ' exit @ # jmp - end-code - - - - -\ *** Block No. 93, Hexblock 5d - -\ (core? ks 31 oct 86 - -\ | : this? ( blk file bufadr -- flag ) -\ dup 4+ @ swap 2+ @ d= ; - -\ .( (core?: offset is handled differently in code! ) - -\ | : (core? ( blk file -- dataaddr / blk file ) -\ BEGIN over offset @ + over prev @ this? -\ IF rdrop 2drop prev @ 8 + exit THEN -\ 2dup >r offset @ + >r prev @ -\ BEGIN dup @ ?dup 0= IF rdrop rdrop drop exit THEN -\ dup r> r> 2dup >r >r rot this? 0= -\ WHILE nip REPEAT -\ dup @ rot ! prev @ over ! prev ! rdrop rdrop -\ REPEAT ; - -\ *** Block No. 94, Hexblock 5e - -\ backup emptybuf readblk ks 23 jul 87 - -| : backup ( bufaddr -- ) dup 6+ @ 0< - IF 2+ dup @ 1+ \ buffer empty if file = -1 - IF BEGIN dup 6+ over 2+ @ 2 pick @ 0 r/w - WHILE 1 ?diskerror REPEAT - THEN 4+ dup @ $7FFF and over ! THEN - drop ; - - : emptybuf ( bufaddr -- ) 2+ dup on 4+ off ; - -| : readblk ( blk file addr -- blk file addr ) - dup emptybuf >r - BEGIN 2dup 0= offset @ and + - over r@ 8 + -rot 1 r/w - WHILE 2 ?diskerror REPEAT r> ; - -\ *** Block No. 95, Hexblock 5f - -\ take mark updates? full? core? ks 04 jul 87 - -| : take ( -- bufaddr) prev - BEGIN dup @ WHILE @ dup 2+ @ -1 = UNTIL - buffers lock dup backup ; - -| : mark ( blk file bufaddr -- blk file ) 2+ >r - 2dup r@ ! over 0= offset @ and + r@ 2+ ! - r> 4+ off buffers unlock ; - -| : updates? ( -- bufaddr / flag) - prev BEGIN @ dup WHILE dup 6+ @ 0< UNTIL ; - - : core? ( blk file -- addr /false ) (core? 2drop false ; - - - -\ *** Block No. 96, Hexblock 60 - -\ block & buffer manipulation ks 01 okt 87 - - : (buffer ( blk file -- addr ) - BEGIN (core? take mark REPEAT ; - - : (block ( blk file -- addr ) - BEGIN (core? take readblk mark REPEAT ; - - Code isfile@ ( -- addr ) - D push isfile #) D mov Next end-code -\ : isfile@ ( -- addr ) isfile @ ; - - : buffer ( blk -- addr ) isfile@ (buffer ; - - : block ( blk -- addr ) isfile@ (block ; - - -\ *** Block No. 97, Hexblock 61 - -\ block & buffer manipulation ks 02 okt 87 - - : update $80 prev @ 6+ 1+ ( Byte-Order! ) c! ; - - : save-buffers buffers lock - BEGIN updates? ?dup WHILE backup REPEAT buffers unlock ; - - : empty-buffers buffers lock prev - BEGIN @ ?dup WHILE dup emptybuf REPEAT buffers unlock ; - - : flush file-link - BEGIN @ ?dup WHILE dup fclose REPEAT - save-buffers empty-buffers ; - - - - -\ *** Block No. 98, Hexblock 62 - -\ Allocating buffers ks 31 oct 86 - $10000 Constant limit Variable first - - : allotbuffer ( -- ) - first @ r0 @ - b/buf 2+ u< ?exit - b/buf negate first +! first @ dup emptybuf - prev @ over ! prev ! ; - - : freebuffer ( -- ) first @ limit b/buf - u< - IF first @ backup prev - BEGIN dup @ first @ - WHILE @ REPEAT - first @ @ swap ! b/buf first +! THEN ; - - : all-buffers BEGIN first @ allotbuffer first @ = UNTIL ; - -| : init-buffers prev off limit first ! all-buffers ; \ *** Block No. 99, Hexblock 63 From 155eceadcf4e89e03c701c5c36dfd80358a24f28 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sat, 19 Mar 2022 22:37:33 +0100 Subject: [PATCH 08/21] Set up block tests --- 8086/msdos/Makefile | 8 ++++++++ 8086/msdos/tests/empty.fb | 1 + 8086/msdos/tests/test-blk.fth | 18 +++++++++--------- 3 files changed, 18 insertions(+), 9 deletions(-) create mode 100644 8086/msdos/tests/empty.fb diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 3d447a0..c0a7b58 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -84,6 +84,14 @@ test-std.log: \ "include logprep.fth include test-std.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ +test-blk.log: \ + $(patsubst %, dosfiles/%, v4th.com $(prepsrcs)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ + "include logprep.fth include test-blk.fth") + dos2unix -n dosfiles/OUTPUT.LOG $@ + incltest-volks4th.log: v4thfile.com tests/log2file.fb tests/incltest.fth rm -f OUTPUT.LOG diff --git a/8086/msdos/tests/empty.fb b/8086/msdos/tests/empty.fb new file mode 100644 index 0000000..f5b7445 --- /dev/null +++ b/8086/msdos/tests/empty.fb @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/8086/msdos/tests/test-blk.fth b/8086/msdos/tests/test-blk.fth index ed2799d..3f8ac53 100644 --- a/8086/msdos/tests/test-blk.fth +++ b/8086/msdos/tests/test-blk.fth @@ -1,25 +1,25 @@ include log2file.fth -logopen test.log +logopen output.log include ans-shim.fth : \vf [compile] \ ; immediate -include prelimtest.fth +include prelim.fth include tester.fth \ 1 verbose ! include core.fr -include coreplustest.fth +include coreplus.fth -include utilities.fth -include errorreport.fth +include util.fth +include errorrep.fth -include coreexttest.fth -include doubletest.fth -1 drive include blocktest.fth +include coreext.fth +include doubltst.fth +use empty.fb +include block.fth REPORT-ERRORS logclose -dos s0:notdone From 91c74f083044e367c59673ad50d8f82a486842fe Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sat, 19 Mar 2022 23:55:06 +0100 Subject: [PATCH 09/21] Tweak block test incl. golden file to make it pass: Close and reopen log file before and after FLUSH. Adapt golden file to 16x64 screen format and .fb instead of direkt disk access. --- 8086/msdos/Makefile | 4 ++ 8086/msdos/tests/block.fth | 3 ++ 8086/msdos/tests/golden/block.golden | 63 ++++------------------------ 8086/msdos/tests/test-blk.fth | 3 +- 4 files changed, 18 insertions(+), 55 deletions(-) diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index c0a7b58..554fb76 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -117,6 +117,10 @@ test-std.golden: $(patsubst %, tests/golden/%.golden, \ prelim core coreplus coreext doubltst report-noblk) cat $^ > $@ +test-blk.golden: $(patsubst %, tests/golden/%.golden, \ + prelim core coreplus coreext doubltst block report-blk) + cat $^ > $@ + test-volks4th-min.golden: $(patsubst %, tests/golden/%.golden, \ volks4th-prelim core) cat $^ > $@ diff --git a/8086/msdos/tests/block.fth b/8086/msdos/tests/block.fth index 7def227..cb1b450 100644 --- a/8086/msdos/tests/block.fth +++ b/8086/msdos/tests/block.fth @@ -27,6 +27,9 @@ \ - errorreport.fth has been loaded prior to this file \ - utilities.fth has been loaded prioir to this file \ ------------------------------------------------------------------------------ + +use empty.fb + TESTING Block word set DECIMAL diff --git a/8086/msdos/tests/golden/block.golden b/8086/msdos/tests/golden/block.golden index 998ca33..d241942 100644 --- a/8086/msdos/tests/golden/block.golden +++ b/8086/msdos/tests/golden/block.golden @@ -1,5 +1,5 @@ - -blocktest.fth**=== NOT TESTED === *******Scr 21 Dr 1 + FLUSH exists +BLOCK.FTH **=== NOT TESTED === ******* Scr 21 Dr 5 EMPTY.FB 0 Should show a (mostly) blank screen 1 2 @@ -16,16 +16,7 @@ blocktest.fth**=== NOT TESTED === *******Scr 21 Dr 1 13 14 15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -Scr 20 Dr 1 + Scr 20 Dr 5 EMPTY.FB 0 List of the First test block 1 2 @@ -42,16 +33,7 @@ Scr 20 Dr 1 13 14 15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -Scr 29 Dr 1 + Scr 29 Dr 5 EMPTY.FB 0 List of the Last test block 1 2 @@ -68,16 +50,7 @@ Scr 29 Dr 1 13 14 15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -Scr 25 Dr 1 + Scr 25 Dr 5 EMPTY.FB 0 1 2 @@ -93,18 +66,9 @@ Scr 25 Dr 1 12 13 14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 End of Screen -Scr 21 Dr 1 - 0 Should show another (mostly) blank scree +15 End of Screen + Scr 21 Dr 5 EMPTY.FB + 0 Should show another (mostly) blank screen 1 2 3 @@ -120,15 +84,6 @@ Scr 21 Dr 1 13 14 15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -*** | exists Given Characters per Line: 41 +*** | exists Given Characters per Line: 64 * End of Block word tests diff --git a/8086/msdos/tests/test-blk.fth b/8086/msdos/tests/test-blk.fth index 3f8ac53..76840f0 100644 --- a/8086/msdos/tests/test-blk.fth +++ b/8086/msdos/tests/test-blk.fth @@ -16,7 +16,8 @@ include errorrep.fth include coreext.fth include doubltst.fth -use empty.fb + +: flush logclose flush logreopen ; include block.fth REPORT-ERRORS From c9a62fc7ff80188a3f412f7b818b9645a8c81d01 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 20 Mar 2022 14:05:06 +0100 Subject: [PATCH 10/21] First refactoring step to move all buffers/blocks related code to vf86bufs.fth and to make vf86core.fth independent of vf86bufs.fth. --- 8086/msdos/src/vf86bufs.fth | 52 +++++++++++++++++++++++++++---------- 8086/msdos/src/vf86core.fth | 52 ++++++++++++++++--------------------- 2 files changed, 61 insertions(+), 43 deletions(-) diff --git a/8086/msdos/src/vf86bufs.fth b/8086/msdos/src/vf86bufs.fth index 1361b46..0191253 100644 --- a/8086/msdos/src/vf86bufs.fth +++ b/8086/msdos/src/vf86bufs.fth @@ -14,6 +14,26 @@ +\ *** Block No. 81, Hexblock 51 + +\ +load thru +thru --> rdepth depth ks 26 jul 87 + + : (load ( blk offset -- ) isfile@ >r + loadfile @ >r fromfile @ >r blk @ >r >in @ >r + >in ! blk ! isfile@ loadfile ! .status interpret + r> >in ! r> blk ! r> fromfile ! r> loadfile ! + r> isfile ! ; + + : load ( blk -- ) ?dup 0=exit 0 (load ; + + : +load ( offset -- ) blk @ + load ; + + : thru ( from to -- ) 1+ swap DO I load LOOP ; + + : +thru ( off0 off1 -- ) 1+ swap DO I +load LOOP ; + + : --> 1 blk +! >in off .status ; immediate + @@ -22,19 +42,13 @@ \ buffer mechanism ks 04 okt 87 - Variable isfile isfile off \ addr of file control block Variable fromfile fromfile off \ fcb in kopieroperationen Variable prev prev off \ Listhead -| Variable buffers buffers off \ Semaphor $408 Constant b/buf \ physikalische Groesse $400 Constant b/blk \ bytes/block - Defer r/w \ physikalischer Diskzugriff - Variable error# error# off \ Nummer des letzten Fehlers - Defer ?diskerror \ Fehlerbehandlung - \ *** Block No. 92, Hexblock 5c @@ -123,14 +137,15 @@ : (block ( blk file -- addr ) BEGIN (core? take readblk mark REPEAT ; - Code isfile@ ( -- addr ) - D push isfile #) D mov Next end-code -\ : isfile@ ( -- addr ) isfile @ ; - : buffer ( blk -- addr ) isfile@ (buffer ; : block ( blk -- addr ) isfile@ (block ; + : (blk-source ( -- addr len ) blk @ ?dup + IF loadfile @ (block b/blk exit THEN tib #tib @ ; + + ' (blk-source IS source + \ *** Block No. 97, Hexblock 61 @@ -138,9 +153,11 @@ : update $80 prev @ 6+ 1+ ( Byte-Order! ) c! ; - : save-buffers buffers lock + : (save-buffers buffers lock BEGIN updates? ?dup WHILE backup REPEAT buffers unlock ; +' (save-buffers IS save-buffers + : empty-buffers buffers lock prev BEGIN @ ?dup WHILE dup emptybuf REPEAT buffers unlock ; @@ -148,13 +165,20 @@ BEGIN @ ?dup WHILE dup fclose REPEAT save-buffers empty-buffers ; + : list ( scr -- ) dup capacity u< + IF scr ! ." Scr " scr @ . + ." Dr " drv . isfile@ .file + l/s 0 DO cr I 2 .r space scr @ block + I c/l * + c/l -trailing type + LOOP cr exit + THEN 9 ?diskerror ; + \ *** Block No. 98, Hexblock 62 \ Allocating buffers ks 31 oct 86 - $10000 Constant limit Variable first : allotbuffer ( -- ) first @ r0 @ - b/buf 2+ u< ?exit @@ -168,4 +192,6 @@ : all-buffers BEGIN first @ allotbuffer first @ = UNTIL ; -| : init-buffers prev off limit first ! all-buffers ; +| : (init-buffers prev off limit first ! all-buffers ; + +' (init-buffers IS init-buffers diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index eeaf857..039ecbe 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -955,8 +955,11 @@ swap ]? C >in #) add Variable loadfile loadfile off - : source ( -- addr len ) blk @ ?dup - IF loadfile @ (block b/blk exit THEN tib #tib @ exit ; + defer source + + : (source ( -- addr len ) tib #tib @ ; + + ' (source IS source : word ( char -- addr ) source (word ; @@ -1453,26 +1456,6 @@ Target Forth also definitions Defer .status ' noop Is .status - : (load ( blk offset -- ) isfile@ >r - loadfile @ >r fromfile @ >r blk @ >r >in @ >r - >in ! blk ! isfile@ loadfile ! .status interpret - r> >in ! r> blk ! r> fromfile ! r> loadfile ! - r> isfile ! ; - - : load ( blk -- ) ?dup 0=exit 0 (load ; - - -\ *** Block No. 81, Hexblock 51 - -\ +load thru +thru --> rdepth depth ks 26 jul 87 - - : +load ( offset -- ) blk @ + load ; - - : thru ( from to -- ) 1+ swap DO I load LOOP ; - - : +thru ( off0 off1 -- ) 1+ swap DO I +load LOOP ; - - : --> 1 blk +! >in off .status ; immediate : rdepth ( -- +n ) r0 @ rp@ 2+ - 2/ ; @@ -1602,14 +1585,6 @@ Target Forth also definitions &64 Constant c/l \ Screen line length &16 Constant l/s \ lines per screen - : list ( scr -- ) dup capacity u< - IF scr ! ." Scr " scr @ . - ." Dr " drv . isfile@ .file - l/s 0 DO cr I 2 .r space scr @ block - I c/l * + c/l -trailing type - LOOP cr exit - THEN 9 ?diskerror ; - @@ -1634,6 +1609,23 @@ Target Forth also definitions $E9 4 * >label >taskINT + $10000 Constant limit Variable first + + Variable isfile isfile off \ addr of file control block + Code isfile@ ( -- addr ) + D push isfile #) D mov Next end-code +\ : isfile@ ( -- addr ) isfile @ ; + +| Variable buffers buffers off \ Semaphor + + Defer r/w \ physikalischer Diskzugriff + Variable error# error# off \ Nummer des letzten Fehlers + Defer ?diskerror \ Fehlerbehandlung + + Defer save-buffers ' noop IS save-buffers + Defer init-buffers ' noop IS init-buffers + + include vf86bufs.fth From f3376268f838494e86c9cc29dc947c9d949aa576 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 21 Mar 2022 00:50:22 +0100 Subject: [PATCH 11/21] Make v4th.com tests independent of .fb sources: Provide .fth variants of asm.fb, extend.fb, dos.fb, multi.vid Also add detection of unresolved symbols to v4th.com make rule --- 8086/msdos/Makefile | 10 +- 8086/msdos/src/86asm.fth | 397 +++++++++++++++++++++++++++++++++++ 8086/msdos/src/dos2.fth | 255 ++++++++++++++++++++++ 8086/msdos/src/dos3.fth | 195 +++++++++++++++++ 8086/msdos/src/extend2.fth | 182 ++++++++++++++++ 8086/msdos/src/multivid.fth | 192 +++++++++++++++++ 8086/msdos/src/t86asm.fth | 14 ++ 8086/msdos/tests/logprep.fth | 16 +- 8 files changed, 1254 insertions(+), 7 deletions(-) create mode 100644 8086/msdos/src/86asm.fth create mode 100644 8086/msdos/src/dos2.fth create mode 100644 8086/msdos/src/dos3.fth create mode 100644 8086/msdos/src/extend2.fth create mode 100644 8086/msdos/src/multivid.fth create mode 100644 8086/msdos/src/t86asm.fth diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 554fb76..72d0ab3 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -32,6 +32,7 @@ v4th.com: metafile.com src/meta.fb src/mk-v4th.fth \ dos2unix -n OUTPUT.LOG v4th.log mv V4TH.COM v4th.com grep -F 'new kernel written as v4th.com' v4th.log + grep -i 'unresolved:.*[^ ]' v4th.log && exit 1 || true # o4th for old volks4th - the new v4th is built with precompiled # metacompiler metafile.com and mk-v4th.fth which writes a compile log. @@ -60,6 +61,9 @@ logappendtest.log: v4thfile.com tests/logapp.fth prepsrcs = asm.fb extend.fb multi.vid dos.fb include.fb +prepfths = asm.fb extend.fb multi.vid dos.fb include.fb 86asm.fth \ + t86asm.fth extend2.fth multivid.fth dos2.fth dos3.fth + incltest.log: \ $(patsubst %, dosfiles/%, v4th.com $(prepsrcs) log2file.fb \ incltest.fth) @@ -69,7 +73,7 @@ incltest.log: \ dos2unix -n dosfiles/OUTPUT.LOG $@ test-min.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepsrcs)) \ + $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) rm -f dosfiles/OUTPUT.LOG (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ @@ -77,7 +81,7 @@ test-min.log: \ dos2unix -n dosfiles/OUTPUT.LOG $@ test-std.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepsrcs)) \ + $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) rm -f dosfiles/OUTPUT.LOG (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ @@ -85,7 +89,7 @@ test-std.log: \ dos2unix -n dosfiles/OUTPUT.LOG $@ test-blk.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepsrcs)) \ + $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) rm -f dosfiles/OUTPUT.LOG (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ diff --git a/8086/msdos/src/86asm.fth b/8086/msdos/src/86asm.fth new file mode 100644 index 0000000..b30614a --- /dev/null +++ b/8086/msdos/src/86asm.fth @@ -0,0 +1,397 @@ + +\ *** Block No. 0, Hexblock 0 + +\ 8086 Assembler cas 10nov05 +\ This 8086 Assembler was written by Klaus Schleisiek. +\ Assembler Definitions are created with the definig word +\ CODE and closed with the word END-CODE. + +\ The 8086 Registers naming and usage in volksFORTH + +\ Intel vForth Used for 8bit-Register +\ AX A free A+ A- +\ DX D topmost Stackitem D+ D- +\ CX C free C+ C- +\ BX R Returnstack Pointer R+ R- +\ BP U User Pointer +\ SP S Stack Pointer +\ SI I Instruction Pointer +\ DI W Word Pointer, mostly free + +\ *** Block No. 1, Hexblock 1 + +\ 8086 Assembler loadscreen cas 10nov05 + Onlyforth + +| : u2/ ( 16b -- 15b ) 2/ $7FFF and ; +| : 8* ( 15b -- 16b ) 2* 2* 2* ; +| : 8/ ( 16b -- 13b ) u2/ 2/ 2/ ; + + Vocabulary Assembler + Assembler also definitions + +\ 3 &21 thru clear .( Assembler loaded ) cr + +\ *** Block No. 3, Hexblock 3 + +\ Code generating primitives cas 10nov05 + + Variable >codes \ points at table of execution vectors + +| Create nrc ] c, , here ! c! [ + + : nonrelocate nrc >codes ! ; nonrelocate + +| : >exec ( n -- n+2 ) Create dup c, 2+ + Does> c@ >codes @ + perform ; + +0 | >exec >c, | >exec >, | >exec >here + | >exec >! | >exec >c! drop + + + + +\ *** Block No. 4, Hexblock 4 + +\ 8086 Registers cas 10nov05 + + 0 Constant A 1 Constant C 2 Constant D 3 Constant R + 4 Constant S 5 Constant U 6 Constant I 7 Constant W +' I Alias SI ' W Alias DI ' R Alias BX + + 8 Constant A- 9 Constant C- $A Constant D- $B Constant R- +$C Constant A+ $D Constant C+ $E Constant D+ $F Constant R+ +' R- Alias B- ' R+ Alias B+ + + $100 Constant E: $101 Constant C: + $102 Constant S: $103 Constant D: + +| Variable isize ( specifies Size by prefix) +| : Size: ( n -- ) Create c, Does> c@ isize ! ; + 0 Size: byte 1 Size: word word 2 Size: far + +\ *** Block No. 5, Hexblock 5 + +\ 8086 Assembler System variables cas 10nov05 + +| Variable direction \ 0 reg>EA, -1 EA>reg +| Variable size \ 1 word, 0 byte, -1 undefined +| Variable displaced \ 1 direct, 0 nothing, -1 displaced +| Variable displacement + +| : setsize isize @ size ! ; +| : long? ( n -- f ) $FF80 and dup 0< not ?exit $FF80 xor ; +| : wexit rdrop word ; +| : moderr word true Abort" invalid" ; +| : ?moderr ( f -- ) 0=exit moderr ; +| : ?word size @ 1- ?moderr ; +| : far? ( -- f ) size @ 2 = ; + + + +\ *** Block No. 6, Hexblock 6 + +\ 8086 addressing modes cas 10nov05 + +| Create (EA 7 c, 0 c, 6 c, 4 c, 5 c, +| : () ( 8b1 -- 8b2 ) + 3 - dup 4 u> over 1 = or ?moderr (EA + c@ ; + + -1 Constant # $C6 Constant #) -1 Constant C* + + : ) ( u1 -- u2 ) + () 6 case? IF 0 $86 exit THEN $C0 or ; + : I) ( u1 u2 -- u3 ) + 9 - dup 3 u> ?moderr $C0 or ; + + : D) ( n u1 -- n u2 ) + () over long? IF $40 ELSE $80 THEN or ; + : DI) ( n u1 u2 -- n u3 ) + I) over long? IF $80 ELSE $40 THEN xor ; + +\ *** Block No. 7, Hexblock 7 + +\ 8086 Registers and addressing modes cas 10nov05 + +| : displaced? ( [n] u1 -- [n] u1 f ) + dup #) = IF 1 exit THEN + dup $C0 and dup $40 = swap $80 = or ; + +| : displace ( [n] u1 -- u1 ) displaced? ?dup 0=exit + displaced @ ?moderr displaced ! swap displacement ! ; + +| : rmode ( u1 -- u2 ) 1 size ! dup 8 and 0=exit + size off $FF07 and ; + +| : mmode? ( 9b - 9b f) dup $C0 and ; + +| : rmode? ( 8b1 - 8b1 f) mmode? $C0 = ; + + +\ *** Block No. 8, Hexblock 8 + +\ 8086 decoding addressing modes cas 10nov05 + +| : 2address ( [n] source [displ] dest -- 15b / [n] 16b ) + size on displaced off dup # = ?moderr mmode? + IF displace False ELSE rmode True THEN direction ! + >r # case? IF r> $80C0 xor size @ 1+ ?exit setsize exit + THEN direction @ + IF r> 8* >r mmode? IF displace + ELSE dup 8/ 1 and size @ = ?moderr $FF07 and THEN + ELSE rmode 8* + THEN r> or $C0 xor ; + +| : 1address ( [displ] 9b -- 9b ) + # case? ?moderr size on displaced off direction off + mmode? IF displace setsize ELSE rmode THEN $C0 xor ; + + +\ *** Block No. 9, Hexblock 9 + +\ 8086 assembler cas 10nov05 +| : immediate? ( u -- u f ) dup 0< ; + +| : nonimmediate ( u -- u ) immediate? ?moderr ; + +| : r/m 7 and ; + +| : reg $38 and ; + +| : ?akku ( u -- u ff / tf ) dup r/m 0= dup 0=exit nip ; + +| : smode? ( u1 -- u1 ff / u2 tf ) dup $F00 and + IF dup $100 and IF dup r/m 8* swap reg 8/ + or $C0 or direction off + THEN True exit + THEN False ; + +\ *** Block No. 10, Hexblock a + +\ 8086 Registers and addressing modes cas 10nov05 + +| : w, size @ or >c, ; + +| : dw, size @ or direction @ IF 2 xor THEN >c, ; + +| : ?word, ( u1 f -- ) IF >, exit THEN >c, ; + +| : direct, displaced @ 0=exit + displacement @ dup long? displaced @ 1+ or ?word, ; + +| : r/m, >c, direct, ; + +| : data, size @ ?word, ; + + + +\ *** Block No. 11, Hexblock b + +\ 8086 Arithmetic instructions cas 10nov05 + +| : Arith: ( code -- ) Create , + Does> @ >r 2address immediate? + IF rmode? IF ?akku IF r> size @ + IF 5 or >c, >, wexit THEN + 4 or >c, >c, wexit THEN THEN + r@ or $80 size @ or r> 0< + IF size @ IF 2 pick long? 0= IF 2 or size off THEN + THEN THEN >c, >c, direct, data, wexit + THEN r> dw, r/m, wexit ; + + $8000 Arith: add $0008 Arith: or + $8010 Arith: adc $8018 Arith: sbb + $0020 Arith: and $8028 Arith: sub + $0030 Arith: xor $8038 Arith: cmp + +\ *** Block No. 12, Hexblock c + +\ 8086 move push pop cas 10nov05 + + : mov [ Forth ] 2address immediate? + IF rmode? IF r/m $B0 or size @ IF 8 or THEN + >c, data, wexit + THEN $C6 w, r/m, data, wexit + THEN 6 case? IF $A2 dw, direct, wexit THEN + smode? IF $8C direction @ IF 2 or THEN >c, r/m, wexit + THEN $88 dw, r/m, wexit ; + +| : pupo [ Forth ] >r 1address ?word + smode? IF reg 6 r> IF 1+ THEN or >c, wexit THEN + rmode? IF r/m $50 or r> or >c, wexit THEN + r> IF $8F ELSE $30 or $FF THEN >c, r/m, wexit ; + + : push 0 pupo ; : pop 8 pupo ; + +\ *** Block No. 13, Hexblock d + +\ 8086 inc & dec , effective addresses cas 10nov05 + +| : inc/dec [ Forth ] >r 1address rmode? + IF size @ IF r/m $40 or r> or >c, wexit THEN + THEN $FE w, r> or r/m, wexit ; + + : dec 8 inc/dec ; : inc 0 inc/dec ; + +| : EA: ( code -- ) Create c, [ Forth ] + Does> >r 2address nonimmediate + rmode? direction @ 0= or ?moderr r> c@ >c, r/m, wexit ; + + $C4 EA: les $8D EA: lea $C5 EA: lds + + + + +\ *** Block No. 14, Hexblock e + +\ 8086 xchg segment prefix cas 10nov05 + : xchg [ Forth ] 2address nonimmediate rmode? + IF size @ IF dup r/m 0= + IF 8/ true ELSE dup $38 and 0= THEN + IF r/m $90 or >c, wexit THEN + THEN THEN $86 w, r/m, wexit ; + +| : 1addr: ( code -- ) Create c, [ Forth ] + Does> c@ >r 1address $F6 w, r> or r/m, wexit ; + + $10 1addr: com $18 1addr: neg + $20 1addr: mul $28 1addr: imul + $38 1addr: idiv $30 1addr: div + + : seg ( 8b -) [ Forth ] + $100 xor dup $FFFC and ?moderr 8* $26 or >c, ; + +\ *** Block No. 15, Hexblock f + +\ 8086 test not neg mul imul div idiv cas 10nov05 + + : test [ Forth ] 2address immediate? + IF rmode? IF ?akku IF $A8 w, data, wexit THEN THEN + $F6 w, r/m, data, wexit + THEN $84 w, r/m, wexit ; + +| : in/out [ Forth ] >r 1address setsize + $C2 case? IF $EC r> or w, wexit THEN + 6 - ?moderr $E4 r> or w, displacement @ >c, wexit ; + + : out 2 in/out ; : in 0 in/out ; + + : int 3 case? IF $CC >c, wexit THEN $CD >c, >c, wexit ; + + + +\ *** Block No. 16, Hexblock 10 + +\ 8086 shifts and string instructions cas 10nov05 + +| : Shifts: ( code -- ) Create c, [ Forth ] + Does> c@ >r C* case? >r 1address + r> direction ! $D0 dw, r> or r/m, wexit ; + + $00 Shifts: rol $08 Shifts: ror + $10 Shifts: rcl $18 Shifts: rcr + $20 Shifts: shl $28 Shifts: shr + $38 Shifts: sar ' shl Alias sal + +| : Str: ( code -- ) Create c, + Does> c@ setsize w, wexit ; + + $A6 Str: cmps $AC Str: lods $A4 Str: movs + $AE Str: scas $AA Str: stos + +\ *** Block No. 17, Hexblock 11 + +\ implied 8086 instructions cas 10nov05 + + : Byte: ( code -- ) Create c, Does> c@ >c, ; + : Word: ( code -- ) Create , Does> @ >, ; + + $37 Byte: aaa $AD5 Word: aad $AD4 Word: aam + $3F Byte: aas $98 Byte: cbw $F8 Byte: clc + $FC Byte: cld $FA Byte: cli $F5 Byte: cmc + $99 Byte: cwd $27 Byte: daa $2F Byte: das + $F4 Byte: hlt $CE Byte: into $CF Byte: iret + $9F Byte: lahf $F0 Byte: lock $90 Byte: nop + $9D Byte: popf $9C Byte: pushf $9E Byte: sahf + $F9 Byte: stc $FD Byte: std $FB Byte: sti + $9B Byte: wait $D7 Byte: xlat + $C3 Byte: ret $CB Byte: lret + $F2 Byte: rep $F2 Byte: 0<>rep $F3 Byte: 0=rep + +\ *** Block No. 18, Hexblock 12 + +\ 8086 jmp call conditions cas 10nov05 +| : jmp/call >r setsize # case? [ Forth ] + IF far? IF r> IF $EA ELSE $9A THEN >c, swap >, >, wexit + THEN >here 2+ - r> + IF dup long? 0= IF $EB >c, >c, wexit THEN $E9 + ELSE $E8 THEN >c, 1- >, wexit + THEN 1address $FF >c, $10 or r> + + far? IF 8 or THEN r/m, wexit ; + : call 0 jmp/call ; : jmp $10 jmp/call ; + + $71 Constant OS $73 Constant CS + $75 Constant 0= $77 Constant >= + $79 Constant 0< $7B Constant PE + $7D Constant < $7F Constant <= + $E2 Constant C0= $E0 Constant ?C0= + : not 1 [ Forth ] xor ; + +\ *** Block No. 19, Hexblock 13 + +\ 8086 conditional branching cas 10nov05 + + : +ret $C2 >c, >, ; + : +lret $CA >c, >, ; + +| : ?range dup long? abort" out of range" ; + + : ?[ >, >here 1- ; + : ]? >here over 1+ - ?range swap >c! ; + : ][ $EB ?[ swap ]? ; + : ?[[ ?[ swap ; + : [[ >here ; + : ?] >c, >here 1+ - ?range >c, ; + : ]] $EB ?] ; + : ]]? ]] ]? ; + + +\ *** Block No. 20, Hexblock 14 + +\ Next user' end-code ;c: cas 10nov05 + + : Next lods A W xchg W ) jmp + >here next-link @ >, next-link ! ; + + : u' ' >body c@ ; + + Forth definitions + +\needs end-code : end-code toss also ; + + Assembler definitions + + : ;c: recover # call last off end-code 0 ] ; + + + +\ *** Block No. 21, Hexblock 15 + +\ 8086 Assembler, Forth words cas 10nov05 + Onlyforth + + : Assembler Assembler [ Assembler ] wexit ; + + : ;code 0 ?pairs compile (;code + reveal [compile] [ Assembler ; immediate + + : Code Create [ Assembler ] >here dup 2- >! Assembler ; + + : >label ( addr -- ) + here | Create immediate swap , 4 hallot + here 4 - heap 4 cmove heap last @ (name> ! dp ! + Does> ( -- addr ) @ state @ 0=exit [compile] Literal ; + + : Label [ Assembler ] >here >label Assembler ; + + + clear .( Assembler loaded ) cr diff --git a/8086/msdos/src/dos2.fth b/8086/msdos/src/dos2.fth new file mode 100644 index 0000000..4618be8 --- /dev/null +++ b/8086/msdos/src/dos2.fth @@ -0,0 +1,255 @@ + +\ *** Block No. 0, Hexblock 0 + +\ 28 jun 88 + +\ This file is a pure .fth-version of dos.fb. + +\ DOS loads higher level file functions which go beyond +\ including a screen file. Calls to MS-DOS are implemented +\ and used for directory manipulation. These functions may +\ not work for versions before MS-DOS 3.0. + + +\ *** Block No. 1, Hexblock 1 + +\ MS-DOS file handli cas 09jun20 + Onlyforth \needs Assembler 2 loadfrom asm.fb + + : fswap isfile@ fromfile @ isfile ! fromfile ! ; + + $80 Constant dta + +| : COMSPEC ( -- string ) [ dos ] + $2C @ ( DOS-environment:seg) 8 ds@ filename &60 lmove + filename counted &60 min filename place filename ; + +\ 1 &12 +thru .( MS-DOS functions loaed ) cr + + + + +\ *** Block No. 2, Hexblock 2 + +\ moving blocks ks 04 okt 87 + +| : full? ( -- flag ) prev BEGIN @ dup @ 0= UNTIL 6 + @ 0< ; + + : used? ( blk -- f ) + block count b/blk 1- swap skip nip 0<> ; + +| : (copy ( from to -- ) + full? IF save-buffers THEN isfile@ fromfile @ - + IF dup used? Abort" target block not empty" THEN + dup isfile@ core? IF prev @ emptybuf THEN + isfile@ 0= IF offset @ + THEN + isfile@ rot fromfile @ (block 6 - 2! update ; + + + + +\ *** Block No. 3, Hexblock 3 + +\ moving blocks ks 04 okt 87 + +| : blkmove ( from to quan -- ) 3 arguments save-buffers + >r over r@ + over u> >r 2dup u< r> and + IF r@ r@ d+ r> 0 ?DO -1 -2 d+ 2dup (copy LOOP + ELSE r> 0 ?DO 2dup (copy 1 1 d+ LOOP + THEN save-buffers 2drop ; + + : copy ( from to -- ) 1 blkmove ; + + : convey ( blk1 blk2 to.blk -- ) + 3 arguments >r 2dup swap - >r + fswap dup capacity 1- > isfile@ 0<> and + fswap r> r@ + capacity 1- > isfile@ 0<> and or >r + 1+ over - dup 0> not r> or Abort" nein" r> swap blkmove ; + + +\ *** Block No. 4, Hexblock 4 + +\ MORE extending forth files ks 10 okt 87 + Dos also definitions + +| : addblock ( blk -- ) dup buffer dup b/blk blank + isfile@ f.size dup 2@ b/blk 0 d+ rot 2! + swap isfile@ fblock! ; + + Forth definitions + + : more ( n -- ) 1 arguments isfile@ + IF capacity swap bounds ?DO I addblock LOOP close exit + THEN drop ; + + + + + +\ *** Block No. 5, Hexblock 5 + +\ file eof? create dta-addressing ks 03 apr 88 + Dos definitions + + : ftime ( -- mm hh ) + isfile@ f.time @ $20 u/mod nip $40 u/mod ; + + : fdate ( -- dd mm yy ) + isfile@ f.date @ $20 u/mod $10 u/mod &80 + ; + + : .when base push decimal + fdate rot 3 .r ." ." swap 2 .r ." ." 2 .r + ftime 3 .r ." :" 2 .r ; + + + + + +\ *** Block No. 6, Hexblock 6 + +\ ks 20mar88 + + : (.fcb ( fcb -- ) + dup .file ?dup 0=exit pushfile + isfile ! &13 tab ." is" + isfile@ f.handle @ 2 .r + isfile@ f.size 2@ 7 d.r .when + space isfile@ f.name count type ; + + Forth definitions + + : files file-link + BEGIN @ dup WHILE cr dup (.fcb stop? UNTIL drop ; + + : ?file isfile@ (.fcb ; + + +\ *** Block No. 7, Hexblock 7 + +\ dir make makefile ks 25 okt 87 + Forth definitions + + : killfile close + isfile@ f.name filename >asciz ~unlink drop ; + + : emptyfile isfile@ 0=exit + isfile@ f.name filename >asciz 0 ~creat ?diskerror + isfile@ f.handle ! isfile@ f.size 4 erase ; + + : make close name isfile@ fname! emptyfile ; + + : makefile File last @ name> execute emptyfile ; + + + + +\ *** Block No. 8, Hexblock 8 + +\ getpath ks 10 okt 87 + Dos definitions + +| &40 Constant pathlen +| Create pathes 0 c, pathlen allot + +| : (setpath ( string -- ) count + dup pathlen u> Abort" path too long" pathes place ; + +| : getpath ( +n -- string / ff ) + >r 0 pathes count r> 0 + DO rot drop Ascii ; skip stash Ascii ; scan LOOP + drop over - ?dup + IF here place here dup count + 1- c@ + ?" :\" ?exit Ascii \ here append exit + THEN 0= ; + +\ *** Block No. 9, Hexblock 9 + +\ pathsearch .path path ks 09 okt 87 + + : pathsearch ( string -- asciz *f ) dup >r + (fsearch dup 0= IF rdrop exit THEN 2drop 0 0 + BEGIN drop 1+ dup getpath ?dup 0= + IF drop r> filename >asciz 2 exit THEN + r@ count 2 pick attach (fsearch + 0= UNTIL nip rdrop false ; + + ' pathsearch Is fsearch + + Forth definitions + + : .path pathes count type ; + + : path name nullstring? IF .path exit THEN (setpath ; + +\ *** Block No. 10, Hexblock a + +\ call another executable file ks 04 aug 87 + Dos definitions + +| Create cpb 0 , \ inherit parent environment + dta , ds@ , $5C , ds@ , $6C , ds@ , Label ssave 0 , + +| Code ~exec ( asciz -- *f ) + I push R push U push S ssave #) mov cpb # R mov + $4B00 # A mov $21 int C: D mov D D: mov D S: mov + D E: mov ssave #) S mov CS not + ?[ A A xor A push $2F # A+ mov $21 int E: A mov + A D: mov C: A mov A E: mov R I mov dta # W mov + $40 # C mov rep movs A D: mov A pop + ]? A W xchg dta # D mov $1A # A+ mov $21 int + W D mov U pop R pop I pop Next + end-code + +\ *** Block No. 11, Hexblock b + +\ calling MS-DOS thru forth interpreter ks 19 mr 88 + +| : execute? ( extension -- *f ) + count filename count Ascii . scan drop swap + 2dup 1+ erase move filename 1+ ~exec ; + + : fcall ( string -- ) count filename place ds@ cpb 4+ ! + " .EXE" execute? dup IF drop " .COM" execute? THEN + ?diskerror ; + + : fdos ( string -- ) + dta $80 erase " /c " count dta place count dta attach + status push status off .status COMSPEC fcall curat? at ; + + + + +\ *** Block No. 12, Hexblock c + +\ einige MS-DOS Funktionen msdos call ks 10 okt 87 + + : dos: Create ," Does> count here place + Ascii " parse here attach here fdos ; + + Forth definitions + + dos: dir dir " + dos: ren ren " + dos: md md " + dos: cd cd " + dos: rd rd " + dos: fcopy copy " + dos: delete del " + dos: ftype type " + + +\ *** Block No. 13, Hexblock d + +\ msdos call ks 23 okt 88 + + : msdos savevideo status push status off .status + flush dta off COMSPEC fcall restorevideo ; + + : call name source >in @ /string c/l umin + dta place dta dta >asciz drop [compile] \ + status push status off .status fcall curat? at ; + + + .( MS-DOS functions loaed ) cr + + Onlyforth diff --git a/8086/msdos/src/dos3.fth b/8086/msdos/src/dos3.fth new file mode 100644 index 0000000..ad3ae7b --- /dev/null +++ b/8086/msdos/src/dos3.fth @@ -0,0 +1,195 @@ + +\ *** Block No. 0, Hexblock 0 + +\ 28 jun 88 + +\ This file is an .fth-version of dos.fb without the block-related +\ words. + +\ DOS loads higher level file functions which go beyond +\ including a screen file. Calls to MS-DOS are implemented +\ and used for directory manipulation. These functions may +\ not work for versions before MS-DOS 3.0. + + +\ *** Block No. 1, Hexblock 1 + +\ MS-DOS file handli cas 09jun20 + Onlyforth \needs Assembler 2 loadfrom asm.fb + + : fswap isfile@ fromfile @ isfile ! fromfile ! ; + + $80 Constant dta + +| : COMSPEC ( -- string ) [ dos ] + $2C @ ( DOS-environment:seg) 8 ds@ filename &60 lmove + filename counted &60 min filename place filename ; + + +\ *** Block No. 5, Hexblock 5 + +\ file eof? create dta-addressing ks 03 apr 88 + Dos also definitions + + : ftime ( -- mm hh ) + isfile@ f.time @ $20 u/mod nip $40 u/mod ; + + : fdate ( -- dd mm yy ) + isfile@ f.date @ $20 u/mod $10 u/mod &80 + ; + + : .when base push decimal + fdate rot 3 .r ." ." swap 2 .r ." ." 2 .r + ftime 3 .r ." :" 2 .r ; + + + + + +\ *** Block No. 6, Hexblock 6 + +\ ks 20mar88 + + : (.fcb ( fcb -- ) + dup .file ?dup 0=exit pushfile + isfile ! &13 tab ." is" + isfile@ f.handle @ 2 .r + isfile@ f.size 2@ 7 d.r .when + space isfile@ f.name count type ; + + Forth definitions + + : files file-link + BEGIN @ dup WHILE cr dup (.fcb stop? UNTIL drop ; + + : ?file isfile@ (.fcb ; + + +\ *** Block No. 7, Hexblock 7 + +\ dir make makefile ks 25 okt 87 + Forth definitions + + : killfile close + isfile@ f.name filename >asciz ~unlink drop ; + + : emptyfile isfile@ 0=exit + isfile@ f.name filename >asciz 0 ~creat ?diskerror + isfile@ f.handle ! isfile@ f.size 4 erase ; + + : make close name isfile@ fname! emptyfile ; + + : makefile File last @ name> execute emptyfile ; + + + + +\ *** Block No. 8, Hexblock 8 + +\ getpath ks 10 okt 87 + Dos definitions + +| &40 Constant pathlen +| Create pathes 0 c, pathlen allot + +| : (setpath ( string -- ) count + dup pathlen u> Abort" path too long" pathes place ; + +| : getpath ( +n -- string / ff ) + >r 0 pathes count r> 0 + DO rot drop Ascii ; skip stash Ascii ; scan LOOP + drop over - ?dup + IF here place here dup count + 1- c@ + ?" :\" ?exit Ascii \ here append exit + THEN 0= ; + +\ *** Block No. 9, Hexblock 9 + +\ pathsearch .path path ks 09 okt 87 + + : pathsearch ( string -- asciz *f ) dup >r + (fsearch dup 0= IF rdrop exit THEN 2drop 0 0 + BEGIN drop 1+ dup getpath ?dup 0= + IF drop r> filename >asciz 2 exit THEN + r@ count 2 pick attach (fsearch + 0= UNTIL nip rdrop false ; + + ' pathsearch Is fsearch + + Forth definitions + + : .path pathes count type ; + + : path name nullstring? IF .path exit THEN (setpath ; + +\ *** Block No. 10, Hexblock a + +\ call another executable file ks 04 aug 87 + Dos definitions + +| Create cpb 0 , \ inherit parent environment + dta , ds@ , $5C , ds@ , $6C , ds@ , Label ssave 0 , + +| Code ~exec ( asciz -- *f ) + I push R push U push S ssave #) mov cpb # R mov + $4B00 # A mov $21 int C: D mov D D: mov D S: mov + D E: mov ssave #) S mov CS not + ?[ A A xor A push $2F # A+ mov $21 int E: A mov + A D: mov C: A mov A E: mov R I mov dta # W mov + $40 # C mov rep movs A D: mov A pop + ]? A W xchg dta # D mov $1A # A+ mov $21 int + W D mov U pop R pop I pop Next + end-code + +\ *** Block No. 11, Hexblock b + +\ calling MS-DOS thru forth interpreter ks 19 mr 88 + +| : execute? ( extension -- *f ) + count filename count Ascii . scan drop swap + 2dup 1+ erase move filename 1+ ~exec ; + + : fcall ( string -- ) count filename place ds@ cpb 4+ ! + " .EXE" execute? dup IF drop " .COM" execute? THEN + ?diskerror ; + + : fdos ( string -- ) + dta $80 erase " /c " count dta place count dta attach + status push status off .status COMSPEC fcall curat? at ; + + + + +\ *** Block No. 12, Hexblock c + +\ einige MS-DOS Funktionen msdos call ks 10 okt 87 + + : dos: Create ," Does> count here place + Ascii " parse here attach here fdos ; + + Forth definitions + + dos: dir dir " + dos: ren ren " + dos: md md " + dos: cd cd " + dos: rd rd " + dos: fcopy copy " + dos: delete del " + dos: ftype type " + + +\ *** Block No. 13, Hexblock d + +\ msdos call ks 23 okt 88 + + : msdos savevideo status push status off .status + flush dta off COMSPEC fcall restorevideo ; + + : call name source >in @ /string c/l umin + dta place dta dta >asciz drop [compile] \ + status push status off .status fcall curat? at ; + + + .( MS-DOS functions loaed ) cr + + Onlyforth diff --git a/8086/msdos/src/extend2.fth b/8086/msdos/src/extend2.fth new file mode 100644 index 0000000..2f70456 --- /dev/null +++ b/8086/msdos/src/extend2.fth @@ -0,0 +1,182 @@ + +\ *** Block No. 0, Hexblock 0 + +\ ks 11 mai 88 + +\ This file is a pure .fth-version of extend.fb. +\ It contains definitions needed for several further system +\ and application files. + +\ Among others there are MSDOS specific commands such as allocating +\ memory outside the Forth core 64k memory segment, some routines +\ that make using the video display easier, and some string +\ manipulation words. + + +\ *** Block No. 1, Hexblock 1 + +\ loadscreen for often used words ks cas 25sep16 + + Onlyforth \needs Assembler include t86asm.fth + + ' save-buffers Alias sav + + ' name &12 + Constant 'name + + ' page Alias cls + +\ 1 8 +thru + +\ *** Block No. 2, Hexblock 2 + +\ Postkernel words ks 22 dez 87 + + : blank ( addr quan -- ) bl fill ; + + Code stash ( u1 u2 -- u1 u1 u2 ) + S W mov W ) push Next end-code +\ : stash ( u1 u2 -- u1 u1 u2 ) over swap ; + + : >expect ( addr len -- ) stash expect span @ over place ; + + : .field ( addr len quan -- ) + over - >r type r> 0 max spaces ; + + : tab ( n -- ) col - 0 max spaces ; + + + +\ *** Block No. 3, Hexblock 3 + +\ postkernel ks 08 mär 89 +\ hier sollte END-CODE eigentlich aehem, also z.B. -TRANSIENT + +\needs end-code : end-code toss also ; + + : u? ( addr -- ) @ u. ; + + : adr ' >body state @ 0=exit [compile] Literal ; immediate + + : Abort( ( f -- ) IF [compile] .( true abort" !" THEN + [compile] ( ; + + : arguments ( n -- ) + depth 1- > Error" zu wenige Parameter" ; + + + +\ *** Block No. 4, Hexblock 4 + +\ MS-DOS memory management + + Code lallocate ( pages -- seg ff / rest err# ) + R push D R mov $48 # A+ mov $21 int CS + ?[ A D xchg A pop R push A R xchg + ][ R pop A push 0 # D mov ]? Next end-code + + Code lfree ( seg -- err# ) + E: push D E: mov $49 # A+ mov $21 int CS + ?[ A D xchg ][ 0 # D mov ]? E: pop Next end-code + + + + + + + +\ *** Block No. 5, Hexblock 5 + +\ postkernel ks 03 aug 87 + + c/row c/col * 2* Constant c/dis \ characters per display + + Code video@ ( -- seg ) D push R D mov $F # A+ mov + $10 int R D xchg 0 # D- mov 7 # A- cmp + 0= ?[ $B0 # D+ mov ][ $B8 # D+ add ]? Next + end-code + + : savevideo ( -- seg / ff ) + [ c/dis b/seg /mod swap 0<> - ] Literal lallocate + IF drop false exit THEN video@ 0 2 pick 0 c/dis lmove ; + + : restorevideo ( seg -- ) ?dup 0=exit + dup 0 video@ 0 c/dis lmove lfree drop ; + + +\ *** Block No. 6, Hexblock 6 + +\ string operators append attach ks 21 jun 87 + +| : .stringoverflow true Abort" String zu lang" ; + + Code append ( char addr -- ) + D W mov D pop W ) A- mov 1 # A- add CS + ?[ ;c: .stringoverflow ; Assembler ]? + A- W ) mov 0 # A+ mov A W add + D- W ) mov D pop Next end-code + + Code attach ( addr len addr1 -- ) D W mov C pop + I D mov I pop W ) A- mov A- A+ mov C- A+ add CS + ?[ ;c: .stringoverflow ; Assembler ]? + A+ W ) mov A+ A+ xor A+ C+ mov A W add W inc + rep byte movs D I mov D pop Next end-code + + +\ *** Block No. 7, Hexblock 7 + +\\ string operators append attach detract ks 21 jun 87 + + : append ( char addr -- ) + under count + c! dup c@ 1+ swap c! ; + + : attach ( addr len addr.to -- ) + >r under r@ count + swap move r@ c@ + r> c! ; + + : detract ( addr -- char ) + dup c@ 1- dup 0> and over c! + count >r dup count -rot swap r> cmove ; + + + + + + +\ *** Block No. 8, Hexblock 8 + +\ ?" string operator ks 09 feb 88 + +\ : (?" ( 8b -- index ) "lit under count rot +\ scan IF swap - exit THEN 2drop false ; + +| Create months ," janfebmäraprmaijunjulaugsepoktnovdez" + + : >months ( n -- addr len ) 3 * 2- months + 3 ; + +| Code (?" ( 8b -- index ) + A D xchg I ) C- mov 0 # C+ mov C I add + I W mov I inc std 0<>rep byte scas cld + 0= ?[ C inc ]? C D mov Next + end-code + + : ?" compile (?" ," align ; immediate restrict + +\ *** Block No. 9, Hexblock 9 + +\ Conditional compilation ks 12 dez 88 +| Defer cond + + : .THEN ; immediate + + : .ELSE ( -- ) 0 + BEGIN name nullstring? IF drop exit THEN + find IF cond -1 case? ?exit ELSE drop THEN + REPEAT ; immediate + + : .IF ( f -- ) ?exit [compile] .ELSE ; immediate + +| : (cond ( n cfa -- n' ) + ['] .THEN case? IF 1- exit THEN + ['] .ELSE case? IF dup 0= + exit THEN + ['] .IF = 0=exit 1+ ; ' (cond is cond + +.( Systemerweiterung geladen) cr diff --git a/8086/msdos/src/multivid.fth b/8086/msdos/src/multivid.fth new file mode 100644 index 0000000..6915ccd --- /dev/null +++ b/8086/msdos/src/multivid.fth @@ -0,0 +1,192 @@ + +\ *** Block No. 0, Hexblock 0 + +\ This file is a pure .fth-version of multi.vid. + +\ This display interface uses BIOS call $10 functions for a fast +\ display interface. A couple of state variables is contained +\ in a vector that is task specific such that different tasks +\ may use different windows. For simplicity windows always +\ span the whole width of the screen. They can be defined by +\ top and bottom line. This mechanism is used for a convenient +\ status display line on the bottom of the screen. + + + + + + + + + +\ *** Block No. 1, Hexblock 1 + +\ Multitsking display interface loadscreen ks phz 31jan22 + Onlyforth \needs Assembler include t86asm.fth + + User area area off \ points at active window + Variable status \ to switch status on/off +| Variable cursor \ points at area with active cursor + +\ 1 8 +thru .( Multitasking display driver loaded ) cr + + + + + + + + + +\ *** Block No. 2, Hexblock 2 + +\ Multitsking display interface ks 6 sep 86 + + : Area: Create 0 , 0 , 7 c, Does> area ! ; +\ | col | row | top | bot | att | + +Area: terminal terminal area @ cursor ! + + : (area Create dup c, 1+ Does> c@ area @ + ; + +0 | (area ccol | (area crow | (area ctop + | (area cbot (area catt drop + + : window ( topline botline -- ) cbot c! ctop c! ; + + : full 0 c/col 2- window ; full + + +\ *** Block No. 3, Hexblock 3 + +\ Multitask (type (emit ks 20 dez 87 + + Code (type ( addr len -- ) W pop I push R push + u' area U D) I mov U push D U mov + $F # A+ mov $10 int u' catt I D) R- mov + 3 # A+ mov $10 int C push D push $E0E # C mov + 1 # A+ mov $10 int I ) D mov 1 # C mov + U inc [[ U dec 0= not ?[[ 2 # A+ mov $10 int + D- inc ' c/row >body #) D- cmp 0= not + ?[[ W ) A- mov W inc 9 # A+ mov $10 int ]]? ]? + D I ) mov D pop cursor #) I cmp 0= ?[ I ) D mov ]? + 2 # A+ mov $10 int C pop 1 # A+ mov $10 int U pop + R pop I pop D pop ' pause #) jmp end-code + + : (emit ( char -- ) sp@ 1 (type drop ; + + +\ *** Block No. 4, Hexblock 4 + +\ Multitask (at (at? ks 04 aug 87 + Code (at ( row col -- ) A pop A- D+ mov + u' area U D) W mov D W ) mov cursor #) W cmp 0= + ?[ R push U push $F # A+ mov $10 int + 2 # A+ mov $10 int U pop R pop + ]? D pop Next end-code + + Code (at? ( -- row col ) + D push u' area U D) W mov W ) D mov + D+ A- mov 0 # A+ mov A+ D+ mov A push Next + end-code + + Code curat? ( -- row col ) D push R push + $F # A+ mov $10 int 3 # A+ mov $10 int + R pop 0 # A mov D+ A- xchg A push Next + end-code + +\ *** Block No. 5, Hexblock 5 + +\ cur! curshape setpage ks 28 jun 87 + + : cur! \ set cursor into current task's window + area @ cursor ! (at? (at ; cur! + + Code curshape ( top bot -- ) D C mov D pop + D- C+ mov 1 # A+ mov $10 int D pop Next + end-code + + Code setpage ( n -- ) + $503 # A mov D- A- and $10 int D pop Next + end-code + + + + + +\ *** Block No. 6, Hexblock 6 + +\ Multitask normal invers blankline ks 01 nov 88 + : normal 7 catt c! ; : invers $70 catt c! ; + : underline 1 catt c! ; : bright $F catt c! ; + + Code blankline D push R push U push $F # A+ mov + $10 int u' area U D) W mov u' catt W D) R- mov + 3 # A+ mov $10 int C push D push + $E0E # C mov 1 # A+ mov $10 int W ) D mov + 2 # A+ mov $10 int ' c/row >body #) C mov + D- C- sub bl # A- mov 9 # A+ mov + C- C- or 0= not ?[ $10 int ]? + D pop 2 # A+ mov $10 int \ set cursor back + C pop 1 # A+ mov $10 int \ cursor visible again + U pop R pop D pop ' pause #) jmp end-code + +| : lineerase ( line# -- ) 0 (at blankline ; + +\ *** Block No. 7, Hexblock 7 + +\ Multitask (del scroll (cr (page ks 04 okt 87 + + : (del (at? ?dup + IF 1- 2dup (at bl (emit (at exit THEN drop ; + + Code scroll D push R push U push + u' area U D) W mov u' catt W D) R+ mov + u' ctop W D) D mov D- C+ mov 0 # C- mov + ' c/row >body #) D- mov D- dec $601 # A mov + $10 int U pop R pop D pop Next + end-code + + : (cr (at? drop 1+ dup cbot c@ u> + IF scroll drop cbot c@ THEN lineerase ; + + : (page ctop c@ cbot c@ DO I lineerase -1 +LOOP ; + +\ *** Block No. 8, Hexblock 8 + +\ Multitask status display ks 10 okt 87 + + ' (emit ' display 2 + ! ' (cr ' display 4 + ! + ' (type ' display 6 + ! ' (del ' display 8 + ! + ' (page ' display &10 + ! + ' (at ' display &12 + ! ' (at? ' display &14 + ! + + : .base base @ decimal dup 2 .r base ! ; + : .sp ( n -- ) ." s" depth swap 1+ - 2 .r ; + : (.drv ( n -- ) Ascii A + emit ." : " ; + : .dr ." " drv (.drv ; + : .scr blk @ IF ." Blk" blk ELSE ." Scr" scr THEN + @ 5 .r ; + : .space ." Dic" s0 @ here $100 + - 6 u.r ; + + + +\ *** Block No. 9, Hexblock 9 + +\ statuszeile ks ks 04 aug 87 + +| : fstat ( n -- ) .base .sp + .space .scr .dr file? 2 spaces order ; + +| Area: statusline + statusline c/col 1- dup window page invers terminal + + : (.status output @ display area @ statusline + status @ IF (at? drop 0 (at 2 fstat blankline + ELSE normal page invers + THEN area ! output ! ; + ' (.status Is .status + + : bye status off .status bye ; + +.( Multitasking display driver loaded ) cr diff --git a/8086/msdos/src/t86asm.fth b/8086/msdos/src/t86asm.fth new file mode 100644 index 0000000..f58411e --- /dev/null +++ b/8086/msdos/src/t86asm.fth @@ -0,0 +1,14 @@ + +\ *** Block No. 2, Hexblock 2 + +\ conditional Assembler compiler cas 10nov05 + here + + : maybe-include-tmp-asm ( addr -- ) hide last off dp ! + " ASSEMBLER" find nip ?exit here $1800 + sp@ u> + IF display cr ." Assembler won't fit" abort THEN + here sp@ $1800 - dp ! + include + dp ! ; + + maybe-include-tmp-asm 86asm.fth diff --git a/8086/msdos/tests/logprep.fth b/8086/msdos/tests/logprep.fth index 44c7a6e..0adc3ce 100644 --- a/8086/msdos/tests/logprep.fth +++ b/8086/msdos/tests/logprep.fth @@ -1,5 +1,13 @@ - include extend.fb - include multi.vid - include dos.fb - include log2file.fb + include extend2.fth + include multivid.fth + +\ : .blk|tib +\ blk @ ?dup IF ." Blk " u. ?cr exit THEN +\ incfile @ IF tib #tib @ cr type THEN ; + +\ ' .blk|tib Is .status + +\ include dos2.fth + include dos3.fth + include log2file.fth From 48544073a1d3d992e80d2ec81061a2162bad0410 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 21 Mar 2022 09:27:51 +0100 Subject: [PATCH 12/21] 2nd refactoring step to enable building a v4th.com from vf86core.fth, vf86dos.fth and vf86file.fth, without vf86bufs.fth. --- 8086/msdos/Makefile | 1 + 8086/msdos/src/mk-v4th.fth | 2 + 8086/msdos/src/vf86bufs.fth | 205 +++++++++++++++++++++++++++++++----- 8086/msdos/src/vf86core.fth | 19 +--- 8086/msdos/src/vf86dos.fth | 170 +++++------------------------- 8086/msdos/src/vf86file.fth | 6 +- 6 files changed, 216 insertions(+), 187 deletions(-) diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 72d0ab3..41bc064 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -31,6 +31,7 @@ v4th.com: metafile.com src/meta.fb src/mk-v4th.fth \ metafile.com "include mk-v4th.fth" dos2unix -n OUTPUT.LOG v4th.log mv V4TH.COM v4th.com + grep -F 'unresolved:' v4th.log grep -F 'new kernel written as v4th.com' v4th.log grep -i 'unresolved:.*[^ ]' v4th.log && exit 1 || true diff --git a/8086/msdos/src/mk-v4th.fth b/8086/msdos/src/mk-v4th.fth index 9fc6f4e..f8d86fd 100644 --- a/8086/msdos/src/mk-v4th.fth +++ b/8086/msdos/src/mk-v4th.fth @@ -22,6 +22,8 @@ include vf86file.fth + include vf86bufs.fth + : forth-83 ; \ last word in Dictionary 0 ' limit >body ! $DFF6 s0 ! $E77C r0 ! diff --git a/8086/msdos/src/vf86bufs.fth b/8086/msdos/src/vf86bufs.fth index 0191253..878e9aa 100644 --- a/8086/msdos/src/vf86bufs.fth +++ b/8086/msdos/src/vf86bufs.fth @@ -12,28 +12,9 @@ \ 8 : Data ... 1 Kb ... + Forth definitions -\ *** Block No. 81, Hexblock 51 - -\ +load thru +thru --> rdepth depth ks 26 jul 87 - - : (load ( blk offset -- ) isfile@ >r - loadfile @ >r fromfile @ >r blk @ >r >in @ >r - >in ! blk ! isfile@ loadfile ! .status interpret - r> >in ! r> blk ! r> fromfile ! r> loadfile ! - r> isfile ! ; - - : load ( blk -- ) ?dup 0=exit 0 (load ; - - : +load ( offset -- ) blk @ + load ; - - : thru ( from to -- ) 1+ swap DO I load LOOP ; - - : +thru ( off0 off1 -- ) 1+ swap DO I +load LOOP ; - - : --> 1 blk +! >in off .status ; immediate - @@ -42,13 +23,13 @@ \ buffer mechanism ks 04 okt 87 - Variable fromfile fromfile off \ fcb in kopieroperationen - - Variable prev prev off \ Listhead + Variable prev prev off \ Listhead of the buffers' list +| Variable buffers buffers off \ Semaphor $408 Constant b/buf \ physikalische Groesse $400 Constant b/blk \ bytes/block + Defer r/w \ physikalischer Diskzugriff \ *** Block No. 92, Hexblock 5c @@ -158,12 +139,103 @@ ' (save-buffers IS save-buffers - : empty-buffers buffers lock prev + : (empty-buffers buffers lock prev BEGIN @ ?dup WHILE dup emptybuf REPEAT buffers unlock ; - : flush file-link - BEGIN @ ?dup WHILE dup fclose REPEAT - save-buffers empty-buffers ; +' (empty-buffers IS empty-buffers + + + Dos definitions + +\ *** Block No. 137, Hexblock 89 + +\ /block *block ks 02 okt 87 + + Code /block ( d -- rest blk ) A D xchg C pop + C D mov A shr D rcr A shr D rcr D+ D- mov + A- D+ xchg $3FF # C and C push Next + end-code +\ : /block ( d -- rest blk ) b/blk um/mod ; + + Code *block ( blk -- d ) A A xor D+ D- xchg D+ A+ xchg + A+ sal D rcl A+ sal D rcl A push Next + end-code +\ : *block ( blk -- d ) b/blk um* ; + + + + + +\ *** Block No. 138, Hexblock 8a + +\ fblock@ fblock! ks 19 mär 88 + Dos definitions + +| : ?beyond ( blk -- blk ) dup 0< 0=exit 9 ?diskerror ; + +| : fblock ( addr blk fcb -- seg:addr quan fcb ) + fcb ! ?beyond dup *block fcb @ fseek ds@ -rot + fcb @ f.size 2@ /block rot - ?beyond + IF drop b/blk THEN fcb @ ; + + : fblock@ ( addr blk fcb -- ) fblock lfgets drop ; + + : fblock! ( addr blk fcb -- ) fblock lfputs ; + + + + +\ *** Block No. 139, Hexblock 8b + +\ (r/w flush ks 18 mär 88 + Forth definitions + + : (r/w ( addr blk fcb r/wf -- *f ) over fcb ! over + IF IF fblock@ false exit THEN fblock! false exit + THEN >r drop /drive ?drive + r> IF block@ exit THEN block! ; + + ' (r/w Is r/w + + + Dos definitions + +| : filebuffer? ( fcb -- fcb bufaddr / fcb ff ) + prev BEGIN @ dup WHILE 2dup 2+ @ = UNTIL ; + +: (flush-file-buffers ( fcb -- ) + BEGIN filebuffer? ?dup + WHILE dup backup emptybuf REPEAT drop ; + +' (flush-file-buffers IS flush-file-buffers + + +\ *** Block No. 81, Hexblock 51 + + Forth definitions + +\ +load thru +thru --> rdepth depth ks 26 jul 87 + + : (load ( blk offset -- ) isfile@ >r + loadfile @ >r fromfile @ >r blk @ >r >in @ >r + >in ! blk ! isfile@ loadfile ! .status interpret + r> >in ! r> blk ! r> fromfile ! r> loadfile ! + r> isfile ! ; + + : load ( blk -- ) ?dup 0=exit 0 (load ; + ' load IS include-load + + : +load ( offset -- ) blk @ + load ; + + : thru ( from to -- ) 1+ swap DO I load LOOP ; + + : +thru ( off0 off1 -- ) 1+ swap DO I +load LOOP ; + + : --> 1 blk +! >in off .status ; immediate + + : loadfrom ( n -- ) pushfile use load close ; + + : \\ b/blk >in ! ; immediate : list ( scr -- ) dup capacity u< IF scr ! ." Scr " scr @ . @@ -173,9 +245,88 @@ LOOP cr exit THEN 9 ?diskerror ; + : view 'file list ; + : help 'file capacity 2/ + list ; + +\ *** Block No. 122, Hexblock 7a + +\ Disk capacities ks 08 aug 88 + Dos definitions + + 6 Constant #drives + + Create capacities $4B0 , $4B0 , $1B31 , $1B31 , $1B0F , 0 , + +| Code ?capacity ( +n -- cap ) D shl capacities # W mov + D W add W ) D mov Next end-code + + + + + + + + +\ *** Block No. 123, Hexblock 7b + +\ MS-dos disk handlers direct access ks 31 jul 87 + +| Code block@ ( addr blk drv -- ff ) + D- A- mov D pop C pop R push U push + I push C R mov 2 # C mov D shl $25 int + Label end-r/w I pop I pop U pop R pop 0 # D mov + CS ?[ D+ A+ mov A error# #) mov D dec ]? Next + end-code + +| Code block! ( addr blk drv -- ff ) D- A- mov D pop + C pop R push U push I push C R mov 2 # C mov + D shl $26 int end-r/w # jmp + end-code + + + + +\ *** Block No. 124, Hexblock 7c + +\ MS-dos disk handlers direct access ks cas 18jul20 + +| : ?drive ( +n -- +n ) dup #drives u< ?exit + Error" beyond drive capacity" ; + + : /drive ( blk1 -- blk2 drive ) 0 swap #drives 0 + DO dup I ?capacity under u< IF drop LEAVE THEN + - swap 1+ swap LOOP swap ; + + : blk/drv ( -- capacity ) drv ?capacity ; + + Forth definitions + + : >drive ( blk1 +n -- blk2 ) ?drive + 0 swap drv 2dup u> dup >r 0= IF swap THEN + ?DO I ?capacity + LOOP r> IF negate THEN - ; + +\ *** Block No. 143, Hexblock 8f + +\ drive drv capacity drivenames ks 18 mär 88 + + : drive ( n -- ) isfile@ IF ~select exit THEN + ?drive offset off 0 ?DO I ?capacity offset +! LOOP ; + + : drv ( -- n ) + isfile@ IF ~disk? exit THEN offset @ /drive nip ; + + : capacity ( -- n ) isfile@ ?dup + IF dup f.handle @ 0= IF dup freset THEN + f.size 2@ /block swap 0<> - exit THEN blk/drv ; + +| : Drv: Create c, Does> c@ drive ; + + 0 Drv: A: 1 Drv: B: 2 Drv: C: 3 Drv: D: + 4 Drv: E: 5 Drv: F: 6 Drv: G: 7 Drv: H: + \ *** Block No. 98, Hexblock 62 \ Allocating buffers ks 31 oct 86 diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index 039ecbe..0005378 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -1002,7 +1002,7 @@ swap ]? C >in #) add : \ blk @ IF >in @ negate c/l mod >in +! ELSE #tib @ >in ! THEN ; immediate - : \\ b/blk >in ! ; immediate + : have ( -- f ) name find nip 0<> ; immediate : \needs have 0=exit [compile] \ ; @@ -1611,23 +1611,6 @@ Target Forth also definitions $10000 Constant limit Variable first - Variable isfile isfile off \ addr of file control block - Code isfile@ ( -- addr ) - D push isfile #) D mov Next end-code -\ : isfile@ ( -- addr ) isfile @ ; - -| Variable buffers buffers off \ Semaphor - - Defer r/w \ physikalischer Diskzugriff - Variable error# error# off \ Nummer des letzten Fehlers - Defer ?diskerror \ Fehlerbehandlung - - Defer save-buffers ' noop IS save-buffers - Defer init-buffers ' noop IS init-buffers - - - include vf86bufs.fth - \ *** Block No. 99, Hexblock 63 diff --git a/8086/msdos/src/vf86dos.fth b/8086/msdos/src/vf86dos.fth index 0f628b8..83e13df 100644 --- a/8086/msdos/src/vf86dos.fth +++ b/8086/msdos/src/vf86dos.fth @@ -1,3 +1,24 @@ + + Forth definitions + + Defer save-buffers ' noop IS save-buffers + Defer init-buffers ' noop IS init-buffers + Defer empty-buffers ' noop IS empty-buffers + + Defer flush-file-buffers ( fcb -- ) + ' drop IS flush-file-buffers + + Variable isfile isfile off \ addr of file control block + Variable fromfile fromfile off \ fcb in kopieroperationen + + Code isfile@ ( -- addr ) + D push isfile #) D mov Next end-code +\ : isfile@ ( -- addr ) isfile @ ; + + Variable error# error# off \ Nummer des letzten Fehlers + Defer ?diskerror \ Fehlerbehandlung + + \ *** Block No. 112, Hexblock 70 \ lc@ lc! l@ l! special 8088 operators ks 27 oct 86 @@ -188,67 +209,10 @@ -\ *** Block No. 122, Hexblock 7a - -\ Disk capacities ks 08 aug 88 - Vocabulary Dos Dos also definitions - - 6 Constant #drives - - Create capacities $4B0 , $4B0 , $1B31 , $1B31 , $1B0F , 0 , - -| Code ?capacity ( +n -- cap ) D shl capacities # W mov - D W add W ) D mov Next end-code - - - - - - - - -\ *** Block No. 123, Hexblock 7b - -\ MS-dos disk handlers direct access ks 31 jul 87 - -| Code block@ ( addr blk drv -- ff ) - D- A- mov D pop C pop R push U push - I push C R mov 2 # C mov D shl $25 int - Label end-r/w I pop I pop U pop R pop 0 # D mov - CS ?[ D+ A+ mov A error# #) mov D dec ]? Next - end-code - -| Code block! ( addr blk drv -- ff ) D- A- mov D pop - C pop R push U push I push C R mov 2 # C mov - D shl $26 int end-r/w # jmp - end-code - - - - -\ *** Block No. 124, Hexblock 7c - -\ MS-dos disk handlers direct access ks cas 18jul20 - -| : ?drive ( +n -- +n ) dup #drives u< ?exit - Error" beyond drive capacity" ; - - : /drive ( blk1 -- blk2 drive ) 0 swap #drives 0 - DO dup I ?capacity under u< IF drop LEAVE THEN - - swap 1+ swap LOOP swap ; - - : blk/drv ( -- capacity ) drv ?capacity ; - - Forth definitions - - : >drive ( blk1 +n -- blk2 ) ?drive - 0 swap drv 2dup u> dup >r 0= IF swap THEN - ?DO I ?capacity + LOOP r> IF negate THEN - ; - \ *** Block No. 125, Hexblock 7d \ MS-DOS file access ks 18 mär 88 - Dos definitions + Vocabulary Dos Dos also definitions | Variable fcb fcb off \ last fcb accessed | Variable prevfile \ previous active file @@ -386,16 +350,9 @@ b/fcb Host ' tb/fcb >body ! : fname! ( string fcb -- ) f.name >r count dup fnamelen < not Abort" file name too long" r> place ; -| : filebuffer? ( fcb -- fcb bufaddr / fcb ff ) - prev BEGIN @ dup WHILE 2dup 2+ @ = UNTIL ; - -| : flushfile ( fcb -- ) - BEGIN filebuffer? ?dup - WHILE dup backup emptybuf REPEAT drop ; - : fclose ( fcb -- ) ?dup 0=exit dup f.handle @ ?dup 0= IF drop exit THEN - over flushfile ~close f.handle off ; + over flush-file-buffers ~close f.handle off ; \ *** Block No. 133, Hexblock 85 @@ -473,66 +430,20 @@ Assembler [[ W R xchg C pop D pop : file! ( 8b dfaddr fcb -- ) dup >r fseek r> fputc ; - -\ *** Block No. 137, Hexblock 89 - -\ /block *block ks 02 okt 87 - - Code /block ( d -- rest blk ) A D xchg C pop - C D mov A shr D rcr A shr D rcr D+ D- mov - A- D+ xchg $3FF # C and C push Next - end-code -\ : /block ( d -- rest blk ) b/blk um/mod ; - - Code *block ( blk -- d ) A A xor D+ D- xchg D+ A+ xchg - A+ sal D rcl A+ sal D rcl A push Next - end-code -\ : *block ( blk -- d ) b/blk um* ; - - - - - -\ *** Block No. 138, Hexblock 8a - -\ fblock@ fblock! ks 19 mär 88 - Dos definitions - -| : ?beyond ( blk -- blk ) dup 0< 0=exit 9 ?diskerror ; - -| : fblock ( addr blk fcb -- seg:addr quan fcb ) - fcb ! ?beyond dup *block fcb @ fseek ds@ -rot - fcb @ f.size 2@ /block rot - ?beyond - IF drop b/blk THEN fcb @ ; - - : fblock@ ( addr blk fcb -- ) fblock lfgets drop ; - - : fblock! ( addr blk fcb -- ) fblock lfputs ; - - - - -\ *** Block No. 139, Hexblock 8b - -\ (r/w flush ks 18 mär 88 Forth definitions - : (r/w ( addr blk fcb r/wf -- *f ) over fcb ! over - IF IF fblock@ false exit THEN fblock! false exit - THEN >r drop /drive ?drive - r> IF block@ exit THEN block! ; - - ' (r/w Is r/w - | : setfiles ( fcb -- ) isfile@ prevfile ! dup isfile ! fromfile ! ; : direct 0 setfiles ; + : flush file-link + BEGIN @ ?dup WHILE dup fclose REPEAT + save-buffers empty-buffers ; \ *** Block No. 140, Hexblock 8c - + Dos definitions \ File >file ks 23 mär 88 : File Create file-link @ here file-link ! , @@ -580,33 +491,13 @@ Assembler [[ W R xchg C pop D pop : from isfile push use ; - : loadfrom ( n -- ) pushfile use load close ; - - : include 1 loadfrom ; +\ Old pure-block-file include: +\ : include 1 loadfrom ; -\ *** Block No. 143, Hexblock 8f - -\ drive drv capacity drivenames ks 18 mär 88 - - : drive ( n -- ) isfile@ IF ~select exit THEN - ?drive offset off 0 ?DO I ?capacity offset +! LOOP ; - - : drv ( -- n ) - isfile@ IF ~disk? exit THEN offset @ /drive nip ; - - : capacity ( -- n ) isfile@ ?dup - IF dup f.handle @ 0= IF dup freset THEN - f.size 2@ /block swap 0<> - exit THEN blk/drv ; - -| : Drv: Create c, Does> c@ drive ; - - 0 Drv: A: 1 Drv: B: 2 Drv: C: 3 Drv: D: - 4 Drv: E: 5 Drv: F: 6 Drv: G: 7 Drv: H: - \ *** Block No. 144, Hexblock 90 \ lfsave savefile savesystem ks 10 okt 87 @@ -652,9 +543,6 @@ Assembler [[ W R xchg C pop D pop | : 'file ( -- scr ) r> scr push isfile push >r [ Dos ] ' @view >file isfile ! ; - : view 'file list ; - : help 'file capacity 2/ + list ; - | : remove? ( dic symb addr -- dic symb addr f ) 2 pick over 1+ u< ; diff --git a/8086/msdos/src/vf86file.fth b/8086/msdos/src/vf86file.fth index d0dfa04..e7fa7a0 100644 --- a/8086/msdos/src/vf86file.fth +++ b/8086/msdos/src/vf86file.fth @@ -77,9 +77,13 @@ BEGIN freadline >r .status >in off interpret r> UNTIL ; + Defer include-load +| : block-not-implemented 1 abort" block file access not implemented" ; + ' block-not-implemented IS include-load + : include ( -- ) pushfile use cr file? - probe-for-fb isfile@ freset IF 1 load close exit THEN + probe-for-fb isfile@ freset IF 1 include-load close exit THEN incfile push isfile@ incfile ! incpos push incpos off incpos 2+ dup push off savetib >r interpret-via-tib close r> restoretib ; From b24511437e2310589c0f2c7d65a31f97aef114f6 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 00:23:43 +0100 Subject: [PATCH 13/21] First block/buffer free MSDOS v4th.com. v4thblk.com is now the version with block/buffer implemented. --- 8086/msdos/Makefile | 21 ++++++++++++---- 8086/msdos/src/extend2.fth | 16 ++++++------ 8086/msdos/src/mk-v4th.fth | 47 ------------------------------------ 8086/msdos/src/v4th.fth | 32 ++++++++++++++++++++++++ 8086/msdos/src/v4thblk.fth | 33 +++++++++++++++++++++++++ 8086/msdos/src/vf86end.fth | 12 +++++++++ 8086/msdos/tests/logprep.fth | 1 + 7 files changed, 102 insertions(+), 60 deletions(-) delete mode 100644 8086/msdos/src/mk-v4th.fth create mode 100644 8086/msdos/src/v4th.fth create mode 100644 8086/msdos/src/v4thblk.fth create mode 100644 8086/msdos/src/vf86end.fth diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 41bc064..f25c151 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -24,17 +24,28 @@ metafile.com: v4thfile.com src/meta.fb src/mk-meta.fth tests/log2file.fb dos2unix -n OUTPUT.LOG metafile.log grep -F 'Metacompiler saved as metafile.com' metafile.log -v4th.com: metafile.com src/meta.fb src/mk-v4th.fth \ - src/vf86core.fth src/vf86dos.fth src/vf86file.fth src/vf86bufs.fth +v4th.com: metafile.com src/meta.fb src/v4th.fth src/vf86core.fth \ + src/vf86dos.fth src/vf86file.fth src/vf86end.fth rm -f v4th.com V4TH.COM OUTPUT.LOG FORTHPATH="f:\\;f:\\src;f:\\tests" ./emulator/run-in-dosbox.sh \ - metafile.com "include mk-v4th.fth" + metafile.com "include v4th.fth" dos2unix -n OUTPUT.LOG v4th.log mv V4TH.COM v4th.com grep -F 'unresolved:' v4th.log grep -F 'new kernel written as v4th.com' v4th.log grep -i 'unresolved:.*[^ ]' v4th.log && exit 1 || true +v4thblk.com: metafile.com src/meta.fb src/v4thblk.fth src/vf86core.fth \ + src/vf86dos.fth src/vf86file.fth src/vf86bufs.fth src/vf86end.fth + rm -f v4thblk.com V4THBLK.COM OUTPUT.LOG + FORTHPATH="f:\\;f:\\src;f:\\tests" ./emulator/run-in-dosbox.sh \ + metafile.com "include v4thblk.fth" + dos2unix -n OUTPUT.LOG v4thblk.log + mv V4THBLK.COM v4thblk.com + grep -F 'unresolved:' v4thblk.log + grep -F 'new kernel written as v4thblk.com' v4thblk.log + grep -i 'unresolved:.*[^ ]' v4thblk.log && exit 1 || true + # o4th for old volks4th - the new v4th is built with precompiled # metacompiler metafile.com and mk-v4th.fth which writes a compile log. o4th.com o4th.log: volks4th.com src/kernel.fb @@ -90,10 +101,10 @@ test-std.log: \ dos2unix -n dosfiles/OUTPUT.LOG $@ test-blk.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ + $(patsubst %, dosfiles/%, v4thblk.com $(prepfths)) \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) rm -f dosfiles/OUTPUT.LOG - (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ + (cd dosfiles && ../emulator/run-in-dosbox.sh v4thblk.com \ "include logprep.fth include test-blk.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ diff --git a/8086/msdos/src/extend2.fth b/8086/msdos/src/extend2.fth index 2f70456..0852488 100644 --- a/8086/msdos/src/extend2.fth +++ b/8086/msdos/src/extend2.fth @@ -124,17 +124,17 @@ \ *** Block No. 7, Hexblock 7 -\\ string operators append attach detract ks 21 jun 87 +\ string operators append attach detract ks 21 jun 87 - : append ( char addr -- ) - under count + c! dup c@ 1+ swap c! ; +\ : append ( char addr -- ) +\ under count + c! dup c@ 1+ swap c! ; - : attach ( addr len addr.to -- ) - >r under r@ count + swap move r@ c@ + r> c! ; +\ : attach ( addr len addr.to -- ) +\ >r under r@ count + swap move r@ c@ + r> c! ; - : detract ( addr -- char ) - dup c@ 1- dup 0> and over c! - count >r dup count -rot swap r> cmove ; +\ : detract ( addr -- char ) +\ dup c@ 1- dup 0> and over c! +\ count >r dup count -rot swap r> cmove ; diff --git a/8086/msdos/src/mk-v4th.fth b/8086/msdos/src/mk-v4th.fth deleted file mode 100644 index f8d86fd..0000000 --- a/8086/msdos/src/mk-v4th.fth +++ /dev/null @@ -1,47 +0,0 @@ - - logopen output.log - - \ : .blk|tib - \ blk @ ?dup IF ." Blk " u. ?cr exit THEN - \ incfile @ IF tib #tib @ cr type THEN ; - - \ ' .blk|tib Is .status - - Onlyforth - - 2 loadfrom META.fb - use kernel.fb - - new v4th.com Onlyforth Target definitions - - \ 4 &110 thru \ Standard 8088-System - include vf86core.fth - - \ &112 &146 thru \ MS-DOS interface - include vf86dos.fth - - include vf86file.fth - - include vf86bufs.fth - - : forth-83 ; \ last word in Dictionary - - 0 ' limit >body ! $DFF6 s0 ! $E77C r0 ! - s0 @ s0 2- ! here dp ! - - Host tudp @ Target udp ! - Host tvoc-link @ Target voc-link ! - Host tnext-link @ Target next-link ! - Host tfile-link @ Target Forth file-link ! - Host T move-threads H - save-buffers cr .( unresolved: ) .unresolved - - - - logclose - flush \ close n4th.com - logreopen - - cr .( new kernel written as v4th.com) cr - - logclose diff --git a/8086/msdos/src/v4th.fth b/8086/msdos/src/v4th.fth new file mode 100644 index 0000000..6f56c3c --- /dev/null +++ b/8086/msdos/src/v4th.fth @@ -0,0 +1,32 @@ + +\ with build log: +' noop alias \log +\ without build log: +\ ' \ alias \log + +\log logopen output.log + + \ : .blk|tib + \ blk @ ?dup IF ." Blk " u. ?cr exit THEN + \ incfile @ IF tib #tib @ cr type THEN ; + + \ ' .blk|tib Is .status + + Onlyforth + + 2 loadfrom META.fb + + new v4th.com Onlyforth Target definitions + + include vf86core.fth + include vf86dos.fth + include vf86file.fth + include vf86end.fth + +\log logclose + flush +\log logreopen + + cr .( new kernel written as v4th.com) cr + +\log logclose diff --git a/8086/msdos/src/v4thblk.fth b/8086/msdos/src/v4thblk.fth new file mode 100644 index 0000000..e0aa7a1 --- /dev/null +++ b/8086/msdos/src/v4thblk.fth @@ -0,0 +1,33 @@ + +\ with build log: +' noop alias \log +\ without build log: +\ ' \ alias \log + +\log logopen output.log + + \ : .blk|tib + \ blk @ ?dup IF ." Blk " u. ?cr exit THEN + \ incfile @ IF tib #tib @ cr type THEN ; + + \ ' .blk|tib Is .status + + Onlyforth + + 2 loadfrom META.fb + + new v4thblk.com Onlyforth Target definitions + + include vf86core.fth + include vf86dos.fth + include vf86file.fth + include vf86bufs.fth + include vf86end.fth + +\log logclose + flush +\log logreopen + + cr .( new kernel written as v4thblk.com) cr + +\log logclose diff --git a/8086/msdos/src/vf86end.fth b/8086/msdos/src/vf86end.fth new file mode 100644 index 0000000..e249ea2 --- /dev/null +++ b/8086/msdos/src/vf86end.fth @@ -0,0 +1,12 @@ + + : forth-83 ; \ last word in Dictionary + + 0 ' limit >body ! $DFF6 s0 ! $E77C r0 ! + s0 @ s0 2- ! here dp ! + + Host tudp @ Target udp ! + Host tvoc-link @ Target voc-link ! + Host tnext-link @ Target next-link ! + Host tfile-link @ Target Forth file-link ! + Host T move-threads H + save-buffers cr .( unresolved: ) .unresolved diff --git a/8086/msdos/tests/logprep.fth b/8086/msdos/tests/logprep.fth index 0adc3ce..4e4e3d6 100644 --- a/8086/msdos/tests/logprep.fth +++ b/8086/msdos/tests/logprep.fth @@ -1,5 +1,6 @@ include extend2.fth +\needs drv : drv 2 ; \ showing C: if drv isn't defined include multivid.fth \ : .blk|tib From 82cd5ba3da53fd0ce919b74add9aa5e8a59c6e1e Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 00:24:27 +0100 Subject: [PATCH 14/21] Update the latest binaries v4th.com and v4thblk.com --- 8086/msdos/v4th.com | Bin 15867 -> 14835 bytes 8086/msdos/v4thblk.com | Bin 0 -> 16971 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 8086/msdos/v4thblk.com diff --git a/8086/msdos/v4th.com b/8086/msdos/v4th.com index e95f373ccf486f5a7c207682353d10a748c621e4..3cfafc55bad939f2395b85c52075a8b6f02ce1a8 100644 GIT binary patch literal 14835 zcmdsed0d>;_4hOLtjqud1PDU{%&=sDfeBkeHi2Olm@v#tW*9bWFeadw38XAWQe%^5 zG|OnJX|*P`bt!FK($-pn8Z~MXqhcd5)n+k`#wAA47>PACM)`fu^MKmlfA8o0=l#6; zAw2iobMHO(+_T@y9UpDZz2hT3mkBeB;Pty|T%MeiLmyq9V3;r8{_^dcKD@AiVKmGi z3m+)>+Q2YZTSm(8>;Lora#B)n=nk#yb$a~`wT1Ia4L$8QSPZ3>dBv8pVkWFnMR^>} z4TWx(r!FVuxl$%vrWXAUo43*7&q=AP+fu&tPrsVTVVE}cCHlBheVzJi`dFc6!cH~k z@p^ro`24Y29Vq%rFEQbp)M`JzG)(wbwc76cN*~RH?@$X~r!(Ma_(~tkgm-D_1N7G|5y5CCOoPZt<~6x!~T^% zg$ci>mKwb_nfR~tsZ4lW9p!Yn9g~2WOjymbL82j@2~T6$fUjy6>yNxa^sfTZ=>#&) zXCv>n5~z@6!o?Wit8xSDO#)Q`WG9fZjg5RPV+8;&ky?9VFvPqN_hbQ$(1!2Zhq%wO?$ z44iJW(a;wFdy!T9tKK0PLEZ%9ID3oV?)Uos%_>+Q0yf5Sj%HVb#6`*#;MV|7utLz| zaRdNn!igMTNhoGcd!)7h7)=%ju#pprt{}LL;C;`JongZBIMLDUumu|&&0OSCD_t|NubCT1Z?BfwyK|?y)|i=p$W?{VIP3TI{<9n%*z|Q1;8zwXlwA+)VLjw zP*0K4vlBhPuO!>{=5Ev-vrUpAg>5)v)BKg&|E5mjso9 z%gkHodz)BYJ$8`^{|qAwe=RPiksTQMON=ahR9s9W2Z3Gqgt&O|*m)-Wn8-EwgN{M{ z!~_$5R^**lcK|JTr|^iVDpJ0ViK^m3y$Y~*MODe5UX8C$L{;gap2gRfqN;3A&*6)a z)P+E#sWg(>>zOG%IWZBrv_%p2`$0#N#KIz%Nl!8ise6I6(GC5V{E~;E zq&>2SVft0__T8BBHi<1-RPm?+?^EFS0scEl9bB|e!Z`uISAjnP_|t$_oRGG+j(xy{ z{~@Usotea0r{IhN=N(B^@eQG19~ZG~g(j->`LW|nn2k~wEt(!B(=edmUjTkwlkTv^9poc7sc9(uDCr4!rRC0Q8Dt?H=yH|D7F2HkiJN)6(do^qTd3r zXgI0`n{LMJ>javAXH-9LegPb)CZYIC6kG4|oS=2qsaZva4`8k%fLoi#34YVZ>^|E0 z$5C7mxPk_--hTpigb9B`Fl%!v!Fu)qwwDRVYXtavhsR!|*}g-T`!kp@N5fjH12&EJ z$bec=o^m+wg&NKda7b^_Sh*sRh+d-Em}~cjG|lV3SYKD?bZ#k!_Y&*s%!em^SUtwA z(1ddmHTta?JGa;^KBWq+UatIx-Yi`XoQ_sIOs_Cs`?_v8Il}oLKhh&@7#K$whx~x$x zP6n(=V4EZYMr(2U+FPsrR*$W=NXwQH&h)(z$;!mfRUo?eI?XXr_^aIqC$r*mB6)JsJmmj=M z5f>Vx`@4Gkdit05_4l-|pka?{_qm)QeV5Lzy-IsV=KQPL0}ZtfPe^aooDqk#eOkgh zr9I$)oe1d()TOfk+sXH7brN-6(7sshKoA_#-=;k;&k+~>VpA;wq>%nR@Xw3N{8s7P ziFzT8Q=s>0NwdG5Fh`MQmti)G_S^)`ml=J~@9;US4MdnlTNO>ftD|2GdKz3X2sD`j z>yO?C83EvW%~je<^2%GH_d_BGcE@+Hd!rA~8HV(iWa5u&x^%lV%Dx_peo;Q(slE$8 z=zBH#7PrIN==eMuA{1Hkt;eGrauZg+%6#|3tTK07^@EtK6&9M`h%{zQ!M>Zbde)G8M>_cBH zG-_rWx^HOj=?HbNAp-6M0kikTyncxY_!(AtIz}}+q`xQT5t+Wf$FP`(+6uiVV)%TT zIiw$E(_%*0t{9r+;}~^528~Y+Vq*EAf^-t%*&w6nVuhf6YUD}r6x)E&PJUSaO><<$ z^0s>TZcpspk&(8gt>c4oWbiUbvd0Q?SH<;{eJ=JZ_H!#@jJq!r*;gX8Z;Rz<^lg(E z3%~6>F*(CeV;=zUQp?gMHDhO)@Wxo)=eF7)iTA~BlQm}-R)!I1csW)HCTp5#(%)dx zy|EmkdiUwr?JaGs16j<>qq z-UfqC)fg>Xq68fiPS&XkNOwOqSr*s>h)ruz$Ku zHgCO8)}axWLeF7#lvB*Y3LQ7Q!Bst|NB$XJuj8`N$Vnj&e!GsVkQ=|({XdazhIi`N z3d)X&ICC6Z?MCuP-{o;!z-OK8u*I<;I;4L3-`2S8E$>Nf7yjI*_F9`Fauk&do^L?6&FXnr=^p=c|M%VZA{D$p zPMjTR@Vh)Uuf{dEnD_N^?BUYq+1Hh5{Apl37boS~tUgzR)t!^FXj#vUML+3DS`_YQ zAKSKn(J%39$Nohd`qhu^++SwckEl3KoW!0Pzy0iM6LJXnFU%7c&j)?TWlG~ADsQv-1(i@57a28= z^v&Ef9=SPsb4<o4k2?s=(&&*K!+ zzIK|%YO@9FgKnHcNKdxdDI<|@x@+>QRvcl8H@l~aHm?Vn6B zznItoKO551-tWYgLi&TTI!QVHkbVbn3DzVPY~amNPS9jAN4+Nd{M7g+DSI`XeG~|e zJ0J>NlT`b^+OwwG8l^vn+7feKq~;OX!M{6=wfmr!6BCF~xC?9c>djOpZuq@H8jb`Yql=jAHcS?^Y z?wj^>qB?OC22tCtJwK6>Xh@`HNOyxujQ6lMDI-E)v|AlW5L+l4w_Z`2p@VVFSMnj3rV|Bt^OE>m7EN zEKN;P)h9q^!d$Y1C=|xk2FYoX)+^8%$r>9%DL*WLt*$CL(jm$I@fWDX6( zLSmH=H=FH-1m7jwmknU&dGRbyJy)r>##SVEs0l`^xs&0CtqAOBXp*gKMG#`Q^QJZ)1cLHchGsv~nY9%RX+)S?V{U$T(9 z(B>sRjBZc_GgA(?ndY&-)tJ~drxwEA7vYRU-qO`l3{ic>g` z(^|PCr7g1msSGA^g?6GZW$RVytmC)0uooR_1JkFDWGp<<|H19+)RChRxsX_ha%^o1 zU!k~}Z*cG}yj?q!Su1exLr&hCvJ!2HIl^}c0%y^_GojeO4Jkq{jlr=UjBS!Ko|%-E z-6{MexP{-F;)IxEJI@GK@P&AI2uoFa?TAIXW%Kh%3QtYU^03^#oWffaQfS$kObh?V zWV=>m_9UopGE6R1WU_#uJqc`OW#tJY%^Iy2m4jG7{CG5p&S6LDY3`&LPM1YOuR@Po ze<7JFM_$PV^<{H}Nf!6KAxq|%>h5c*v2>SIx za8k!wcs;_%aX5*IV=yi;!QS?sWj*c73?2QU5Oq0$pcuu+^jt9D@Y96n#i#T(nsjSW zJ$1X`?VC;_*fPaEvKW-xr6YY4VK*Tkds9ezLiz(pL;2-B%X+UP z%A-!ob6=9i#A6nKkVCd~zwtS_`gdIRQ zFRn~YIP4tD z(Gn#3@eqBO;1qdAi*`)*XWUGlB1)hwPDqU(W{EZulijoKl&GRtz#N)Ixy>ndr_mfm zk=_7zilvBwY66M+6GjVMdl_P@kqL6)iYXu9hS|L-r{I#IsO0;}qf>Le(%gY41|CUi zNV1yd&*XE#Bm1+6qucyj`I^Yl-ONx%=7C6=_RGHXt!{PZ-xs{x|9NBN63qXFKP>G( zgWr*FQ7;=qK_3-5?@~EWN!tdV7))ghj(J$z3&_(m$pSsX-!xNz zLOl#$wlbCa-^V7DD27Q>!EsY$n8yX-;+Db6t?M@3Upa;6P`kwp6+L)z#f+ zSkd0m-ZNSKx;wp^M%1LW@VnB#NKpua~wH&f6}TKPo);7@n(EKlZ1mel;Nn64GYJ^0S7uhGu!W{RTE*!-X_meY|B*`?Hi7?n8r+E8h`^ z^cQdjpTerIHJmU?xz-Zyf!UN_93PWr}}#(!fR<&+AWn5kZr1y)BRNefWNQZFcQaJ^?8anz=7Vmb|yBd_MztJq-iTeUMwhHMdqhS)yH&gb) zKR+)y5#cHsJq1dXm>q)^n4*ND-?I~Bktl`xD9f%*VW?Deiv0rL8s-!{_ZKNC8d4*R zcCQ?V+>uN{grYuiFsZ}rZc)gleu`6Y|DJ_}mCC)!)=A6CCM|C)Y6A)h7KEIaPNGWX44TrjQ=+vgi%&HnoXe!m5*qpf$Tq~Uav7=ETbLej_@>AgTUB1gVCOr z14)vGwE~6z)JwsobA}SUG2zwOF}7f!!CPOb>|U{4*XH2<)>R+US7G`M{0G@NIZtO> z%GcyjTALyUlPL{bpQL!obveA8cvHUD!Y^jSIn+x$eI!TBMKD=I{+Du=g~q7PUPJG| zs%yGKp6qZA;T*^jrclU5S|y{3YDz#|-P7IIzPzt}#g-H$;rXElq@ibXcn2H@f>>n~ zEp3%bF8NutJ57aqUX?pmiCK5cG3&$sD`thN%;K^f0o$N{27@}K zX(K8|dg^PG5Gz*1CFI59xHj$Wanzd<`5`+C|7F%h9Icv+!16j*0VGYXHV2ag|AJ#W36=x=pOL zq4L97xJYU=;YCMNNdF^~QfygfVr^cOYkp*+T=u_ctO1Q9KcMl)CP9ALG)1E6vyn*> z?=`V?j+TfC6b_p>d{#zGpz#HhfJ!4u91#SHt zf=Wn*;okImLrtz#GDAL2fn2L}qx#}MvbXSO8L~7q$a1GZK}&n<1CT% z<5}9b`h>r7{}{9Ff0~Kgf9Z1R^V^P{eShM%5%$Ek{ZBFKy$loicKr7*34`p@S+~Xh zfqh9}m@4p^$TkiMe9WtK13y&zlyZ$1t{RV&i`6(BebJUh$yd%ZnS^6{!F*F9~~-R8JY0@!#*g zCHJF7OtLnQBQ`z+N}kJ$CM7Ja4my#9PX>!4dC`X6F#FF0w%JM~}ziLUoKayOOPjQ+BG&%AGIl7q)y_V){ zD($X7oeXPB{a`i|UX{l~OEYj4$&C+=X}-I(ynHuSgK)@%yq~YIBihX8LItbp&DeXTS@UJTFeDx_ZaqBA zY@SWAKPks%Pn)@{Y6s#I z5%%JJGn-Y7_(a0@=jdp#;_@*Hjc?H5b`IhZCJwxS&9eCi^)dKPE)a7Ss}j;*G*hKK z8ZOhyEi~=G3S_Dk$YK=OPZ$N{E)<=fLgccI8(~vTZ88m+m_@NhaK^wq3HMA_f#lvb z%rmBcqONvMcD8s9Qy^hq)n4QYkDB(Gd&~s|Jq36MRUq1Gt$vv8CkobIn&?-5J3{Ph zeXc!=vVunoc-w54+CjY!RF6;#sxhd?bExpK0zQ{)I{C+)Mp~09S?gaDb{CLeIa9#q zlJ}Tdu)81*KLq0oIcyt-`l5Mv!A|4u0{TrI`a(9Bo--&iQvx)YdJ-#z*;R#nE_sBI z{+)u8;`NBOvt<#Zp-T!moCD?@o1AM^A=lvYq3BIk=VeH&453OxM|XeMic1P`^|HR}4Br7ciN;Rr z>+UwJTGlmS=w994WuS4rO%hLCQC;1JWy_bh_W}?_fP`z>2fDjf7~1jE-67*PNjmC@ z=?sP1uU!^0tmx^yp&d7C1dLzaj~Yi8svVs@h|{`z2AZUJ>d>y~>F&B#!7bzWByjf5 z-j&BKugb~qh((k8ovB435DI&Zg;EO*b8Y@mlRz9?n1c9PV=nU0soIvs@_eFN%x|EgJh5OdNsS-hg9s(WVna6^D$Q z{vpd~M-g5_qfbs=27%r>*C;2$!wl zXwgvYq+09->Z_QFcv1OTk$*_9SY}e0chL8K5q~p1X4e$^hrB;r<1#v#Vh#iSvx+0% zE*+{lWQ<(=o(6p}#cmrAUyciiFC!leAhsknq!n{ci^p42jDXBvEIBR8TlAV@ysTbY zEI2K8T-wwW!>x8vtHD)|7G780M6H0U6)ilj+e$4`jGE#YCVWpZ9*R3{u+(O#%^%Q5 zU3jwmK=Cltv4vk_d0(Qto&-f=anWNSi3~wNMxeJu*APa@%vPkKh3_n$Dj_Qg-v&M- z|JI_;VhRrF!f)rlQ9z=R9~Voxc!+QH+fZ}bY?*0k;opQTJy=AY*(Ks+Ut8+z5@qgf zxIdUEqolTgc{C{&1+7so7P&$PM$Igv+XcGcnM!UpTMoubcoeWUpXRfc2u{RTl*^FN zPLWB9dTSBolMfWvm3T|0mz-jMQLI5d;cmp4>@CHoq0slx=Nf#T7Xw9W^GDcDeAA?N zmhd3bQFp!s5yLuGJJGK_+c*keP;#y$job8fOY4(NHO}|#9#Iy+`NiAM&K)I!Hoe`_ znlV&)$avc;+m1)x-mX;jl1tA{m%HIRN(8qPsaL>VD$hN32zw}H9bULndP^HD<*D07 z?=DV?+3adK#xpRYi%aw5OLr!`3>dJ2@~iY=_FM_bE=}Wpjp>xdtBA1ew~cOl8zsj3 zUn8o_ulFm2&MiH=?KRjKQhfvdW|=ia1OpoCgUZy*IzZavEn~fyt=E5Am|Wf_DqJS;hgK6lazZsHBXSL&uPw&YE(1 z4MKzq#TM=O#PK{%K3AcP9%R8S?wd|Xl8yv|E?4kKqlHh`U5q6#CnFf!mWHC`Oky>A)tj0l0c^e#{(#hmgbzYyB?nm}(1G~}6Z2M7<;$SG6pn8Q)Lj^Y=n zyHB3|{W%a3C1)pvJ}LG>U+C<2l#Z~s%8Gq)jzkE`?pCu$cq;7E{O#>4dgZ%hW-jd_ zb*_f+0xf|C2i9=UsxPBlPSWL|8+9n4@N=Sar*5y6CpQ#8{wbbh1uBm7CceipZF7ra z#s!Q6K;SOMej#4Vtvy|e4u_P);5 ztNWB-?18y_g|Y!!P!TX1x>le?$v~Zxuav3we%i1#gBUc-)}%c=_sm?9dC~!;C`E-R zYE21v9AhY_5`-e=pG?HE1KHkuL-`}J@DrAzGou{AteiK0N`I>73V0z0`=A6xJ>|T^ z>vlq{eo|h7yPvoMB1=Ls@Fc=(dfh_j{*&@l>5NGAFXfr;hH}y6vC-C)S)M3Islev* z1}5XE@Jr>mm9Z60nw}TRM>#V0iVz(x|2IdFb0spol-f;_3QuBc#lz(q+2$WBkAfMt z+Tma!gpF~Vbo+3JIFEV1yoKLVzE?g1WD44Ca#5}fZJIj~kjA(aky7?unx9||fusCt zla3&J5>nSJ>*>N7Eii;SyC~M`lZ9#3vKtMXbmubZK4KbxJ=dp zJV9<<`F|a5{?M8z-{EufgsUdka?MA)GhbP&A}8gmd3f(LUnDh=A4e)r%SJhR+qHZ? z6{Q;H(-nR~U*|P+C)Io1cMpB33_=$W;{qX`V%>(C8nAbM{CAgig^ez2p*${o-Y~lhFQrN(PddH8Ixm-MKbw!*fz2JX z<8R~e0I@CAf)dXeTxA)r33byAJB7m;3rIw1IBwdgl+bEU-q{SLYM) ztqU}{GJ};1ri=5I&p*wT%Hi&=1<`WPBsZuO_0$3?MbWsI7D#e&3xCN-uXO$gf7qby literal 15867 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 (t$-{0WkIM?C_aH z$)0%!1#WpuggCM{C70uehiyw|!d-`IBle30#NIYjBK1gw?T|Xbzig&rZQxNecQ)-; z3ZjP374)#qZ<#3~a>O5JP;P-d<1oP~)031H#arSYLokisvUTw0OK{s>Q|OI>o-7k` zfUrQ#67Oo;Oo{M1f?t^3?^y5e&xD9@pPerBNwpXEh0cCk(Xee?k z3fkX;ETF!lv+IVAzRndZ`ZySSXqH^Y7eE7Y0i&j?6&jQj)OnUtrr7&w)23wFpdqm; z>CstdW|7R(9pFJJ3Pe$9LcpU0(`*Vsa54XQJVIQR=FT?FevAn}aq&AdA`#6hxw9wk zPvtBHFXW&fI4J6wEj!#UC&cQfvkQ^?iOQvEX$S_M1iYr#Ep+Zbot>ziQ7Qh#pXsif zt=81rXlcBcr)DEmVDq>ef;h_m(rjd9YO4kce`=kkN~%+@gix zNldkRXtti|{A062p@yw?7+45lbJT{&J;)(mCA>eoP2MB1S!HTgQb2y68*VOqZEC#DUN=Tj&jF$u(; zMW)3!F6!wub>7g`jr>kp#{083&Ta=v`S&<=N(Zq4aUH_f34%MjvuI-1cIb~_*Jwz3 zF@z_(S1EWOXl){_|HU*96C^nFG8thmTd3p77OGc<(bu zrE9_-NAjm-BNDysT0Dn>QjK#cg&)(`c|GN%dT;#hp)Z9&C;>615aTJ)1q{A;P7)qU z(egUy=qVQAMhJo)UD5^CRH`Osil4ZC5I>;?yXQoIm#oWcuCeB^c4=1)i97I8s!*$+ zMlY}~uu$!%a}YbQxti?w+c-QxY)>qJke)#*%Y41Bn=E+` z7izt8hC~ru!{V!RXz~l^>ND8}^90kSs}|2WEfq1iyJKz`s|oG~g`%FGOQ9%g_tIPm z$;oCqbADUip9?sJ2nW1iRDZ!ru3E0E#1hdv18;0RhI0+S; z)44ne5re2Z|2sLZg+3bpbndOGZE}AJanU2@)o}AqOY5L}CptfcRKaPu{WScibN`mg z`=fqH?S8*%{>K6POYnRf+v_try)O1Eq41*_}PeD91|;XkVK*@mO{u%NHh)B^oR>lqk3}6Ax%d zOO+-ML3Q@_ZFKI4v{`Lec~ZZ~`bDLW8mI8l0M?%wRMB&AhE`fy0N-9zH=oo8G+r!n)JrBKyNWPl@2)I#0=F zeEa7Wy>R=Rx1Txm{^29^!~W`E2!A$2hSCbn9!ikWXS^Oz?!>${dG9>(1kV?eO{cGW z3%-zkJ&#`KotVdyKZX*b(=P6sr#jgnK&R*C%@4xG0Q{_;F|d zIU1HKnbaQ9hQUR@$yN`eHT~u|K=220is<0)@XQE0;Jj zQ)VA$>n^Rp8%`I(S;}k-jfR~3V40d~_u?5U!j1^G`vH zf+>-BHFZzL;dh^3Um*tni1*mMhbuPiS=iRl)Eqeev`#qu?!okHuf67Ka>JEPXMW$A z&HhyGw-vAaH{0~lqjUkfDqhg&RZd(m=E4Firp1d^ELz-2?=bM>szRB;CdYHZT@|zy zCdidwxT|8fOdCk<@uy+*Ad$|Kwt@S_AyyUo1g)EW#{Jg2AjyKiu0kmbcJ~&#a?1Oy ztCeHGbweTnBnb$fNBZun!1kak{^FTleN%IfRSvdxXVbuM#L++f`GKGRcD<$wGxMyQK_rMR|r!6l{y=~5auYU)Yf1RU?f5PW^Om2c9!(bTuuET zHA$u#GGe4K$>NR9>hFe literal 0 HcmV?d00001 From 3e42ca8b2a947365991e86260bc4f7064a903ec7 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 08:50:04 +0100 Subject: [PATCH 15/21] Update readme.org and remove the obsolete test-min.log make target. --- 8086/msdos/Makefile | 10 +--------- 8086/msdos/readme.org | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index f25c151..2aab4da 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -6,7 +6,7 @@ fbfiles_uppercase = $(wildcard src/*.FB tests/*.FB) fthfiles_caseconverted = $(patsubst %.fb, %.fth, \ $(shell ../../tools/echo-tolower.py $(fbfiles_uppercase))) -test: incltest.result logtest.result test-min.result test-std.result \ +test: incltest.result logtest.result test-std.result test-blk.result \ incltest-volks4th.result test-volks4th-min.result fth: $(fthfiles) $(fthfiles_caseconverted) @@ -84,14 +84,6 @@ incltest.log: \ v4th.com "include include.fb include incltest.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ -test-min.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ - $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) - rm -f dosfiles/OUTPUT.LOG - (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ - "include logprep.fth include test-min.fth") - dos2unix -n dosfiles/OUTPUT.LOG $@ - test-std.log: \ $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) diff --git a/8086/msdos/readme.org b/8086/msdos/readme.org index 7653759..80cfcdb 100644 --- a/8086/msdos/readme.org +++ b/8086/msdos/readme.org @@ -25,8 +25,16 @@ kernels with build-in .fth interface. ** Binary make targets =make v4th.com= -builds the new minimal VolksForth kernel v4th.com from -.fth sources using metafile.com. +builds the new minimal VolksForth kernel v4th.com +from .fth sources using metafile.com. v4th.com does not have the block +words and the buffer mechanism anymore. The only way to load code from +files is via =include filename.fth=. + +=make v4thblk.com= +builds the new minimal VolksForth kernel v4thblk.com +from .fth sources using metafile.com. v4thblk.com contains the block +words and the buffer mechanism and can load and include both .fth +stream sources and .fb block sources. =make metafile.com= builds the metacompiler with included .fth file interface. @@ -47,8 +55,13 @@ adds the .fth file interface to the old volks4th binary. =make test= runs all current tests. -=make test-min.result= -runs v4th.com through the initial minimal set of unit tests. +=make test-std.result= +runs v4th.com through the standard set of unit tests, without the block +tests, of course + +=make test-blk.result= +runs v4thblk.com through full set of unit tests, including the block +tests. =make test-volks4th-min.result= runs the same initial minimal set of unit tests on v4thfile.com From 22079fe734ad608b9a915a3254ef19d61b756d10 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 22:12:09 +0100 Subject: [PATCH 16/21] Make rules to compare the content of the DOS and FORTH vocabularies before and after the 2 recent refactorings, using v4thfile.com (volks4th.com plus include .fth interface) as reference --- 8086/msdos/Makefile | 57 +++++++++++++++++++++++++++++++++++ 8086/msdos/tests/vocdos.fth | 9 ++++++ 8086/msdos/tests/vocforth.fth | 9 ++++++ 3 files changed, 75 insertions(+) create mode 100644 8086/msdos/tests/vocdos.fth create mode 100644 8086/msdos/tests/vocforth.fth diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 2aab4da..3fa4351 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -100,6 +100,63 @@ test-blk.log: \ "include logprep.fth include test-blk.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ +forthblkdos: v4thblk.dos v4thblk.forth + +forthdos: forthblkdos v4thfile.dos v4thfile.forth v4th0.dos v4th0.forth + +v4th0.dos: \ + $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ + "include logprep.fth include vocdos.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ + +v4th0.forth: \ + $(patsubst %, dosfiles/%, v4th.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4th.com \ + "include logprep.fth include vocforth.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ + +v4thblk.dos: \ + $(patsubst %, dosfiles/%, v4thblk.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4thblk.com \ + "include logprep.fth include vocdos.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ + +v4thblk.forth: \ + $(patsubst %, dosfiles/%, v4thblk.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4thblk.com \ + "include logprep.fth include vocforth.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ + +v4thfile.dos: \ + $(patsubst %, dosfiles/%, v4thfile.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4thfile.com \ + "include log2file.fth include vocdos.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ + +v4thfile.forth: \ + $(patsubst %, dosfiles/%, v4thfile.com $(prepfths)) \ + $(patsubst tests/%, dosfiles/%, $(wildcard tests/*.*)) + rm -f dosfiles/OUTPUT.LOG + (cd dosfiles && ../emulator/run-in-dosbox.sh v4thfile.com \ + "include log2file.fth include vocforth.fth") + dos2unix -n dosfiles/OUTPUT.LOG output.log + tr " " "\n" $@ incltest-volks4th.log: v4thfile.com tests/log2file.fb tests/incltest.fth rm -f OUTPUT.LOG diff --git a/8086/msdos/tests/vocdos.fth b/8086/msdos/tests/vocdos.fth new file mode 100644 index 0000000..a74e972 --- /dev/null +++ b/8086/msdos/tests/vocdos.fth @@ -0,0 +1,9 @@ + +logopen output.log + +clear + +forth also dos words +cr + +logclose diff --git a/8086/msdos/tests/vocforth.fth b/8086/msdos/tests/vocforth.fth new file mode 100644 index 0000000..8239fc2 --- /dev/null +++ b/8086/msdos/tests/vocforth.fth @@ -0,0 +1,9 @@ + +logopen output.log + +clear + +forth words +cr + +logclose From 67f6188fe3479570717b15b2f4762676e185551d Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 22:13:51 +0100 Subject: [PATCH 17/21] Move FILE and [FCB] from DOS to FORTH, after comparing vocabularies with original volks4th.com --- 8086/msdos/src/vf86dos.fth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8086/msdos/src/vf86dos.fth b/8086/msdos/src/vf86dos.fth index 83e13df..0bf9aa8 100644 --- a/8086/msdos/src/vf86dos.fth +++ b/8086/msdos/src/vf86dos.fth @@ -443,7 +443,7 @@ Assembler [[ W R xchg C pop D pop \ *** Block No. 140, Hexblock 8c - Dos definitions + \ File >file ks 23 mär 88 : File Create file-link @ here file-link ! , From a6976accb7edd7acbdc5b687ffb706b85fe3e473 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 22:34:40 +0100 Subject: [PATCH 18/21] Fix incltest.log to use v4thblk.com instead of v4th.com as it uses log2file.fb --- 8086/msdos/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/8086/msdos/Makefile b/8086/msdos/Makefile index 3fa4351..2760555 100644 --- a/8086/msdos/Makefile +++ b/8086/msdos/Makefile @@ -77,11 +77,11 @@ prepfths = asm.fb extend.fb multi.vid dos.fb include.fb 86asm.fth \ t86asm.fth extend2.fth multivid.fth dos2.fth dos3.fth incltest.log: \ - $(patsubst %, dosfiles/%, v4th.com $(prepsrcs) log2file.fb \ + $(patsubst %, dosfiles/%, v4thblk.com $(prepsrcs) log2file.fb \ incltest.fth) rm -f dosfiles/OUTPUT.LOG (cd dosfiles && ../emulator/run-in-dosbox.sh \ - v4th.com "include include.fb include incltest.fth") + v4thblk.com "include incltest.fth") dos2unix -n dosfiles/OUTPUT.LOG $@ test-std.log: \ From 1a814700b9be7a4f70b7019eb8d6bcda9fbefc2e Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 22:35:40 +0100 Subject: [PATCH 19/21] Update v4th.com and v4thblk.com binaries --- 8086/msdos/v4th.com | Bin 14835 -> 14835 bytes 8086/msdos/v4thblk.com | Bin 16971 -> 16971 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/8086/msdos/v4th.com b/8086/msdos/v4th.com index 3cfafc55bad939f2395b85c52075a8b6f02ce1a8..3f36486cf45097528201c853d46cd9f191b2633e 100644 GIT binary patch delta 26 icmexd{JD5TrZJ=I Date: Wed, 23 Mar 2022 22:45:42 +0100 Subject: [PATCH 20/21] Update version to 3.9.1-MSDOS --- 8086/msdos/src/vf86core.fth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8086/msdos/src/vf86core.fth b/8086/msdos/src/vf86core.fth index 0005378..2c4fa43 100644 --- a/8086/msdos/src/vf86core.fth +++ b/8086/msdos/src/vf86core.fth @@ -12,7 +12,7 @@ Create origin here origin! here $100 0 fill $E9 int end-code -4 , $FC allot \ this is the multitasker initialization in the user area -| Create logo ," volksFORTH-83 rev. 3.81.41" +| Create logo ," volksFORTH-83 rev. 3.9.1-MSDOS" From f8c3d7c16ec9b7506c25c094eee79919d8812c2b Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 23 Mar 2022 22:55:58 +0100 Subject: [PATCH 21/21] Update binaries to the new version number 3.9.1 --- 8086/msdos/v4th.com | Bin 14835 -> 14839 bytes 8086/msdos/v4thblk.com | Bin 16971 -> 16975 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/8086/msdos/v4th.com b/8086/msdos/v4th.com index 3f36486cf45097528201c853d46cd9f191b2633e..6e4849f179e88bab96f9dad6fd54bdc3357311c4 100644 GIT binary patch literal 14839 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 HO6PwAy|lg3 literal 14835 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 diff --git a/8086/msdos/v4thblk.com b/8086/msdos/v4thblk.com index ed7dc376ad4db6bc188f36214bcd9cce2a5b81c7..eb95cb137d2baf0e3a1e0e3654d0d563721215d2 100644 GIT binary patch literal 16975 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 z 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 CmL75d