1985 · U.S. Gold

Time Tunnel

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/time-tunnel with me to Gold.

A gnome with a broken time machine visits seven eras for the seven pieces of a scripture. The game draws each of its 53 rooms from a packed screen of about 400 bytes, runs every puzzle as a short routine of its own, and plays eight tunes on two voices.

01 · The game

A gnome who wants to be king

The gnome wants to be King of the Gnomes. The scripture that says how is in seven pieces, one in each of seven eras.

The credits screen: U.S. Gold presents Time Tunnel by Applied Systems Engineering
The credits print themselves a letter at a time, then the game starts by itself.
The gnome in the living room of Gnome Mansion, beside a fireplace and an armchair
Play starts in the living room of Gnome Mansion, in the present day.

The time machine stands in the mansion, missing a part. Lighting a fire in the living room brings the part out onto the table, and with it in place the machine goes to any of seven years: the Stone Age, Magical Persia, Mythological Greece, Colonial Salem, the California gold rush, an intergalactic spaceship, and the Black Hole.

Each era is a handful of rooms with one puzzle in it, solved by bringing the right objects, some of them from another era. The gnome carries one thing at a time, and the button does everything: it picks things up, puts them down, opens doors and fires a lightning bolt. When all seven pieces lie in the Black Hole they show a message, and the message says how the game ends.

02 · Music

Music: each era's tune keeps its own speed

Each era has a tune, and the mansion, the Black Hole and the throne room share one. The flute in Persia has two more.

The game's own music code, taken from its listing (the program as the Source code tab shows it, here addresses $BB11-$C5A7) and run on the site's 6502, a copy of the C64's processor written for this page. It runs once a frame, a fiftieth of a second, as the game's raster interrupt runs it: a call the video chip makes at the same point of every picture it draws. A button starts its tune as the game does, with tune_start and the era's tempo. test_music.js runs the game's own starts (era_enter's and the flute's) on the kit's simulator and checks that both write the same values to the sound chip, frame by frame, for 3,000 frames a tune.

