Release notes – Clone Reaction

So, another month sees us posting a new demo and this time the result is actually an amalgamation of Rob Hubbard’s Zoolook Moozook and W.A.R. by Stoat & Tim – the name for this Frankenstein-like creation is Clone Reaction because your correspondent always remembers the former of those demos under the filename Chain Reaction and, since trying to shoehorn references to both demos into the name would have been unwieldy, harking back to that alternative title instead felt like a nice alternative.

Clone Reaction (C64)All of the code that duplicates Zoolook Moozook is running via raster interrupt, but the moving plates need to stop occasionally to fetch new text – look for main_init in the source code for that bit – which would have taken a lot of processing time otherwise. panel_render is a subroutine which takes care of actually drawing the panels to screen memory and there are two versions of the draw routine called panel_odd_top and panel_even_top which deal with calling the actual renderers; the priority changes with each pass so the former draws the even numbered panel first and then the odd one over the top whilst the latter does the reverse.

Looking next at panel_render_1 which is based on the moving blocks of text from W.A.R. finds a loop that starts like this:

lda panel_1_ln0,y
beq *+$05
sta $0540,x

That branch is there to skip over any zeroes in the data which are used in panel_1_ln0 and the related tables because those parts are meant to be “transparent” and therefore don’t need to be drawn. This code is a little suboptimal in that respect since the first panel drawn doesn’t need to be masked and having a second version of each subroutine for the lower priority one would have removed the need to clean the work space each refresh, but your correspondent wanted the source code to be as easy to read as possible and decided to keep things relatively simple instead.

Sprite movement is handled by a subroutine called sprite_0_mover and its table preset_data near the end of the source code; there’s a group of labels just above said table that define movement control values such as left_1 or down_2 which mean “move left at speed 1” and “go down, speed 2” respectively[1] which isn’t that far removed from how your correspondent and indeed others have managed enemy attack patterns in games. The first hardware sprite follows these commands directly and its position after each update is stored into a series of ring buffers called sprite_x_ring, sprite_msb_ring and sprite_y_ring which are near the top of memory at $fc00 onwards – three tables are needed because the X position for a hardware sprite is actually a value between 0 and 511 and stored as a nine bit value between the sprite’s X register at $d000 and one bit in the sprite MSB (Most Significant Bit) at $d010.

The masked panels and the sprite movement both make this a reasonably challenging piece of code to follow and, whilst your correspondent has tried to keep everything tidy by avoiding the dirtier tricks such as self modifying code and hopes that the comments peppered throughout the source code or the extra detail in this post will make it more legible, the contents of the Github repository probably shouldn’t be perused by beginners who don’t yet have at least a reasonable working knowledge of the C64 or 6502 assembly language – that said, if anybody does dive around and finds themselves a little lost when coming up for air, please feel free to ask questions or get clarifications.

[1] Essentially these bytes contain the same bit patterns as would be found when reading the directions of a joystick so $01, $02, $04 and $08 translate to up, down, left and right respectively. That uses the lower four bits of the byte, but the upper four work in the same way with $10 meaning up, $20 down and so on so $01 and $10 move the sprite in the same way but $11 will shift it twice as fast.

Advertisements
This entry was posted in Programming and tagged , , , , , , , . Bookmark the permalink.