1985 · Beyond Software

Shadowfire

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

A rescue mission played entirely by pointing at icons. The C64 redraws its screen fifty times a second, and each time it does, the game moves one of the fifty people aboard Zoff's ship, so everyone, the player's team and the enemy alike, gets one turn a second.

01 · The screen

The screen is one bitmap with windows cut in it

The whole picture is a single multicolour bitmap from top to bottom, with no change of mode part way down. The upper thirteen cell rows are the command panel, loaded from tape as a finished picture, and in play the game draws only into its windows.

One frame of the status screen with Syylk chosen, recorded in the emulator and drawn here from the bitmap at $2000, the colours at $0C00, colour RAM and the sprites, by the site's renderer. All 104,448 pixels of the drawing match the emulator's own picture of the frame.

The panel's frame and its lamps are never drawn by the program: they arrive in the bitmap as the tape loads it. In play the game changes only the status icons' colours, the clock, the ticker, the view screen and the portrait monitor.

The lower twelve rows are cleared for each of the nine screens and drawn again from a list of icons (draw_screen, $4A63). An icon in the list is a picture, a place on the screen, and the routine that runs when the player presses fire with the cursor on it.

02 · The tunes

Music: the title music is six tunes played in a ring

Fred Gray's driver holds nine tunes. Six of them make the title music, each ending by asking for the next, and the one heard in play starts silent.

The page runs the game's own music driver, its bytes $1600-$1FC5 from the listing, on the kit's 6502, and plays what it writes through a model of the SID. Title music starts as the game starts it and runs the ring for as long as it plays; the tune lit under the player is the one playing, and a click on another moves the music there. test_music.js checks every write of each button against the same driver run on the simulator, two rounds of the ring for the title music.

Tune 7 sets voices 2 and 3 to a sawtooth and asks for tune 4 on its first frame. From there the ring runs 4, 5, 6, 2, 3, 8 and back to 4, 4,368 frames round, about 87 seconds. Tunes 2 and 3 play from the same three note tables, 3 for 144 steps where 2 stops at 96, and tune 5 is the first 72 steps of tune 4 again. Tune 9 sits in the driver with its own notes and effect, and nothing in the game asks for it.

Tune 1 is the music in play. Its voices 2 and 3 are pulse waves whose width is the byte at $1603 times eight, and a new game finds it at 0, a pulse of no width, which is silence. Holding fire on the team screen's up arrow raises it a step at a time to $40, so the music fades in; the down arrow fades it out. The player's "In play" button has it turned all the way up.

The driver turns each note on by storing the waveform in the voice's control register and then incrementing the register, which adds the gate bit ($1662). The SID's registers cannot be read back: a read returns whatever is still on the data bus, which here is the waveform just written, so the increment works. A SID that read back 0 would turn every note into a gate with no waveform, so the player above keeps the bus's last value too.

03 · The effects

Sound: the effects keep time with the in-game tune

Voice 1 plays the sound effects, and the in-game tune starts each one on its beat, every eighth frame. Some effects repeat on every beat until the game changes them; one plays once.

The same driver on the same 6502, playing tune 1 with its pulse width at 0 as a new game sets it, so that only voice 1 sounds. Each button sets the byte the game sets for that moment ($1602, or $1601 for the icon). test_music.js checks these four as well.

On every beat the driver takes the byte at $1602 and starts it as an effect. The game keeps it at $30, changes it to $3E while a message scrolls through the ticker, and to $0F while a character is weak: a heartbeat, whose low bit makes the driver flip another bit on every beat, so it alternates between two sounds. Choosing an icon puts $DE in $1601, played once at the next beat.

One byte describes a whole effect. Its bits choose the waveform, the envelope, the starting pitch, and how fast the pitch climbs (voice1_effect, $1F6B).

04 · The view screen

The view screen looks through a window on one map of the ship

The whole ship is one map of 32 by 32 tiles. The view screen shows five tiles by five of it around the chosen character, drawn into the bitmap behind an iris.

