1986 · Durell Software

Fat Worm Blows a Sparky

This minisite was contributed by air, yozlet. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/spectrum/fat-worm-blows-a-sparky with me to Gold.

A worm crosses a circuit board of 129 squares, drawn in solid perspective about seven times a second. Every block on the board is two rectangles, the sound effects are played by the loop that copies the picture to the screen, and the tape still carries the routine that made it.

01 · The view

Every block is two rectangles

The board is seen from straight above, and a block shows its sides only when it is away from the middle of the picture. The game gets that look from one table and one multiply.

A block is stored as an outline and two heights. The game draws the outline twice, once at the height of the block's foot and once at the height of its top, and magnifies each copy about the middle of the view by an amount the table gives for that height. A higher rectangle grows more, so a block's top slides away from its foot as the block nears the edge of the picture. The walls are the gaps between the two rectangles. A wall is drawn only where the top's edge has moved inward past the foot's, which happens on the side facing the middle.

The view, rebuilt from the board's own bytes with a port of the game's projection ($811E, $81DB). Move with the buttons, or click the picture and use the arrow keys. The port was held against the game's code in a Z80 simulator for 102,656 values of the multiply and 3,000 outlines, with no difference. The order the records are drawn in is the game's own too: $AAF3 lists the nine cells round the worm in the order it walks them, and $B008 puts each record after the last one $B045 says it must be drawn after. The filling is the page's own, from the game's pattern bytes ($80CB). The worm, the creatures, and the spindles' pictures are not drawn, a spindle is a small ring, and the seven boxes cut on a diagonal are drawn whole.

The table is 128 bytes at $6300, one for every two units of height. A coordinate v becomes v × (128 + byte) / 128. The bytes stay within 1.2 of 128h / (384 − h), which is the perspective of an eye 384 units above the board, where a square of the board is 256 units across.

The view never turns. Steering turns the worm, and the board only slides under it.

HeightTable byteMagnified by

02 · The board

The board: 129 squares, with two links a flat board could not have

The board is a linked list. Each square names its four neighbours by address, and the game keeps track of only the 5 by 5 squares round the worm. Laid out from those links, the squares fit a grid 16 wide and 22 deep, except at two links. Going east from one square marked A arrives at the other A, which the grid puts 13 columns away, and the two squares marked B are joined the same way across 7 columns.

Point at a square.

All 129 squares, drawn from the bytes at $6464 to $757B and placed by following each square's links from the start square. Click a square to put the view above there.

A square holds a list of items of seven bytes each: the height of the top, the height of the foot, a position, a size, and a type.

ItemsCountType
plain boxes176$C0 to $DF
data buses102$E2
spindles58$F7, 12 units deep
chequered blocks36$E8 to $EF
ramps34$40 to $BF
handler records23$F7, any other depth
eruption pads7$F4
boxes cut on a diagonal7$00 to $3F
blocks with a counter on top6$E0
de-bugger blocks, and the pads under them4 and 4$E3, $F5
pyramid, and the disk1 and 1$E1, $F6

The 23 handler records are instructions to the game. Each is a routine's address and four numbers, placed in the list just before the item the routine moves. One routine raises and lowers a block. Another sets a block's height from a sine wave. Thirteen blocks carry that one, and where several stand in a row with their phases staggered, the row ripples. A third sinks an eruption pad, waits, raises the pad again, and releases a Crawly from it. The handlers run only for the nine squares round the worm ($AF49), so the rest of the board stands still until the worm arrives.

Six blocks carry a three-digit counter in seven-segment digits ($BD12). The counter goes up when a sparky riding a data bus reaches one of four terminal blocks ($DEB8). The manual does not mention it.

03 · Sound

Sound: the loop that copies the picture plays the effects

The Spectrum's speaker is a single bit, and a program makes a tone by flipping the bit at a steady rate. In play the game has no time to spare for that, since drawing one frame takes about six to nine fiftieths of a second. The tone is made inside the drawing. The loop that copies the finished picture to the screen counts rows, and after every n rows it flips the speaker ($EA82). A small n gives many flips and a buzz, and a large n gives a few clicks.

The loop that fills the buffer before drawing does the same with a second number ($EACC). Filling a row is about three times quicker than copying one, so the same n sounds about three times higher there.

one frame with n =

The six effect lists, read from the bytes at $E4B2 to $E4F6. A list gives the copy loop one value of n for each frame. The page plays a frame as the loop would: the whole part of 128 / n flips, one every n rows of 564 T-states, and frames a seventh of a second apart. The count of flips was checked against the game's loop in a simulator for all 256 values of n.

ListStarted byValues of nThen

04 · Music

Music: 55 seconds on the menu, and a noise voice nothing uses

The menu plays a tune of 490 tones that lasts 55 seconds and then starts again. While a tone sounds the player holds the processor, so the menu's keys are read only between tones ($E791).

The tune as the game's own player produced it in a Z80 simulator: 75,491 flips of the speaker in 193,970,724 T-states. The page holds it as 43 shapes of tone and the order they come in. The bar shows each tone's pitch, and the pitch of every tone falls over its last 44 flips.

The tune is ten scripts of notes, half-length notes, and slides ($E5F8). The player also has a noise voice, switched on by a script byte of $C8 that rewrites one instruction of the tone loop ($E75D). None of the ten scripts contains that byte.

05 · Bugs on the worm

Four bugs: one on each section of the worm

A Crawly that touches the worm is counted onto the section it touched, and the worm has four sections. Every frame the counts shuffle. A bug moves one section toward the tail when the next section has none, and a second bug on a section moves one section toward the head. The worm dies when every section holds a bug, so four bugs are always enough.

