Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?

Optical Illusion tutorial with the Commodore 64 and DurexForth

Whats up once more. Begin right here if you do not know what DurexForth is, or even perhaps what a Commodore 64 is.

Let’s develop on my earlier publish with one thing a bit extra enjoyable than yet-another-fizzbuzz.

On this publish, we’ll implement the “stepping feet” illusion. This is an instance:

Let’s take into consideration the best way to implement this. We’ll want the black and white vertical bars, and a approach to shortly swap them off to point out a plain grey background (thus revealing the phantasm). Commodore 64 character graphics appear nearly preferrred for this.

The colored “ft” may be {hardware} sprites transferring throughout this background. Two large rectangles have to be simply in regards to the easiest sprites we may think about!

However first, the alternating bars. I wish to implement the colors in color reminiscence, after which simply fill the display with “reversed” areas to show the colored bars. That means I can flip off the bars by merely filling the display with “non-reversed” areas (that are invisible), leaving the alternating colors intact within the color reminiscence however permitting the background “display color” to point out by. I will make this grey identical to within the instance.

Let’s start by beginning up the DurexForth ‘v’ editor, and getting into some helpful constants.

$0400 fixed SCREENMEM
$d800 fixed COLORMEM
53281 fixed SCREENCOLOR
32 fixed SPACE-CHAR
160 fixed REVERSE-CHAR
12 fixed GRAY2
Enter fullscreen mode

Exit fullscreen mode

Discover how simply numbers may be entered in both hexadecimal or decimal. You may also enter numbers as binary by prefixing with ‘%’, e.g. %10000011.

Now I will make a helper phrase (i.e. a operate) to fill the display with a given character. Though DurexForth is a lot sooner than Primary, utilizing a loop to fill within the display reminiscence remains to be noticeably slower than for those who had been to do it in meeting. Thankfully, there’s a higher means. Let’s check out the fill phrase from the DurexForth handbook:

fill ( addr len char — )
Fill vary [addr, len + addr) with char.

Note the stack comment, ( addr len char — ). This indicates what values the word will expect to take off the stack (before the dash), and what values it may leave on the stack (after the dash). So, the fill word will consume three parameters from the stack and add nothing back onto the stack. It’s good practice to leave comments like this on your own words too, as it helps you to prevent stack overflow or underflow, which will crash your program.

So, using this word to fill the first 100 characters of screen memory with the ‘A’ character would look like this:

$0400 100 1 fill
Enter fullscreen mode

Exit fullscreen mode

where $0400 is the start address of the fill operation, 100 is the number of bytes to fill, and 1 is the byte you want to fill that memory area with (i.e. the character code for the letter ‘A’).

We want to fill screen memory, so the first two parameters will always be $0400 and 1000. Here’s how the helper word looks:

: fillscreen ( char -- )
 SCREENMEM 1000 rot fill ;
Enter fullscreen mode

Exit fullscreen mode

first, take a look at the stack comment. This word expects the character code to already be on the stack. Then the word itself will push the SCREENMEM constant onto the stack ($0400), followed by size in bytes of screen memory (1000).

The stack will now contain char addr len. Referring back to the documentation for fill we see that it requires those values in this order: addr len char.

Now let’s take a look at the documentation for the built-in stack-manipulation word, rot:

rot ( a b c — b c a )
Rotate the third item to the top.

Substitute a b c for char addr len, and you can see this will give us just what we need. There are many such stack-manipulation words for getting parameters into the required order.

Now we have our fillscreen helper word which we can use to fill the screen with any character we give it. For example, using our predefined character constants:

REVERSE-CHAR fillscreen   show the black and white bars
SPACE-CHAR fillscreen     hide them again
Enter fullscreen mode

Exit fullscreen mode

Next, we’ll implement the colours. We can put this into a setup word, as once we’ve defined these colours, we don’t need to touch them again. Also, as this is a one-off setup routine, I don’t mind using a slightly slow loop construct.

: coloursetup
GRAY2 SCREENCOLOR c!
1000 0 do
 i 1 and COLORMEM i + c!
loop ;
Enter fullscreen mode

Exit fullscreen mode

The snippet i 1 and will give us a zero for even-numbered iterations, and a one for odd-numbered iterations. Fortuitously, these are the colour codes for black and white respectively. c! simply stores a byte at an address. It’s POKE with a less silly name.

Let’s add a couple of words to test what we have so far:

: mainloop
 REVERSE-CHAR fillscreen
 key drop
 SPACE-CHAR fillscreen
 key drop
recurse ;

: main
 screen-setup
 mainloop ;
Enter fullscreen mode

Exit fullscreen mode

The key word gets one character from input and leaves it on the stack. We don’t want to use that character for anything, we only want to check if a key has been pressed, so we can discard that value from the stack with the drop word.

Let’s try it out. If you’re in the ‘v’ editor, hit F7 to compile and return to the immediate prompt, and then run the main word. Tapping a key will toggle the black and white bars on or off. Hit RESTORE to exit the program (“Page up” on my Vice key mapping… YMMV).