Drawn by a port of draw_view_map ($6A50) from the tile map at $84CB, the colour map at $88CB, the tile set at $BF96 and the map's 235 characters at $C288. test_map.js checks every cell of all 164 windows against the routine itself run on the simulator. The outline marks the cell where the character's own icon goes. Maps / levels draws the whole ship.

A tile is two cells by two, each cell one of the map's own 235 multicolour characters, and a tile's four cells share one colour byte from the colour map. The routine copies the characters straight into the bitmap: the map is 1 KB of tile numbers and 1 KB of colours, and the tiles and characters add 2.6 KB.

A location is a record of a map position, its exits and its name. Each exit is two bytes: the location it leads to, and a byte holding the distance in its low three bits and a door in the other five, 0 for none. A character walks a unit of distance in a time set by its agility (section 05), and a locked door stops it until a key card of the door's colour opens it, or Sevrina picks the lock.

05 · The team

Five numbers tell the six characters apart

Strength, agility and stamina in each record, a base added to agility and a factor that turns strength into damage and carrying: the six are the same code with different numbers.

Portraits from the table at $4A21 and the team screen's pictures from $818F, drawn from the listing by a port of draw_picture ($42D9). test_pictures.js checks it against the routine on every one of the 83 pictures these pages draw. The numbers are the records as a new game starts them: $CA0E onwards, agility_base at $CFB7 and strength_factor at $CF85.

Strength and the factor decide what a character can carry and how hard it hits. Strength times factor over 256 is both the most weight a character can carry and the damage it deals before its weapon's strength scales it. Above that weight, agility drains by a sixteenth of the excess every second. Maul's factor is the largest, $FF.

Agility and the base decide how fast a character walks. The game takes a quarter of the two added together, subtracts that from 127, divides by 8 and makes the answer odd: the seconds each unit of an exit's distance takes, from 15 at the lowest agility to 1 at the highest. Torik, with a base of $FF, walks fastest, and Maul, with $40, slowest.

Stamina pays for strength. Strength recovers on its own, faster the weaker the character and the more stamina it has left, and each step of recovery uses stamina up.

06 · The objects

Weapons that look alike hit differently

The ship holds 54 objects: eighteen tools, keys and devices, and 36 weapons drawn with eighteen pictures between them.

Every object's picture and record as a new game starts them ($CD98, seven bytes each), with its strength from weapon_strength ($CF15). The game names none of them.

An object is seven bytes: flags, where it is (a location, or the character carrying it), its weight, its picture and the routine that Activate runs. The flags say whether it is carried, whether it can be readied, whether it can be activated, and whether it can be picked up at all. A weapon fires by itself in combat, but only the one readied, and a character with none fights with bare hands, a strength of $20.

A weapon's strength byte holds two figures: the high four bits for an enemy in the same location and the low four for one next door. Weapons drawn alike do not share them: object 20 is $83 and the four after it $63, object 25 $63 and the four after it $F1. In combat the second figure is worked out and then never read, so every weapon hits the next location as hard as its own (Discoveries).

07 · The people

Everyone aboard gets one turn a second

Each time the screen is redrawn, fifty times a second, the game moves one of the fifty people aboard, always in the same order. Each of them gets one turn a second and does nothing in between.

The fifty records as a new game starts them, eighteen bytes each from $CA0E, in the order the interrupt runs them.

The interrupt fires at raster line $F8. After the input handler moves the cursor it plays a frame of music, then runs the next person's second (irq_entity, $66D1): a step of walking, a round of combat, a lock picked a little further, strength recovered. Then it rolls the clock's digits, scrolls the ticker, redraws one cell of the view screen's map and works out the places that person can reach. After the fiftieth, the time lock, the self-destruct and the mission clock each count one second.

Each person acts only in its own frame, so a fight between two people is one exchange a second each, and the six characters the player commands keep the same timetable as everyone else aboard.

The mission clock starts at 99:58 and counts down. Past 00:00 Kryxix is executed and the clock counts up instead (Discoveries).