1984 · Mastertronic

Squirm

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/squirm with me to Gold.

A maze game drawn entirely in characters, the letter-sized tiles of the screen, where each cell takes its colour from where it is, so the worms change colour as they crawl. Even a death depends on the machine: its noise falls differently on each of the two sound chips the C64 was made with.

01 · The game

Collect 255 eggs in a maze full of worms

The player collects eggs in a maze that fills one screen, while five worms crawl the corridors.

The title screen: SQUIRM in large letters, a worm, the eggs worth 10 points each, a mystery bonus, and PLUG JOYSTICK IN PORT 1
The title: an egg is worth 10, the treasure is a mystery bonus.
Level 1: a blue maze on black, worms coloured cell by cell, a few eggs, and the status lines in red
Level 1, a few seconds in. The player is the small figure at the left edge.
The bonus run: a yellow border, the timer counting down from 900, and a trail of solid blocks behind the player
The bonus run: a yellow border, a timer, and a trail of blocks.

Squirm was written by Tony Kelly and sold by Mastertronic on cassette in 1984. The player is a small spinning figure in a maze that fills the screen, and five worms crawl the corridors with it. Two of the worms lay an egg in the cell their tail has just left. The other three clear that cell, so they eat any egg they crawl over.

Each egg the player collects scores 10, and the 255th ends the level. A worm's head or body landing on the player's cell costs one of three lives. After the last egg comes a bonus run of about 15 seconds. In it the worms stand still, and each worm the player eats scores points. From the second level, on three levels out of every four, a treasure walks the maze as well, worth nothing, 10, or 100 points.

The C64's memory is a row of 65,536 bytes, each holding a number from 0 to 255. Numbers written with a $ are hexadecimal: they count in sixteens, with the digits 0 to 9 and then A to F, so $10 is 16 and $FF is 255. Those in dark boxes are addresses in that memory, or the names the listing gives them, and each opens the Source code tab at that point.

02 · The music

Music: the title tune is one low note's harmonics

Every note of the tune is a whole-number multiple of one low note, about 150 Hz (vibrations a second), so it sounds like a bugle call rather than a melody in a key.

The player runs the game's own sound code, taken from the listing, on a model of the C64's processor, the 6502. It runs the code once a jiffy, about a sixtieth of a second or 16,422 of the processor's cycles. That is how often the KERNAL, the C64's built-in system code, interrupts the game: a timer makes the processor stop what it is doing, run a short routine, and go back. The code is the set-up of the sound chip in new_game ($3B25), then the title loop ($3BB2), the level jingle ($38B0), or the bonus run (bonus_run, $3780, and bonus_tune_step, $3D5C).

The C64's sound chip, the SID, has three voices, and each plays one note at a time. The game plays every sound on two of them. Both are set to a pulse wave, a buzzy square tone, with the same envelope, the shape of each note's rise and fall in volume (new_game, $3B33). A voice's pitch is a number two bytes long. The game writes only the high byte, the one that counts in steps of 256 ($D401 for voice 1 and $D408 for voice 2), and never the low byte. So a note can be one of 255 pitches, each about 15 Hz above the one before.

The title tune is two tables of 100 bytes, one for each voice (title_tune_voice1, $3E80, and title_tune_voice2, $3EE4). Every byte in them is a multiple of 10, from $0A (10) to $64 (100). A high byte of 10 is about 150 Hz, 20 about 300 Hz, and 100 about 1,500 Hz. These are the harmonics of 150 Hz, its whole-number multiples, which are the notes a bugle can play. Each harmonic is a smaller step in pitch above the one below it. Each step of the tune lasts 10 jiffies, a sixth of a second. The title plays the 100 steps round and round until fire is pressed.

The level jingle is the title tune's first 30 steps. The bonus run plays a tune of its own on voice 2 (bonus_tune, $3DB8), one note for each pass of the run. A pass is one time round the game's main loop, in which everything that moves takes one step. The tune is 151 notes long, and on the first four levels the run lasts 151 passes, so the two end together. The routine that plays the tune counts on to 255 notes, though, so a faster run goes past the end of it (Discoveries).