Image description

Now let’s move on to the sprites. First, let’s add some more useful constants to the top of the program:

53280 constant VIC
14 constant SPRITEPTR
4 constant BLUE
7 constant YELLOW
Enter fullscreen mode

Exit fullscreen mode

Note that it is common in BASIC to store a base address for the VIC-II registers as V=53280, and then reference the various registers by their offset, e.g. POKE V+21, 3. While I am going to do the same in my program, I’m using the name VIC, so as not to collide with the command to open the ‘v’ text editor. Despite my convention of using ALL CAPS for constant names, these names are case insensitive so naming this constant ‘V’ would be a problem.

Here’s the wall of POKEs required to initialise the two sprites:

: init-sprites
 SPRITEPTR 2040 c!  sprite 0
 SPRITEPTR 2041 c!  sprite 1
 SPRITEPTR 64 * 64 $ff fill  data
 YELLOW VIC 39 + c!
 BLUE VIC 40 + c!
  sprite x expand
 3 VIC 29 + c!
  sprite initial position
 50 VIC c!        sprite 0 xpos
 100 VIC 1 + c!   sprite 0 ypos
 50 VIC 2 + c!    sprite 1 xpos
 180 VIC 3 + c!   sprite 1 ypos
;

: show-sprites
 3 VIC 21 + c! ;

: hide-sprites
 0 VIC 21 + c! ;
Enter fullscreen mode

Exit fullscreen mode

This is straightforward sprite boilerplate. As I mentioned, I’m just poking values into various VIC registers to initialise the sprites, their size, their colour and their positions. I use the fill word again to initialise the sprite data because we just want to turn on every pixel… i.e. a plain rectangle of pixels. There a many resources online which explain the various registers and how to set up your sprites. Here’s a pretty good example.

At this point I want to add a value to track whether the black and white bars are currently hidden. This can go near the top of the program with the constants:

0 value hidebars
Enter fullscreen mode

Exit fullscreen mode

The syntax for using a value is nice and simple. hidebars will push the current value of hidebars to the stack, and val to hidebars will set hidebars with a new value. In our case we want to toggle the value between true and false, so we’ll use hidebars invert to hidebars.

Now all that is left is to modify our main and mainloop words to incorporate the sprites.

: mainloop
 begin
 [ VIC inc, VIC 2 + inc, ]
 100 0 do
  key? if
   key drop
   hidebars invert to hidebars
   hidebars if
    SPACE-CHAR fillscreen
   else
    RVS-CHAR fillscreen
   then
  then
 loop
 once more ;

: foremost
 screen-setup
 init-sprites
 RVS-CHAR fillscreen
 show-sprites
 mainloop ;
Enter fullscreen mode

Exit fullscreen mode

Discover that I’ve used some inline meeting to increment the x-position of the 2 sprites. It is a uncommon case the place I really feel meeting code offers nicer syntax.

The choice in forth could be:

VIC dup c@ 1+ swap c!
VIC 2 + dup c@ 1+ swap c!
Enter fullscreen mode

Exit fullscreen mode

One other change is that I am now utilizing key? to verify whether or not there’s a character obtainable for key. This prevents this system from ready for enter when there’s none, which might pause the animation.

Let’s check out the tip outcome:


This is the total program:

$0400 fixed SCREENMEM
$d800 fixed COLORMEM
53281 fixed SCREENCOLOR
32 fixed SPACE-CHAR
160 fixed RVS-CHAR
12 fixed GRAY2
53248 fixed VIC
14 fixed SPRITEPTR
6 fixed BLUE
7 fixed YELLOW
0 worth hidebars

: screen-setup  ( -- )
 GRAY2 SCREENCOLOR c!
 1000 0 do
  i 1 and COLORMEM i + c!
 loop ;

: fillscreen ( char -- )
SCREENMEM 1000 rot fill ;

: init-sprites
 SPRITEPTR 2040 c!  sprite 0
 SPRITEPTR 2041 c!  sprite 1
 SPRITEPTR 64 * 64 $ff fill  knowledge
 YELLOW VIC 39 + c!
 BLUE VIC 40 + c!
  sprite x develop
 3 VIC 29 + c!
  sprite preliminary place
 50 VIC c!        sprite 0 xpos
 100 VIC 1 + c!   sprite 0 ypos
 50 VIC 2 + c!    sprite 1 xpos
 180 VIC 3 + c!   sprite 1 ypos
;

: show-sprites
 3 VIC 21 + c! ;

: hide-sprites
 0 VIC 21 + c! ;

: mainloop
 start
 [ VIC inc, VIC 2 + inc, ]
 100 0 do
  key? if
   key drop
   hidebars invert to hidebars
   hidebars if
    SPACE-CHAR fillscreen
   else
    RVS-CHAR fillscreen
   then
  then
 loop
 once more ;

: foremost
 screen-setup
 init-sprites
 RVS-CHAR fillscreen
 show-sprites
 mainloop ;
Enter fullscreen mode

Exit fullscreen mode

Add a Comment

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?