The routine at $77A0, ported and held against the game's code in a simulator for 556 arrangements of bugs, with no difference.

The de-bugger is a striped block held off the board with a pad under it that is never drawn ($F5). Each section of the worm that crosses the pad has its count cleared ($A5DD). The head's own touch clears nothing.

A dying worm slows by 4 a frame and draws itself together, and each section that closes up loses its bugs. The game ends when the last bug has gone. The four sections should then turn into four explosions, but the code addresses the worm's records one place too low ($7841), so three sections explode and the tail stays as it was.

06 · The disk

Secret: the disk does not count your spindles

The manual asks for 50 spindles and then the disk drive. The board has 58 spindles. The code that ends the game when the worm's head touches the disk reads no count at all ($9E66).

The count is read in one place, by the routine that works the disk drive ($BED8). At 50 spindles that routine raises one block from height 32 to height 80. The block is the middle of a bridge. A ramp leads up to the block from the west, a platform stands at the same height to its east, and from the platform the drive's arm runs north over the wall round the disk. With the block down, the worm drops 48 units off the ramp and faces a step of 48, and the head can climb 10. Whether the disk can be reached another way was not tested.

Four moments of the ending: a hand comes down, closes on the disk, and lifts it away

The ending, reached here with no spindles collected by writing a disk item into the worm's path. A hand made of 15 four-sided shapes ($BAAE) comes down one row a frame, takes the disk, which is lettered DURELL, and lifts it out three rows a frame. The sequence ran for 86 frames.

The panel's SPINDLES figure counts spindles taken, from 0 upward. Each spindle gives five sparkies and scores its own number, so the fiftieth is worth 50 points and the first fifty are worth 1,275 ($A5AC).

07 · The tape

The tape still holds the routine that made it

The game was saved from the author's machine as it stood, 49,000 bytes from the start of the screen upward, and two leftovers came with it.

The first is the routine that made the tape ($EB9C). The routine writes the handler addresses into the board, builds the tables the sprites use, puts the game's entry address on the stack, and jumps to a save routine. The saved image therefore holds a stack that returns into the game. One jump leads to the routine, at $757C, three bytes before the game's real start, and nothing reaches that jump.

The second is the save routine's home, a tape utility signed “© 1983 NMS” ($FA56). Most of the utility is the Spectrum ROM's own cassette code, moved up in memory with its timing changed: 1,174 of 1,245 bytes are the ROM's.

The loader on the tape is the same ROM routine with the same faster timing. Every way out of the loader, the error exits included, returns to the game's entry, so a load that fails starts the game anyway, with whatever arrived.

The first screen: a 100 pound reward for information about forgeries

The first screen. The game shows the warning when the byte at $FC00 is not zero ($7C92). That byte is part of an instruction inside the tape utility, so it is always $FF on the tape.

On the tapeBytesWhat
BASIC program FAT96clears memory, loads WORM, calls 64242
WORM190the loader, for $FAF2
turbo block49,000$4000 to $FF67, with bits 453 and 709 T-states long where the ROM's are 855 and 1,710

08 · Controls

Eight controls, named by the game

BitKeyThe game's nameEach frameKempston
0PRIGHTERheading − 12 of 256right
1OLEFTERheading + 12left
2QFASTERspeed + 1, to 10up
3ASLOWERspeed − 3, to 0down
4HBOUNCERthe halt screen
5SPACEBLASTERfires a sparky forwardfire
61BURPERlays a sparky and turns the worm roundfire and down
7GABORTERends the game
The key redefiner, listing the eight controls by name

The redefiner ($E544) accepts any of the 40 keys for any control, the same key twice included.

The controls are collected into one byte a frame ($7C13). The manual lists Protek and Interface 2 joysticks as well as Kempston. The game reads one joystick port, the Kempston's, and only after the menu's option 2. The other interfaces work by pressing keys, which the redefiner covers.

A burper is a mine. A burper waits 160 frames, about 22 seconds, and then rises, and a Sputnik passing over the burper sets it rising at once ($DDDC). A sparky of either kind can be picked up again 55 frames after it was fired.

09 · Left in the code

Bug: a hi-score above 999 loses its thousands

The game keeps the hi-score correctly and draws it wrongly. The routine that draws one digit leaves a register at zero, and the hi-score code reads that register for the two leading digits without saving it first ($78B8). The score line beside it saves the register and is right.

Other things the game shipped with:

  • With 129 sparkies or more the worm cannot fire. The test before a shot treats the count as a signed byte ($7708), and spindles give five sparkies each with no ceiling.
  • Each frame the routine that builds the list of things to draw writes two zeros to addresses 0 and 1 ($AAF3). Those addresses are ROM, so nothing happens.
  • The trapezoid fill has a return behind two pushes ($93E5). An edge 256 pixels or more across would send the processor into the picture buffer. Of 900,000 shapes tried, none narrower than that did it, and whether play can draw one that wide is not established.
  • Nothing seeds the random numbers ($E472), so the first game after loading always meets the same creatures at the same moments if the player does the same things.
The menu after a game that scored 1234: the hi-score reads 00234

After a game that scored 1,234. The stored hi-score is 1,234 and the panel shows 00234. MY-SCORE reads 78 because the panel counts up to the real score three points a frame, and the game ended 26 frames after the score was set.

10 · The halt screen

H stops the game and bounces a ball

The manual calls the halt key's screen a bouncing ball routine. The ball is chequered, with eight gores and six bands, and it spins and bounces over a dotted grid with a shadow to its right ($D05E). Any key goes back to the game.

The ball's position and spin are never reset, so each halt carries on from where the last one stopped. H itself also leaves the screen, and then enters it again as soon as the key is let go.

The halt screen: a chequered ball over a dotted grid