03 · The sound effects

Sound: an effect is one pitch, held for one pass

The main loop silences both voices at the end of every pass, so on the first levels each sound lasts a tenth of a second.

The same player, on the game's own code. The eggs are the main loop's write ($3C0F), once a pass of 6 jiffies. The treasure plays its note ($39C6). The death (lose_life, $3A7D) plays once for each model of the sound chip, with the chip's data lines fading as the VICE emulator fades them on that model (below). The new best score is the five beeps of a score climbing the high-score table, each made by fade_beep ($30A2). The first eggs are below 100 Hz, which laptop and phone speakers barely play.

Every pass of the main loop ends by writing 0 to both voices' pitch ($3C5F), so a sound written during a pass lasts until the pass ends: six jiffies on the first four levels. An egg writes the number of eggs collected so far to voice 1's pitch ($3C0F). The first egg sounds at 15 Hz and the 255th at about 3,800 Hz, so the tone climbs through the whole level. The treasure plays notes 2 to 30 of the title tune's first voice on voice 2, one for each step it takes ($39C6).

The death switches voice 1 to noise and lowers its pitch once for each row the player falls. It does that with an instruction that reads the pitch back from the chip, and the SID cannot be read back. The read gets whatever value is left on the chip's data lines, the wires that carry each byte to it. That value fades at a different speed on the two models of the chip, the 6581 and the 8580 (Discoveries).

The name entry's beeps are the one sound that fades: fade_beep ($30A2) steps the volume and voice 1's pulse width, the share of each wave spent high, from 15 down to 0, six jiffies a step.

04 · The screen

The play screen, rebuilt from the game's memory

Everything on the screen is a character: the maze, the worms, the eggs, and the player. There are no sprites, the shapes the C64 can move over the screen on their own.

Drawn by the page from the game's own code, run on the model of the 6502: the start-up (start, $3B1D), with fire pressed on the title, up to the first wait of the first pass of play ($3C56). The page cuts the game's waits short, so it then runs the game's interrupt routine (irq_handler, $3CB3) 95 times by itself. That turns the moving characters to a pose they reach in play.

The screen is 40 columns by 25 rows of characters. For each cell the video chip reads one byte, the character's number, from the screen memory at $0400. It draws that character's shape, 8 by 8 pixels, from the game's own character set at $2800.

The maze screen turns on multicolour mode ($D016 = $D8, set at $3BE0), which lets each cell be drawn in one of two ways. Colour RAM, at $D800, holds a number from 0 to 15 for every cell. A number of 8 or more makes its cell multicolour: each pair of bits in the shape is one wide pixel, in one of four colours. They are the black background, two colours shared by every cell ($D022 and $D023, both blue), and the cell's own colour, its number less 8. A number below 8 draws the cell the ordinary way, each bit one pixel in that colour.

colour_maze ($35E8) fills colour RAM once, as a level starts. A wall cell gets 9, a multicolour cell whose own colour is white. Every other cell gets a counter that steps from 1 to 7 and round again on every cell, walls included, so the colour of an empty cell depends only on where it is. The game never colours a cell again. A worm, an egg, or the player takes the colour of the cell it is drawn in, so a worm changes colour cell by cell as it crawls. The second button above writes each cell's number over it.

The movement in the picture comes from the character set itself. On every seventh call of its interrupt routine, about 8.6 times a second, the game rewrites the shapes of a few characters (irq_handler, $3CB3). Each row of the egg rolls one pixel to the left. The two treasures swap between two poses. The eight frames of a spinning figure move round one place (rotate_spinner, $2508). The spinning figure is the player, and the three figures beside LIVES are three of its other frames. Every egg on the screen rolls at once, because every egg is the same character and the game changes its one shape.

05 · The player

The player keeps going until a wall stops it

The stick chooses a turn, and the player carries on the way it was going until the turn is open or a wall blocks the way.

