From 44a5e831887539d3297e2e76aebf76b1a9b8fc31 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sat, 9 Dec 2023 21:49:47 +0100 Subject: [PATCH 01/33] typo fix in C64 RELEASE_NOTES.md --- 6502/C64/RELEASE_NOTES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 42380b6..db12bbf 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -31,6 +31,7 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains * `tests_petscii/` - the files from `tests/` converted to PETSCII ## Versions + The following version descriptions are only valid for VolksForth 6502 C64 Releases. As of now (Dec 2023), the different VolksForth platforms (6502, 68k, 8080, 8086) don't have shared code or shared versioning. From 627522012b4280fb1fd9e030a1529e3ece4d7d7a Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Fri, 10 May 2024 22:58:37 +0200 Subject: [PATCH 02/33] Add two linked list utility words that are extracted from cc64's profiler.fth. --- 6502/C64/src/lists.fth | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 6502/C64/src/lists.fth diff --git a/6502/C64/src/lists.fth b/6502/C64/src/lists.fth new file mode 100644 index 0000000..b9b2686 --- /dev/null +++ b/6502/C64/src/lists.fth @@ -0,0 +1,14 @@ +\ utility words for handling linked lists. +\ The first word of each list node contains the link to the next node. + +: end-of-list ( list-node -- last-node ) + BEGIN dup @ WHILE @ REPEAT ; + +: reverse-list ( list-root-var -- ) + dup >r @ 0 ( node[0] 0 ) + BEGIN over WHILE ( node[i] node[i-1] ) + over @ ( node[i] node[i-1] node[i+1] ) + >r over ! r> ( node[i] node[i+1] ) + swap REPEAT ( 0 node[n] ) + r> ! drop ; + From 3678e8f90b25a5e2dc293f46b528b192a4b54fbe Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 26 May 2024 22:43:18 +0200 Subject: [PATCH 03/33] On X16, clear IOStatus byte (C64: $0090) via new Kernal call instead of writing directly to Kernal variable (which may break between Kernal revisions) --- 6502/C64/src/vf-sys-cbm.fth | 6 ++++-- 6502/C64/src/vf-sys-x16.fth | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/6502/C64/src/vf-sys-cbm.fth b/6502/C64/src/vf-sys-cbm.fth index 0b21057..b5047fb 100644 --- a/6502/C64/src/vf-sys-cbm.fth +++ b/6502/C64/src/vf-sys-cbm.fth @@ -150,8 +150,10 @@ Label nodevice 0 # ldx 1 # ldy \ ?device clv12jul87 -Label (?dev - IOStatus stx \ because IOStatus isn't cleared by LISTEN or TALK +Label (?dev ( a: dev ) + \ Clear IOStatus because it isn't cleared by LISTEN or TALK + (C64 IOStatus stx ( ) (C16 IOStatus stx ( ) + (X16 pha 1 # lda ExtApi jsr pla ( ) \ It's unclear in which situation or use case the following \ workaround for a C16 OS error is needed. The v4th tests pass \ even with the following line removed. diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index 802617b..c959cfa 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -7,7 +7,7 @@ include vf-lbls-cbm.fth 0ffd2 >label ConOut 0febd >label KbdbufPeek - 0287 >label IOStatus \ aka status +0feab >label ExtApi 028d >label MsgFlg 09f2c >label BrdCol 0376 >label BkgPenCol \ aka color From 384f2717f8aaae6f4f9997fa6a5fa0d3290c7bd7 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 26 May 2024 23:24:44 +0200 Subject: [PATCH 04/33] Remove the direct clearing of MsgFlg (C64: $009d) at the beginning of (busin and (busout. MsgFlg controls what Kernal messages are printed, and if this needs to be set or cleared, then we should do this in the system setup, not with each (busin/out, and we should do it with the Kernal call SETMSG ($ff90) instead of writing to a Kernal variable which may change between X16 Kernal revisions. --- 6502/C64/src/vf-sys-c16.fth | 1 - 6502/C64/src/vf-sys-c64.fth | 1 - 6502/C64/src/vf-sys-cbm.fth | 4 ++-- 6502/C64/src/vf-sys-x16.fth | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/6502/C64/src/vf-sys-c16.fth b/6502/C64/src/vf-sys-c16.fth index 31c6b44..6082deb 100644 --- a/6502/C64/src/vf-sys-c16.fth +++ b/6502/C64/src/vf-sys-c16.fth @@ -8,7 +8,6 @@ include vf-lbls-cbm.fth 0ff4c >label ConOut 090 >label IOStatus - 09a >label MsgFlg 0ae >label CurDev 0ff19 >label BrdCol 0ff15 >label BkgCol diff --git a/6502/C64/src/vf-sys-c64.fth b/6502/C64/src/vf-sys-c64.fth index 707573a..af29c60 100644 --- a/6502/C64/src/vf-sys-c64.fth +++ b/6502/C64/src/vf-sys-c64.fth @@ -8,7 +8,6 @@ include vf-lbls-cbm.fth 0E716 >label ConOut 090 >label IOStatus - 09d >label MsgFlg 0d020 >label BrdCol 0d021 >label BkgCol 0286 >label PenCol diff --git a/6502/C64/src/vf-sys-cbm.fth b/6502/C64/src/vf-sys-cbm.fth index b5047fb..41cc9cb 100644 --- a/6502/C64/src/vf-sys-cbm.fth +++ b/6502/C64/src/vf-sys-cbm.fth @@ -171,7 +171,7 @@ Label (?dev ( a: dev ) i/o lock (?device ; Code (busout ( dev 2nd -- ) - MsgFlg stx 2 # lda Setup jsr + 2 # lda Setup jsr N 2+ lda (?dev jsr N 2+ lda LISTEN jsr N lda 60 # ora SECOND jsr @@ -194,7 +194,7 @@ Label (?dev ( a: dev ) 0E0 or busout busoff ; Code (busin ( dev 2nd -- ) - MsgFlg stx 2 # lda Setup jsr + 2 # lda Setup jsr N 2+ lda (?dev jsr N 2+ lda TALK jsr N lda 60 # ora (C16 $ad sta ( ) diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index c959cfa..e1946aa 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -8,7 +8,6 @@ include vf-lbls-cbm.fth 0ffd2 >label ConOut 0febd >label KbdbufPeek 0feab >label ExtApi - 028d >label MsgFlg 09f2c >label BrdCol 0376 >label BkgPenCol \ aka color 0381 >label CurFlg \ aka qtsw From 611fbf1782eac3d5b6c3e677432b8c57d26964ee Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 28 May 2024 08:03:56 +0200 Subject: [PATCH 05/33] Move c64key, c64decode, c64expect and keyboard input vector definition from vf-sys-cbm.fth to vf-sys-c16/c64/x16.fth, so X16 version can be changed to use BASIN. Reason: on X16 curon and curoff and thereby c64key use Kernal variables which can change between Kernal releases. Also, curoff is buggy and half the time leaves an inverse space on on backspace. --- 6502/C64/src/vf-sys-c16.fth | 28 ++++++++++++++++++++++++++++ 6502/C64/src/vf-sys-c64.fth | 28 ++++++++++++++++++++++++++++ 6502/C64/src/vf-sys-cbm.fth | 28 ---------------------------- 6502/C64/src/vf-sys-x16.fth | 28 ++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 28 deletions(-) diff --git a/6502/C64/src/vf-sys-c16.fth b/6502/C64/src/vf-sys-c16.fth index 6082deb..4885975 100644 --- a/6502/C64/src/vf-sys-c16.fth +++ b/6502/C64/src/vf-sys-c16.fth @@ -50,6 +50,34 @@ Code curoff \ -- end-code +\ *** Block No. 131, Hexblock 83 +83 fthpage + +( #bs #cr ..keyboard clv12.4.87) + +: c64key ( -- 8b) + curon BEGIN pause c64key? UNTIL + curoff getkey ; + +14 Constant #bs 0D Constant #cr + +: c64decode + ( addr cnt1 key -- addr cnt2) + #bs case? IF dup IF del 1- THEN + exit THEN + #cr case? IF dup span ! exit THEN + >r 2dup + r@ swap c! r> emit 1+ ; + +: c64expect ( addr len1 -- ) + span ! 0 + BEGIN dup span @ u< + WHILE key decode + REPEAT 2drop space ; + +Input: keyboard [ here input ! ] + c64key c64key? c64decode c64expect ; + + include vf-sys-cbm.fth diff --git a/6502/C64/src/vf-sys-c64.fth b/6502/C64/src/vf-sys-c64.fth index af29c60..66323a6 100644 --- a/6502/C64/src/vf-sys-c64.fth +++ b/6502/C64/src/vf-sys-c64.fth @@ -58,6 +58,34 @@ Code curoff ( --) 1 # ldy Next jmp end-code +\ *** Block No. 131, Hexblock 83 +83 fthpage + +( #bs #cr ..keyboard clv12.4.87) + +: c64key ( -- 8b) + curon BEGIN pause c64key? UNTIL + curoff getkey ; + +14 Constant #bs 0D Constant #cr + +: c64decode + ( addr cnt1 key -- addr cnt2) + #bs case? IF dup IF del 1- THEN + exit THEN + #cr case? IF dup span ! exit THEN + >r 2dup + r@ swap c! r> emit 1+ ; + +: c64expect ( addr len1 -- ) + span ! 0 + BEGIN dup span @ u< + WHILE key decode + REPEAT 2drop space ; + +Input: keyboard [ here input ! ] + c64key c64key? c64decode c64expect ; + + include vf-sys-cbm.fth diff --git a/6502/C64/src/vf-sys-cbm.fth b/6502/C64/src/vf-sys-cbm.fth index 41cc9cb..3cb9351 100644 --- a/6502/C64/src/vf-sys-cbm.fth +++ b/6502/C64/src/vf-sys-cbm.fth @@ -1,32 +1,4 @@ -\ *** Block No. 131, Hexblock 83 -83 fthpage - -( #bs #cr ..keyboard clv12.4.87) - -: c64key ( -- 8b) - curon BEGIN pause c64key? UNTIL - curoff getkey ; - -14 Constant #bs 0D Constant #cr - -: c64decode - ( addr cnt1 key -- addr cnt2) - #bs case? IF dup IF del 1- THEN - exit THEN - #cr case? IF dup span ! exit THEN - >r 2dup + r@ swap c! r> emit 1+ ; - -: c64expect ( addr len1 -- ) - span ! 0 - BEGIN dup span @ u< - WHILE key decode - REPEAT 2drop space ; - -Input: keyboard [ here input ! ] - c64key c64key? c64decode c64expect ; - - \ *** Block No. 132, Hexblock 84 84 fthpage diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index e1946aa..8b739a1 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -56,6 +56,34 @@ Code curoff ( --) blnsw sty Next jmp end-code +\ *** Block No. 131, Hexblock 83 +83 fthpage + +( #bs #cr ..keyboard clv12.4.87) + +: c64key ( -- 8b) + curon BEGIN pause c64key? UNTIL + curoff getkey ; + +14 Constant #bs 0D Constant #cr + +: c64decode + ( addr cnt1 key -- addr cnt2) + #bs case? IF dup IF del 1- THEN + exit THEN + #cr case? IF dup span ! exit THEN + >r 2dup + r@ swap c! r> emit 1+ ; + +: c64expect ( addr len1 -- ) + span ! 0 + BEGIN dup span @ u< + WHILE key decode + REPEAT 2drop space ; + +Input: keyboard [ here input ! ] + c64key c64key? c64decode c64expect ; + + include vf-sys-cbm.fth From 1d659853a7cbd9b4b3a1fe17da2e5ff6f85ffa68 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 29 May 2024 23:39:15 +0200 Subject: [PATCH 06/33] Switch X16 keyboard input to use Kernal CHRIN instead of GETKEY. This further reduces the use of undocumented Kernal variables and fixes the residue of inverted blanks when backspacing on the X16. It also now makes use of the CBM/X16 screen editor for Forth input. Downside is that during EXPECT now no background tasks of the tasker will be run, as no PAUSE is performed during CHRIN input until the return key is pressed. Test golden file generating had to be enhanced because with CHRIN the typed characters aren't echoed into the test logfile anymore. So X16 needs a slightly different core.golden file. --- 6502/C64/Makefile | 42 ++++++++++------- 6502/C64/src/vf-sys-x16.fth | 46 +++++-------------- .../{core.golden => core-template.golden} | 4 +- 3 files changed, 39 insertions(+), 53 deletions(-) rename 6502/C64/tests/golden/{core.golden => core-template.golden} (92%) diff --git a/6502/C64/Makefile b/6502/C64/Makefile index 729c35f..ed42872 100644 --- a/6502/C64/Makefile +++ b/6502/C64/Makefile @@ -19,6 +19,7 @@ test_files = $(wildcard tests/*.f*) test_files_petscii = $(patsubst tests/%, cbmfiles/%, $(test_files)) test_logs = $(patsubst %, test-%.log, $(vf_flavours)) test_resuls = $(patsubst %, test-%.result, $(vf_flavours)) +test_keyboard_input = some 12345 keys release_zipfile = volksforth-6502-c64-release.zip @@ -35,6 +36,7 @@ clean: rm -f *.log *.result *.golden rm -f cbmfiles/c??-testbase rm -f disks/scratch.d64 emulator/sdcard.img + rm -f tests/golden/mycore*.golden # Convenience targets @@ -130,51 +132,51 @@ test-v4thblk-c64.log: emulator/v4thblk-c64.T64 disks/empty.d64 rm -f cbmfiles/test.log disks/scratch.d64 cp disks/empty.d64 disks/scratch.d64 DISK9=scratch emulator/run-in-vice.sh v4thblk-c64 \ - "include run-blk-tests.fth\n1234567890" + "include run-blk-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4th-c64.log: emulator/v4th-c64.T64 rm -f cbmfiles/test.log emulator/run-in-vice.sh v4th-c64 \ - "include run-std-tests.fth\n1234567890" + "include run-std-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4thblk-c16+.log: emulator/v4thblk-c16+.T64 disks/empty.d64 rm -f cbmfiles/test.log disks/scratch.d64 cp disks/empty.d64 disks/scratch.d64 VICE=xplus4 DISK9=scratch emulator/run-in-vice.sh v4thblk-c16+ \ - "include run-blk-tests.fth\n1234567890" + "include run-blk-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4th-c16+.log: emulator/v4th-c16+.T64 rm -f cbmfiles/test.log VICE=xplus4 emulator/run-in-vice.sh v4th-c16+ \ - "include run-std-tests.fth\n1234567890" + "include run-std-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4thblk-c16-.log: emulator/v4thblk-c16-.T64 rm -f cbmfiles/test.log VICE=xplus4 emulator/run-in-vice.sh v4thblk-c16- \ - "include run-min-tests.fth\n1234567890" + "include run-min-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4th-c16-.log: emulator/v4th-c16-.T64 rm -f cbmfiles/test.log VICE=xplus4 emulator/run-in-vice.sh v4th-c16- \ - "include run-std-tests.fth\n1234567890" + "include run-std-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ test-v4th-x16.log: cbmfiles/v4th-x16 emulator/sdcard.img rm -f cbmfiles/test.log emulator/run-in-x16emu.sh v4th-x16 \ - "include run-std-tests.fth\n1234567890" + "include run-std-tests.fth\n$(test_keyboard_input)" mcopy -i emulator/sdcard.img ::TEST.LOG cbmfiles/test.log petscii2ascii cbmfiles/test.log $@ test-v4th-x16e.log: cbmfiles/v4th-x16e emulator/sdcard.img rm -f cbmfiles/test.log emulator/run-in-x16emu.sh v4th-x16e \ - "include run-std-tests.fth\n1234567890" + "include run-std-tests.fth\n$(test_keyboard_input)" mcopy -i emulator/sdcard.img ::TEST.LOG cbmfiles/test.log petscii2ascii cbmfiles/test.log $@ @@ -190,37 +192,45 @@ emulator/sdcard.img: emulator/sdcard.sfdisk mv $@.tmp $@ test-v4thblk-c64.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double block report-blk) + prelim mycore coreext double block report-blk) cat $^ > $@ test-v4th-c64.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) + prelim mycore coreext double report-noblk) cat $^ > $@ test-v4thblk-c16+.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double block report-blk) + prelim mycore coreext double block report-blk) cat $^ > $@ test-v4th-c16+.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) + prelim mycore coreext double report-noblk) cat $^ > $@ test-v4thblk-c16-.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core) + prelim mycore) cat $^ > $@ test-v4th-c16-.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) + prelim mycore coreext double report-noblk) cat $^ > $@ test-v4th-x16.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) + prelim mycore-x16 coreext double report-noblk) cat $^ > $@ test-v4th-x16e.golden: $(patsubst %, tests/golden/%.golden, \ - prelim core coreext double report-noblk) + prelim mycore-x16 coreext double report-noblk) cat $^ > $@ +tests/golden/mycore.golden: tests/golden/core-template.golden + sed -e 's/TMPL_KEYS_ECHO_TMPL/$(test_keyboard_input)/' \ + -e 's/TMPL_KEYS_RECEIVED_TMPL/$(test_keyboard_input)/' $< >$@ + +tests/golden/mycore-x16.golden: tests/golden/core-template.golden + sed -e 's/TMPL_KEYS_ECHO_TMPL//' \ + -e 's/TMPL_KEYS_RECEIVED_TMPL/$(test_keyboard_input)/' $< >$@ + # Rules for building Forth binaries on top of the plain vanilla # c64-volksforth83. diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index 8b739a1..88781ea 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -16,19 +16,6 @@ include vf-lbls-cbm.fth 1 >label RomBank 0 >label RamBank - 037B >label blnsw \ C64: $cc -\ 037C >label blnct \ C64: $cd -\ 037D >label gdbln \ C64: $ce -\ 037E >label blnon \ C64: $cf -\ 0262 >label pnt \ C64: $d1 -\ 0380 >label pntr \ C64: $d3 -\ 0373 >label gdcol - -\ C64 labels that X16 doesn't have: - -\ 028a >label KeyRep \ aka rptflg - - \ *** Block No. 129, Hexblock 81 81 fthpage @@ -44,44 +31,33 @@ Code getkey ( -- 8b) Push0A jmp end-code -\ *** Block No. 130, Hexblock 82 -82 fthpage - -\ X16 curon curoff - -Code curon ( --) - blnsw stx Next jmp end-code - -Code curoff ( --) - blnsw sty Next jmp end-code - - \ *** Block No. 131, Hexblock 83 83 fthpage ( #bs #cr ..keyboard clv12.4.87) -: c64key ( -- 8b) - curon BEGIN pause c64key? UNTIL - curoff getkey ; +: x16key ( -- 8b) + BEGIN pause c64key? UNTIL getkey ; 14 Constant #bs 0D Constant #cr -: c64decode +: x16decode ( addr cnt1 key -- addr cnt2) - #bs case? IF dup IF del 1- THEN - exit THEN #cr case? IF dup span ! exit THEN - >r 2dup + r@ swap c! r> emit 1+ ; + >r 2dup + r> swap c! 1+ ; + +Code basin ( -- 8b) + CHRIN jsr + Push0A jmp end-code -: c64expect ( addr len1 -- ) +: x16expect ( addr len1 -- ) span ! 0 BEGIN dup span @ u< - WHILE key decode + WHILE basin x16decode REPEAT 2drop space ; Input: keyboard [ here input ! ] - c64key c64key? c64decode c64expect ; + x16key c64key? x16decode x16expect ; include vf-sys-cbm.fth diff --git a/6502/C64/tests/golden/core.golden b/6502/C64/tests/golden/core-template.golden similarity index 92% rename from 6502/C64/tests/golden/core.golden rename to 6502/C64/tests/golden/core-template.golden index ecb08b7..a3a6a87 100644 --- a/6502/C64/tests/golden/core.golden +++ b/6502/C64/tests/golden/core-template.golden @@ -21,8 +21,8 @@ YOU SHOULD SEE THE NUMBER RANGES OF SIGNED AND UNSIGNED NUMBERS: UNSIGNED: 0 FFFF * PLEASE TYPE UP TO 80 CHARACTERS: -1234567890 -RECEIVED: "1234567890" +TMPL_KEYS_ECHO_TMPL +RECEIVED: "TMPL_KEYS_RECEIVED_TMPL" * GDX exists End of Core word set tests From 322025842a65f371fa774005f648403cb1e06d37 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 29 May 2024 23:45:15 +0200 Subject: [PATCH 07/33] Initial checkin of the previous GETIN based C64EXPECT etc. which does call PAUSE during EXPECT and thus runs background tasks during interactive input. Downside is the known residue of inverse spaces during backspace, and the use of undocumented - and therefore changeable (between Kernal versions) - Kernal variables. This file is as yet not expected to work when INCLUDEd; it'll at least need the 6502 assembler loaded, and probably a few more tweaks, before it can be just loaded from a v4th-x16 system, rather than being included in a target compile that produces v4th-x16. --- 6502/C64/src/x16input-tsk.fth | 84 +++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 6502/C64/src/x16input-tsk.fth diff --git a/6502/C64/src/x16input-tsk.fth b/6502/C64/src/x16input-tsk.fth new file mode 100644 index 0000000..f334ee6 --- /dev/null +++ b/6502/C64/src/x16input-tsk.fth @@ -0,0 +1,84 @@ + +include vf-lbls-cbm.fth + +7f fthpage + +\ X16 labels + +0ffd2 >label ConOut +0febd >label KbdbufPeek +0feab >label ExtApi +09f2c >label BrdCol + 0376 >label BkgPenCol \ aka color + 0381 >label CurFlg \ aka qtsw + 0385 >label InsCnt \ aka insrt + +1 >label RomBank +0 >label RamBank + + 037B >label blnsw \ C64: $cc +\ 037C >label blnct \ C64: $cd +\ 037D >label gdbln \ C64: $ce +\ 037E >label blnon \ C64: $cf +\ 0262 >label pnt \ C64: $d1 +\ 0380 >label pntr \ C64: $d3 +\ 0373 >label gdcol + +\ C64 labels that X16 doesn't have: + +\ 028a >label KeyRep \ aka rptflg + + +\ *** Block No. 129, Hexblock 81 +81 fthpage + +\ X16 c64key? getkey + +Code c64key? ( -- flag) + KbdbufPeek jsr + txa pha + Push jmp end-code + +Code getkey ( -- 8b) + GETIN jsr + Push0A jmp end-code + + +\ *** Block No. 130, Hexblock 82 +82 fthpage + +\ X16 curon curoff + +Code curon ( --) + blnsw stx Next jmp end-code + +Code curoff ( --) + blnsw sty Next jmp end-code + + +\ *** Block No. 131, Hexblock 83 +83 fthpage + +( #bs #cr ..keyboard clv12.4.87) + +: c64key ( -- 8b) + curon BEGIN pause c64key? UNTIL + curoff getkey ; + +14 Constant #bs 0D Constant #cr + +: c64decode + ( addr cnt1 key -- addr cnt2) + #bs case? IF dup IF del 1- THEN + exit THEN + #cr case? IF dup span ! exit THEN + >r 2dup + r@ swap c! r> emit 1+ ; + +: c64expect ( addr len1 -- ) + span ! 0 + BEGIN dup span @ u< + WHILE key decode + REPEAT 2drop space ; + +Input: keyboard-pause [ here input ! ] + c64key c64key? c64decode c64expect ; From ab0abf1f8ecd8b8213caeed5f59221a29fd93da4 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 10 Jun 2024 03:06:02 +0200 Subject: [PATCH 08/33] Make x16input-tsk.fth directly loadable by v4th-x16, and rename the native input implementations for X16 c64key? -> x16key? etc. --- 6502/C64/Makefile | 38 +++++++++++++------ 6502/C64/src/vf-lbls-cbm.fth | 3 -- 6502/C64/src/vf-sys-x16.fth | 8 ++-- 6502/C64/src/x16input-tsk.fth | 69 +++++------------------------------ 4 files changed, 41 insertions(+), 77 deletions(-) diff --git a/6502/C64/Makefile b/6502/C64/Makefile index ed42872..94a62fc 100644 --- a/6502/C64/Makefile +++ b/6502/C64/Makefile @@ -126,7 +126,7 @@ cbmfiles/v4th-x16e: # Core test targets -$(test_logs): $(test_files_petscii) emulator/run-in-vice.sh +$(test_logs): $(test_files_petscii) $(wildcard emulator/run-in-*.sh) test-v4thblk-c64.log: emulator/v4thblk-c64.T64 disks/empty.d64 rm -f cbmfiles/test.log disks/scratch.d64 @@ -192,45 +192,61 @@ emulator/sdcard.img: emulator/sdcard.sfdisk mv $@.tmp $@ test-v4thblk-c64.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore coreext double block report-blk) + prelim mycore-echo coreext double block report-blk) cat $^ > $@ test-v4th-c64.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore coreext double report-noblk) + prelim mycore-echo coreext double report-noblk) cat $^ > $@ test-v4thblk-c16+.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore coreext double block report-blk) + prelim mycore-echo coreext double block report-blk) cat $^ > $@ test-v4th-c16+.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore coreext double report-noblk) + prelim mycore-echo coreext double report-noblk) cat $^ > $@ test-v4thblk-c16-.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore) + prelim mycore-echo) cat $^ > $@ test-v4th-c16-.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore coreext double report-noblk) + prelim mycore-echo coreext double report-noblk) cat $^ > $@ test-v4th-x16.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore-x16 coreext double report-noblk) + prelim mycore-noecho coreext double report-noblk) cat $^ > $@ test-v4th-x16e.golden: $(patsubst %, tests/golden/%.golden, \ - prelim mycore-x16 coreext double report-noblk) + prelim mycore-noecho coreext double report-noblk) cat $^ > $@ -tests/golden/mycore.golden: tests/golden/core-template.golden +tests/golden/mycore-echo.golden: tests/golden/core-template.golden sed -e 's/TMPL_KEYS_ECHO_TMPL/$(test_keyboard_input)/' \ -e 's/TMPL_KEYS_RECEIVED_TMPL/$(test_keyboard_input)/' $< >$@ -tests/golden/mycore-x16.golden: tests/golden/core-template.golden +tests/golden/mycore-noecho.golden: tests/golden/core-template.golden sed -e 's/TMPL_KEYS_ECHO_TMPL//' \ -e 's/TMPL_KEYS_RECEIVED_TMPL/$(test_keyboard_input)/' $< >$@ +# Sample test with a changed input that would run the tasker +# even while waiting for keyboard input: +test-v4th-x16-tsk.log: cbmfiles/v4th-x16 emulator/sdcard.img \ + $(test_files_petscii) $(wildcard emulator/run-in-*.sh) \ + cbmfiles/6502asm.fth cbmfiles/trns6502asm.fth \ + cbmfiles/vf-lbls-cbm.fth cbmfiles/x16input-tsk.fth + rm -f cbmfiles/test.log + emulator/run-in-x16emu.sh v4th-x16 \ + "include x16input-tsk.fth\ninclude run-min-tests.fth\n$(test_keyboard_input)" + mcopy -i emulator/sdcard.img ::TEST.LOG cbmfiles/test.log + petscii2ascii cbmfiles/test.log $@ + +test-v4th-x16-tsk.golden: $(patsubst %, tests/golden/%.golden, \ + prelim mycore-echo) + cat $^ > $@ + # Rules for building Forth binaries on top of the plain vanilla # c64-volksforth83. diff --git a/6502/C64/src/vf-lbls-cbm.fth b/6502/C64/src/vf-lbls-cbm.fth index 1a2b77d..60b3428 100644 --- a/6502/C64/src/vf-lbls-cbm.fth +++ b/6502/C64/src/vf-lbls-cbm.fth @@ -1,7 +1,4 @@ -\ *** Block No. 126, Hexblock 7e -7e fthpage - \ CBM-Labels 05nov87re $FFA5 >label ACPTR diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index 88781ea..bf281ab 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -19,9 +19,9 @@ include vf-lbls-cbm.fth \ *** Block No. 129, Hexblock 81 81 fthpage -\ X16 c64key? getkey +\ X16 x16key? getkey -Code c64key? ( -- flag) +Code x16key? ( -- flag) KbdbufPeek jsr txa pha Push jmp end-code @@ -37,7 +37,7 @@ Code getkey ( -- 8b) ( #bs #cr ..keyboard clv12.4.87) : x16key ( -- 8b) - BEGIN pause c64key? UNTIL getkey ; + BEGIN pause x16key? UNTIL getkey ; 14 Constant #bs 0D Constant #cr @@ -57,7 +57,7 @@ Code basin ( -- 8b) REPEAT 2drop space ; Input: keyboard [ here input ! ] - x16key c64key? x16decode x16expect ; + x16key x16key? x16decode x16expect ; include vf-sys-cbm.fth diff --git a/6502/C64/src/x16input-tsk.fth b/6502/C64/src/x16input-tsk.fth index f334ee6..43e6ad0 100644 --- a/6502/C64/src/x16input-tsk.fth +++ b/6502/C64/src/x16input-tsk.fth @@ -1,51 +1,12 @@ +\ Sample: a changed input that would run the tasker +\ even while waiting for keyboard input, similar to +\ the keyboard input on C16 and C64: -include vf-lbls-cbm.fth - -7f fthpage +include trns6502asm.fth \ X16 labels -0ffd2 >label ConOut -0febd >label KbdbufPeek -0feab >label ExtApi -09f2c >label BrdCol - 0376 >label BkgPenCol \ aka color - 0381 >label CurFlg \ aka qtsw - 0385 >label InsCnt \ aka insrt - -1 >label RomBank -0 >label RamBank - - 037B >label blnsw \ C64: $cc -\ 037C >label blnct \ C64: $cd -\ 037D >label gdbln \ C64: $ce -\ 037E >label blnon \ C64: $cf -\ 0262 >label pnt \ C64: $d1 -\ 0380 >label pntr \ C64: $d3 -\ 0373 >label gdcol - -\ C64 labels that X16 doesn't have: - -\ 028a >label KeyRep \ aka rptflg - - -\ *** Block No. 129, Hexblock 81 -81 fthpage - -\ X16 c64key? getkey - -Code c64key? ( -- flag) - KbdbufPeek jsr - txa pha - Push jmp end-code - -Code getkey ( -- 8b) - GETIN jsr - Push0A jmp end-code - - -\ *** Block No. 130, Hexblock 82 -82 fthpage + $037B >label blnsw \ C64: $cc \ X16 curon curoff @@ -55,18 +16,6 @@ Code curon ( --) Code curoff ( --) blnsw sty Next jmp end-code - -\ *** Block No. 131, Hexblock 83 -83 fthpage - -( #bs #cr ..keyboard clv12.4.87) - -: c64key ( -- 8b) - curon BEGIN pause c64key? UNTIL - curoff getkey ; - -14 Constant #bs 0D Constant #cr - : c64decode ( addr cnt1 key -- addr cnt2) #bs case? IF dup IF del 1- THEN @@ -77,8 +26,10 @@ Code curoff ( --) : c64expect ( addr len1 -- ) span ! 0 BEGIN dup span @ u< - WHILE key decode + WHILE curon key curoff decode REPEAT 2drop space ; -Input: keyboard-pause [ here input ! ] - c64key c64key? c64decode c64expect ; +Input: keyboard-tasker [ here input ! ] + x16key x16key? c64decode c64expect ; + +keyboard-tasker From 1a549c155358f7a794e14240c11c16e2659804d2 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 10 Jun 2024 03:26:27 +0200 Subject: [PATCH 09/33] Add alltests target that includes sample test, and make emulator/sdcard.img an "order-only" prerequisite, so that tests aren't rerun if it is newer than a test log. --- 6502/C64/Makefile | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/6502/C64/Makefile b/6502/C64/Makefile index 94a62fc..5d27071 100644 --- a/6502/C64/Makefile +++ b/6502/C64/Makefile @@ -45,6 +45,8 @@ binaries: $(vf_binaries) test: $(test_resuls) +alltests: test test-v4th-x16-tsk.result + test64: std64 blk64 blk64: test-v4thblk-c64.result @@ -166,14 +168,14 @@ test-v4th-c16-.log: emulator/v4th-c16-.T64 "include run-std-tests.fth\n$(test_keyboard_input)" petscii2ascii cbmfiles/test.log $@ -test-v4th-x16.log: cbmfiles/v4th-x16 emulator/sdcard.img +test-v4th-x16.log: cbmfiles/v4th-x16 | emulator/sdcard.img rm -f cbmfiles/test.log emulator/run-in-x16emu.sh v4th-x16 \ "include run-std-tests.fth\n$(test_keyboard_input)" mcopy -i emulator/sdcard.img ::TEST.LOG cbmfiles/test.log petscii2ascii cbmfiles/test.log $@ -test-v4th-x16e.log: cbmfiles/v4th-x16e emulator/sdcard.img +test-v4th-x16e.log: cbmfiles/v4th-x16e | emulator/sdcard.img rm -f cbmfiles/test.log emulator/run-in-x16emu.sh v4th-x16e \ "include run-std-tests.fth\n$(test_keyboard_input)" @@ -233,10 +235,11 @@ tests/golden/mycore-noecho.golden: tests/golden/core-template.golden # Sample test with a changed input that would run the tasker # even while waiting for keyboard input: -test-v4th-x16-tsk.log: cbmfiles/v4th-x16 emulator/sdcard.img \ +test-v4th-x16-tsk.log: cbmfiles/v4th-x16 \ $(test_files_petscii) $(wildcard emulator/run-in-*.sh) \ cbmfiles/6502asm.fth cbmfiles/trns6502asm.fth \ - cbmfiles/vf-lbls-cbm.fth cbmfiles/x16input-tsk.fth + cbmfiles/vf-lbls-cbm.fth cbmfiles/x16input-tsk.fth \ + | emulator/sdcard.img rm -f cbmfiles/test.log emulator/run-in-x16emu.sh v4th-x16 \ "include x16input-tsk.fth\ninclude run-min-tests.fth\n$(test_keyboard_input)" From 76ce66e2a457c55e46b8a1e90a83e74edfe36517 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 12 Jun 2024 19:23:03 +0200 Subject: [PATCH 10/33] Extract tasker from VF Disk3 into fth files. Copy over tmp6502asm.fth and x16tmpheap.fth from cc64. --- 6502/C64/src/multitask.fth | 25 ++++++++++ 6502/C64/src/taskdemo.fth | 26 +++++++++++ 6502/C64/src/tasker.fth | 92 +++++++++++++++++++++++++++++++++++++ 6502/C64/src/tmp6502asm.fth | 8 ++++ 6502/C64/src/x16tmpheap.fth | 2 +- 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 6502/C64/src/multitask.fth create mode 100644 6502/C64/src/taskdemo.fth create mode 100644 6502/C64/src/tasker.fth create mode 100644 6502/C64/src/tmp6502asm.fth diff --git a/6502/C64/src/multitask.fth b/6502/C64/src/multitask.fth new file mode 100644 index 0000000..5703da7 --- /dev/null +++ b/6502/C64/src/multitask.fth @@ -0,0 +1,25 @@ +\ *** Block No. 58, Hexblock 3a + +\ Multitasker BP 13.9.84 ) + +\needs Code include trns6502asm.fth + +Code stop + SP 2dec IP lda SP X) sta + IP 1+ lda SP )Y sta + SP 2dec RP lda SP X) sta + RP 1+ lda SP )Y sta + 6 # ldy SP lda UP )Y sta + iny SP 1+ lda UP )Y sta + 1 # ldy tya clc UP adc W sta + txa UP 1+ adc W 1+ sta + W 1- jmp end-code + +| Create taskpause Assembler + $2C # lda UP X) sta ' stop @ jmp +end-code + +: singletask + [ ' pause @ ] Literal ['] pause ! ; + +: multitask taskpause ['] pause ! ; diff --git a/6502/C64/src/taskdemo.fth b/6502/C64/src/taskdemo.fth new file mode 100644 index 0000000..d5dd4e1 --- /dev/null +++ b/6502/C64/src/taskdemo.fth @@ -0,0 +1,26 @@ +\ *** Block No. 62, Hexblock 3e + +\ Taskdemo clv12aug87 + +: taskmark ; \needs cbm>scr : cbm>scr ; + +: scrstart ( -- adr) + (64 $288 C) (16 $53e C) c@ $100 * ; + +Variable counter counter off + +$100 $100 Task Background + +: >count ( n -) + Background 1 pass + counter ! + BEGIN counter @ -1 counter +! ?dup + WHILE pause 0 <# #s #> + 0 DO pause dup I + c@ cbm>scr + scrstart I + c! LOOP drop + REPEAT + BEGIN stop REPEAT ; \ stop's forever +: wait Background sleep ; +: go Background wake ; + +multitask $100 >count page diff --git a/6502/C64/src/tasker.fth b/6502/C64/src/tasker.fth new file mode 100644 index 0000000..a2c019d --- /dev/null +++ b/6502/C64/src/tasker.fth @@ -0,0 +1,92 @@ +\ *** Block No. 57, Hexblock 39 + +\ Multitasker BP 13.9.84 ) + +Onlyforth + +\needs multitask include multitask.fth save + +\ *** Block No. 59, Hexblock 3b + +\ pass activate ks 8 may 84 ) + +: pass ( n0 .. nr-1 Tadr r -- ) + BEGIN [ rot ( Trick ! ) ] + swap $2C over c! \ awake Task + r> -rot \ IP r addr + 8 + >r \ s0 of Task + r@ 2+ @ swap \ IP r0 r + 2+ 2* \ bytes on Taskstack + \ incl. r0 & IP + r@ @ over - \ new SP + dup r> 2- ! \ into ssave + swap bounds ?DO I ! 2 +LOOP ; +restrict + +: activate ( Tadr --) + 0 [ -rot ( Trick ! ) ] REPEAT ; +-2 allot restrict + +: sleep ( Tadr --) + $4C swap c! ; \ JMP-Opcode + +: wake ( Tadr --) + $2C swap c! ; \ BIT-Opcode + + +\ *** Block No. 60, Hexblock 3c + +\ building a Task BP 13.9.84 ) + +| : taskerror ( string -) + standardi/o singletask + ." Task error : " count type + multitask stop ; + +: Task ( rlen slen -- ) + allot \ Stack + here $FF and $FE = + IF 1 allot THEN \ 6502-align + up@ here $100 cmove \ init user area + here $4C c, \ JMP opcode + \ to sleep Task + up@ 1+ @ , + dup up@ 1+ ! \ link Task + 3 allot \ allot JSR wake + dup 6 - dup , , \ ssave and s0 + 2dup + , \ here + rlen = r0 + under + here - 2+ allot + ['] taskerror over + [ ' errorhandler >body c@ ] Literal + ! + Constant ; + + + +\ *** Block No. 61, Hexblock 3d + +\ more Tasks ks/bp 26apr85re) + +: rendezvous ( semaphoradr -) + dup unlock pause lock ; + +| : statesmart + state @ IF [compile] Literal THEN ; + +: 's ( Tadr - adr.of.taskuservar) + ' >body c@ + statesmart ; immediate + +\ Syntax: 2 Demotask 's base ! +\ makes Demotask working binary + +: tasks ( -) + ." MAIN " cr up@ dup 1+ @ + BEGIN 2dup - WHILE + dup [ ' r0 >body c@ ] Literal + @ + 6 + name> >name .name + dup c@ $4C = IF ." sleeping" THEN cr + 1+ @ REPEAT 2drop ; + + + + + diff --git a/6502/C64/src/tmp6502asm.fth b/6502/C64/src/tmp6502asm.fth new file mode 100644 index 0000000..f220469 --- /dev/null +++ b/6502/C64/src/tmp6502asm.fth @@ -0,0 +1,8 @@ + + cr .( tmpheap transient forth assembler) cr + +here $800 tmp-hallot dp ! + + include 6502asm.fth + +dp ! diff --git a/6502/C64/src/x16tmpheap.fth b/6502/C64/src/x16tmpheap.fth index 07b9a90..973c1c7 100644 --- a/6502/C64/src/x16tmpheap.fth +++ b/6502/C64/src/x16tmpheap.fth @@ -5,7 +5,7 @@ \ tmpclear will remove all words on the tmpheap, wheras regular clear \ will remove all words on tmpheap and heap together. -\ Other than the reference tmpheap living on the regular heap, this +\ In contrast to the reference tmpheap living on the regular heap, this \ custom tmpheap needs no initialization as its position and \ size (8k) is fixed. From eff900d842b8a9e43528aa166402248d7ef756ae Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 12 Jun 2024 19:34:07 +0200 Subject: [PATCH 11/33] Add description of other Forth sources that are shipped with release --- 6502/C64/RELEASE_NOTES.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index db12bbf..baefb05 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -22,7 +22,33 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains * `v4th*.fth` - the binaries' main files * `vf-*.fth` - sources from which VolksForth kernels are compiled - * further Forth sources + * `6502asm.fth` - the 6502 assembler, needed to compile Code words + * `trns6502asm.fth` - the transient 6502 assembler. It lives on the + heap and is removed by `clear`. This allows building applications that + have code words but don't carry the assembler itself after saving. + * `tmp6502asm.fth` - like the transient 6502 assembler, but living on the + tmpheap instead of the heap. See below for tmpheap. + * `rom-ram-sys.fth` + * `tracer.fth` - the debugger + * `tasker.fth` - the multitasker + * `multitask.fth` - the small bit of assembly code needed by tasker.fth + * `taskdemo.fth` - a C64/C16 demo of the tasker + * `x16input-tsk.fth`- The usual v4th X16 keyboard input uses the regular + screen editor for line input, so no task switches happen during line input. + This input implementation allows task switches during input but uses Kernal + variables and has a cursor bug after backspace. + * `cbmopen.fth` - Forth words for Kernal channel I/O + * `lists.fth` - two list utility words + * `profiler.fth` - *** [4d2023-04](https://forth-ev.de/wiki/res/lib/exe/fetch.php/vd-archiv:4d2023-04.pdf) (English) + * `tmpheap.fth` - the reference implementation of the tmpheap design + as described at + [SVFIG 04-2021](https://www.forth.org/svfig/kk/04-2021.html), in the + [4d2021-03](https://forth-ev.de/wiki/res/lib/exe/fetch.php/vd-archiv:4d2021-03.pdf) (German) and used + in [cc64](https://github.com/pzembrod/cc64/blob/master/src/cc64/cc64.fth#L11) + * `x16tmpheap.fth` - a X16 tmpheap implementation that uses banked ram + * `notmpheap.fth` - a null implementation that redirects the tmpheap + to the regular VolksForth heap + * `tc-base.fth` - loadfile for the resident part of the target compiler * `src_petscii/` - the files from `src/` converted to PETSCII From a14e74261941c5a9b9fbff70453cf2d7f9eccd16 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 16 Jun 2024 16:49:49 +0200 Subject: [PATCH 12/33] split the rom-ram-sys.fth file into a c16 and a c64 variant - skipping entire screens gated by (C64 doesn't work well with stream sources. :-) --- 6502/C64/RELEASE_NOTES.md | 5 +++-- .../src/{rom-ram-sys.fth => rom-ram-c16.fth} | 22 ++++--------------- 6502/C64/src/rom-ram-c64.fth | 14 ++++++++++++ 3 files changed, 21 insertions(+), 20 deletions(-) rename 6502/C64/src/{rom-ram-sys.fth => rom-ram-c16.fth} (70%) create mode 100644 6502/C64/src/rom-ram-c64.fth diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index baefb05..0ce9e77 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -22,13 +22,14 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains * `v4th*.fth` - the binaries' main files * `vf-*.fth` - sources from which VolksForth kernels are compiled - * `6502asm.fth` - the 6502 assembler, needed to compile Code words + * `6502asm.fth` - the 6502 assembler, needed to compile `Code` words * `trns6502asm.fth` - the transient 6502 assembler. It lives on the heap and is removed by `clear`. This allows building applications that have code words but don't carry the assembler itself after saving. * `tmp6502asm.fth` - like the transient 6502 assembler, but living on the tmpheap instead of the heap. See below for tmpheap. - * `rom-ram-sys.fth` + * `rom-ram-c16.fth` - macros for C16 bank switching + * `rom-ram-c64.fth` - macros for C64 bank switching * `tracer.fth` - the debugger * `tasker.fth` - the multitasker * `multitask.fth` - the small bit of assembly code needed by tasker.fth diff --git a/6502/C64/src/rom-ram-sys.fth b/6502/C64/src/rom-ram-c16.fth similarity index 70% rename from 6502/C64/src/rom-ram-sys.fth rename to 6502/C64/src/rom-ram-c16.fth index b6f8e2d..4b82465 100644 --- a/6502/C64/src/rom-ram-sys.fth +++ b/6502/C64/src/rom-ram-c16.fth @@ -1,4 +1,3 @@ -\ *** Block No. 2, Hexblock 2 \ rom ram sys cas16aug06 \ Shadow with Ctrl+W---> @@ -7,36 +6,23 @@ \ in the ROM Area Assembler also definitions -(16 \ Switch Bank 8000-FFFF +\ Switch Bank 8000-FFFF : rom here 9 + $8000 u> abort" not here" $ff3e sta ; : ram $ff3f sta ; : sys rom jsr ram ; \ if suffering from abort" not here" -\ see next screen Screen --> C) +\ see next screen Screen -(64 \ Switch Bank A000-BFFF -: rom here 9 + $A000 u> abort" not here" - $37 # lda 1 sta ; -: ram $36 # lda 1 sta ; -C) - - - - - -\ *** Block No. 3, Hexblock 3 - \ sysMacro Long cas16aug06 -(64 .( not for C64 !) \\ C) - \ for advanced users, use macros +\ the following macro must be compiled well +\ below the address of $8000 to work. here $8000 $20 - u> ?exit \ not possible - ' 0 | Alias ??? Label long ROM diff --git a/6502/C64/src/rom-ram-c64.fth b/6502/C64/src/rom-ram-c64.fth new file mode 100644 index 0000000..2478d42 --- /dev/null +++ b/6502/C64/src/rom-ram-c64.fth @@ -0,0 +1,14 @@ + +\ rom ram cas16aug06 + +\ macros switching the C64 BASIC ROM ($A000-$Bfff) +\ on and off. By default VolksForth runs with BASIC ROM +\ switched off. + +Assembler also definitions + +\ Can't swich on BASIC ROM (A000-BFFF) if current code +\ location is under the BASIC ROM. +: rom here 9 + $A000 u> abort" not here" + $37 # lda 1 sta ; +: ram $36 # lda 1 sta ; From 6870cc1383a380531beebd90406f72a3e638a115 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 16 Jun 2024 17:21:33 +0200 Subject: [PATCH 13/33] Add convenience targets to run all 4 main flavours with all sources in cbmfiles. --- 6502/C64/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/6502/C64/Makefile b/6502/C64/Makefile index 5d27071..3b8157d 100644 --- a/6502/C64/Makefile +++ b/6502/C64/Makefile @@ -66,6 +66,18 @@ run-testbase: emulator/testbase.T64 run-testbase16: emulator/testbase16.T64 VICE=xplus4 emulator/run-in-vice.sh testbase16 +run-c64: emulator/v4th-c64.T64 $(all_src_files_petscii) + emulator/run-in-vice.sh v4th-c64 + +run-c16+: emulator/v4th-c16+.T64 $(all_src_files_petscii) + VICE=xplus4 emulator/run-in-vice.sh v4th-c16+ + +run-c16-: emulator/v4th-c16-.T64 $(all_src_files_petscii) + VICE=xplus4 emulator/run-in-vice.sh v4th-c16- + +run-x16: cbmfiles/v4th-x16 $(all_src_files_petscii) | emulator/sdcard.img + emulator/run-in-x16emu.sh v4th-x16 + release: tmp/$(release_zipfile) COPYING RELEASE_NOTES.md rm -rf release From 1575422ca7996ac3aa886a559fb487dc171ace0a Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 18 Jun 2024 19:12:03 +0200 Subject: [PATCH 14/33] Guard taskdemo.fth against x16, and print space after downcounting number. --- 6502/C64/src/taskdemo.fth | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/6502/C64/src/taskdemo.fth b/6502/C64/src/taskdemo.fth index d5dd4e1..2195e0b 100644 --- a/6502/C64/src/taskdemo.fth +++ b/6502/C64/src/taskdemo.fth @@ -1,7 +1,8 @@ -\ *** Block No. 62, Hexblock 3e - \ Taskdemo clv12aug87 +(CX cr .( this taskdemo works on c64 and c16 only) C) +(CX abort C) + : taskmark ; \needs cbm>scr : cbm>scr ; : scrstart ( -- adr) @@ -15,9 +16,10 @@ $100 $100 Task Background Background 1 pass counter ! BEGIN counter @ -1 counter +! ?dup - WHILE pause 0 <# #s #> + WHILE pause 0 <# #s #> dup >r 0 DO pause dup I + c@ cbm>scr scrstart I + c! LOOP drop + bl r> scrstart + c! REPEAT BEGIN stop REPEAT ; \ stop's forever : wait Background sleep ; From 083ed795ec22cc51c3ee0f06bc0daf07c41fe266 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 18 Jun 2024 19:39:35 +0200 Subject: [PATCH 15/33] Port taskdemo.fth to the X16, directly writing to VERA's VRAM. --- 6502/C64/src/taskdemo-x16.fth | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 6502/C64/src/taskdemo-x16.fth diff --git a/6502/C64/src/taskdemo-x16.fth b/6502/C64/src/taskdemo-x16.fth new file mode 100644 index 0000000..4d1682c --- /dev/null +++ b/6502/C64/src/taskdemo-x16.fth @@ -0,0 +1,33 @@ +\ Taskdemo for X16 + +: taskmark ; \needs cbm>scr : cbm>scr ; + +\ This method of writing directly into the X16's screen memory +\ is a bit hacky and relies on the default settings that the +\ Kernal uses for text mode. +: scrstart ( -- adr) $b000 ; +: ctrl@ ( -- b ) $9f25 c@ ; +: addr-sel@ ( -- 0/1 ) ctrl@ 1 and ; +: datax! ( c -- ) $9f23 addr-sel@ + c! ; +: addrx-l/m! ( u -- ) $9f20 ! ; +: scr! ( scrcode vram-addr -- ) + addrx-l/m! datax! ; + +Variable counter counter off + +$100 $100 Task Background + +: >count ( n -) + Background 1 pass + counter ! + BEGIN counter @ -1 counter +! ?dup + WHILE pause 0 <# #s #> dup >r + 0 DO pause dup I + c@ cbm>scr + scrstart I 2* + scr! LOOP drop + bl r> 2* scrstart + scr! + REPEAT + BEGIN stop REPEAT ; \ stop's forever +: wait Background sleep ; +: go Background wake ; + +multitask $1000 >count page From 9e3e95c3e8a6b81a6f03af5d98ee46ec258615c8 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 18 Jun 2024 19:45:25 +0200 Subject: [PATCH 16/33] Load assembler in x16input-tsk.fth only when needed. --- 6502/C64/src/x16input-tsk.fth | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/6502/C64/src/x16input-tsk.fth b/6502/C64/src/x16input-tsk.fth index 43e6ad0..1f70885 100644 --- a/6502/C64/src/x16input-tsk.fth +++ b/6502/C64/src/x16input-tsk.fth @@ -2,7 +2,7 @@ \ even while waiting for keyboard input, similar to \ the keyboard input on C16 and C64: -include trns6502asm.fth +\needs Code include trns6502asm.fth \ X16 labels From 82b7f31ae448ba71cad88fd2dd54ee4a2e85ce17 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Wed, 19 Jun 2024 22:32:27 +0200 Subject: [PATCH 17/33] Rename Kernal variable labels CurFlg to QtSw and InsCnt to Insrt - those are their names in the canonical CBM documentation and in the X16 ROM sources. Also remove their use in the X16 variant of VolksForth --- 6502/C64/src/vf-sys-c16.fth | 4 ++-- 6502/C64/src/vf-sys-c64.fth | 4 ++-- 6502/C64/src/vf-sys-cbm.fth | 10 +++++++++- 6502/C64/src/vf-sys-x16.fth | 6 ++++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/6502/C64/src/vf-sys-c16.fth b/6502/C64/src/vf-sys-c16.fth index 4885975..c8b1790 100644 --- a/6502/C64/src/vf-sys-c16.fth +++ b/6502/C64/src/vf-sys-c16.fth @@ -12,8 +12,8 @@ include vf-lbls-cbm.fth 0ff19 >label BrdCol 0ff15 >label BkgCol 053b >label PenCol - 0cb >label CurFlg - 0cf >label InsCnt + 0cb >label QtSw + 0cf >label Insrt 0540 >label KeyRep 055d >label PKeys diff --git a/6502/C64/src/vf-sys-c64.fth b/6502/C64/src/vf-sys-c64.fth index 66323a6..43d888c 100644 --- a/6502/C64/src/vf-sys-c64.fth +++ b/6502/C64/src/vf-sys-c64.fth @@ -11,8 +11,8 @@ include vf-lbls-cbm.fth 0d020 >label BrdCol 0d021 >label BkgCol 0286 >label PenCol - 0d4 >label CurFlg - 0d8 >label InsCnt + 0d4 >label QtSw + 0d8 >label Insrt 028a >label KeyRep 0cc >label blnsw diff --git a/6502/C64/src/vf-sys-cbm.fth b/6502/C64/src/vf-sys-cbm.fth index 3cb9351..db441e7 100644 --- a/6502/C64/src/vf-sys-cbm.fth +++ b/6502/C64/src/vf-sys-cbm.fth @@ -6,7 +6,15 @@ Code con! ( 8b --) SP X) lda Label (con! ConOut jsr SP 2inc -Label (con!end CurFlg stx InsCnt stx +Label (con!end +\ So far VolksForth switches off quote switch and insert count +\ after every printed character. This introduces a dependency +\ on Kernal variables QtSw and Insrt that are undesirable on the +\ X16 where their addresses may change between Kernal versions. +\ Therefore we'll try how the system behaves without them on the +\ X16. Possibly this isn't needed at all, in the end. +(C64 QtSw stx Insrt stx ) +(C16 QtSw stx Insrt stx ) 1 # ldy ;c: pause ; Label (printable? \ for CBM-Code ! diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index bf281ab..ce9b09d 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -10,8 +10,10 @@ include vf-lbls-cbm.fth 0feab >label ExtApi 09f2c >label BrdCol 0376 >label BkgPenCol \ aka color - 0381 >label CurFlg \ aka qtsw - 0385 >label InsCnt \ aka insrt +\ I'm tentatively removing QtSw & Insrt from the X16 variant; +\ see comment at the top of vf-sys-cbm.fth +\ 0381 >label QtSw +\ 0385 >label Insrt 1 >label RomBank 0 >label RamBank From 616b40873230ba4b4f302470a368829a8d49a64e Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 23 Jun 2024 00:05:09 +0200 Subject: [PATCH 18/33] Drafted 6502-C64 3.9.6 release notes --- 6502/C64/RELEASE_NOTES.md | 41 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 0ce9e77..ba418e5 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -34,6 +34,7 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains * `tasker.fth` - the multitasker * `multitask.fth` - the small bit of assembly code needed by tasker.fth * `taskdemo.fth` - a C64/C16 demo of the tasker + * `taskdemo-x16.fth` - a X16 demo of the tasker * `x16input-tsk.fth`- The usual v4th X16 keyboard input uses the regular screen editor for line input, so no task switches happen during line input. This input implementation allows task switches during input but uses Kernal @@ -60,9 +61,47 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains ## Versions The following version descriptions are only valid for VolksForth 6502 -C64 Releases. As of now (Dec 2023), the different VolksForth platforms +C64 Releases. As of now (June 2024), the different VolksForth platforms (6502, 68k, 8080, 8086) don't have shared code or shared versioning. +### 6502-C64 3.9.6 - in preparation + +Several dependencies of the VolksForth kernel on X16 Kernal variable addresses +and thus likely breakage points with new Kernal release were replaced with +Kernal API calls, so the VolksForth kernel should now be much more robust +when the X16 Kernal changes. The only remaining Kernal variable used is +$0376 - BkgPenCol. + +* Clearing the IOStatus is now possible through the ExtApi call ($FEAB, thanks + to *** for implementing this), so the dependency on the address of IOStatus + could be removed. +* The implementation of line input in EXPECT was changed from switching cursor + on and off and using GETIN to using BASIN - which automatically handles the + cursor and also makes use of the CBM screen editor. The Kernal var dependency + that came with switching the cursor on and off is now removed. + The downside is that the + cooperative multitasker now can't run tasks during line input. The old + tasker-compatible EXPECT is now available as separtate source + x16input-tsk.fth. For details on this see MISC_DOC.md. +* The direct clearing of MsgFlg (X16: $028d) at the beginning of + (busin and (busout was removed; it shouldn't have had any real purpose. +* Likewise the clearing of the Kernal variables QtSw and Insrt after each + char written to the console via CHROUT: It was removed from the X16 variant + as it shouldn't be necessary. + +The cooperative multitasker was extracted from the original disk 3 (see +[`disks/vforth4_3.fth`](https://github.com/forth-ev/VolksForth/blob/master/6502/C64/disks/vforth4_3.fth)) +into the files `tasker.fth, multitask.fth` and `taskdemo.fth`. The latter was +ported to the X16 as `taskdemo-x16.fth`. + +`rom-ram-sys.fth` was split up into a C64 and a C16 flavour. There is no X16 +equivalent; X16 bank switching poses challenges and opportunities completely +different from those on C16 and C64. + +New sources added: `lists,fth, tasker.fth, multitask.fth, +taskdemo.fth, taskdemo-x16.fth, x16input-tsk.fth, tmp6502asm.fth, +x16tmpheap.fth, rom-ram-c16.fth, rom-ram-c64.fth` + ### 6502-C64 3.9.5 This release adapts the X16 VolksForth to the R46 ROM. From 162e45a2eaaf15dc876852adfbdf94c3286421de Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 24 Jun 2024 14:35:51 +0200 Subject: [PATCH 19/33] Add mooinglemur to RELEASE_NOTES.md --- 6502/C64/RELEASE_NOTES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index ba418e5..264b320 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -73,8 +73,8 @@ when the X16 Kernal changes. The only remaining Kernal variable used is $0376 - BkgPenCol. * Clearing the IOStatus is now possible through the ExtApi call ($FEAB, thanks - to *** for implementing this), so the dependency on the address of IOStatus - could be removed. + to mooinglemur for implementing this), so the dependency on the address of + IOStatus could be removed. * The implementation of line input in EXPECT was changed from switching cursor on and off and using GETIN to using BASIN - which automatically handles the cursor and also makes use of the CBM screen editor. The Kernal var dependency From 423ecea90830eebf07a1c8a167baec5bc05e83b0 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 1 Jul 2024 02:24:18 +0200 Subject: [PATCH 20/33] for X16, replace ink-pot with x16-ink-pot which holds PETSCII codes instead of color codes for pen and background, removing the dependency on Kernal variable BkgPenCol --- 6502/C64/src/vf-sys-x16.fth | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index ce9b09d..230b01e 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -69,11 +69,9 @@ include vf-sys-cbm.fth \ ... continued 8f fthpage -Create ink-pot -\ border bkgnd pen 0 - 6 c, 6 c, 3 c, 0 c, \ Forth - 0E c, 6 c, 3 c, 0 c, \ Edi - 6 c, 6 c, 3 c, 0 c, \ User +Create x16-ink-pot +\ border bkgnd-color-petscii pen-color-petscii + 6 c, $1f c, $9f c, \ Forth \ *** Block No. 144, Hexblock 90 @@ -99,10 +97,10 @@ Label first-init sei cld RomBank lda $f8 # and RomBank sta \ map in KERNAL ROM IOINIT jsr CINT jsr RESTOR jsr \ init. and set I/O-Vectors - ink-pot lda BrdCol sta \ border - ink-pot 1+ lda - .a asl .a asl .a asl .a asl \ backgrnd - ink-pot 2+ ora BkgPenCol sta \ pen + x16-ink-pot lda BrdCol sta \ border + x16-ink-pot 1+ lda ConOut jsr \ backgrnd + 1 # lda ConOut jsr \ swap backgrnd <-> pen + x16-ink-pot 2+ lda ConOut jsr \ pen $0e # lda ConOut jsr \ lower/uppercase cli rts end-code first-init dup bootsystem 1+ ! From e73e4bc6d4cabab6b2ab2882d7cf89c3e5d371d6 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 1 Jul 2024 23:52:48 +0200 Subject: [PATCH 21/33] Remove 0376 >label BkgPenCol from vf-sys-x16.fth and update RELEASE_NOTES.md accordingly. --- 6502/C64/RELEASE_NOTES.md | 17 ++++++++++++++--- 6502/C64/src/vf-sys-x16.fth | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 264b320..8e2a980 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -66,11 +66,11 @@ C64 Releases. As of now (June 2024), the different VolksForth platforms ### 6502-C64 3.9.6 - in preparation -Several dependencies of the VolksForth kernel on X16 Kernal variable addresses +The known dependencies of the VolksForth kernel +on X16 Kernal variable addresses and thus likely breakage points with new Kernal release were replaced with Kernal API calls, so the VolksForth kernel should now be much more robust -when the X16 Kernal changes. The only remaining Kernal variable used is -$0376 - BkgPenCol. +when the X16 Kernal changes. * Clearing the IOStatus is now possible through the ExtApi call ($FEAB, thanks to mooinglemur for implementing this), so the dependency on the address of @@ -88,6 +88,17 @@ $0376 - BkgPenCol. * Likewise the clearing of the Kernal variables QtSw and Insrt after each char written to the console via CHROUT: It was removed from the X16 variant as it shouldn't be necessary. +* Up to version 3.9.5, the VolksForth kernel used BkgPenCol (X16: $0376) + to set both background and pen color during initialization. It would be + great ot have e.g. an ExtApi function to set BkgPenCol, similar to the + X16 BASIC command `COLOR`. I'm planning to suggest this, + but for the time being setting the background and pen color is + instead done via PETSCII control codes instead. To reflect this change, + the CBM VolksForth word `INK-POT` has been renamed to `X16-INK-POT`, + and it contains only 3 values (border color code, background color PETSCII + control charcter, pen color PETSCII control character. This removes the + dependency on BkgPenCol and thereby on the last remaining Kernal variable + that was used by VolksForth. The cooperative multitasker was extracted from the original disk 3 (see [`disks/vforth4_3.fth`](https://github.com/forth-ev/VolksForth/blob/master/6502/C64/disks/vforth4_3.fth)) diff --git a/6502/C64/src/vf-sys-x16.fth b/6502/C64/src/vf-sys-x16.fth index 230b01e..d0852fc 100644 --- a/6502/C64/src/vf-sys-x16.fth +++ b/6502/C64/src/vf-sys-x16.fth @@ -9,7 +9,6 @@ include vf-lbls-cbm.fth 0febd >label KbdbufPeek 0feab >label ExtApi 09f2c >label BrdCol - 0376 >label BkgPenCol \ aka color \ I'm tentatively removing QtSw & Insrt from the X16 variant; \ see comment at the top of vf-sys-cbm.fth \ 0381 >label QtSw From 521949e47057dcec7af4e588149887a12c449c58 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Fri, 5 Jul 2024 22:27:28 +0200 Subject: [PATCH 22/33] Bump of version in src 3.9.5 -> 3.9.6 More updates to RELEASE_NOTES.md --- 6502/C64/RELEASE_NOTES.md | 45 ++++++++++++++++++++++++------------ 6502/C64/src/vf-head-c16.fth | 4 ++-- 6502/C64/src/vf-head-c64.fth | 2 +- 6502/C64/src/vf-head-x16.fth | 2 +- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 8e2a980..0a3c0c0 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -1,6 +1,8 @@ -# VolksForth 6502 C64 Releases +# VolksForth 6502-C64 Releases -Release notes of VolksForth for 6502 on CBM-like machines (C64/C16/X16) +Release notes of VolksForth 6502-C64 which is the flavour of VolksForth +running on CBM-like 6502 machines - currently the C64, the C16/Plus4 and the +Commander X16. ## Release content @@ -60,18 +62,26 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains ## Versions -The following version descriptions are only valid for VolksForth 6502 -C64 Releases. As of now (June 2024), the different VolksForth platforms +The following version descriptions are only valid for VolksForth 6502-C64 +releases. As of now (June 2024), the different VolksForth platforms (6502, 68k, 8080, 8086) don't have shared code or shared versioning. ### 6502-C64 3.9.6 - in preparation -The known dependencies of the VolksForth kernel -on X16 Kernal variable addresses -and thus likely breakage points with new Kernal release were replaced with -Kernal API calls, so the VolksForth kernel should now be much more robust +Main topic of this release is the removal of all usages of Kernal variable +uses esp. in the X16 VolksForth kernel. Because the addresses of Kernal +variables can change between different X16 Kernal releases, their use was in +the past the main reason why VolksForth broke after new X16 ROM releases. + +With Kernal variable access replaced by Kernal API calls or by emitting +control characters, the VolksForth kernel should now be much more robust when the X16 Kernal changes. +A secondary topic if this release is more bundled Forth sources, which are +now also better described (see Release content above). + +Changes affecting only the X16 VolksForth kernel: + * Clearing the IOStatus is now possible through the ExtApi call ($FEAB, thanks to mooinglemur for implementing this), so the dependency on the address of IOStatus could be removed. @@ -83,11 +93,9 @@ when the X16 Kernal changes. cooperative multitasker now can't run tasks during line input. The old tasker-compatible EXPECT is now available as separtate source x16input-tsk.fth. For details on this see MISC_DOC.md. -* The direct clearing of MsgFlg (X16: $028d) at the beginning of - (busin and (busout was removed; it shouldn't have had any real purpose. -* Likewise the clearing of the Kernal variables QtSw and Insrt after each - char written to the console via CHROUT: It was removed from the X16 variant - as it shouldn't be necessary. +* The clearing of the Kernal variables QtSw and Insrt after each + char written to the console via CHROUT most likely has no real purpose. + It was therefore removed from the X16 variant. * Up to version 3.9.5, the VolksForth kernel used BkgPenCol (X16: $0376) to set both background and pen color during initialization. It would be great ot have e.g. an ExtApi function to set BkgPenCol, similar to the @@ -100,6 +108,11 @@ when the X16 Kernal changes. dependency on BkgPenCol and thereby on the last remaining Kernal variable that was used by VolksForth. +Changes affecting all VolksForth kernels (C64, C16, X16): + +* The direct clearing of MsgFlg (X16: $028d) at the beginning of + (busin and (busout was removed; it shouldn't have had any real purpose. + The cooperative multitasker was extracted from the original disk 3 (see [`disks/vforth4_3.fth`](https://github.com/forth-ev/VolksForth/blob/master/6502/C64/disks/vforth4_3.fth)) into the files `tasker.fth, multitask.fth` and `taskdemo.fth`. The latter was @@ -115,8 +128,10 @@ x16tmpheap.fth, rom-ram-c16.fth, rom-ram-c64.fth` ### 6502-C64 3.9.5 -This release adapts the X16 VolksForth to the R46 ROM. -It also adds an X16 binary with added words to invoke the +This release adapts the X16 VolksForth kernel to the R46 X16 ROM. +July 2024 note: version 3.9.5 also runs with the R47 ROM. + +The release also adds an X16 binary with added words to invoke the ROM-based X16Edit (XED), to list directories and files (DIR and CAT) and to issue DOS commands and read the error channel (DOS). diff --git a/6502/C64/src/vf-head-c16.fth b/6502/C64/src/vf-head-c16.fth index ca8446a..c185104 100644 --- a/6502/C64/src/vf-head-c16.fth +++ b/6502/C64/src/vf-head-c16.fth @@ -28,5 +28,5 @@ here dup origin! $100 allot Create logo - (C16+ ," volksFORTH-83 3.9.5-C16+ " ) - (C16- ," volksFORTH-83 3.9.5-C16- " ) + (C16+ ," volksFORTH-83 3.9.6-C16+ " ) + (C16- ," volksFORTH-83 3.9.6-C16- " ) diff --git a/6502/C64/src/vf-head-c64.fth b/6502/C64/src/vf-head-c64.fth index 994bc03..a5fb4eb 100644 --- a/6502/C64/src/vf-head-c64.fth +++ b/6502/C64/src/vf-head-c64.fth @@ -28,4 +28,4 @@ here dup origin! $100 allot Create logo - ," volksFORTH-83 3.9.5-C64 " + ," volksFORTH-83 3.9.6-C64 " diff --git a/6502/C64/src/vf-head-x16.fth b/6502/C64/src/vf-head-x16.fth index 4771059..4e3f527 100644 --- a/6502/C64/src/vf-head-x16.fth +++ b/6502/C64/src/vf-head-x16.fth @@ -27,4 +27,4 @@ here dup origin! $100 allot Create logo - ," volksFORTH-83 3.9.5-X16 " + ," volksFORTH-83 3.9.6-X16 " From ac4936a2686e1cb7096e91d673e7e3323b6e694c Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Thu, 18 Jul 2024 17:01:37 +0200 Subject: [PATCH 23/33] Check in new 3.9.6 binaries --- 6502/C64/cbmfiles/v4th-c16+ | Bin 14029 -> 14025 bytes 6502/C64/cbmfiles/v4th-c16- | Bin 13868 -> 13866 bytes 6502/C64/cbmfiles/v4th-c64 | Bin 13942 -> 13938 bytes 6502/C64/cbmfiles/v4th-x16 | Bin 13824 -> 13768 bytes 6502/C64/cbmfiles/v4th-x16e | Bin 14177 -> 14120 bytes 6502/C64/cbmfiles/v4thblk-c16+ | Bin 16202 -> 16198 bytes 6502/C64/cbmfiles/v4thblk-c16- | Bin 16042 -> 16039 bytes 6502/C64/cbmfiles/v4thblk-c64 | Bin 16115 -> 16111 bytes 8 files changed, 0 insertions(+), 0 deletions(-) diff --git a/6502/C64/cbmfiles/v4th-c16+ b/6502/C64/cbmfiles/v4th-c16+ index 4e6da3627b204789990e2600666d03e0bd29fd68..be67aba875da4ef64dd1cba4c14ec7c99642e9cd 100644 GIT binary patch delta 1210 zcmYjPUrbw796tR=TlNRm+pS$&vEXI^PYFJ*Um04=4Bg zet*8-?>pzN4v9nO4%V%(0Mvrkz|EdNy|t`s3f-AHx{G^W)1dLCk7#tyX&$BNhD$p% z_31xaPH8pM+*{DyI7nab9-ux2y?&!4$Vx_1;{G}HynC8<@ASLR?HNpe13UFxp&j}E z3L3L(a;Yp7BhY1k(6DbiI6%cgEi&P7u27N%690|Fb(Ksbs%ge4vB)Cs)sD8&Ze*y? z2z(eA^o7s>H32?CdK_zt4+vy4?29bY?kf`C(@CedAo z?CAHA)?}qMSU{w4zS8J(O@LfwAF)_oQ=WC^QNVeh8vU>JHZm>=l2noc5jYlb+3R8` zkFr*my?t!|tkVkO);x+^`vSAhM{3#@bJl~Q!+BKYLx<;W#NQYX!foS?E zwjCVC`4pW{)zqoPw(9;;b;s3(*XhK5b>S$T*sCtQK_|KmsV@>i!vdw6^$CiYe!HIo z$7y5E_c9r|LA$59Upwv50&T*fsA*x}bGkyz$XGOPE9z3MY zOC{M;xefAum8-bhQ}s%G^1#6{-X^MtF)tTNnI+GXu>Pdg1bEQT4SP|`2Mn~n$XxXf zP!UM*=lI0XWu~ubq;b(P<_Lm3W?AbQ?sxC-Xdazm+HB-r`vO(fU^i-rTbc}@~ z@MP$j%qO-imJ3_0=nC3Cpohocn@RT-qzhhV{y!~iZL^Uwi2o=aydN?xXL5?TF5t%{ z%V1CU>?HG3sP077LgjDuWD11{%!X#2O#s)B(lJLpAj1Prh~{m3owB2n2wO?}&CnjP zs0dP75){w6nDHoLHUh6Pw=LH@4>p)Y1mPHTGCr3;}G2SYsb`wsf*PU%EMPMd5P6ZWgcol z3>;#$YZ&S=WLWKK8Dk^Hud!MY!`&FZ!)l5=Jb=-AL_@)XHJE(JYHsn+h0zFWkOhUP v{IV|wzGC%7VMF1e8K*e5W@EETXZ$g63GY-YE4NBK+{QM3WObPG@O#U@f7S61 delta 1237 zcmYjPe`p(39DkP|P2%dhC25l-v8Hvywp?Pm*r;9F%e%{6N{Jw=qW=sgN)bkxzgX)U zNU_>&X*0LoSx4=v>nxf<*&q3DQbv+qT(0jF4(-71AtE9W-D1Gg~pyfE|3mPh-tYj)mA~>(kxTk4%eb9Yo_tErua=%V9F~i^R z!QT5JLv~dzl|?B+y6pFwn*bcNBtShhqH?ZSl0{ssgA(U9y_-QTE5N{wDJPl73k`zae`l)L1ZcGLsPsaSY; z$00io2e5UaY7LbkHZD|+0oNq>uDYXwR9;mcIVDIr?^@#jSvR3!S*%n_6)HlGQ!abM z7?fbv>azRB_slu1AYqkY!rD*GIsa1AwwQAl80wZ_jSqD%*zkm(0D?9Yq??{{NqNw* zwWS4j(TD%ffe5{$AQcpkydf*%$~*M@{h8=&Jcu@$oT5*krc-oZ>RjK|B`wjH0`nl6 zeu%~njUYWmCsj2yoZMF3AF1wyx;Q{5_o$06)5%74@fA9GK%W{*hV+XT)uc;W@X)Uv z=E3WeN#R9Mrj2M>{-(GgYngfT4WDW0XZpe+ zeN@jNOA~|oN4Hb~Y|*CWlI*FT5Wdyw@!aXD&5vgnKr>JITP=_=<%^}vvS(Rbd(dG7 z0(g^u-w)g0W=LxXbJag+iI5n7h`up+ndxsGZCP@RJ3>H0ENh+MH~k}V2~IFx8$RoP zs+N9?F_t7xHTv_;6KsS$7Jd}-fh~*TSZfo!0=M_-$N}=;MfVl-<}Ne;@0PWCZFrd% zy)pqD2^;g7oKjd5(S_s9pqYNPW98d$L$EeN^$mM6#bSiahv%HF0Ik7G#~r%>ZcaJ9 zaKYB-lpR%pwPO1!zq_l^mSui0U)#U0)nqUF{x;7!@2Oa`@I77a&m9jx&0Y$hY%$rf zj_VX_^5zRgQOc~KxBX}1aQArkpk)+{vP@fNAVOly^B1}T@h{jn+H&g)>?l}c>0EnF zy3HE%rHXRh^SmDyV&Heyl#yj|C0i6L?Op(~+<-R*0MM6LAsRr` z&FL@|$QKZKhSOBa0;vHp5acwg2u{P*7kU zBJXmA{qU<`bP_Eah>w@L!JjmAiG KT0{l%Yx6%kU-F~? diff --git a/6502/C64/cbmfiles/v4th-c16- b/6502/C64/cbmfiles/v4th-c16- index 01b1f663375c094baf0f6fc2ac0ad68d6e6c9315..cc5420d33fbe833ba2de9382b9f6849589448597 100644 GIT binary patch delta 1151 zcmYLHUrbw782@f5{o~LwT4>i+R&YzGIqgc>szRYXx4m>RJQ(+&J}jD8Ys@w^F>!O$ z@Bq$Pwm5cgj7~-dN;J#J9*90HAzKRo{arC?2noiQPuK_mWxj5=X@5{*AVrc*$%UxqPuncNN8Vl zGHx!csB&2>rI6RP)!K3~p0VfP+qi{<=Zmr`()dp_eltdu<+!PXNK)xuoWCDx@3<4M zuhJAM#STTbNcJc=u#v>tI`O30_q9IoMbjvB@VK*iXb;|WtL|4K)YMZo#WUD9tq(-J zqi_(@o>Hm2qNUKB`xAEqq;bsitNmflo7lV{DvGScQt0KF*JbnKG%h&2uF&v~36BGE zjx^3WP;A2Ur#|b}4ft|X4 zZeTom%r~O@a{A0|e0qmIvx!eP>oY&|ZQoEg(ObJHy`uof zSyNHovn2IVUGHhZE@1d?!Z!PP*1A}f^9z9marN&fEg--(el3jsMHV?uuvfY=_7tLc zgB&k5C7x{`Y@2fryW?b=rbNMUi^pBZhSK;J8+6h=p;)bBDT)8f zyyq;Ca-8E@oWl=x8PNgs{G^Y=H)Ezm#tskL6&yh)^;O6#5a7FnWidamNvk6HTh-gR zYbG2BC{%=lwOMm$NL& zinbJZx{C&~u%EN$RaIOr6h*}!1lZYsAeaS!`tpjplot^4X5lT)L|KT?2%+zDMoI@5@`*M6f_YcbIh86 zyafHo)vKaLtK4YG!Y`b$Bvv#5S&8&JXR55%=y)^>Ouwltm$fxnKo7_mjs10m3h1k* Fe*s6D%sBu6 delta 1168 zcmYjPO>7%Q6dwP@UK~hkJGE<@u#OrjDPzlx69cK6-C28WTIGP~0i+61gcMn&IZzI5 ziBS+i6*w}qctI#FrcD+8)ErPQ2oY7bv!UBKyT-dtlOR$Ml>Qv5s)YbOWSOy5!C|!D z_r3SN_ukHYb@;;JlU;3(Cjoc}v@(l(Zbe3T|0%S7>Y0c0j~O}){j-Ax)1!t1vs}kn zyW#lkuRX6B4fgzVkPeu*i@S%NuY;#!)|#kl#hR9lP3e=gougZ0^vSKJ*^l8Zlkvo4 z{;hET;Ca?ss;f#>lvB{}xzn-j0z2%?f^S$Gmdh1I6^Z^c(XTQjqOdL9I3&q`u-M{W zxO40#YiS56C^N4_@8bFi;6Y}r1^UrBEB%E&blx!mAR?W#)hc$J^M2%Q1&mK~M$m6w z)q5~XikLdR%g`YX zdvE9hIKWZ!iW+PzMlPVS)%u?1*koh@ypjL3x6^r+qZTSkaXvUNF5lm20|F@LwO-Vt zaM1NG_ibd@nSuoWf)9}+T_tue+T3A=`{A?a=)LGFL&g8!t>g;1N!l8I5CXUyw=ERQ znzSt9dm_W&ovwRG#G7bKH&IhAI10WyI>|kfFZA_1u^K;-Fecs! zP#zK|dLcoD7Nm+O7nktkyw`qoV0>WMISSSi@$OyG6eRd=ezPw+wwZXjyS!rNM?pW& zm3x{YhPN#!HSJRH$p{fLU>{EvRaIOnRm56P2!KFxe<%Y0uvF{nrJ?|#KLcLnTL=qd z8pU*sHxnwrr!aYsH`b~GG=dB`%^T|&nlb#0Hy%|nwqpD>Zt@9RD)QHPZ+cMw=ZL7j{()Y(8k z6k(*4HC)(ald?L>=7)ZYus=|0l3wv3%^i2w+6o(P$~M%AY@M63nZ0jU-tsREAQ!SUS)R_;U%{YVmPt&q1Ia!)^twl-*z zx*ItYXn|?#Ea-)L6!VP2MWg%6`o!m!SpXsKqwUDZZ^iME!v;p2nl%pZIaJ4q04|zn z6vZc@d#OGV?wAE{Lp+06lQ*>&H5oYKd}RHvW*Uwe*91k8l#wL$Uc^P({V)T|HWxWK zvuDBC0dlqs%-Ir=1?OM&qCM**!MR`tHu<^Wk{$2#A-KvvI@EcPpf3@p;}_-teT`0C z)1^$yfKKI7ms3l`9KrVmySsjYRYTVlztiRC19Dt6nl z`bzHsGg<9_YFThTuH)RV`THSnq?@TSDdvOyW)kZ-evdH+*2St&D{Y|v_j}u9a3+|x zP60RjYJWJCq%e;1n3z#G2M6MZ4*b4&gu+%(Lc_stOzB zs-SrL064`R>&pTFTIEgkW~o5=I&aF{d5lC0g53ewqq6O*;%fAeyvu^+Z delta 1149 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 delta 2185 zcmZWq4Qw0b8UAc1{=19q#%`NNR&d>;N~q&d=YD*SFCigOLZS;&}SkV&Tz4F#UG-%ogTOx)4viftmECzpwv)&l{* z9V6Cjk>Wy8%&HNpwYGztuxH5DS|90JlXO~Z<8Fg3dG6qAcarbY@m;)3X5ZAv3JII2iT0`q6a;Pf)xpsqV7pb^Vw> znq&HrgRKNlR*q0!W(sQPM|ZJ!b~$l2Lb)BkoMIH8_QI|(i(!iE(|?2kxgGIxz#a`E ztv()a_iwQ7*TU0k+t1_Q@o$a|X(8%jQM|~G={-xfQItEl;&`J6%ELuKn={e(*r?1r zhyK8ta*|Smv#n02;m79aUTE#P}x1t7IWC~VT%g4~bS zC})6DampA%N70*{F*BzCK`(LR7q}JU&;`!(T4{U|i<6w^mC~s041&$R%_aS1+Jho- z6-`Nh%I@`9?*EGC-i`T!K@>Z8G-6MAh+sU95P z1G!QMEjZh+dZ6m)DS8lnGpKbl2i;})~N z7;_anBo0TM4;pb+DgVL$CH-wV=}DY)vYb>2R%(aKIo}8H<4DI>fNf(P56%9j6n)ux z9IfSX8JKMmYO?xdH5o%~PL*);*Q%B3E*S1{RIf$dvy1nnFn^At9Xu{k$`^4*S`g~w z+nme9|6(5IO*v7P3o`8fKF;m1Tlh{s15CQR558{~8YDaUL2@0JblxaU*n6E0bRf{l zW1YHDIuJjP_>}f`ji7(>_#?$w z_lDp`g`Gu1`#&pa4*6g%KgRO0$vgY*q1{- z@*AOdwqQG!--5@&FNJp09@;Qj-B*1NOnoVoAitZ`2BWvEiL?gc@tP4frHnyKjX$$X9~_{+7GKx68NlbWMPlxTVk+^JYlD z9Usd9k48|k#XOzPs&Es)dU07Wn!h=)XSu~Lln0?PxG_Bom*UNqq|=Mw3_jXd?Latr zn==P3UiCzvFVIaKLa&9l)n^wX6qcvsr)V}NhreCFm0buQ zLKfjm*@m*qDVV1VvO3ckY{rIOR3}){iXvWyzXiErGeVyVyEgYCger@3%1k;z`CPrI zLoj0PZctfJcL^0(O;9{2j|h6Xn4lg&z3BUbeh$Q)AU-ANpHM*F4RXJrmq7eFh{J*| zpP&wc^diPk0r0D!qy*iS1obFLZwi%)sA7~QTQ9mGROH14H9_qG*G0j&uvk`4(Y@#j X)Kn;{R|*O07PRq^U;s5i{o48;oRd=D diff --git a/6502/C64/cbmfiles/v4th-x16e b/6502/C64/cbmfiles/v4th-x16e index 98dcaeb0dddfbeb7259edce8fade04202c8eb0e7..ae4ee58db27661d7e25dbf50e6a14b2e2a7b17ca 100644 GIT binary patch delta 2497 zcmY*aeQXow8GmgjcI>;@#+MFoT{zr>CBqIS`0jj8Y&UH)hsk3Vg96*6AvRfb6eJie ztOP8UrU{PP#`D3tjhaAfMu3!}?0f2pKaSy&*q-ka5~fyUg#~RA%0`izbmjKE_NuZ! zY(JmB=i~joucvpN*)_1-^5q~xCY0t5vHw{4Y`_t3|1kb^ePXF*iG~{qXx2Aq?{XtQ zdFVo&X4A+MO9lyzZRDdSt5)-T;^URuv_&DY*|n5S3-7Io5HF%mkD)BdO1iAXJg3y3 z(?x+MJ@kMvE!+nGDKw}FZ$gLBA&+5lHJ3Q=S{Cg_fAr`e_>oGz?PRbT@Qiz%Je5)ZznNWrd*gME|#C6l%dX0I` zbdZ#47<$OV4>7p9u8oJRc79&WLC24b32{AZv#DW1_WWxds#rKb=+?&(21hauBS@cW6MHLr+nslX^xCFy82Wf0}|%vvw*g_dz+ zFx{2#aW4EO`!YJh8FG2KG@73JcFQgHGd96lITsh?ws8@n7yX(e@~et&V1Y6&2S4KI z-{PhBBAKhrtjdgD6&Y01i~h+OKwgzAPl(J})Eh-}Tumcr^G<|9jFoqh4r`spi~)^& zZLXZ3fcbR%mM`5jc97WmD6bDZVAhy#8eQZMD+vN$14zLTgH0NwZ>z(7SnT8JbLybx6aqGP z^U3Ban?VuznpMf>l*Q>XuKNc4RL3)GpX`VbokJS>-2LtJMRjN^olpS=)-YSUeS7%# z{MI9=pRa2S=A?;yR?>Qb786na0q%s)^GDD<-tfPO5Yx@?Xhz-$aRe>&8X9qr9YZn)=a)l^!tHLd?6iV>S{6qm)A2^4_$`wym(*e)O+O*5eL=PGR=+BTB&i1lOV7hZZJ9P`A{D*}O; z?rrD^)4M?=4)(uY+#rVhU$yy7}BoD|>|0Wr$z@QI3O z266M&I2sXJ@g>H9qz@iVIKBqobN^A}2>Fb;qU^4Wg%7MUQ=F|fjr)zG#fcYMoY6L) z@$zUfopS@L=ACsYj=uZ3rKOOYcUs_9Wyo{ZqvV{Yd%+TOlG39Q%Q^xh=}`fs6g-w8 zW}5q(r4_s+`i$M-bCJt^e^`m_SUw1!vNz@Xn*G4ycWvFa$B|t~`7-2T-^+=GYgX!} zIWf_(rZZ|64*Qxdc+Fs`^tjtsS1h4jTYc#ZjcS?s7V-z@q?XjoX6F%viDKH?5XvbrBUVyVIla zW~N({loLS=4(+yC5iTC22D~ZDLzHZ*IPk&6QK@wSyw_5>RF)L?L_Y0S@)_Wp@4D%| zuPnD4t)q=|rX)41;#hN=Az#Rjj^lr!)pi%@bW!jEtX-Gr_t>cCTb*sm*1p9?D^A1V zzQjA8h0zzvo9!!Ex4x0Xn=H#-#97d z+?jOYsyy%1sE7PR;W2cnR6nM>RH_@(KYXdAgZmtV&+GoTU-X|p;HPz$fbVhiT;c}1 zFc9%8gu_}N@!ui3{FsKv{1qAc$G?t8Ot9n4tGSM+)^3Op2heH%la1NQ5QF7A{shah z{Jj5rjjK5nIDl3Mp2#*;eXW7I%f+&C#qC{#4PEG~0b^R0r7`$xE;p?}=#j)pj*9LK z=u6}BmB-Q|!!>lF1A!W>ii`kCETAoyMCNJKg?<{)j)S-!#8UyS4B|!*hXdL?h~EM6 zcL7a7WcGlR#SjYMZ2)B~pt&Y8KLF`^pjMU?4Dx}w3*8LV6r@Q-bTga4_wRsya;l;; b$30z0g`SEf?nC3|pbk`#`K9T<|Iyeo delta 2520 zcmZWq3v5%@89vu`{JKtji9-mPn;LT)C5>&0b05BrAEm`JAggPjJl4mQJrvQdpovDM z9WEXXDG)|VW|wMP=OuL68X(X%?N+*Gjb9nJF}CaLq)F8<*x1TCDT_omK?HdJu@|k< zELrD&od5lu|Gu&N%I@R$=sUa!Y0_*oa`Rce7p=(e#qFDLrL_R`S z0&Qe9V3bTHvdNU6u4Nysi5jXuUW+-k}fhql%|DeKvKT=utZeFx-yJ@Nqpn$uwmb&}$b-js`` z4)HP^;~jM!2hn*}o6C!tLM)z6d1V|pxWXPMKI#ovYI@Lh7I!dpQ7jnCnm1*`wm_2Y zK@?X3nnd1Do7r*5p$FZ|;oc=vX+LeGelgBUmePS$E)KiNt%&^*8f2uxWrOV{7qP;# z;dQo^+NVqAv4Z!f;qTcRLwzNa!fY<}5jQL|%~cJcXaa80jF6x9@fMwtQWI6!p@*+X=EZ3!#le5G z_NvCG!_pnR((@HDQFT>g(LGZ#*v%`zlh;pU5mDvfUs!=Hj_@iFiy0ASe@fFy9!3Ma z98$$0LkJy4Z}ZCdlmq~s7nFS;@TRlHkugk;@ut(o0pcWr$-c)&ZDrU4Bl3zh zQQMH-Y|%XQ4bytxwv7+^I?296GSged;SN){2ri%n3l%$e2Il#WBWRpgH+hq(X)%#% zb-?&Z2jC~P1fakb{s?MxsQ!DyPrt{1-?rA#NghEP9I7Uq-&El#N8d47X-Y#~*uD#5 z4ein3Xus})tOKtxz35wxQZ-XhE%vb!eDtDY4i$EhOJy)H788w;j z%w?<)d2Dgsp~O+e%%%Se`c66M2^@5+98_{tlrEQJeg@8uB0^ArY*m8*#lBGtyskZp zmJ2uyj5a?#R(+yc7eZb`fiwzNtEK7=Xzo$eRI<8%i(neU_&JI;2{=VDlfxC2j8MDa zHO!O$vw2KVB~$r)HV?Dk$QvoWMraq}fTa7n;eFSjUR}G;tE=Ush8x9Eeb7LmUG{bX z^Yo44F8h!km;5r?FQ~-Kq&1fe3%P&Vh7PRoI%nQe!l@C|JQ`*tdkNzp(M~Z!| zcfv-6nFX9r-zxSahf|ZxO4d>#cuJ)z#@TY(Dx6|JY7cwt=1`YYGm*~5l2(AzqFIgl z(W^@mdnUPP*27bZ>rPXz=*(>QvW6X4m#-D%N1 z;e5XZ%Q5{f{58Uyb5s4km1EW2)%Qc!=bUlfdFM;vKiOO4wY(UvY~2uQ7tT9vdfZu% zlyV$)suh>_ zEeSa4N6|L*L@ZH&O#tJ?X+di~r?6(eP46x@qJ&^;EDcNXW?R%?MsNpT?XIQ}4(>H1 z9Ygx%2C2HFz(eatYFBs}Q?ue<&QG-;-g{5IhDtZx)J6>pMXdaK*u^x5M%o^AO}8Ch zsiCkQ%lEi6wh1wv%ET@Lh_6@fwRhXG{H#k3(_0X-G@z4o9%0f0}to`9D2Bdc4Uh{40zYfrmoAd#{ezKOx0MOcoHU;En zAV2lUo|Ayy3iMw+G7-qf5zq@BA`_wa0CfvHDS*dEfKhshPa^bFKpDIhQmTO6%vA-^ uU0y{dHB*St+dIT_8alT^TEEQ&B}JC1}L^e$Qm7 zru||0z4v+V^SvC!0nrI2nM5AI_I#aiw)@ZkfXkjaPUNIWTt$o^Mk&sC5LCeI9^Sb}4O&bpeu zCPuBOZtA|hn{H!#_%ZN9Mg?sZCz-RFKx?M_y-dKK@%&nQ3>;-pHhC@uSuYxf49kJt zDB~xX+Xl(7lSZLul~6~VL4l)6AZQS2lWDt~ z>bINpEBwq96DCah+Wu7|Mgj~FQ_KL-VIMI*%7jS2aV6-nO)*)$$2Ll$`c8l+j3$;dz=)p&iO%u4|h{YJ`8_;=3Qq;<-v-JhJJ$sOhGM7yeiykIM6r6yy~nWQC~ak zS@wO-{A9wSP@k#mce$y3ZHqK7lVM2bA_(R@v#?f0ZKa++TYjF&b-e5RYPK*@Ln1c{ zPE-(luPr}15s_opM0mOAFtDaOdW5{+w&I0s3CgruCgO276>b|bRs!gQT>A|x0ZMK+ zQp_k>Vw4OD;381?)wbeTLKf4hv?yDy#U?CrEbOK(Id5n`tgosp(8p`%wIjyQGRSv@ zz-+9>f84gl^{cj{6$N^PBYTr@Xd{X37fx+l_xuT$dIM^xo2sj%2uwHR^5H)42bW5| zoSt!0HRLIHo#X^e_3vO8%qQ26H*&8a_@sH%9BAZ5 zs{AAk9R z%Cp(j1N!;AMTTL%mq)SZdG*uKVgBceBt2 z2;66GDn!(fEvX z*-cehceNvi*VU;b0nFX zgHM7O=6CR@R+MVM-2`P7sIuNJMq_%4i1KfdZ;>t{7p8a#JQgX!Mrv^ z4#9Wyc}Y%3f=rNrL`aqOZVB?P?@(ovB*^9tWH>EcuvP3u@(;lIj%DyoCgsKJc|cP{ z94776IXDkVtU81{xZmj>(7OqQpz6^97YG-DI)@mfj>2eK6u(OF3GLu|bp+h&H2{Ux zy6Xi;Q(2jVLqsU3q!XoGYBKWrSUB9Y`de>wqPPOM9!k2)y!b5=)4{BYQ48Ma?A4j{ zcz2meUySLzc$hf;6d6zuEkg7NIj-o%NQbRQcReV4(PZx1)mfMpCnhB^A}8TID_^1o z$HLnDZFRP~2C9}q+wRLwwDES*8uk#5Jc|5`*7J90LJuMU^qytc(=l0GBw16kM8jIP zC_LGvsRS=Lv>wEVlpQOw$?E@KG9P{%eA|PB4}2aZ+2o~p{3>74WD*adHlva@M-6Zo*P=N2h+`K(JD}Zk=1B8c9q;Mx$Qxp z)X#+zEygub-lRA8+c4Xb3j%-kTwXMmm=tH>hzeI)*3=;08(PJ8UW?gEbxZz;?jZQ% zb53&|?WT~tTqtd&`}E%Lnj^EN-h-ga%SNiR&~|TrG?|t!TQ)TygCFej7EDNzcqJSc z)73QqG<9vQ@dE(VDfqf3f)r))gJa%2q}4)|hUzc8Dx?Of%}{yIo0CojsT|-3zxU?M zKv4z7KY4TZOHkH8dD@#3gW@w#yynFcL250OK1LieB+P@#zr5J>AZ3EmBd=N#WyJCq xogd_MsS@I>9Ha^$w6ZI2b}p+9H~YcruDnz-C0|blsRdXD)s+j?AoW}Ae*nt71zi9D delta 2636 zcmZuzeQZN1PBK_KTmf-H-$lobc>91fGdW;=JdN_mUW=8mrn)>O{8@p;4d{ z6Hss)+Ki7TID9-qyFjBr7qzLDA>_YCg;<=}!@=0D?Es-2LW~x+X|%KqN?XOd=NSf? z7Rkyv=XZX;d(XY+9y|KR)EftD=CyYrRE+8!pS1j=vENs5h`n~`*-~*KQ9-N-wGy|~ z#EnobX(%RM3vm^n6fGrIuS3PQIhpZG5p#Gt8jYkg#~SL}*CDNKPAn12J_)))txJAi zK#-xo)om#tj*8FIl~tR$bE~>FJCM+X}wg`tO;>k<|;@2Tw*apZVR$;BN8IDyQVNWOnt+~n%a{))r`@Xs#?Pp=V>`V&lp4A`K z&p{4DRwJ@E^%?zI2B;$vwJpU0aYQ0A#(wk{X-Ba{YC8LvnP44;JDQ#+)N8DAGLlXw z(+-~Qbr^N?cCiUIOd568-UUMj67`V@wvX&^3>m)7g($yaKH6wcuz7!@eT0Gv4FR-a$`T?0_C}}=eWQs`RJ}d zn|w@@Q^^7vDEfu9B6^uqPB6=1$I@mk~do&>wcX`$e(I~;lSt8-BEGOtl#EaxV*>?wA3v5a0r z|M*1ZDco}(IiFrFOj;;Nv*0cZq7AO1==el7b}51{95#b%x}^i;W7oXqd7@pBBqjlv82nRrR@LHPtFz-1<;GWcVrv zm_}?_QMYu5Yl-`P*S;#14seJ&+$u{n7LO#xFXG<*rhJ>d*WRt^MmxnrD{6a0w|pra zDNi?4(Z?}e8@Cn3as>u)CHP6 z-nTrzLe1he#$9^dqnwOoF5vb$*6>f!YV#0Qaht7{7!ZeS)>13)H_YT7s^K;n@l)GE zV!8Oet%dwK`spaJp$uwN>^Pbz~A*x%m5xpoV z@eG2&2+>b@Lh$1*17xFsr&ByRaUl;Jm!SI?Iw=erPs;>csJF?u5$zQej|GN>Z30kF z3GzqGVd0<@2@55ro^bqvIg^}DPvA?1tGk8wT7;&ApF4b-j_Q3?G;WwpC@UzYQFHU{(=yuzrbfssEyw3_FDJ7N;o-;AA&T+1$uF3DjGNrr ziPfbd~5?);_F8eo6rmG@@RZIbDpPbZ0p-$1N+2xn|NYM zyxwGJ8f=%FCX%Tco(_}4!pi~_16l*T1KToGW4l=f{dt6(65gTSq1>brYivfd;&Qvg zuIPZ~^c!^Op*lnz#ZTy)az#giN>GRbq{eo;9I}}XS$>fO)z$%lA#u!J)dTjc=u}4u zevZlP;|sXQ&}1Ahx<%{qcqwwh>l&BmkJ@|8IuZ~l4>mYUx=A=2P`KPt98E_ePYZm( zxIA05Bp&k?1hnOt6eej&Vv824q)Bo0s<{hY9#96A1)Z>uC&vo3&&3_9p808CCkUzV zs3_mC(5JaU5n8+rDX2z$om;d3kES%fIbud-RvZyVpGeKd3QVOyncfM-R<1uy{guVn_J42x4rO< z`atY&F)W%Aj5<@Vov=fn4Ly?|a|cjhwIUizOh&HY0WHQ_78PP0@yiyS2Dm%XpI19g z4Gd3%JzvzfGCfA$FH93xs(m}r8Xq@Nmxo^R6-ATj?0NIbMhN)PdY@`MlZjjm$0O-F z3qp>rH5NZYNS?xPV?0RHMn5{>Q-Ej1E`#0od@^u@bQ5;|;44U{f^-4$qd)lyrm-o* z=A^G+TL#-oY$tsMF>KDo=2ah&2-1tO^*Lx{v7iDwU;2p4LE4C|AAIsmBnv8k)%ua5 tOO}XS$p&c^hR80(m6^PIyxEVcx)iBoDtkE@q-Sv%)~-VA2I&vf{{iCI?PLG| diff --git a/6502/C64/cbmfiles/v4thblk-c16- b/6502/C64/cbmfiles/v4thblk-c16- index 17c9eed9d44cf06e168f9d0dc92994c4525f7903..34329c6ba1fe6613b64dc0cc495d3f987a349761 100644 GIT binary patch delta 2612 zcmZuy4{Q_X75^@^9Xo%T#y6f&pX1A!#IdS%Xk`_w62be!pLU8= znqr!E0m?$tH9LoP1tLP5bz))~%8I5+4D94G+!)*QT|$CXm?&)!Y=8j4(h0opofBo6 zX35ff@AuyCeeZqmdv|KzXZt>=F8XZ%p*&RJn%Hn__09Iue&%Zb3x#|cQA*fHnuu8~ z;Tl;^n(~OL5l`vg)GN38x1&5qff$(*tkKEwaUm@pwY}@xjtq{1SRy7Z8iz)jYCg>& zULX0owljxN^FN@=E0E{>`k?Mj>Uz;xw;G#A<4I8f``^KS%>~FMx5|Q{SmM5$e_UT_ znRP2=m7^1`9rk-T`Y<9H1-4b#n4#SA-(~!tXb&R`&)D?ctC$-lV#zCZa9S@rxr0pk zaK>*pA4Xdk$QetdCMAwOS8}AJ0Cg}f(;eMn%x)%kOh~7bX%|QT$YnMbnVAkIN}7%J zJxc~nBd>#zWhP(lrZ^)? z!lfL~$;Ti2k2StgzCTmmn>qb8)3+pZ`Ucad&z$~-uV~PB-)C}1?Q0;U$%DIzeGww& ze+Le}`^(vUcj9&6+#*(5{E(Q84 z*Ku`2_MmXaFnZIYiYHfHj5PtCS#MyBh~PhODAFDGXvX8o$e49ZnEGyo8immX{&E9T z8~4!ULC+VfgF21|`6~XK8C7#@<=%>OB|Rl>+)Y(;l)TO}tKaDEV6J=WDCiUI$|g*E z)X9WZrao%B;pOOb^8!s56~%NcdBM#xPnRj^7wPW}m9xw>m#R6aLyPI6WE};5(|8KP z=&#M{@yMtYn-cJC$)_OGrXGl@=uHR4ihZVo{DRZN8#C-%wqtF~;lXw1cL58Ss6LKe48E z&+`!TPkZafwj5|K-I!XN1OID4EyT@X$457#X3zUNi0gdTIWt&%1Q z!(%UC6swRfrYAYNjvBxx%tJ2IV=oLRfL2zy@_*4Xb^&c=o2^!Sl?lpLxt)YVoNs`r zpRfuzMX}W!L~pYSToJxgq(DLR9)Emo32~PH^ICKM0DHi4`UrcVwtSesw$^DGW>eRP zEbpv1L7cJluQ)xxz5{T-W!Ta;zz)~;9bx^~*q@=_@Qj@;+|ZIc7857%tR1!ac;4PZ z^zm2h%Zb}O;ixa{YYCZVGILs(8lG=*lo9>>R!40&&(dU+95g+PqU27BCI^gzraQQ! z*h@xe^7q*CD3is4x}B(}MLC*G!(IQ0y{R9eg1TMkESHOy1*|WyKF@9CLU`f;`I5tH zB%U0d$O3aM06oG`hC5+Cqv-ZsJfrZhGw(t-IMo8f6HekFw!o*H4}HS@Q?``(@-f?l zRZLE%NAZ2atJ$O!EMUQ<-%V;t+!_iUl3HKKcYK2s{TaIB_fvO!hieYjG$Qs{=)Q1#H zcHk7RqL=xP*14S9HUd+~WJGh?5$XtjY!CF?HYTV9g(yI(9XIvh&2Lm>lO(9)8^Q2z zzSvo@8|2qeL2EvKxJhZ@dLG(oGLDmW8irUuMK0N=8)E-pcxc~F0s_^;0iTjA37rFm zHLZE$X+ijJf^Y3ZY^Q<5+q@1zSbq!8pKz9y4Y5E3L9fec7n=-T9{#Fx=?`aHAx?vL zh<-;|KzE%Y3^=Q7)S}tePJ`K~+fimV788bmE=t~=M{diA77!yKcV)d8bliHl>j(U% z^_Fg-H7_kh#zbLMO5%BzzdxtkPnW4T*_^i3bUh6_@ufD{i?7&^GW&GkQD|m5+q$p` z9z-ANYRkWzj!D7-NtJ$)#$$a!=E<&BIrx;jQ|1F@OHnpi!~aVb)V+_+wW;BuXTRlg z_yxDwShWf#KgxiE(XRoA`LDX{F)e@9-$(2C&5g}O6@R?3W@Vu5U|YzfLV>o4wkz7s zHo`Ecg;k(HgG*sJI`lX7tRKFk-{0KDZ_jmHvW!Zcp(ymdoW z9q?Y!%D!`2!dYrq^ar}VXlZ-1#b)PdkazKKZLoKDwQsYGPItHOMSpDfjMiqMFWS}P z$+UFQ`uu7zgpkm#iHM?bDH<2jwRH#`3%pntLI^2S_;p3XG;I!{f3&MWtH-JxtKYRN zKn>IDu%Zd%q*Gx!2ZfL!kTZ!z1r{p;IeSDb=VF--!=F!b|)YI-KC9%~Gtw*snEG9_J3hUurc OjK07#SPj#kY5xN$kMmRj delta 2568 zcmZuyeQZ78?a=lt$D_nv$1#l8>wj;$^Jz=KdeDzr~-zSH#g?p4R>FOF|1;wmJoB+bDV z$t{({8LTFB`I4ESbJbt+*1zoDhVm_i>CiN93QvuX^QrWih5^?$q_Gr6<5A&}@%>=S zy7#4$J;A@#^hzZK-1C&7GRJvslUMyFa@iCqJ}rb&!hr33=Cq-}X(+TAj+NvDPf>Sr zr0<;O_SZMJj5rkGsdOUA$5~3R{b7~nlEbSWKvx`j*c^!^(mdGz3idDUfFvBbMhr#c z_Z^txUVT;ncMiE|V5zu$hj|{yA4XbQhHaJ2^f`s$j~Vxf>M){cSV@>kV#cfGC&~+v zT_>oU=x@r?^%AtSKiimjwaL`Ue0Y^7#+nb$v*fc)L&!l^t z=T)E7E3dN7Km0=O-tNTQ3mHFp!KoZeq)lRBZ~$UeUu@2%4JrFkA9uE~Ni(A zG1C}7{h&4v`B8)u8tIyZlOo=A{<+DkW+{-r!k>XwwsuzSt-M-(pxl9auofo1*TiJ38p4H8Scs>e+LK4*E;G zvi0%R!bBYjZnL-{{OFU`yzx*(h)(nPoFExo(=9C^4;k=%jSFn3SwGYIPMfstP^D4}IM@Si%DVArjE{$|Ah$_Bf}NpBSkXgMMt``%y7WoJ0o@7|CSD;aVn`d%&Ebs(uVD+>f3RI1Nu=Pw|HRxb z4U%5o3b(xKj5<{Z4d~ z&0S_du4xuxi(T@Ep~&^UXsL1)^kce7Q#vt~ir`a)v%7_p%|o@W7Q08?S#_wA!X2~= zZE)pICC5U7IO*PkqFy2E$T>A&FS&}0kI!M2l38|`-)6H+9Nw7w8JQ)3#}`Wl$svXz zZkq3#8DhHAt7dkgH(f>i^`tPfJh8Lkumlj~<9)k}Ddrzi>_S&u^6}VIdIDbn%Y+LO zxXmp-#Y$>9dZTXR1DD(wNhD`jDoh~P$1D^BTzA_8SeBu+mTyX+L5GN1*Gcju$q>KB z9KS&?aYGyJR&NLNpHHVni>e@b0^g~7rQVJ>87C15$Xd(oQt&>}A2n4m<8UJX=jcy^TTsPL%2CMB9MF((>T=uT&^Mz2-xsL*RmBpQ!8Ow2z-=0rpVh!&7}Q7-{~ zl|%!_yTCoW$;eD}=BN13SelOr3EaZsi*w1bv?lK-4c3Mxs-A*T_(B(q!>#7Cbe|eL ziVXDbu0CvnJ1~fR+_g=belf~v+9HN!2dLicFmEiF3As0Pn#fSWe6xq0++FB*m+-cjo;%B-OxZLnEKF|HbrdwU>(rb+etP(5qS>TE6Bs+@kx^u^)@iG1eOI35Vn^)&x9&XEK ztr}wYB13npvBAtzAiv7(-E8jnb^pp3xv{@{FA8=$BQ;s*YIojvA|*_io@xSv4^4C{ zL+LbsJsjgxHFXG`^*mSSLkP)}_-=&!6s7l}@4ItBtH-JttN-bif$FC=Vx`a{O(p%5 z6!}n@M>>T?85Y-gq_3y3tibY<9%&SdE3jzwNaB8K4VD-W<`6JpE>@oQNIvybdMv%@ zk*9e9SU%VIkk=!N^EU)PrNq#0J-Ih#vg&&_AKK^1O(v4UrwKo`gv&VQ$-%0hx~Tdu D2>a^c diff --git a/6502/C64/cbmfiles/v4thblk-c64 b/6502/C64/cbmfiles/v4thblk-c64 index 9ecbfc2b03d47da2ce1ae1a1f4217a65e072072d..493baa7dd6a2041895a86c394d6ed84361efe1d3 100644 GIT binary patch delta 2615 zcmZuyeN0=|6~B+z;E!iN<42YRTt3nV*ufuQ2=+66_!(mxb%=IL*GZMOA$2(2NWvtF z(l(CVC_;;1q+yRF-4akC-VZpPJtGp>X7mM+k>?uQv?E>Gj;PGT!cxqgpXs-TE z9yT@cxuG`?>*2m{EU)NrOw|XJZ-cgmf()M(A{k+z;q3aa%X=KOOOe*8@Q*YRG z8p1^P(NSEdsXbg6CX2uT-bWAMZd;gqxIRGyNe$R*?W1%0Uh5cvYI+x(pK@#1brkI5M_b$) z1^1e@LbXZ{m8Zx5O%GM1#~*OR)(QvfD41?+Kz<)N;1_5=-EjNsVKDBH&!n;@F?ZBq zG4cC5bD5#6hQT!V59@aFjzb8UE_y?J_V7MXUOa1mggTtEv~>34{Pb$)8Z)}-V!^K{a76QPRK4}0q^qjGY8L)g z_g9bKWcu~vx0rrI`F+mN=+NJ1(znm(5A7JmF6xJOK==@XhxKFnp_|N@VdxgqUfujt z@EJGQ=vDPM7tF-7m*EVaG92S>Hu|tRjn^NW2IgT`R@Wt#Fx**wYJyl`y!ajSs@aQ|c#!uLtKzSu zh53yIo%1%M5Qsnln^q4?{nrzUec&5b8cWP&XZ=*AMdd~mCeBOy;U*uVOK6u{s-I4! z=lxU^_pVSo8STQ(a}^G<>byHi zBnd#E*{!rJsSv*4mgH!Y#NT1i9^m0#byS3q{4?-!ixS?^l(5m=RkIOKz%ae)Wu~1d zDmJDWTw>?4XMMR5`tq8G+dLhzFF*W+2OxZmWvUllDs@A5wlmeyfYTO~gztvWL}a^oOmO^{FFrv3m1kPkg#t!!XK{szaIE zrIwsG_X|d~3Fg3^X10Qn_2?TL{1lS^$bG^zh9chA^wZZr@g4vVy)Dy*9F*si z#Znnz)?}|oh9FS+&a>4X;*YgfbQdL4z+JX|+&ogldaV zg47X;hRSz*d71PGl?Q_0hrYZyC`zFC6JOr`ER+kN{Dv7aDRC(ZH#V!5dfg7ZE}lD{sDP;v-;qbI<*I|C9cAs))xv03@Ko`k-OG#^Ng*b^m$vh>R`A%CLqh2lhyb zotvsIIv~L+r<%+DB&zwKr2|N6@pSkeXNWA!&T^^rWnJ3U0ruA7v3M-=%(yY-c)~NN?AP>~ilg*&eL(ts&}u12ap_Drl^L@9BzsBILu+u0<{k0Tsf+r5?cx3K z$L#sK2FGt~1(AhxBFV-5q+0QhGWoPEARPjCY$9lm&L`3wvi}9yH?0U+wF$Klip2{k zNFg+72AjJK2*lsIsz zGSU|6BV}57+=zmXw27oT5+_v3PPJvm4V(IaQxZpT!JP-hvq}l}e{sgDx{@Y6o~D0S6Oj5zB-g;7iE3|pzO=98mU2+(0=-a+;I-_V z^=AfpsoEwZfxeI1nrAO>5+&k>9Q9>g9pfjceV&_B#_$%oTgDwWEahbqnX$}4jvLJ2KMwwfshk+;%L5w+^iYG^YebP+dihM z1keY$4k{G@C3mVeY~w_+Dy_@`UL1wLW-pAzGh8Z};xdMNv9KW%i}=Y-Hfbrwe$Rel z(bXKZC+%(aw@So{s#0+-<(ge=oQ=(M@$g+ZiBDvw&4cEEGyq7JZm1rxGlClQN&Td$ zRF7kF4}-8*7=C6hwcsa>#Ccee1dgtUK|_eZUKsMfXy<>>3yjBLaQMkMVJhvwQ4!OJ zP}Hv(KB}UyN*w_63?Fs?j}T};04y?sNG-hgAyUM@!kg4CRf42o?zS+wd7S59vkeEN z51F&tiB;yTPV*UC)kteUW0I>^wQn4{f=y~i4^2E|-azoEc3eCBkQvtvuQF{lj_-hv z**6=#vbP-tGqLm?I9-=@A$F|qKOnb zci>o)O%VZU7vQ-H;0i%|4OxHS{JRiHIg2OJ2DaxyAN6s{15iBtDfQ?0q(DE7rxGk6_m#unfP&ChT<#ZYMuEMXWGh{1fA*(TkUR zkav{L+KLT`0r^Wn1h>LY9`8iF3NW`|c77o}=O?Rb3*9Kf#JVXz+|zGU2PltQpp7Py zOMWtfA9hJxC?n#sI@g?IDn6*H{YZ=^@I2n*dY5>Y@ZvXNSKYA2Wy)E6!;Qu-sM-&< zBvZr%cuAhfZm=d=rCf3I^R#i|uP|vh@Ut(`6$MECE_j)JjV{q`Fl|IpVZU^P`IUUr z*nw{v(cxL0DE&6>#ZjZk`*rpec$4avA`h8~n)Zx96B^24z5jHcOeB*&BAbh+SZ+jNc( zDPJe@$;|&RSwK1h#4RFp7$Dde|e(UcAvOoZWHhW=}B(jfnh#M6J*cnztmFxlI0y7jgE1Z+ku3 zMvI?B@^9HF(>TC+U(rSv?|A#bQ*U!rmxqKt(QG1>nKRhxks$~Qed2IB&E1X6b17Xl z0BgSX>L36>kc4+593u5aL16OKEajE@(Cq8y5YJ}e$0NhpmVjtnFeLgk_lyB{LeP#X6M(p(0yEX#x7hL0cT p7BeAI453>-;o?$Wea{jEe}pw9l9~I75V;N8Sn} Date: Thu, 8 Aug 2024 15:18:26 +0200 Subject: [PATCH 24/33] Add tasker.md, with related tweaks to RELEASE_NOTES.md and x16input-tsk.fth --- 6502/C64/RELEASE_NOTES.md | 2 +- 6502/C64/doc/tasker.md | 107 ++++++++++++++++++++++++++++++++++ 6502/C64/src/x16input-tsk.fth | 4 +- 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 6502/C64/doc/tasker.md diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 0a3c0c0..9933989 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -92,7 +92,7 @@ Changes affecting only the X16 VolksForth kernel: The downside is that the cooperative multitasker now can't run tasks during line input. The old tasker-compatible EXPECT is now available as separtate source - x16input-tsk.fth. For details on this see MISC_DOC.md. + x16input-tsk.fth. For details on this see [tasker.md](doc/tasker.md). * The clearing of the Kernal variables QtSw and Insrt after each char written to the console via CHROUT most likely has no real purpose. It was therefore removed from the X16 variant. diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md new file mode 100644 index 0000000..8438577 --- /dev/null +++ b/6502/C64/doc/tasker.md @@ -0,0 +1,107 @@ + +# The Multitasker + +VolksForth comes with a simple but powerful multitasker which allows the creation of printer poolers, clocks, counters and other simple background tasks. + +The main characteristic of this multitasker is that it uses cooperative, not +preemtive multitasking. This means that each task has to explicitly yield +execution control and access to I/O devices to make them available for other +tasks. However, each task can choose when this happens, esp. when to yield +execution control. Of course this must happen often enough for all tasks +to work well. Execution control is yielded via the word PAUSE. + +## Motivating Use Case + +Block 74 of [Disk 3](../disks/vforth4_3.fth) of the original +VolksForth/UltraForth distribution contains a print spooler that creates a task +`Printspool` to print a range of source blocks via `pthru` in the background +while the user can still interact with the system in the foreground. + +Caveat: The printer code hasn't yet been extracted into `.fth` files and may +need some adaption to current VolksForth versions and esp. to the X16. +In particular, source block printing doesn't make much sense with the X16 as of +now because block source compiling is currently only supported on the C64 and +C16/Plus4. + +## Task Demo + +A simpler task demo has been extracted from Disk 3's block 62 into +[src/taskdemo.fth](../src/taskdemo.fth). + +### On C64 or C16/Plus4 +``` +include tasker.fth +include taskdemo.fth +``` +will create a counter in the top left corner, counting down in the background +from 256 to 0. A fun way to see the time spent in the background task is to +type +``` +words +``` +while the counter is running: The speed of words listing will increase +noticably once the counter has run out. + +### On the X16 + +On the X16 things are slightly different: +``` +include tasker.fth +include taskdemo-x16.fth +``` +will create a counter in the top left corner, counting down in the background +from 4096 to 0. However, unlike on C64/C16/Plus4 this counter doesn't run while +the cursor is prompting for user input. Pressing repeated RETURNs or typing +`words` +will cause the counter to proceed, but it'll stop again on the input prompt. + +This is because since version 3.9.6 the line input in EXPECT uses BASIN, i.e. +delegates the input wait to the CBM screen editor which only returns to +Forth code after RETURN is pressed, which means that until then PAUSE isn't +called and execution control isn't yielded to other tasks. + +An alternative EXPECT is available in `x16input-tsk.fth` with the EXPECT +implementation of versions 3.9.5 and prior, similar to the C64/C16/Plus4 +EXPECT, which implements the input loop in Forth, with a PAUSE call. On the +X16 this has the disadvantages that it uses a Kernal variable that could change +between Kernal versions, and has a bug that often leaves inverted spaces after +backspace is pressed. This being said, +``` +include x16input-tsk.fth +``` +after starting `taskdemo-x16.fth` will cause the counter to start running even +while waiting for input. + +Typing `keyboard` will activate the original X16 EXPECT again and stop the +counter; typing `tasker-keyboard` will reactivate the task-switching EXPECT +and start the counter again. + +## Implementation + +As mentioned, +execution control is yielded via the word PAUSE. PAUSE saves the current state +of the currently active task and calls the task switcher. The state of a task +consists of the values of the Instruction Pointer (IP), +Return stack Pointer (RP) and Stack Pointer (SP). + +The task switcher consists of a closed loop +(see picture). Each task contains a machine code jump on +the next task ("jmp XXXX" in the picture), followed by +"jsr (wake) in the picture. At the address, on +which the jump command aims, are located +Instructions of the next task. If this task is stopped, +there is also a machine code jump to the next task +made. If, on the other hand, the task is active, +the (non-executive) BIT command has been replaced. The +follows the call of the wake-up procedure. This procedure invites +state of task (consisting of SP ‘a RP and IP) and sets the +Userpointer (UP), so that it shows this task. + + +## Glossary + +#### 's + +#### `'s ( Tadr -- usradr )` "tick-s" + +`'s ( Tadr -- usradr )` "tick-s" diff --git a/6502/C64/src/x16input-tsk.fth b/6502/C64/src/x16input-tsk.fth index 1f70885..7c904ad 100644 --- a/6502/C64/src/x16input-tsk.fth +++ b/6502/C64/src/x16input-tsk.fth @@ -29,7 +29,7 @@ Code curoff ( --) WHILE curon key curoff decode REPEAT 2drop space ; -Input: keyboard-tasker [ here input ! ] +Input: tasker-keyboard [ here input ! ] x16key x16key? c64decode c64expect ; -keyboard-tasker +tasker-keyboard From 3c9b171cad570c2fc1bcda230122f09210fc5206 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 8 Sep 2024 16:48:54 +0200 Subject: [PATCH 25/33] Add memory map diagrams to tasker.md --- 6502/C64/doc/tasker.md | 133 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index 8438577..6076510 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -78,7 +78,7 @@ and start the counter again. ## Implementation -As mentioned, +As mentioned, the multitasker uses cooperative multitasking where execution control is yielded via the word PAUSE. PAUSE saves the current state of the currently active task and calls the task switcher. The state of a task consists of the values of the Instruction Pointer (IP), @@ -97,6 +97,137 @@ follows the call of the wake-up procedure. This procedure invites state of task (consisting of SP ‘a RP and IP) and sets the Userpointer (UP), so that it shows this task. +#### Memory map of a task +``` +r0 @ -> ╔════════════════════╗ ───── + ║ return stack ║ ⋀ +rp@ -> ╠═════════════════|══╣ | + ║ ⋁ ║ + ║ free ║ rlen + ║ ⋀ ║ + ╠═════════════════|══╣ | + ║ user area ║ ⋁ +up@ -> ╠════════════════════╣ ───── + ║ heap ║ ⋀ +heap -> ╠════════════════════╣ | + ║ (stack underflow) ║ +s0 @ -> ╠════════════════════╣ + ║ stack ║ +sp@ -> ╠═════════════════|══╣ slen + ║ ⋁ ║ + ║ free ║ + ║ ⋀ ║ +here -> ╠═════════════════|══╣ | + ║ dictionary ║ ⋁ + ╚════════════════════╝ ───── +``` +There's a small unused area of 6 bytes between stack and heap to prevent heap +corruption in case of a small stack underrun. + +And typically, the dictionary of any task but the main task will be empty, as +that is where the outer interpreter is running which usally populates the +dictionary through definitions. However, `dp` is a user variable, so each task +has its own `here`, and if a task calls `allot`, the memory will be allocated +in its own dictionary. + +#### Tasks' user areas + +A task is characterized by the address of its user area. The tasker's round +robin loop consists of + + +``` + task 3: jmp XXXX => task is sleeping + + │ ... │ task3 + 6 + ├───────────┤ + │ jsr (wake │ task3 + 3 + ├───────────┤ + ┌> -> -> │ jmp XXXX │-> ┐ task3 + 0 + ⋀ └───────────┘ ⋁ + | ┌ <- <- <-- <- <- <┘ + ⋀ ⋁ + | | task 2: bit XXXX => task is active + ⋀ ⋁ + | | │ ... │ task2 + 6 + ⋀ ⋁ ├───────────┤ + | | │ jsr (wake │ task2 + 3 + ⋀ ⋁ ├───────────┤ + | └> │ bit XXXX │-> ┐ task2 + 0 + ⋀ └───────────┘ ⋁ + | ┌ <- <- <-- <- <- <┘ + ⋀ ⋁ + | | task 1: bit XXXX => task is active + ⋀ ⋁ + | | │ ... │ task1 + 6 + ⋀ ⋁ ├───────────┤ + | | │ jsr (wake │ task1 + 3 + ⋀ ⋁ ├───────────┤ + | └> │ bit XXXX │-> ┐ task1 + 0 + ⋀ └───────────┘ ⋁ + └ <- <- <- <- <-- <- <- <┘ +``` + +#### Overall memory map + +``` +0xFFFF -> ╔════════════════════╗ + ║ I/O and ROM ║ + ║ (starts at 0x8000, ║ + ║ 0x9F00, 0xD000 or ║ + ║ 0xFD00 depending ║ + ║ on platform) ║ + limit -> ╠════════════════════╣ + ║ buffers ║ +first @ -> ╠════════════════════╣ + ║ (unused) ║ + r0 @ -> ╠════════════════════╣ ───── + ║ return stack ║ ⋀ + rp@ -> ╠═════════════════|══╣ | + ║ ⋁ ║ + ║ free ║ rlen + ║ ⋀ ║ + ╠═════════════════|══╣ | + ║ user area ║ ⋁ + up@ -> ╠════════════════════╣ ───── + ║ heap ║ ⋀ + heap -> ╠════════════════════╣ | + ║ (stack underflow) ║ + s0 @ -> ╠════════════════════╣ + ║ stack ║ + sp@ -> ╠═════════════════|══╣ slen + ║ ⋁ ║ + ║ free ║ + ║ ⋀ ║ + here -> ╠═════════════════|══╣ + ║ ║ + ║ dictionary ║ + ║ ║ + ╠════════════════════╣ | + ║ boot area ║ ⋁ + origin -> ╠════════════════════╣ ───── + ║ 10 SYS(2064) ║ + ╠════════════════════╣ + ║ video memory ║ + ╠════════════════════╣ + ║ Kernal vars ║ + ║ 6502 ZP, stack ║ + ╚════════════════════╝ +``` + +#### 6502 zero page + +|Label | C64 | C16 | X16 | +|-------|-------|-------|-------| +|N |0x0029 |0x0029 |0x0067 | +|W |0x0021 |0x0021 |0x006F | +|IP |0x000E |0x000E |0x005C | +|NEXT |0x0009 |0x0009 |0x0057 | +|SP |0x0007 |0x0007 |0x0055 | +|Put A |0x0006 |0x0006 |0x0054 | +|UP |0x0004 |0x0004 |0x0052 | +|RP |0x0002 |0x0002 |0x0050 | + ## Glossary From 61e6d7814c815d636db904d525e0db371ba216a3 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 23 Sep 2024 22:22:49 +0200 Subject: [PATCH 26/33] Finish the Implementation section of tasker.md. --- 6502/C64/doc/tasker.md | 83 ++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index 6076510..77a4e18 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -1,10 +1,13 @@ # The Multitasker -VolksForth comes with a simple but powerful multitasker which allows the creation of printer poolers, clocks, counters and other simple background tasks. +VolksForth comes with a simple but powerful multitasker which allows the +creation of printer spoolers, clocks, counters and other simple background +tasks. -The main characteristic of this multitasker is that it uses cooperative, not -preemtive multitasking. This means that each task has to explicitly yield +The main characteristic of this multitasker is that it uses cooperative +multitasking instad of preemtive multitasking. +This means that each task has to explicitly yield execution control and access to I/O devices to make them available for other tasks. However, each task can choose when this happens, esp. when to yield execution control. Of course this must happen often enough for all tasks @@ -84,18 +87,58 @@ of the currently active task and calls the task switcher. The state of a task consists of the values of the Instruction Pointer (IP), Return stack Pointer (RP) and Stack Pointer (SP). -The task switcher consists of a closed loop -(see picture). Each task contains a machine code jump on -the next task ("jmp XXXX" in the picture), followed by -"jsr (wake) in the picture. At the address, on -which the jump command aims, are located -Instructions of the next task. If this task is stopped, -there is also a machine code jump to the next task -made. If, on the other hand, the task is active, -the (non-executive) BIT command has been replaced. The -follows the call of the wake-up procedure. This procedure invites -state of task (consisting of SP ‘a RP and IP) and sets the -Userpointer (UP), so that it shows this task. +The task switcher consists of a closed round-robin loop made up of the +first 6 bytes of the user area of each task. +See the picture [Tasks' user areas](#tasks-user-areas) in the +[Memory map](#memory-map) section. +Each task's user area starts with a machine code jump to +the next task's user area (`JMP XXXX` in the picture), followed by +`JSR wake`. `wake` is the task wake-up routine which sets UP to the task's +user area address calculated from return address left by the `jsr`, +restores SP from `user area + 6`and then restores RP and IP from the task's +data stack. The task's state is thereby restored, and the next iteration of +`NEXT` will call the task's next word, the one following the `PAUSE` that was +last invoked by the task. + +A trick is employed to switch a task between active and inactive. +The JMP XXXX instruction at the user area's start, as described above, marks +an inactive task. When the round-robin loop reaches the task, the JMP +immediately forwards execution to the next task; the `JSR wake` is never +reached. For an active task, the JMP opcode is replaced by a BIT opcode (0x2c), +so that, when the task is jumped to, execution does reach the `JMP wake` +instruction, and the task runs until its reaaches the next `PAUSE`, which takes +the address of the BIT instruction for an indirect jump to the next task. + +`SINGLETASK` changes `PAUSE` into a fast no-op so that no task change at all +takes place when `PAUSE` is called. This is the default of a VolksForth +system without loaded multitasker. `MULTITASK` enables the task-switching +behaviour of `PAUSE`. + +The system supports the multitasker by invoking `PAUSE` during many I/O +operations such as `KEY`, `TYPE` and `BLOCK`. In many situations this is +already sufficient for a task (e.g. the printer pooler) to run smoothly. +In other situations a suitable placement of `PAUSE` calls within foreground +or background task code may be useful. + +Tasks are created in the dictionary of the foreground or console task. Each +task has its own user area with a copy of the user variables. +The implementation of the system is, however, simplified through the +restriction that only the console task can interpret or compile input text. +There is e.g. only one vocabulary search order across the system; if one task +changes the search order, this affects all other tasks, too. But this is not +really disturbing, since only the console task should use the search order +anyway. + +Incidentally, it is possible to forget active tasks: `FORGET` removes all +tasks from the round-robin loop that are located in the dictionary range to +forget. This can still go wrong, though, if the forgotten task holds a +"Semaphor" (see below). Semaphores are not released during forgetting, +and the associated device will remain blocked. + +Finally, it should be mentioned that when invoking a task name, the address +of the task's user area will be placed on the stack. + +## Memory map #### Memory map of a task ``` @@ -124,8 +167,8 @@ here -> ╠═════════════════|══╣ | There's a small unused area of 6 bytes between stack and heap to prevent heap corruption in case of a small stack underrun. -And typically, the dictionary of any task but the main task will be empty, as -that is where the outer interpreter is running which usally populates the +And typically, the dictionary of any task but the console task will be empty, +as that is where the outer interpreter is running which usally populates the dictionary through definitions. However, `dp` is a user variable, so each task has its own `here`, and if a task calls `allot`, the memory will be allocated in its own dictionary. @@ -141,7 +184,7 @@ robin loop consists of │ ... │ task3 + 6 ├───────────┤ - │ jsr (wake │ task3 + 3 + │ jsr wake │ task3 + 3 ├───────────┤ ┌> -> -> │ jmp XXXX │-> ┐ task3 + 0 ⋀ └───────────┘ ⋁ @@ -151,7 +194,7 @@ robin loop consists of ⋀ ⋁ | | │ ... │ task2 + 6 ⋀ ⋁ ├───────────┤ - | | │ jsr (wake │ task2 + 3 + | | │ jsr wake │ task2 + 3 ⋀ ⋁ ├───────────┤ | └> │ bit XXXX │-> ┐ task2 + 0 ⋀ └───────────┘ ⋁ @@ -161,7 +204,7 @@ robin loop consists of ⋀ ⋁ | | │ ... │ task1 + 6 ⋀ ⋁ ├───────────┤ - | | │ jsr (wake │ task1 + 3 + | | │ jsr wake │ task1 + 3 ⋀ ⋁ ├───────────┤ | └> │ bit XXXX │-> ┐ task1 + 0 ⋀ └───────────┘ ⋁ From 49cf59a14c65284ab336b4433a13231c20aef7e4 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Mon, 23 Sep 2024 23:38:52 +0200 Subject: [PATCH 27/33] Add description of memory map to tasker.md --- 6502/C64/doc/tasker.md | 152 +++++++++++++++++++++++++---------------- 1 file changed, 92 insertions(+), 60 deletions(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index 77a4e18..c52fb4d 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -140,6 +140,98 @@ of the task's user area will be placed on the stack. ## Memory map +The memory used by VolksForth ranges from +`ORIGIN` to `LIMIT` . Below `ORIGIN` are the +Kernal variables, the screen memory and a single line of +BASIC with a `SYS` command that starts VolksForth. +Beyond `LIMIT` are I/O ports and the Kernal ROM. + +Just below `LIMIT` the block buffers are stored; each with a size +of 1 Kbyte tall. When the system starts, as many buffers are +allocated as fit between `R0` and `LIMIT`. + +The rest of the system, located between `ORIGIN` and `RO`, consists of +two areas. The upper area contains the return stack (growing downwards, +starting at `RO @`) and the user area (growing upwards, starting at `UP@`). + +The dictionary and the data stack plus the heap occupy the other area. +Heap and data stack grow downwards, the heap from `UP@` and the data stack +from `S0 @`. +When the heap grows, the data stack is automatically moved downwards. +New words are stored in the dictionary, which is the fastest-growing +part of the system during compilation. Therefore the system automatically +checks that dictionary and data stack don't collide. + +The Bootarea finally contains the initial values of the user +variables, which is copied during the cold start from there into the +console task's user area. + +#### Overall memory map + +``` +0xFFFF -> ╔════════════════════╗ + ║ I/O and ROM ║ + ║ (starts at 0x8000, ║ + ║ 0x9F00, 0xD000 or ║ + ║ 0xFD00 depending ║ + ║ on platform) ║ + limit -> ╠════════════════════╣ + ║ buffers ║ +first @ -> ╠════════════════════╣ + ║ (unused) ║ + r0 @ -> ╠════════════════════╣ ───── + ║ return stack ║ ⋀ + rp@ -> ╠═════════════════|══╣ | + ║ ⋁ ║ + ║ free ║ rlen + ║ ⋀ ║ + ╠═════════════════|══╣ | + ║ user area ║ ⋁ + up@ -> ╠════════════════════╣ ───── + ║ heap ║ ⋀ + heap -> ╠════════════════════╣ | + ║ (stack underflow) ║ + s0 @ -> ╠════════════════════╣ + ║ stack ║ + sp@ -> ╠═════════════════|══╣ slen + ║ ⋁ ║ + ║ free ║ + ║ ⋀ ║ + here -> ╠═════════════════|══╣ + ║ ║ + ║ dictionary ║ + ║ ║ + ╠════════════════════╣ | + ║ boot area ║ ⋁ + origin -> ╠════════════════════╣ ───── + ║ 10 SYS (2064) ║ SYS (4112) on the C16 + ╠════════════════════╣ + ║ video memory ║ + ╠════════════════════╣ + ║ Kernal vars ║ + ║ 6502 ZP, stack ║ + ╚════════════════════╝ +``` + +#### 6502 zero page + +The system also uses zero page memory, with the inner interpreter `NEXT` +and the stack pointers `RP` and `SP`, among others. + + +|Label | C64 | C16 | X16 | +|-------|-------|-------|-------| +|N |0x0029 |0x0029 |0x0067 | +|W |0x0021 |0x0021 |0x006F | +|IP |0x000E |0x000E |0x005C | +|NEXT |0x0009 |0x0009 |0x0057 | +|SP |0x0007 |0x0007 |0x0055 | +|Put A |0x0006 |0x0006 |0x0054 | +|UP |0x0004 |0x0004 |0x0052 | +|RP |0x0002 |0x0002 |0x0050 | + + + #### Memory map of a task ``` r0 @ -> ╔════════════════════╗ ───── @@ -211,66 +303,6 @@ robin loop consists of └ <- <- <- <- <-- <- <- <┘ ``` -#### Overall memory map - -``` -0xFFFF -> ╔════════════════════╗ - ║ I/O and ROM ║ - ║ (starts at 0x8000, ║ - ║ 0x9F00, 0xD000 or ║ - ║ 0xFD00 depending ║ - ║ on platform) ║ - limit -> ╠════════════════════╣ - ║ buffers ║ -first @ -> ╠════════════════════╣ - ║ (unused) ║ - r0 @ -> ╠════════════════════╣ ───── - ║ return stack ║ ⋀ - rp@ -> ╠═════════════════|══╣ | - ║ ⋁ ║ - ║ free ║ rlen - ║ ⋀ ║ - ╠═════════════════|══╣ | - ║ user area ║ ⋁ - up@ -> ╠════════════════════╣ ───── - ║ heap ║ ⋀ - heap -> ╠════════════════════╣ | - ║ (stack underflow) ║ - s0 @ -> ╠════════════════════╣ - ║ stack ║ - sp@ -> ╠═════════════════|══╣ slen - ║ ⋁ ║ - ║ free ║ - ║ ⋀ ║ - here -> ╠═════════════════|══╣ - ║ ║ - ║ dictionary ║ - ║ ║ - ╠════════════════════╣ | - ║ boot area ║ ⋁ - origin -> ╠════════════════════╣ ───── - ║ 10 SYS(2064) ║ - ╠════════════════════╣ - ║ video memory ║ - ╠════════════════════╣ - ║ Kernal vars ║ - ║ 6502 ZP, stack ║ - ╚════════════════════╝ -``` - -#### 6502 zero page - -|Label | C64 | C16 | X16 | -|-------|-------|-------|-------| -|N |0x0029 |0x0029 |0x0067 | -|W |0x0021 |0x0021 |0x006F | -|IP |0x000E |0x000E |0x005C | -|NEXT |0x0009 |0x0009 |0x0057 | -|SP |0x0007 |0x0007 |0x0055 | -|Put A |0x0006 |0x0006 |0x0054 | -|UP |0x0004 |0x0004 |0x0052 | -|RP |0x0002 |0x0002 |0x0050 | - ## Glossary From 56ff1e9239fb6038bcadf6ed5dcec9f0dc05ab11 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 24 Sep 2024 21:18:19 +0200 Subject: [PATCH 28/33] Add the Semaphore section of tasker.md --- 6502/C64/doc/tasker.md | 55 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index c52fb4d..cf56099 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -261,8 +261,8 @@ corruption in case of a small stack underrun. And typically, the dictionary of any task but the console task will be empty, as that is where the outer interpreter is running which usally populates the -dictionary through definitions. However, `dp` is a user variable, so each task -has its own `here`, and if a task calls `allot`, the memory will be allocated +dictionary through definitions. However, `DP` is a user variable, so each task +has its own `HERE`, and if a task calls `ALLOT`, the memory will be allocated in its own dictionary. #### Tasks' user areas @@ -303,6 +303,57 @@ robin loop consists of └ <- <- <- <- <-- <- <- <┘ ``` +## Semaphores and LOCK + +A problem that has not yet been mentioned: what happens when two tasks want to +print or access the disk drive simultaneously? Obviously, I/O devices may +at any time be used by only one task. This is achieved using Semaphores: + +``` + Create disp 0, + : newtype disp lock type disp unlock; +``` + +This has the following effect: + +If two tasks call `NEWTYPE` at the same time, still only task at a time will +get to run `TYPE`, regardless of how many `PAUSE` are included in `TYPE`. +The phrase `DISP LOCK` will set up a barrier after the first task that performs +it, like switching a traffic light to red, and lets no other task pass. +The other task is held until the first task switches the traffic light to +green again via `DISP UNLOCK`. Then one (!) other task can pass the traffic +light, switching it red again, and so on. + +By the way, the task that switched the traffic lights to red will not be +stopped by another `DISP LOCK` but will be let through. This is +necessary since `TYPE` could also contain a `DISP LOCK`. +(It doesn't in the above example, but it is conceivable.) + +The implementation looks like this: +(Remember that every task is uniquely identifiable by the its user area +address.) + +`DISP` is the so-called Semaphore; it must have the initial value 0. + +`LOCK` looks at the Semaphore: +If it is zero, then the currently asctive task (i.e. its user area address) +is written to the semaphore, and the task may continue on its way. +If the value of the semaphore is the active task, then it may continue, too. +But if the value of the semaphore deviates from the active task's user area +address, then another task is active behind the traffic light, and the task +must `PAUSE` until the light turns green again, i.e. until the semaphore is +zero. + +`UNLOCK` has nothing more to do than to set the value of the semaphore back to +zero. + +`BLOCK` and `BUFFER` are, by the way, secured in this way for use by several +tasks: +only one task can request the loading of a blocks from the diskette at any given +time. +Whether `TYPE`, `EMIT`, etc. are also secured depends on their implementation - +`TYPE`, `EMIT`, etc are essentially deferred words with different possible +implementations. ## Glossary From a60b4e0f3be8668c71c5a05aa916314e916c3efc Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Tue, 24 Sep 2024 22:34:39 +0200 Subject: [PATCH 29/33] Add final remarks section to tasker.md --- 6502/C64/doc/tasker.md | 78 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index cf56099..68100b5 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -349,12 +349,88 @@ zero. `BLOCK` and `BUFFER` are, by the way, secured in this way for use by several tasks: -only one task can request the loading of a blocks from the diskette at any given +only one task can request the loading of a block from the diskette at any given time. Whether `TYPE`, `EMIT`, etc. are also secured depends on their implementation - `TYPE`, `EMIT`, etc are essentially deferred words with different possible implementations. +## Remarks regarding BLOCK and a few other things + +As can be seen from the glossary, only the address of the block buffer last +requested with `BLOCK` or `BUFFER` is valid, i.e. older blocks, depending on +the number of block buffers, may already be stored on the disk again. To be +on the safe side, it is useful to imagine that only one block buffer exists +in the entire system. + +Now any task can run `BLOCK` and thus remove blocks from "under the feet" +of other tasks. +Therefore, one should not continue to use the address of a block after calling +a word that performs `PAUSE` performs. One should rather request the block +using `BLOCK` again. An example: + +``` + : .line ( block -- ) + block c/l bounds DO I c@ emit LOOP ; +``` + +is WRONG because after `EMIT` the address range the address range that the +loop index steps through may no longer be correct. + +``` + : .line ( block -- ) + c/1 0 DO dup block I + c@ emit LOOP drop ; +``` + +is CORRECT because it only keeps the number of the block, not the address of +its buffer. + +``` + : .line ( block -- ) block c/l type ; +``` +is WRONG since `TYPE` may call `EMIT` repeatedly, and thus the address +delivered by `BLOCK` may become invalid during `TYPE`. + +``` + : >type ( adr len -- ) >r pad r@ cmove pad r> type ; + : .line -( block -—) block c/l >type ; +``` +is CORRECT because `PAD` is different for each task. + +In version 3.8 the word LIST was changed in such a way that it can be stopped +and terminated by pressing buttons, similar to `INDEX`. This entails certain +problems when this word is used in a task (e.g. a printer pooler). In this +case, both the console task and the tasks containing the word LIST attempt +to read inputs from the keyboard. If you type a text, the individual +characters are randomly distributed to the two tasks. Therefore, each task +(of course with the exception of the console task) should define its input +vector so that you cannot receive inputs. + +The following code snippet contains an input vector that does not allow inputs. +See section Vectors in chapter Vectors and Deferred Words about defining +input or output vectors using `Input:` or `Output:`. +TODO: Add link once chapter Vectors and Deferred Words is translated. + +``` + : halt ." Task gestoppt!” stop ; \ completely stops the task + + Input: nul-Input halt false drop halt ; + \ instead of: key key? decode expect +``` + +Another implementation of `KEY` for background tasks could be one that always +return a constant harmless character. Whether that works and with which +character must of course be decided for each application. +With `EXPECT` it is hard to envision a better solution, since `EXPECT` is +intended to change the `SPAN` variable which is a global variable, not a +per-task user variable. + +One more note: A background task should not perform `ABORT"` or a similar word. +If it did, the task would become like the console task, resulting in a system +crash. Even if this possibility of error is intercepted and the task is +stopped, the problem remains that semaphores can still be "locked" on this task +and thus the use of certain parts of the forth remains blocked! + ## Glossary #### 's From 170cb3c056b9ef1b6d66e8d07d9e8f85066f03e2 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 29 Sep 2024 19:02:27 +0200 Subject: [PATCH 30/33] Add the Multitask words glossary to tasker.md --- 6502/C64/doc/tasker.md | 155 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 152 insertions(+), 3 deletions(-) diff --git a/6502/C64/doc/tasker.md b/6502/C64/doc/tasker.md index 68100b5..bfc0ea0 100644 --- a/6502/C64/doc/tasker.md +++ b/6502/C64/doc/tasker.md @@ -109,7 +109,7 @@ so that, when the task is jumped to, execution does reach the `JMP wake` instruction, and the task runs until its reaaches the next `PAUSE`, which takes the address of the BIT instruction for an indirect jump to the next task. -`SINGLETASK` changes `PAUSE` into a fast no-op so that no task change at all +`SINGLETASK` changes `PAUSE` into a `NOOP` so that no task change at all takes place when `PAUSE` is called. This is the default of a VolksForth system without loaded multitasker. `MULTITASK` enables the task-switching behaviour of `PAUSE`. @@ -433,8 +433,157 @@ and thus the use of certain parts of the forth remains blocked! ## Glossary -#### 's +Multitasker words #### `'s ( Tadr -- usradr )` "tick-s" -`'s ( Tadr -- usradr )` "tick-s" +is used in the form: + +``` + ’s ... +``` + +reads the name of a user variable `` and leaves the address `usradr` of +this user variable in the task marked by `Tadr`. + +Tadr is usually generated by calling ``. An error condition exists +if `` is not the name of a user variable. +See also `USER` and `TASK`. `’S` is intended for changing the content of user +variables of a task by another task. + +#### `activate ( Tadr -- )` + +activates the task marked by `Tadr` and wakes it up. `Tadr` is usually +generated by calling a task name. +See also `SLEEP` , `STOP` , `PASS` , `PAUSE` , `UP@` , `UP` and `WAKE`. + +#### `lock ( semadr -- )` + +The semaphore with address `semadr` is blocked by the task that calls `LOCK`. +To do this, `LOCK` checks the contents of `semadr`. If the content indicates +that another task has blocked the semaphore, `PAUSE` will be executed until +the semaphore is released. When the semaphore is released, `LOCK` writes the +identifier of the task performing `LOCK` into the semaphore, thus blocking it +for all other tasks. So the code between `semadr LOCK` and `semadr UNLOCK` +can always be executed byonly one task at a time. See also `UNLOCK` and the +description of the [tasker](tasker.md#semaphores-and-lock). + +#### `multitask ( -- )` + +switches multitasking on. After `MULTITASK` has been executed, the word `PAUSE` +is no longer a `NOOP`. Instead, it yields control of the CPU to another task. + +#### `pass (n0 ... nr-1 Tadr r -- )` + +activates the task marked by `Tadr` and wakes it up. `Tadr` is usually +generated by calling a task name. `r` indicates the number of parameters +`nO` to `nr-1?` which are transferred from the stack of the task calling `PASS` +to the stack of the task identified by `Tadr`. The parameters `nO` to `nr-1` +are available to the task identified by `Tadr` for further use. +See also `STOP`, `ACTIVATE`, `PAUSE`, `UP@` and `UP!`. + +#### `pause ( -- )` + +a `NOOP`-word when single task mode is active. However, when multitasking is +activated, the task that performs `PAUSE` will yield control of the CPU to +another task. If there is only one task, or if all other tasks are asleep, +control will be returned to the task performin `PAUSE`. If at least one other +task is active, it will take overcontrol of the CPU, and will only yield it +again to another task when it calls `PAUSE` or `STOP`. Since the tasks are +linked to each other in a closed loop, the task that first performed `PAUSE` +will eventually gain control agian. An error condition exists if a task +never calls `PAUSE` or `STOP`. See also `STOP`, `MULTITASK` and `SINGLETASK`. + +#### `rendezvous ( semadr -- )` + +releases the semaphore with the address `semadr` and calls `PAUSE` in order to +allow other tasks to access the device which has been protected by this +semaphore. Then, `LOCK` is called in order to regain control of the device. +See als `LOCK` and `UNLOCK`. + +#### `singletask ( -- )` + +turns off multitasking. The word `PAUSE` is a `NOOP` word after `SINGLETASK` +has been run. An error condition exists if a background task calls `SINGLETASK` +without a subsequent `MULTITASK`, since in such a case the foreground or +console task would never regain control of the CPU. +See also `UP@` and `UP!` + +#### `sleep ( Tadr -- )` + +puts the task characterized by `Tadr` to sleep. `Tadr` is usually generated by +calling a task name. `SLEEP` has the same effect as the execution of `STOP` +by the task itself. The difference is that `STOP` is usually an end point in +processing. SLEEP will hit the task at an unforeseeable time so that the +ongoing work of the task is interrupted. See also `WAKE`. + +#### `stop ( -- )` + +causes the task calling `STOP` to sleep. The content of `IP` (instruction +pointer), `RP` (return stack pointer) and `SP` (stack pointer) are saved, +then control of the CPU is yielded to the next task. These actions are also +carried out by `PAUSE` (see there). The difference to `PAUSE` is that `STOP` +leaves the task inactive, while `PAUSE` leaves it active. +See also `ACTIVATE`, `PASS`, `WAKE`, `SLEEP`, `UP@` and `UP!`. + +#### `Task ( rlen slen -- )` + +is used in the form: + +``` +rlen slen Task +``` + +`Task` is a defining word that sets up a task. A task is the work area for +another program that is to run simultaneously with the already running +programs. The task is named `cccc`, has a stack of size `slen` bytes and a +return stack of `rlen` bytes. The task's own dictionary (including `PAD`) +is located in the stack area, growing upwards while the stack grows downwards. +In the return stack area contains the task's user area (growing upwards) +and the return stack (growing downwards). +A task is thus a reduced image of the entire VolksForth system. +See the [task](tasker.md#memory-map-of-a-task) and +[system memory map](tasker.md#overall-memory-map). + +Calling `cccc`, the task's name, as a word in any task leaves the same address +on the stack that the task `cccc` itself generates when calling `UP@`. +This address functions as the ID of the task and used by `’S`, `ACTIVATE`, +`LOCK`, `PASS`, `SLEEP`, `TASK` and `WAKE`. + +#### `tasks ( -- )` + +lists the names of all existing tasks and shows whether they are +asleep or active. + +#### `unlock ( semadr -- )` + +releases the semaphore at address `semadr` for all tasks. If the semaphore is +owned by another task, then `UNLOCK` will wait, doing `PAUSE`, for the +until the semaphore is released. See also `LOCK` and the +description of the [tasker](tasker.md#semaphores-and-lock). + +#### `up@ ( -- Tadr )` "u-p-fetch" + +provides the address `Tadr` of the first byte of the user rarea of the +task calling `UP@`. `Tadr` is the address that characterizes each task, +the ID of the task. +See also `’S` , `ACTIVATE`, `LOCK`, `PASS`, `SLEEP`, `TASK` and `WAKE`. + +In the user area, variables and other data structures are stored of which +each task must have its own instance. See also `UP!` + +#### `up! ( adr -- )` "u-p-store" + +sets the `UP` (user pointer) to point to `adr`. See also `UP@`. + +Note: This is potentially dangerous. Better know what you're doing when +using this. + +#### `wake ( Tadr -- )` + +wakes up the task identified by `Tadr`. `Tadr` is usually generated by +calling a task name. The specified task will continue to execute its code +where it was stopped by `SLEEP` - or where it ended itself by `STOP`, +thus be careful!. + +See also `SLEEP`, `STOP`, `ACTIVATE` and `PASS`. From c9f5f8406c10cbfbf4e112196606a300d83fc680 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 29 Sep 2024 19:16:46 +0200 Subject: [PATCH 31/33] Update 6502/C64/RELEASE_NOTES.md --- 6502/C64/RELEASE_NOTES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index 9933989..d0dc762 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -20,6 +20,11 @@ The latest release zip file `volksforth-6502-c64-release.zip` contains * `v4th-x16e` - Commander X16 kernel with added X16Edit and DOS commands +* `doc/` - documentation, the beginning of an English translation + of the original German VolksForth/UltraForth manual for C64 and C16, + with some X16 specifics added. + * [`tasker.md`](doc/tasker.md) - the chapter about the multitasker + * `src/` - sources * `v4th*.fth` - the binaries' main files * `vf-*.fth` - sources from which VolksForth @@ -80,6 +85,11 @@ when the X16 Kernal changes. A secondary topic if this release is more bundled Forth sources, which are now also better described (see Release content above). +And a third topic is the beginning of an English translation of the +original German VolksForth/UltraForth manual for C64 and C16. +Since this release affects some multitasking behaviour, the translation +was started with the [chapter about the multitasker](doc/tasker.md). + Changes affecting only the X16 VolksForth kernel: * Clearing the IOStatus is now possible through the ExtApi call ($FEAB, thanks From 05a9c6897bdc0440fb7892f623f17dd77d932813 Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Sun, 29 Sep 2024 21:10:08 +0200 Subject: [PATCH 32/33] Update VERSIONS.ORG --- VERSIONS.ORG | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/VERSIONS.ORG b/VERSIONS.ORG index 8e59731..d465ba4 100644 --- a/VERSIONS.ORG +++ b/VERSIONS.ORG @@ -2,6 +2,25 @@ * C64/C16/Plus4/CommanderX16 +See also [[6502/C64/RELEASE_NOTES.md]] + +*3.9.6* + + * Removes all known dependencies of the X16 VolksForth kernel on + undocumented X16 Kernal variables and thus (hopefully) on specific + X16 ROM versions. This has some implications on multitasking behaviour + while waiting for console input. + * Adds more bundled Forth sources from the original disks. + * Starts an English translation of the original German manual with a + translation of the chapter on the multitasker. + +*3.9.5* + + * X16 version adapted to the X16 ROM version R46. It also runs with + the R47 ROM. + * Adds a second X16 binary with a word (XED) use the ROM-based editor + X16Edit, and with some DOS and file support (DIR, CAT, DOS). + *3.9.4* * X16 version adapted to Kernal/Emulator version R41 From 92a4efeef19922de7f60b2fabc8e92fb5dcce22a Mon Sep 17 00:00:00 2001 From: Philip Zembrod Date: Fri, 4 Oct 2024 21:17:09 +0200 Subject: [PATCH 33/33] Remove "in preparation" from "6502-C64 3.9.6" in RELEASE_NOTES.md --- 6502/C64/RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/6502/C64/RELEASE_NOTES.md b/6502/C64/RELEASE_NOTES.md index d0dc762..ffa5352 100644 --- a/6502/C64/RELEASE_NOTES.md +++ b/6502/C64/RELEASE_NOTES.md @@ -71,7 +71,7 @@ The following version descriptions are only valid for VolksForth 6502-C64 releases. As of now (June 2024), the different VolksForth platforms (6502, 68k, 8080, 8086) don't have shared code or shared versioning. -### 6502-C64 3.9.6 - in preparation +### 6502-C64 3.9.6 Main topic of this release is the removal of all usages of Kernal variable uses esp. in the X16 VolksForth kernel. Because the addresses of Kernal