Well over a month ago the author posted a BASIC program that he’d been given for the C64 which used the hardware sprites and their collision registers, claiming that it showed “one sprite bouncing off another on the C64”. This isn’t really the case of course, because reacting to a collision in this way doesn’t meet any of the definitions of the word “bounce“, instead one sprite is merely sliding downwards when a collision is detected between it and another moving horizontally.
Linguistic issues aside, the author also promised his readers that another post “explaining the program in detail, along with a conversion into one or more other BASIC dialects” would be following “fairly soon” but there hasn’t been a peep out of him since then. It’s difficult to know if dissecting a mere 11 lines of program or converting it to another BASIC variant is what has delayed that follow up but, just to get the ball rolling a little, let’s go through the C64 listing line by line to see what it actually does.
10 PRINT CHR$(147):V=53248
In turn, the PRINT command is clearing the screen – character code 147 is the same as hitting shift and Clr/Home – and 53248 is the base address of the VIC-II’s registers in memory so V is being set up to point at those locations and subsequent register writes will be done as an offset from that value. This saves anyone having to remember five digit register locations.
12 PRINT CHR$(13);CHR$(13);CHR$(13):PRINT SPC(2)CHR$(209)SPC(22)CHR$(209)
The first PRINT command here is moving the cursor down by three lines, whilst the second prints two spaces, a ball character, 22 spaces and another ball character.
15 FOR T=12288 TO 12350:POKE T,255:NEXT:POKE 2040,192:POKE 2041,192
This builds some sprite data by filling the memory between 12288 and 12350 with a value of 255, making it a solid 24 by 21 pixel block. 2040 and 2041 are the sprite data pointers for sprites 0 and 1, they can point at any 64 byte block in the current 16K video bank and multiplying the value 192 by 64 gets the memory area that the loop has just filled at 12288.
20 POKE V+39,1:POKE V+40,3:SC=V+31:SS=V+30
Set sprite 0’s colour to white and sprite 1 to cyan. SC is being given the location for the sprite to background collision register while SS is being set to the one which deals with sprite to sprite impacts.
25 X=80:DX=1:POKE V,X:POKE V+2,125:POKE V+1,80:POKE V+3,80:C=0:POKE V+21,3
In order, initialise the variable X which holds sprite 0’s current X position, write that value to the actual X register for sprite 0, set sprite 1’s X position to 125, set both sprite Y registers to 80, set C to zero (this appears to be orphaned since it’s not used elsewhere, your correspondent is assuming it’s actually a typo and should say CD=0) and enable sprites 0 and 1 – up until this point the sprites were there but not visible.
30 X=X+DX:POKE V,X
Add the current speed to sprite 0’s X position and then write that value to the relevant hardware sprite register.
Read the collision registers. SC is the register for sprite to background collisions so XX gets its current state and the register at SS deals with sprite to sprite and that’s what ends up in XY.
34 IF CD=0 THEN IF XX=1 THEN DX=-DX:POKE V+3,PEEK(V+3)-23:CD=20
If the collision delay is zero and the value read from the sprite to background collision register is 1 (so sprite 0 has collided with the background) then invert the X direction, subtract 23 from the height of sprite 1 (essentially resetting it) and set the collision delay to 20 to make sure a second collision doesn’t happen for a few iterations of the loop.
35 IF CD0 THEN CD=CD-1
If the collision delay is greater than zero, decrease it by one until it’s zero for line 34 to start checking the sprite to background collisions.
As noted in your correspondent’s previous post, this functions perfectly but presumably by accident; IF CD0 is actually being treated as just IF CD and any value greater than 0 triggers the condition. Your correspondent is assuming it was actually meant to say IF CD>0 since that usage is more commonplace.
38 IF XY=3 THEN POKE V+3,PEEK(V+3)+1
Let’s check to see if a collision has occurred between the two hardware sprites and make sprite 1 move downwards one pixel if so. The reason for XY being checked for the value 3 is that this is a bitwise operation, sprite 0 is represented by the first bit in the byte (which equates to the number 1) and sprite 1 is represented as the second byte (which has a value of 2) so 1 + 2 = 3.
46 GOTO 30
And finally, since we’re all done it’s time to GOTO back to the start of the main loop at line 30.
Just for good measure and to kill a little time on a quiet Thursday, your correspondent has also converted the BASIC program into assembly language (shown in the video above) and the source code is available to examine over at Github. For another, more fleshed out working example of hardware sprite to sprite and sprite to background collision it’s also worth prodding around inside your correspondent’s previous release Super Hyperzap since it utilises both.
Hopefully this post – and perhaps even the assembly language conversion – will enable the author to move forwards towards his stated goal of converting the above program to other flavours of BASIC, because watching him floundering with dialects on other platforms that either don’t have hardware sprites or support them from BASIC should prove to be amusing. Your correspondent wonders if the author will look at the MSX series (released after the C64) first or try to convert the listing to a machine that was released at the same time as the C64 or before it?
 This is a somewhat long-winded approach but necessary to make the program transportable as text over the internet; the same effect could be achieved more optimally either with inline commands – these and the previous line’s PRINT command could even be rolled into a single command – or with one PRINT to clear the screen and four POKEs to the video and colour RAM to position the balls.