Stick:

Each pass runs the game's main loop (main_loop, $3BF6) once, on the model of the 6502, with the joystick port reading what the buttons say. The worms move too, as they do on the first level. The page cuts the loop's waits short, so one pass happens at once. Ten passes play at the game's first speed, ten a second.

move_player ($306E) reads the joystick port once a pass. A direction on the stick is tried first, and the player turns if that way is open. If it is blocked, the player carries on the way it was already going, and stops when that is blocked too. So a turn can be pushed on the stick early and held, and the player takes it at the first opening. Fire alone stops the player where it stands ($3060).

Before each step, try_cell ($2FF9) looks at the character in the next cell. The player may enter a space or any character from $28 up, which takes in the eggs, the worms, and the treasure. The wall shapes are all below $28. The player's position is kept as an address in screen memory, so a step left is one byte back, and a step up is 40 bytes back, a whole row. A step left from the first column therefore lands in the last column of the row above ($304E). The mazes leave those two cells open, on row 12 at the left and row 11 at the right. So the two sides of the maze join, without a line of code to do it.

06 · The worms

How a worm chooses its way

Each worm tries up to four directions in a fixed order, and the order carries on from wherever the last worm to move left it.

Stage:

The game's main loop again, with the player standing still, at the chosen stage of the four that decide which worms move (Progression, below). The list is every test a mover made in the last pass, in order: the direction worm_direction ($2680) gave it and what cell_is_free ($3C93) found in that cell.

Every mover, each worm and the treasure, shares one counter, worm_direction ($2680). The counter steps through right, left, up, and down, then starts again. Before each try a worm turns the counter one step (next_worm_direction, $333D) and tests the cell that way. A free cell takes the head, and the body follows. A blocked one means another turn of the counter, up to four tries. A worm boxed in on all four sides has its head put back on its start cell ($33A4), and its body follows it there one cell a step.

So the direction a worm tries first depends on how many tries the movers before it made in the same pass. Nothing is random, but the order shifts every pass, and a worm wanders.

The test that decides a free cell, cell_is_free ($3C93), takes a space, an egg, or the player's own character. A worm catches the player by crawling onto it, which an older version of the test did not allow (Discoveries).

WormCellsStarts at row, columnLeaves behindMoves at stages
A (step_worm_a)83, 22an egg4
B (step_worm_b)521, 13a space3 and 4
C (step_worm_c)55, 3a space1 to 4
D (step_worm_d)59, 13a space1 to 4
E (step_worm_e)519, 3an egg1 to 4

From reset_worms ($3669), the five routines, and move_creatures ($3A46). The cell lists are at $2648-$267F, head first. On the first three stages of each cycle, worm E lays every egg there is.

07 · Progression

A jiffy faster every four levels

The levels cycle through three mazes and through four stages of what moves. After each cycle of stages, a pass of the main loop waits one jiffy less. A jiffy is one tick of the clock the C64 keeps for itself, about a sixtieth of a second.

Worked out by the game's own code on the model of the 6502: level_complete ($3879), then one pass of the main loop, for each level in turn, with the bonus run left out.

Two counters set a level. maze_number ($2682) picks maze 1, 2 or 3 in turn ($390E). level_stage ($2688) runs from 1 to 4 and says what moves (move_creatures, $3A46): worms C, D, and E at stage 1, the treasure as well at 2, worm B as well at 3, and all five worms and the treasure at 4. When the stage reaches 5, move_creatures adds 1 to step_delay ($2689) and starts the stage again at 1 ($3A72).

step_delay is how long each pass waits. The game stores it in $A2, the low byte of the KERNAL's clock, which the interrupt adds 1 to 60 times a second. Then the game waits while that byte is $80 (128) or more. $FA (250) takes six jiffies to count past $FF to 0, so the first levels play ten passes a second. Each cycle of four levels takes a jiffy off. From level 25 the main loop does not wait at all. The three mazes are drawn on the Maps tab. The level number shown on the top line goes wrong after 19 (Discoveries).

