Programming the 80’s way #3
Introduction to Integers.
One of my favorite tasks using a small system like our ZX Spectrum is to overcome limitations imposed on integers and floating-point numbers.
In ZX Basic, integers have a width of 16 bits (plus sign) allowing you to manipulate numbers between -65.535 and 65.535, and once out of this range, you’re venturing into floating point numbers wilderness.
In Forth, unless you can rely on some floating-point library, all math is integer math, and usually Z80 implementations uses 16-bits single-precision integers and 32-bits double-precision integers, so expanding the range to a wider interval of integers that lie between -2.147.483.648 and 2.147.483.647.
The lack of floating-point and engineering notation is not so bad because the trade-off is a faster speed and great simplicity, by defining suitable fine-grained unit-of-measure like “millimeters” instead of “thousandth of meter”, for instance.
On the other hand, irrational constant numbers, like “Greek-Pi”, that have an infinite number of decimal places, cannot be exactly represented neither using floating-points nor double precision integers, and in Forth, it is very common to exploit irrational constant numbers via Rational Approximation.
The concept behind this useful technique is that any irrational number can be represented by a rational approximation. For example, 355/113 is a very good approximation of “pi” with an error of less than one part in a million.
For instance, the formula to calculate the circumference of a circle can be coded directly as
: CIRCUMFERENCE ( n1 -- n2 ) 2* 355 113 */ ;
in particular, the definition */ is the typical scaling operator that takes a single-precision integer multiplies it by a number (355 in our case) and divides it by another (113 in our case) but ensuring a double-precision intermediate result to avoid loss of precision.
Triple-precision integers
My v-Forth implementation provides a definition UM* to multiply two single-precision numbers and get a double-precision number, and a definition UM/MOD to divide a double-precision number and get two single-precision numbers quotient and reminder.
It seems there is little way to use some “triple-precision” [1] integer i.e. 48-bits of precision, but I’ll show how I had the chance to code an improved definition of */ that operates on a double-precision integer passing through a “triple-precision” integer so we can improve our previous version of CIRCUMFERENCE to cope with “double-precision” integer and use a “triple-precision” intermediate result using this new definition M*/
: CIRCUMFERENCE ( d1 -- d2 ) 2DUP D+ \ double the radius 355 113 M*/ ;
Here below, I expose the implementation of such M*/ using the math definitions already available UM* and UM/MOD.
In the following definition explanation, each symbol represents a single-precision unsigned integer, that is a number between 0 and 65535, so we can think of it as we were using some “65536-based” math.
- we can split the double-precision integer d into its two components dH and dL and then multiply them by m separately getting two double-precision integer a and b, we split in aH, aL and bH, bL.
- we have to add aH part to b obtaining c, we split in cH, cL. This way we now have three single-precision integers cH, cL, aL, that represents our triple-precision intermediate value integer.
- We can perform one first division, dividing c by n obtaining quotient q1 and reminder r1.
- We compose r1 and aL that is the double-precision number we now divide by n to obtain quotient q2, while remainder r2 is discarded for our purposes.
\ dH dL x \ m = \ ---------- \ aH aL \ bH bL \ ---------- \ cH cL aL : n = q1 q2 \ r1 aL \ : M*/ ( d m n -- d2 ) 2dup xor 3 pick xor >R \ keep track of final sign abs >R abs >R swap R@ UM* rot R> UM* \ 1. multiply by m and get a and b rot 0 D+ \ 2. obtain c R@ UM/MOD \ 3. divide n into c giving quotient and reminder rot rot R> UM/MOD \ 4. divide n into the composition r1+aL nip swap \ discard reminder r2 and reorder the two partial-quotients R> D+- \ determine final sign. ;
For example:
500000. CIRCUMFERENCE D.
prints
3141592
In conclusion, using just some Arithmetics we overcame the native 32-bit vForth limitation.
[1] Forth Application Techniques – Elizabeth D. Rather and the technical staff of FORTH Inc. – 2000 Forth Inc.
Hi good afternoon.
next vforth :
why are only about 4800 bytes free when loading the image ?
——————————–
NEEDS OPEN<
NEEDS J
needs layer11
layer11
: DATEN-LOAD< ( — )
OPEN< >R
6912 0 DO
16384 6912
J
F_READ
DROP
LOOP
R> F_CLOSE 42 ?ERROR ;
DATEN-LOAD< ../../fth/bild.scr
: los
;
——————————
thanks, the new version (27.08.) is now running without any flaws.
there are no defects with me.
my english skills are not good.
to switch off the blinking cursor you have to explain to me.
thanks
greeting
Hi Peter
If I understand what you wish to do, you don’t need a DO-LOOP structure to display a .SCR file.
Let me show my example to load, for instance, /DOT/KEYBOARD.SCR keymap file.
NEEDS LAYER11
DECIMAL
: WAIT-BREAK ( -- ) \ wait for [BREAK] while cursor is hidden
BEGIN ?TERMINAL UNTIL
;
: SHOW-SCR
LAYER11
OPEN< \ this leaves file-handle number on TOS
DUP \ for later f_close
16384 6912 \ address and length to be read
ROT \ bring file-handle on TOS
F_READ DROP DROP \ ingore status and actual byte read
F_CLOSE DROP \ ignore status
;
SHOW-SCR /DOT/KEYBOARD.SCR WAIT-BREAK
(The above code is copied by hand while I was testing it on CSpect emulator, it should work, but beware any typo)
( output )
Regards
_M.
hello tanks for : show-scr.
is wonderful.
how do I get this under : wait-break ?
—————————
: starte
case
119 of oben endof
101 of rechts endof
113 of links endof
115 of unten endof
endcase ;
: los
SPRITE 0 SPRITE-UPDATE
begin
key
dup 13 – while
starte
repeat drop ;
————————
thanks
greeting
Peter,
the problem is KEY that “stops execution, shows a flashing cursor and waits for a keypress”.
To avoid such a stop, you have to scan the keyboard yourself or check “LASTK” system variable at 23560 which is updated during standard interrupt routine: vForth much relies on any standard ZX-Spectrum behavior.
To see an example of Pac-Man like game, give a look to my “Chomp-Chomp” example available in Screens# 600-670: you can just give :
600 LOAD
and after a minute, when compilation is done:
GAME
please can you help save f_write?
the datentest.bin is “0”
danke.
gruss
———————————-
NEEDS OPEN<
256 CONSTANT BUFLEN
CREATE BUFER BUFLEN ALLOT
BUFER BUFLEN ERASE
: voll
buflen 0 do
i dup bufer + c!
loop ;
: daten-save
OPEN<
DUP
BUFER BUFLEN
ROT
F_WRITE DROP DROP
F_CLOSE DROP
;
voll
DATEN-save ../../fth/datentest.bin
: los
;
————————-
Hi Peter,
OPEN< opens file in read-only mode and cannot be use to save.
Try SEE OPEN< to understand how it is implemented.
There is a small example in Screens# 184-185 that could help with FILENAME" and SAVE-BYTES
For example
FILENAME" filename.bin" ( keep the string "filename.bin" at PAD which is a volatile memory zone )
16384 6912 SAVE-BYTES ( and try to save the standard screen to filename.bin )
Give a look to PDF manual https://github.com/mattsteeldue/vforth-next/blob/master/doc/vForth1.5-core-en.pdf
Regards.
_Matteo.
—————–
600-670: you can just give :
600 LOAD
——————
thank you, I had read that 10 times.
but could not find my solution.
can you please give a tip where that can be found in there?
thanks.
greeting
hello my great master.
I’ve already learned some important things from you.
thanks.
this is ok:
……..
………
bufer 255 Filename “/daten/test.dat” save-bytes
: starte
;
this is not ok, how do you have to write it in there please?
…….
…….
: starte
bufer 255 Filename “/daten/test.dat” save-bytes
;
this is also not ok:
: starte
show-scr ../../fth/bild.scr
;
greeting
Hi Peter,
There must be no space between Filename and ” since the word is FILENAME” (notice the final “).
Then there must be a space after FILENAME” and your filename that must be terminated with a double-quote ” .
So your phrase should be
bufer 255 Filename” /daten/test.dat” save-bytes
As per LASTK variable, see Screen # 660 where is defined MOVE-PACMAN.
Beware that Screen# 600-668 names “SPRITE” anything that moves, but in reality they are all old-fashion UDGs.
Hi, Thank You.
this is ok.
or do you have another tip please?
greeting
————————
……….
……….
……….
: los
SPRITE 0 SPRITE-UPDATE
begin
23560 c@
2000 0 do loop
starte
again ;
los
——————————–
My tip: You are using a DO-LOOP to produce some delay…. I prefer synchronize everything at some point using SYNC that executes an HALT op-code. There is a few examples of it in Screen # 63, # 239 or # 601.
my sprite loop
——————————–
……….
……….
: starte
case
dup 119 of oben endof
dup 101 of rechts endof
dup 113 of links endof
dup 115 of unten endof
dup 104 of 0 xsprite-hide 1 xsprite-hide 2 xsprite-hide endof
dup 97 of sprnr 1 + to sprnr sprnr SPRITE _spriteid ! SPRITE 0 SPRITE-UPDATE endof
dup 98 of sprnr 1 – to sprnr sprnr SPRITE _spriteid ! SPRITE 0 SPRITE-UPDATE endof
dup 99 of 1 sprite _pattern ! SPRITE 1 SPRITE-UPDATE endof
100 of 2 sprite _pattern ! SPRITE 2 SPRITE-UPDATE endof
endcase ;
: los
SPRITE 0 SPRITE-UPDATE
begin
23560 c@
3000 0 do loop
starte
again ;
los
hello tanks for info.
I use the sprite definition from #scr 400.
this is ok :
…….
…….
bufer 255 Filename” /daten/test.dat” save-bytes
……
……
——————————————————–
this not funktion:
…….
…….
: starte
bufer 255 Filename” /daten/test.dat” save-bytes
;
……
……
thanks
greeting
for safety reason (and because i am often dumb) the example SAVE-BYTES cannot overwrite a file: only new files please.
If you need to overwrite a file you have open it in read/write mode and do that by using the correct “flags-number” used by F_OPEN primitive-word:
f_open ( a1 a2 b — u f )
\ open a file
\ a1 (filespec) is a null-terminated string, such as produced by ,” definition
\ a2 is address to an 8-byte header data used in some cases.
\ b is access mode-byte, that is a combination of:
\ any/all of:
\ esx_mode_read $01 request read access
\ esx_mode_write $02 request write access
\ esx_mode_use_header $40 read/write +3DOS header
\ plus one of:
\ esx_mode_open_exist $00 only open existing file
\ esx_mode_open_creat $08 open existing or create file
\ esx_mode_creat_noexist $04 create new file, error if exists
\ esx_mode_creat_trunc $0c create new file, delete existing
\ Return file-handle u and 0 on success, True flag on error
thank you for your great description of the handling of the files.
a file in here ” : start … ; ” calling with start does not work:
: start
bufer 255 Filename ” /daten/test.dat” save-bytes
;
why not ?
greeting
thanks
greeting
FILENAME” is quite experimental and for now can be used only interactively , i.e. it cannot be compiled as you’re trying to do. I hope improving it in the future.
In general (and in your case), first you need to declare a string containing the filename:
CREATE DATEN-FILE ," /daten/test.dat"
this create a new variable called DATEN-FILE that is a ‘counted-and-zero-terminated’ string suitable to be used with NextZXOS I/O primitives.
You can see its content using
DATEN-FILE COUNT TYPE
or
DATEN-FILE 20 DUMP
Then, I would define something like this
: SAVE-BUFER ( a -- ) \ save bufer to filename given by the counted-zero-terminated-string a
1+ 0 ( a 0 ) \ just to agree with F_OPEN syntax
[ HEX ] 0E [ DECIMAL ] ( a 0 b ) \ option to create or overwrite file
F_OPEN 41 ?ERROR ( fh ) \
DUP BUFER 255 ROT ( fh buf 255 fh )
F_WRITE 47 ?ERROR ( fh n ) \ write file
DROP ( fh ) \ ignore number of bytes written
F_CLOSE 42 ?ERROR ( ) \ close
;
you can use it anywhere as
DATEN-FILE SAVE-BUFFER
thanks for the information.
I would like to invite data several times after you have done it in a game.
i am looking forward to this change
thanks.
greeting.
this : SAVE-BUFER ( a — ) is ok !!!
tanks
greeting
Hi, Thank You.
loading an image also works great
your program
greeting
——————————-
NEEDS J
NEEDS VALUE
NEEDS TO
needs layer11
220 load
down
layer11
100 mmu7!
: load-bild ( a — )
1+ 0
[ HEX ] 01 [ DECIMAL ]
F_OPEN 41 ?ERROR
DUP [ hex ] e000 1b00 [ decimal ] ROT
F_READ 47 ?ERROR
DROP
F_CLOSE 42 ?ERROR
;
CREATE DATEN-FILE ,” /fth/bild.scr”
: los
100 mmu7!
DATEN-FILE COUNT TYPE DATEN-FILE load-bild
[ hex ] 1b00 0 do i e000 + c@ 4000 i + c! loop [ decimal ]
;
————————————–
hello you good man ….
why are they going :
Scr# 400 ( Sprite struct definition )
not by layer2:
if I have set to layer2 and then invite the sprites, the program jumps back to layer12.
thanks
greeting
The reason is in Screen# 409 where i did
BINARY 00001011 HEX 15 REG!
that sets the Layers priority to “SUL” i.e. (Sprite over ULA over Layer2). Change it to “SLU” with
BINARY 00000011 HEX 15 REG!
Hello, thanks for your help.
now it works with the sprite.
greeting
hello you specialist from vforth, good afternoon.
i am happy that with me that vforth always
can do more thanks to your help.
I can’t get this sin-cos down to work with vforth.
can you please help
or do you already have another idea for the future of sin-cos with integrity?
thanks
greeting
————————————-
\ Sinus und Cosinus
\ Tabellengestützte Berechnung für ganze Zahlen.
\ Ergibt auf 10K skalierte Werte.
\ Prototypische Lösung mittels:
\ Gforth 0.6.2, Copyright (C) 1995-2003 Free Software Foundation, Inc.
vocabulary sinus sinus definitions decimal
create sinustabelle \ 0…90 Grad, Index in Grad
0000 , 0175 , 0349 , 0523 , 0698 , 0872 ,
1045 , 1219 , 1392 , 1564 , 1736 , 1908 ,
2079 , 2250 , 2419 , 2588 , 2756 , 2924 ,
3090 , 3256 , 3420 , 3584 , 3746 , 3907 ,
4067 , 4226 , 4384 , 4540 , 4695 , 4848 ,
5000 , 5150 , 5299 , 5446 , 5592 , 5736 ,
5878 , 6018 , 6157 , 6293 , 6428 , 6561 ,
6691 , 6820 , 6947 , 7071 , 7193 , 7314 ,
7431 , 7547 , 7660 , 7771 , 7880 , 7986 ,
8090 , 8192 , 8290 , 8387 , 8480 , 8572 ,
8660 , 8746 , 8829 , 8910 , 8988 , 9063 ,
9135 , 9205 , 9272 , 9336 , 9397 , 9455 ,
9511 , 9563 , 9613 , 9659 , 9703 , 9744 ,
9781 , 9816 , 9848 , 9877 , 9903 , 9925 ,
9945 , 9962 , 9976 , 9986 , 9994 , 9998 ,
10000 ,
: sinus@ cell * sinustabelle + @ ;
: sin ( grad — sinus )
dup 0r abs
360 mod
dup 180 > if 180 – true >r else false >r then
dup 90 > if 180 swap – then
sinus@
r> if negate then
r> if negate then ;
: cos 90 + sin ;
————————————-
I suggest to move all these discussion within SpecNext Forum
https://www.specnext.com/forum/
Maybe we can add someone else’s contribution.
Here is my working version with a little optimization:
: sin ( grad -- sinus )
dup >r \ save grad sign
abs 360 mod
dup 180 > if 180 - -1 else 0 then >r
dup 90 > if 180 swap - then
sinus@
r> +- \ apply sign -1 or 0
r> +- \ apply grad sign
Also needs CELL :
2 constant cell
_M.
Hi, Thank You.
sine-cosine now works wonderfully with vforth.
maybe you can include that in your list?
greeting
I will.
try again here!!!
NEEDS VALUE
NEEDS TO
NEEDS CASE
NEEDS J
include /fth/spriteload3.f
SPRITE-LOADr
abs 360 mod
dup 180 > if 180 – -1 else 0 then >r
dup 90 > if 180 swap – then
sinus@
r> +-
r> +- ;
: cos 90 + sin ;
: los
SPRITE 0 SPRITE-UPDATE
80 to weg
360 0 do
wx i sin weg 10000 */ + to x
wy i cos weg 10000 */ + to y
x SPRITE _xcoord !
y SPRITE _ycoord !
SPRITE 0 SPRITE-UPDATE
1 pause
loop
80 to weg
360 0 do
wx 360 i – sin weg 10000 */ + to x
wy 360 i – cos weg 10000 */ + to y
x SPRITE _xcoord !
y SPRITE _ycoord !
SPRITE 0 SPRITE-UPDATE
1 pause
loop ;
everything is chaotic, the sine table does not appear and some other things also do not.
can you completely delete all three of this demo spritesinus?
thanks.
can you open a new title there “vforth”?
greeting
—————————————–
I suggest to move all these discussion within SpecNext Forum
https://www.specnext.com/forum/
Maybe we can add someone else’s contribution.
——————————————
Hi good afternoon.
the cursor has to be somewhere in vforth as a char.
how can you draw the cursor-char “empty”?
thanks.
greeting
To make disappear the KEY flashing cursor you can give (at your risk…)
HEX
BL 026 +ORIGIN C!
BL 027 +ORIGIN C!
BL 028 +ORIGIN C!
hello thanks for info for cursor.
greeting
hello, good afternoon vforth fachman.
I also read something about float in the vforth.
but unfortunately I can’t find a demo that I understand.
can you please help?
thanks.
greeting
Hi Peter,
vForth 1.4 has a “floating-point option” that relies on ZX Spectrum built-in FP calculator.
I cited a FP number format in the documentation ( https://github.com/mattsteeldue/vforth-next/blob/master/doc/vForth1.5-core-en.pdf ) but I am a little late in porting it to vForth 1.5
I promise within a few days I will release a new build that has a working FP option
_M.
the vforth is very interesting, that’s why my many questions.
thank you for your work for this float.
another question about the flash.
you have set the software flash to 32 with me.
——————————–
\ software-flash: flips face every 320 ms
LDN A’| HEX 10 N,
ANDA (IY+ HEX 3E )|
\ LDN A’| HEX 8F N,
LDA() HEX 026 org^ + AA,
JRF NZ’| HOLDPLACE \ IF,
\ LDN A’| HEX 88 N,
LDA() HEX 027 org^ + AA,
BIT 3| (IY+ HEX 30 )|
JRF Z’| HOLDPLACE \ IF,
\ LDN A’| 5F N,
LDA() HEX 028 org^ + AA,
HERE DISP, \ THEN,
HERE DISP, \ THEN,
—————————————
can you do an emit without the flash being set to the right?
thanks.
greeting
I am not quite sure what you’re meaning by “the flash being set to the right”.
KEY is a low-level word that waits for a keypress and returns its Ascii code and should not be used for real-time keyboard scan typical of games.
Games must use some more complex piece of software like Mr. Jones’ keyboard test routine that I’ve made available in Screen # 48 (you must provide a “scan-code” number and that routine returns a TRUE / FALSE flag).
A very simple game that uses one key at a time can simply use LASTK system variable (location 23560) to check the keyboard status i.e. the last key pressed.
hello, good afternoon master.
i found your newest version vforth with
float. thank you for your service.
I now have to get to know how to use the commands. Enter float numbers and output float numbers again
started it with “needs floating”
thank you very much.
In this last build I’m providing an experimental (but useful) “Floating-Point Option Library”.
Using NEEDS FLOATING the library is loaded in dictionary and provides a simple interface to the ZX Spectrum “standard ROM” Floating-Pointer routine (RST $28).
e.g.
FLOATING ( to set NMODE to 1, that is Floating-Point mode )
12.0 2.5 * F. ( and get 3.0000E1 )
2.0 FSQRT F. ( and get 1.4142E0 )
30.0 DEG>RAD FSIN F. ( and get 0.5000E0 )
INTEGER ( to set back NMODE to 0, that is integer mode )
Screen # 470 contains an example that produce a your Sine-Cosine table values that is “a generated Forth code” in Screen # 471.
I’ve added a chapter in the documentation https://github.com/mattsteeldue/vforth-next/blob/master/doc/vForth1.5-core-en.pdf
_M.
thanks for the little float demo.
I’ve slowly got used to it.
once again my thanks for your work with the float for the vforth.
greeting
thanks.
the Screen # 470 , Screen # 471 is empty .
https://github.com/mattsteeldue/vforth-next/blob/master/doc/txt/!Blocks-64.bin_20210916.txt
greeting
Again, silly me: I’ve just changed my laptop and restored some wrong backups…
Now it should be fine.
Screen # 470 is a funny example of “code generator”: the fastest way to write such a generated code is to write it to a BLOCK
_M.
is ein error in float?
needs floating
30.0 deg>rad fsin f. -0,8660E0 ok
greeting
Silly me !
I released the wrong version where I swapped the two definitions RAD>DEG and DEG>RAD
Now it should be fine.
_M.
my demo :
———————————
needs floating
: los
12.0 2.5 * F.
2.0 FSQRT F.
30.0 DEG>RAD FSIN F.
INTEGER ;
————————————–
los
30.0 deg>rad fsin f. -0,8660E0 ok
greeting
here is the output of my program:
los 0.0000E0 4,4721E0 -0.8660E0 ok
greeting
hello, is noch error :
: los
12.0 2.5 * F.
2.0 FSQRT F.
30.0 DEG>RAD FSIN F.
INTEGER ;
los 0.0000E0 4,4721E0 -0.8660E0 ok
thanks
greeting
this :
https://github.com/mattsteeldue/vforth-next
and this
https://github.com/mattsteeldue/vforth-next/tree/master/download
hello, the result is not yet correct.
thanks.
greeting
los 0.0000E0 4,4721E0 -0.8660E0 ok
I tested it like this:
: deg>rad pi 180.0 f/ f* ;
30.0 deg>rad fsin
f. 0.5000E0 ok
hello,
an error must occur in there when it is loaded with “needs floating”
greeting
Just reloaded the .zip file, maybe it was still old …
Anyway, you’ve managed very well to find the bug.
hello, now it’s wonderful.
I had caught the old vforth again who had the old bug.
now i have the new changed vforth and it works.
thank you for your help.
greeting
thank you again for your great help.
now I would like to make a graph with floating sine-cosine:
plot and draw!
which screen # do I have to load for plot and draw?
in which layer can I please use the plot and draw?
thanks.
greeting
Old standard ZX Spectrum’s ROM PLOT and DRAW routine are available via 43 LOAD
I just tested, they work in LAYER11 and LAYER0 (LAYER10 and LAYER2 seems not to work).
In LAYER12 they behave in a funny way.
I think we should move all these discussion to
https://www.specnext.com/forum/
In “Z80 Assembler” subsection of Programmers’ Corner should be fine: https://www.specnext.com/forum/viewforum.php?f=16
https://www.specnext.com/forum/
do you have the opportunity to bring everything that has been written here so that others can benefit from it?
and you the first point of contact?
thanks.
greeting
hello, here is a demo with draw and floating.
thank you for your help.
greeting
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028
Hi good afternoon.
there is one thing that I cannot clarify myself.
you had made a suggestion how the cursor can be made invisible.
this cursor is still there, but it just can’t be seen and is still to the right of the last click and takes a place.
my question is :
can you switch off the cursor so that it is no longer generated by the program for a certain input and therefore does not occupy any space on the screen?
thanks.
greeting
During execution, the cursor isn’t displayed unless you’re explicitly use KEY.
So, you need to write your own word like the following example that “waits for a keypress” tout-court:
HEX 5C08 CONSTANT LAST-K
: KEYPRESS ( -- c )
0 LAST-K C!
BEGIN LAST-K C@ UNTIL
LAST-K C@
;
KEY is written in machine-code and honestly the flashing cursor cannot be disabled.
In vForth, KEY is used only by ACCEPT which is used by QUERY which in turn is used by QUIT.
QUIT puts in place the main-loop that waits for keystrokes and INTERPRETs them by compiling or executing.
hello, good afternoon you specialist.
it works wonderfully with the floating and the sprites.
now I wanted to load my own interrupt with include.
when it was loaded the vforth crashes.
how can I please load it with include that it works?
how can I please stop it again with int-off
tanks
greeting
—————————
needs interrupt
needs value
needs to
: at. 22 emitc swap emitc emitc ;
: ink. 16 emitc emitc ;
: paper. 17 emitc emitc ;
0 value wert
: isr-test
23672 ( frames ) @ 7 and 0= if
wert 1 + to wert
0 0 at. wert .
endif ;
int-on
———————————
You must first set INT-W properly.
INT-OFF ( for safety reason )
‘ ISR-TEST INT-W ! ( put xt of your “ISR word” to INT-W variable )
INT-ON ( go live )
And remember to give INT-OFF if you FORGET ISR-TEST to re-do the same compilation…
hello, please have a look at the interrupt program with the picture.
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028&p=12967#p12967
What am I doing wrong?
I also have such a crash here with:
——————————-
: at. 22 emitc swap emitc emitc ;
: ink. 16 emitc emitc ;
: paper. 17 emitc emitc ;
hex 5c08 constant last-k decimal
: keypress ( — c )
0 last-k c!
begin last-k c@ until
last-k c@
;
: los
begin
keypress
.
again ;
——————————
thanks.
greeting
It works! But I would modify your infinite loop BEGIN-AGAIN like this
: los
begin
keypress
.
?terminal until ;
To stop the main loop you just have to use [BREAK] key (i.e. Caps Shift + SPACE)
hello thanks for keypress.
greeting
hello, good afternoon master.
my next problem is with layer2 for vforth.
How can you bring in a picture in layer2, please?
I don’t know where the screen address is.
how can you please bring tile in in vfoerth?
would also be a good extension for the vforth.
thanks.
greeting
Hi Peter, I’m glad you’re asking, I’m planning to code some good example.
For now, Layer 2 can be enabled via LAYER2 that effectively invokes 512 IDE_MODE! to select High-Resolution Mode and chooses 64 characters per line to be compatible with the EDITor.
To know which 16K BANKs Layer2 is effectively using, you have to ask the system via HEX 12 REG@ that replies with the first of three 16K BANKs. Usually this is BANK # 9 that means Layer 2 lies on Banks # 9-11, which means 8K-Pages # 18-23.
Layer2 memory is divided into 6 horizontal stripes, 8K each, and the only way to access it in vForth is to -first- map the correct 8K-page on MMU7 using MMU7! and then use addresses $E000-$FFFF. Each address represents one pixel which color is given based on the current Palette.
BTW, in Screen # 520 there is a nice “Colour-Picker” you can use to choose the correct byte-color to use.
Y-Coord value spans from 0 (left-side) to 255 (right-side) and always refers to the low-byte part of the address ( e.g. $xx00 – $xxFF ).
X-Coord value spans from 0 (top-side) to 191 (bottom-side) and must be first divided by 32 to determine which 8K stripe/page the X-Coord lies, the remainder being a number between 0 and 31 that is the pixel inside the 8K stripe.
For example, point 0,0 (top-left corner) can be addressed using ?HEX 12 MMU7! E000 C@ or C!
point 0,255 (top-right corner) can be addressed using HEX 12 MMU7! E0FF C@ or C!
point 191,0 (bottom-left corner) can be addressed using HEX 17 MMU7! FF00 C@ or C!
point 192,255 (bottom-right corner) can be addressed using HEX 17 MMU7! FFFF C@ or C!
point 100,100 is HEX 1A MMU! E464 C!
M.
hello, thanks for your new revision of vforth.
the pdf in there is from build 20210502
I have a new version that already includes floting.
thanks.
greeting
vForth_15e_20210916.zip
error in floating.
needs floating
the error :
1/2? undefined
greeting
Thank you, I’ve just updated such misplaced 1/2
yes i like your vforth.
i am only working with it at the moment.
to learn about special things from the next and implement them in vforth
brings great joy.
thank you for your help.
greeting
hello, demo for layer2 not loop correkt.
thanks
greeting
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028&p=12973#p12973
Give a look to my experiment
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028&p=12974#p12974
I have the screen error again.
where does it come from?
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028
thanks.
greeting
thank you for your great help for layer2.
how do you have to change plot and draw, so that it works in layer2 with the 255 colors. your asm-code plot and draw is unfortunately not a source code screen 43.
thanks.
greeting
Screen# 43 uses “our old 48K Basic” ROM calls to perform PLOT and DRAW.
Layer2 PLOT is quite easy: it’s just a C! like that
: PLOT ( color x y — ) pixeladd c! ;
Layer2 DRAW has to be coded using some Line drawing algorithm
hello thanks for help.
greeting.
i found something in forth here.
unfortunately I can’t do it with my mind for the vforth.
thanks.
greeting
—————————————————
defer steep \ noop or swap
defer ystep \ 1+ or 1-
: line ( x0 y0 x1 y1 color bmp — )
{ color bmp }
rot swap
( x0 x1 y0 y1 )
2dup – abs >r
2over – abs r>
if swap 2swap swap \ ensure x1 > x0
else 2swap
then
( x0 x1 y0 y1 )
2dup >
if [‘] 1-
else [‘] 1+
then is ystep
over – abs { y deltay }
swap 2dup – dup { deltax }
2/ rot 1+ rot
( error x1+1 x0 )
do color i y steep bmp b!
deltay –
dup 0<
if y ystep to y
deltax +
then
loop
drop ;
—————————————
I’ve implemented in vForth this algorithm https://en.wikipedia.org/wiki/Line_drawing_algorithm
Here is the code and the example
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028&p=12996#p12996
hello, good day great master.
i have already learned a lot about the vforth in connection with the spectrum next and have come a long way thanks to your help.
it was my wish to take the spurs off the nextbasic and to give the vforth what you did really well.
I think that one more hurdle was not touched: tilemap
could you imagine touching the last big hurdle in the image display in the vforth?
thanks.
greeting
I accept the challenge…
Let me gather some ideas.
this is a good thing you have in mind for
the vforth. I think it’s the icing on the cake
in vforth this tilemap.
a lot of success and strength for it.
thanks
greeting
hello, good afternoon master.
here is layer2 with floating plot.
greeting
https://www.specnext.com/forum/viewtopic.php?f=13&t=2028&p=12989#p12989
Hi good afternoon.
for the first time i use the built-in text editor from vforth at cspect. but do not get along with the buttons from the menu below.
how are the buttons for the menu operated by the pc?
thanks.
greeting
EDIT is a full-screen editor that can be used to manipulate one Screen at a time. A Screen is composed by two BLOCKs.
In vForth a BLOCK is 512 bytes long and can be persistently stored inside !Blocks-64.bin file. This file is automatically opened at WARM or COLD startup and closed when quitting to Basic via BYE.
The BLOCK/Screen system can be envised as a mass-storage zone accessed one Screen at a time and, for some purposes, a virtual-memory area that can be accessed a BLOCK at a time using a BUFFER i.e a dedicated (but volatile) RAM area.
A Screen can be loaded (i.e. interpreted) using LOAD and vForth begins interpretation of Screen # and to edit a Screen I coded this peculiar or “built-in” editor.
The cursor keys, i.e. [Shift] + [5] / [6] / [7] / [8] keys, allow the flashing cursor to be moved across the screen to point the current position and text can be typed at any position in the Screen.
[Delete] key or [Shift] + [0] removes a character at current cursor position, shifting left the rest of the line.
[Break] key or [Shift] + [SPACE] inserts a space at current cursor position, shifting right the rest of the line.
[Edit] key or [Shift] + [1] enters in “command mode” and the Editor waits for a single key-stroke commands:
[ Q ] : Quit
[ H ] : Hold or take current line content and keep it in PAD
[ R ] : Replace current line with the current PAD content.
[ S ] : make Space at current cursor position shifting down lower lines; last line will be lost.
[ D ] : Delete current line shifting up lower line, but a copy is copied to PAD before deletion using H
[ I ] : Insert PAD at current line: it does commands S and R.
[ N ] : go to Next screen
[ B ] : go Back to previous screen
[ U ] : Undo, the Screen is re-read from disk ignoring any modification done since last FLUSH. This
feature is quite important, since it does for a single Screen what EMPTY-BUFFERS does for all of them.
[ P ] : accepts two hexadecimal digits representing a byte and puts it at cursor position.
Any other key has no meaning and returns the flashing cursor back to its position.
Beware, any modification immediately affects the underlying BUFFER, so if you mess things too much and [Edit] + [ U ] is not enough, there is only a way to recover it: quitting and using EMPTY-BUFFERS to erase all buffers without flushing to disk.
Hello, thanks for the help
the editor is very sensitive to use.
thanks.
greeting
hello, good day great master.
have you already achieved success with the tilemap and vforth.
I am already looking forward to reading how it works with the vforth. this tilemap is very new to me.
thanks.
greeting
Hi Peter, not yet.
The Tilemap mode is quite alien to me too.
M.
First working example using Tilemap.
https://www.specnext.com/forum/viewtopic.php?f=13&t=2043#p13032
hello , layer-scroll functions with layer21.
https://www.specnext.com/forum/viewtopic.php?f=13&t=2042
the layer21 scrolls in the background and with the interrupt.
the sprite can be moved in the foreground.
greeting
https://www.specnext.com/forum/viewtopic.php?f=13&t=2042&p=13031#p13031
https://www.specnext.com/forum/viewtopic.php?t=2043&start=10
hello master, have something new from the tilemap.
maybe you can help me there again?
works fine.
would like to load 255 chars from your own chargen.bin for example chargen from the c64 (winvice)? where do they have to be packed (memory) and how are they packed according to tile-map?
thanks.
greeting
hello, this tilemap runs on the cspect and on the n-go / next.
it always starts in cspect.
only when I start the n-go / next tilemap in vforth does the tilemap screen remain dark. only when I start the tm.nex from the folder c: / demos / tilemap does the vforth tilemap work.
Somehow something has to be switched in the program of the tilemap in the vforth.
thanks.
greeting
Hi good afternoon matteo.
vforth:
in the inc folder with “BORDER..f there is an error.
greeting
———————————
\
\ border..f
\
.( BORDER. )
\
NEEDS CALL#
\
HEX
: BORDER >>>>>>>>>>>> BORDER.
2297
CALL#
DROP
;
DECIMAL
——————————————
Fix released.
hello great master … good afternoon.
the new layer2 is no longer black and white. but blue like the border.
Is that correct?
thanks.
greeting
Hello….
the sprite no longer goes into the tilemap window but remains in the area of layer2, when it leaves layer2 it is no longer visible in the visible area.
greeting
Have you modified some clipping window ? There are registers that allows you clip each layer individually.
For the colors, yes the first Basic loader changes to yellow-on-blue every Layer.
Hello, thanks for your help.
thanks for new vforth.
your new vforth and tilemap now works with it:
7 21 reg!
this ist now with new vforth ok :
—————————–
only when I start the n-go / next tilemap in vforth does the tilemap screen remain dark. only when I start the tm.nex from the folder c: / demos / tilemap does the vforth tilemap work.
Somehow something has to be switched in the program of the tilemap in the vforth.
—————————-
greeting
Hi good afternoon.
I haven’t checked in for a long time.
how can you create a tilemap in the vforth for the next?
Thanks.
greeting
Hi good afternoon.
was on vacation for 8 days.
now it continues with vforth.
greeting
hello, error:
forth15g.bin not found
greeting
Discussion has moved here : https://www.specnext.com/forum/viewforum.php