The trick with writing Forth words is decomposing the work into parts that are simple. Each word should work with 2 or 3 values on the stack, any more and it gets difficult to keep track where each one is.
There are two main pieces of work: calculate the byte address to be updated and calculate the bitmask to update the address with.
For the first we will do the two parts that use the
x and
y values separately first, just to make it clear what they are doing
Code: Select all
( y -- ay )
dup 16 / 336 * swap 15 and +
( x -- ax )
8 / 16 *
If we put this together and call it
getbad (get byte address) it would look like this
Code: Select all
: getbad ( x y -- baddr )
dup 16 / 336 * swap 15 and +
swap 8 / 16 * + 4352 + ;
Next we want the value for the lower three bits of
x, calculating powers of two would be complex, there are only eight masks so it is more efficient to use a table
Code: Select all
( x -- bpos )
create bmask
128 c, 64 c, 32 c, 16 c, 8 c, 4 c, 2 c, 1 c,
7 and bmask + c@
So the set of words to do this all would be
Code: Select all
: getbad ( x y -- baddr )
dup 16 / 336 * swap 15 and +
swap 8 / 16 * + 4352 + ;
create bmask
128 c, 64 c, 32 c, 16 c, 8 c, 4 c, 2 c, 1 c,
: plot ( x y -- )
over swap ( copy of x under original )
getbad swap 7 and bmask + c@
over c@ ( get current value )
or swap c! ;
There are some optimizations (use bit shift instead of division, use return stack to hold values )