08 · The treasure

The mystery bonus is decided by the pass you take it on

The treasure's worth goes round 1, 2, 3 on every pass, ten times a second, and is read at the moment the player reaches it.

A copy, written for this page, of step_treasure's first lines ($39DF), which step treasure_value ($2684) through 1, 2, and 3 and round again, once a pass. It also copies collect_treasure ($373B), which pays nothing for 1, 10 for 2, and 100 for 3. The passes run at the first level's speed.

From the second stage of each cycle of four levels, a treasure walks the maze as the worms do, from row 21, column 13. It moves with the same shared turning counter and the same test of a free cell (move_treasure, $3961). The title calls it a mystery bonus, and the mystery is a counter. step_treasure steps treasure_value on every pass, and collect_treasure reads it when the player lands on the treasure. The worth shows for 30 passes where the treasure was taken, as one of three characters: 100, 10, or a blank. Two hundred passes after it was taken, the treasure comes back as the other of its two pictures.

09 · The bonus run

In the bonus run, the trail is a wall

After the 255th egg the worms stop, the timer counts 900 down, and every cell the player leaves becomes a block it cannot cross again.

The bonus run in VICE: a yellow border, the timer at the bottom right, and a trail of solid blocks behind the player
The bonus run in the VICE emulator: the blocks are character $00, a wall.
A later level in VICE, with LEVEL 10 on the top line
The next level starts with the jingle and its number spelt out.

bonus_run ($3780) turns the border and the status lines yellow and spells out BONUS RUN and GET READY in the middle of the maze. Then it points the interrupt at a routine of its own, bonus_irq ($3D27). bonus_irq counts the timer on the bottom line down by one each sixtieth of a second, so the 900 last 15 seconds. It leaves out the normal interrupt's animation, so the eggs stop rolling for the run.

Only the player moves. A worm's body scores 100, a head 200, and an egg 10. Every cell the player leaves becomes character $00, a solid block, and try_cell ($2FF9) treats every character below $28 as a wall.

10 · Lives

A death drops the player down the screen

The player falls a row at a time to the bottom of the maze, with a falling noise, and the walls flash through every colour.

The game's lose_life ($3A7D) run on the model of the 6502 for a player on its start cell, with a picture taken at each of its waits and shown for as many jiffies as the wait lasts.

The main loop looks at the cell the player has just moved to. A worm's head ($43) or body ($44) there costs a life ($3C2C). lose_life ($3A7D) clears the player's cell and draws the figure one row lower every three jiffies, over whatever is in the way, until the row below is the status line. Then the walls' two shared colours count from 0 to 15 together, a jiffy each, and go back to blue, so the walls flash through all 16 of the C64's colours. One of the figures beside LIVES is wiped ($3AFA), and the player starts again on its start cell at row 12, standing still. The worms stay where they were. A game starts with three lives ($3B9D), and the game never gives another.

11 · High scores

The high-score table is kept inside the screen that shows it

There is no table of scores anywhere in memory. The five rows live in the stored picture of the high-score screen.

The high-score screen: SQUIRM, five rows TK1 to TK5 with 000000, in green, yellow, blue, red and white
The table as it loads: the author's initials, TK, five times.
Name entry: an alphabet along the bottom of the table, one letter highlighted
Name entry: left and right move along the alphabet, fire takes a letter.

The score itself exists only on the screen: six digits drawn light on dark at $0414, which add_score ($3724) adds to one digit at a time. The high-score table works the same way. Its five rows are part of the stored high-score screen at hiscore_screen ($1042), which show_hiscore_screen copies to the display. A new score is written into the bottom row on the display. It climbs a row at a time, with a beep each time it passes one (enter_name, $30DE). Then save_hiscores ($30B8) copies the five rows back into the stored screen. The best score also goes into the stored pattern of the top status line ($0FA4), and that is how HI keeps it until the machine is switched off. Writing it there has a side effect (Discoveries).