The C64's sound chip, the SID, has three voices, and each plays one note at a time. The music uses the second and third, both with a triangle wave, a soft tone like a flute's, and leaves the first to the sound effects. A tune is a list of pairs for each voice, a note and a length (tune_table, $BCCE; a $ marks a number in hexadecimal, base 16, the usual way to write memory addresses). Every note starts at volume 7 of 15 (the chip's sustain level) and drops a level on every fourth step until the next note (music_play, $BCEE), so each note dies away. A voice skips its first pair when the tune starts and plays it when the tune comes round again: in most tunes that pair is a rest, so the pause falls between repeats.

The speed comes from the era. music_play runs every frame, but the tune moves on a step only on some frames. The game counts frames, and the era's record holds a mask: a number whose binary digits pick which counts let the tune step. The mask 1 lets it step on every other frame, 3 on three in four, 7 on seven in eight, and the spaceship's $FF on all but one frame in 256.

TuneWhere it playsTempo maskSteps a second
0Colonial Salem337.5
1The California gold rush125
2Magical Persia, and the flute put down125
3Gnome Mansion, the Black Hole and the throne room743.75
4The intergalactic spaceship$FF49.8
5The Stone Age125
6The flute played in Persia125
7Mythological Greece125

03 · Sound effects

Sound: a second effect is dropped while one plays

The effects play on the sound chip's first voice, one at a time.

The same sound code as the music, from the listing, on the site's copy of the C64's processor. A button calls sfx_start ($BB32) as the game does, then sfx_play ($BB51) once a frame, as the main loop does. Effects 2, 3, 4 and 6 repeat until the game stops them, so here they play until their button is pressed again. test_music.js checks these against the game's own code as it does the tunes.

An effect is a script of one-byte commands (sfx_script, $BC6E): set a pitch, set a waveform, fade, wait, slide up or down, loop, and warble. The code keeps track of one effect at a time, so sfx_start ignores a new effect while another plays. Seventeen places in the game start an effect.

EffectStarted by
0the closet (a store room he can reach from any era) refusing to let him go, the trip into the closet, Medusa beaten
1the living room's fire lighting, Medusa's shot, Salem's brew and the broom it makes
2the oxygen tank's valve appearing, in the gold rush (gold_tank)
3a trip in time (time_travel)
4the time machine's button, the spaceship's teleport
5arriving in an era, the machine's countdown over, the bolt that hits Persia's lamp, the dynamite going off, arriving on the moon
6the Black Hole's message

04 · Objects

Seven sprites for the objects in a room

Everything the gnome can see or carry is an object: the scorpion, the cage, the broom, the king on his throne. Each has a place in time and a picture.

The object in the room where it starts, three times over: the game's own room_enter ($3A47) draws the room and gives the object its sprite, and sprite_draw ($A185) draws each frame into it, from the listing, on the site's copy of the C64's processor. The frames change at the game's speed, as sprite_update ($A15E) steps them: each lasts as many frames of play as the object's table says, and a frame of play is a fiftieth of a second. An object that starts nowhere is drawn on the plain colour that shows it best. Where the object starts comes from obj_start_table ($0909).

Objects 4 to $6C live in the world. For each one the game keeps five bytes in five tables: its era ($069C), its room ($0705, $FF for nowhere and 0 for carried), its x and y ($076E, $07D7), and the sprite it has on screen (obj_slot, $0840). On entering a room, room_enter ($3A47) gives a sprite to every object whose era and room are the current ones. Objects 0 to 3 are the gnome walking up, down, and to either side.

A sprite is a picture the video chip draws over the screen by itself, and it has eight. The gnome always has sprite 0, so sprite_alloc ($A0FE) hands out the other seven, from 7 down, and a room can show seven objects at most, the one the gnome carries among them.

A sprite's picture is 24 pixels wide and 21 high, three bytes to a row. A frame of an object is copied into it in rows of one, two or three bytes, so a narrow object's frames take less memory. The object's flags give its colour, the width of its rows, whether the sprite is stretched to double width, and whether it is multicolour. A second table gives how many frames it has and how many frames of play each one lasts, and whether the gnome can pick it up.

05 · The screen

One frame of play, rebuilt

The living room, drawn on this page from the memory and the video chip's registers (the settings it draws the screen by) that the emulator recorded over one frame of play.

All 104,448 pixels match the emulator's picture of the same frame. The game changes no video register while the frame is drawn, so one set of registers draws the whole screen.

The screen is a grid of cells, 40 across, and each cell shows a character: a small picture, 8 by 8 pixels, from a character set of up to 256 of them. The game draws its rooms with characters in multicolour mode, where each character is four double-width pixels across, in three colours shared by the whole screen and one of the cell's own. The game keeps one character set for each era, packed (squeezed into fewer bytes; a byte is one number from 0 to 255), and unpacks it into memory at $F000 on arrival (era_load_charset, $3456). The gold rush and Salem have two sets each, one for the street and one for the caves or houses. The screen sits in 24-row mode, so the 25th row is hidden under the border.

06 · Rooms

A room in about 400 bytes

Every room is one packed screen. The 44 screens take 17,911 bytes, where the plain screens would take 42,460.

The living room as the game draws it on the page: the game's own code unpacks the era's characters and the room's screen, from the listing, on the site's copy of the C64's processor. The Maps tab draws all 53 rooms the same way.

A packed screen starts with five bytes: the three colours the whole screen shares, and two colours for the cells. The rest is the 960 cells of 24 rows, packed (room_draw, $39A1). The packing (unpack, $3B2C) works in groups of eight cells. A byte is eight bits, each 0 or 1, and the first byte of a group is a flag byte: each of its bits, from the top, says whether the next cell repeats the last value or takes a new byte from the data. So a run of the same character costs one bit a cell. A new byte equal to the last one ends the screen.

Each cell's byte holds a character number, 0 to 127, in its lower seven bits. The top bit picks which of the two cell colours from the header the cell gets. The button above marks those cells. The living room's header is 00 0B 02 06 03: black, dark grey and red for the whole screen, and blue or cyan for the cells. The same packing holds the character sets.

Two rooms are empty. A header with its top bit set means no screen at all (empty_screen, $41A5), and room_draw fills the screen with character 0 on black. The Black Hole's first room is one, so it is black but for its sprites.

07 · Eras

Every era is one record in a table

The time machine has seven years on its dial. The game has nine eras: those seven, the mansion, and the throne room where the game ends.

Read from the listing: each era's record (era1_record ... era9_record), found through era_offsets ($0BA8). The columns name the record's bytes 0-1, 2-3, 4-5, 6, 7 and 8-9; the rooms' packed screens follow from byte 10, one address a room.

The era is one number, kept at $2A, and the room another, at $19. Each era's record names a routine (a piece of the program that others call) that runs every frame of play in that era, another that runs as the gnome walks into one of its rooms, the era's character set, its tune and tempo, where the gnome arrives, and the address of each room's screen. Both routines go straight to the code for the current room through a table of addresses (switch_room, $387D). So the whole game is one main loop that calls the era's routine, and each puzzle is a few dozen instructions in one room's entry of that table.

The time machine control room: seven years around the screen, 1849 lit, and two lines of instructions
The time machine's controls, in the character ROM's letters. Each press of the button lights the next year.

The controls are the mansion's fourth room. Each press of the button lights the next year, and the stick pulled down leaves (controls_pass, $11C1). When the machine runs, the lit year's number, 0 to 6, plus 2 is the era it goes to (machine_countdown_over, $10E4). The game's description in the LaunchBox database says the year is chosen with the joystick and RETURN goes back to the mansion. The screen itself gives the right instructions: FIRE BUTTON SELECTS NEW YEAR, DOWN JOYSTICK RETURNS TO MANSION.

08 · Controls

One button does everything

The game reads both joystick ports at once and one key, F7, for pause.

The button, pressedWhat happens
at a mansion doorthe door opens (door_check, door_use)
at the time machinethe machine runs, and travels if it is mended (machine_button)
carrying somethinghe puts it down (object_drop)
touching something he can carryhe picks it up
none of these, facing left or righthe fires a bolt of lightning (object $11)
held for 128 frames, 2.56 secondshe goes to the closet, and back again after 60 frames held there

From play_button ($361D), play_state ($34B0) and closet_pass ($116A). The main loop combines the two joystick ports ($DC01 and $DC00) into one reading, a bit-by-bit AND, so a joystick in either port works.

A few things cannot be picked up at certain times: the oxygen tank once it stands on its pad in the gold rush with its valve, the log while it burns, the cauldron while it sits in Salem's fireplace, and the cage once it has trapped the scorpion. The gnome walks a step on every other frame, so the joystick moves him 25 steps a second.

F7 pauses and resumes. Pausing silences the sound chip, and the main loop then does nothing but count its two clocks (keys_read, $38FF). The clocks are a count of frames from 0 to 63 ($23) and, under it, a count from 0 to 59 that steps each time the first wraps ($BD), once every 1.28 seconds. The game's slow timers, such as the moon's air and the dynamite's fuse, are in counts of the second.

09 · The closet

A closet outside time

Holding the button takes the gnome to a closet, from any era, with whatever he carries. Holding it again takes him back.

The closet, as the game's own room_enter draws it, with the torch lying where the game starts it.

The closet is room 9 of the gold rush era, a room no door leads to. play_state keeps the era, room and position he left in $B0-$B3, and the closet's own code (closet_pass) puts him back there. So the closet is a store for objects that are needed in other eras, and the torch starts there.

The closet keeps him in when it is too full. Before he leaves, closet_pass counts the objects lying in it. Five or more, and he stays, with a sound. A piece of the scripture puts the count at five by itself, so he cannot leave while a piece lies there. The game's description in the LaunchBox database says the closet holds eight objects; the code lets him leave with four at most. Discoveries has the details.

10 · The end

The message in the Black Hole

The seven pieces drift in the Black Hole until all seven are there. Then they line up and show a message.

The Black Hole's second room, as the game's own code draws it: the message, in mirror writing.
The throne room, era 9, where the game ends, with the staff in the king's hand.

The Black Hole's first room is black. Every eighth frame hole_pass ($184E) looks for the seven pieces of the scripture, objects 4 to 10. While any is missing, each piece that is there drifts a random step. When all seven are there, each moves a step at a time to its own place, and three counts (3.84 seconds) after they are all in place the gnome is taken to the second room.

The second room is the message, drawn in the era's own characters and in mirror writing: "The Daimyo Carries The Staff". It stays 6 counts of the clock (7.7 seconds) the first time, and a count longer each time after, up to 15 (hole_room_entry, $181C). Once it has been read, the snake in Persia's basket rises for good when the flute is played, and the risen snake, picked up, turns into the staff (snake_to_staff, $1CF3). Carrying the staff into the last room of Persia's cave ends the game in the throne room (persia_cave, $1E9E), with "GRATULARI!!!!!" across the screen and the staff in the king's hand.

There are no lives. The scorpion, the stalactites, the bats, the snake, Medusa's shot and the pit in Persia's cave send the gnome home to the mansion, and running out of air on the moon puts him back in the spaceship (gnome_hurt, $3378). The game lasts until it is solved.

11 · The broom

Salem's flying broom

The broom made in Salem's cauldron flies, with its own small physics.

Hold a button, or click the picture and use the arrow keys. Salem's third street room is drawn by the game's own room_enter, with the broom put in it and the gnome on it. Each pass, a fiftieth of a second, the page runs the game's own salem_broom ($3111) with the stick as the buttons set it, then sprite_update for every object, as the main loop does, from the listing, on the site's copy of the C64's processor. The line under the picture is the broom's height over the last 384 passes, higher up the page for higher on the screen; the dashed line is its height at rest. The broom stops at the right edge here, where in the game it flies on to the hillside.

The flying broom is three objects, the left end, the middle and the right end, kept 12 steps apart (salem_broom, $3111). The gnome picks up the middle to ride it, and from then the stick steers the broom, not him. Its height rests at $61. Up starts a hop and down a dip. The speed starts at one line a step, and each step it loses a pull of 2/256 of a line, so a hop rises, slows and comes back down to rest (broom_height, $320F). The broom steps on three frames in four. A dip works the same way upside down. Pushing the other way, down during a hop or up during a dip, switches to a stronger pull: 5/256 for a hop and 4/256 for a dip (broom_pull, $3287).

With the stick at rest the broom wanders by itself, up and left until it nears the left edge, then down and right (broom_wander, $30CA). Ridden off the right edge of the third street room, it flies to the hillside, where the last puzzle of Salem waits under two rocks.