1985 · Epyx

Winter Games

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

Seven winter sports on two disk sides, each one a program of its own that the loader swaps in over the menu. Every judge, pacer and clock in them is a few lines of arithmetic, and in Figure Skating that arithmetic wraps round: twenty falls earn a perfect 6.0.

01 · The game

The game

Up to eight players pick a country and compete in seven events. The menu keeps the scores and hands out the medals.

The title screen: EPYX presents WINTER GAMES by Action Graphics
The title screen, the first thing the loader puts in memory.
The main menu with seven numbered options
The main menu. Option 4, practice, plays one event with no scores kept.

After the title, an opening ceremony runs by itself: a torch bearer runs up the steps and lights the flame, and doves fly. Then the menu asks for the players. Each types a name and chooses one of eighteen flags, one of them Epyx's own. The players can compete in all seven events, in some of them, or in one, or practise any event alone.

The seven events are Hot Dog Aerials (freestyle ski jumps judged on stunts), Biathlon (cross-country skiing with four shooting ranges), Speed Skating (two skaters side by side), Figure Skating and Free Skating (a program of jumps and spins, judged), Ski Jump (distance and style), and Bobsled (a run down an icy chute against the clock). After each event the menu ranks the players, gives gold, silver and bronze, and plays the winner's anthem. After all seven, the medals decide the champion: five points for gold, three for silver and one for bronze.

Hot Dog Aerials
Hot Dog Aerials
Biathlon
Biathlon
Speed Skating
Speed Skating
Figure Skating
Figure Skating
Ski Jump
Ski Jump
Bobsled
Bobsled

Each event at its start, from the emulator. Free Skating looks the same as Figure Skating: it is the same program, entered five bytes further on.

02 · Figure and Free Skating

Skating: every move, and the mark it earns

One program in two modes. Figure Skating has one minute and counts each element once; Free Skating has two and counts each up to three times. Click the moves to skate a program and watch its base mark.

Base mark 0.0

Each skater is drawn by the game's own draw_frame ($1BBB) from the bytes the Source tab lists, run on a model of the C64's processor. A $ marks a number in hexadecimal, base 16, and here each is an address in the C64's memory. Each move plays the frames its records list, each held for as many frames as the list says (a frame is one picture on the screen, fifty a second on a European C64), and a jump rises and falls by the game's own jump_height ($1436). The number under a move is what it would add to the mark now. Each click runs base_mark with the falls, the awkward moves and the elements where the program leaves them ($46, $47 and the list from $4A). The judges then add their random tenths. test_marks.js checks the page against the routine.

The elements are seven: the camel spin, the sit spin, the double and triple lutz, the double and triple axel, and the camel spin into the sit spin. Skating forward, fire with the stick up and right jumps a double axel, down and right a triple. Skating backward, up spins the camel, down the sit spin, and the left diagonals jump the lutzes. A take-off is clean when fire is pressed on the stride's glide, and awkward otherwise. A spin must be left after exactly seven turns, or its ending is awkward; an eighth turn throws the skater down.

In Figure Skating the elements are worth 0.7, 0.7, 0.6, 1.1, 0.6, 1.1 and 1.2, and the seven together make exactly 6.0. Each awkward move costs 0.2 and each fall 0.7. In Free Skating each counts up to three times at a lower value, and the falls and awkward moves also lower a ceiling of 6.0. The arithmetic has two faults. Free Skating's marks come out a tenth short, and Figure Skating's penalty can wrap round: fall 22 times with no elements and the mark is 6.0. Both are on the Discoveries tab.

The skater is eight sprites, the video chip's shapes of 24 by 21 dots that move over the picture, in four pairs making a square two by two. In each pair one sprite is multicolour, orange with blue and light grey, and its dots are two wide. The other, in front of it, is white like the ice, with a hole in the skater's shape. Its edge trims the multicolour dots where they stick out, so the skater's outline is finer than a multicolour sprite can draw alone: untick White sprites to see the difference. The sixty frames are packed (frame_ptrs): each eight bytes of a shape start with a mask byte whose set bits stand for the bytes that follow, and the rest are filled, with 0 in a multicolour shape and with $FF in a white one. draw_frame unpacks each frame into one of two sets of eight shapes, at $BC00 and $BE00 in turn.

03 · Ski Jump

Ski Jump: a centred lean flies furthest

In the air a random drift tips the jumper off balance, and the corner close-up shows which way. Pushing the stick against it brings the jumper back.

For each of the nine bands of the lean, the close-up's pose when the drift works on the stick's left and right (lean_frames_lr) and when it works on up and down (lean_frames_ud, $1A77). Each is drawn by the game's own draw_frame ($1973) over the landing slope's picture, which the game's unpack_list ($1273) unpacks from the listing. Below them, the flight's speed lost each frame in 256ths (drag_table), and the style points lost on coming back to the centre from that band (lean_size and lean_penalties, $16DA).

A flight starts at a speed of 60 and lands when the speed has fallen to 40. Each frame the speed adds to the distance, and the lean's drag takes some off: 14 in the centre band, up to 21 at the edges. So a jumper kept centred stays in the air longest and flies furthest. The drift is drawn at random, a direction on one of two axes. On one the jumper tips back or forward, and the stick's left and right bring the lean back; on the other the skis cross or the knees bend, and up and down bring it back. The stick moves the lean two a frame, three against the drift's own direction.

Style starts at 20. Each return to the centre costs 0, 2, 4 or 8 points, by the worst lean since the last one. A good landing keeps at least 6, and a fall takes 18. The score is three times the distance plus the style points, worked out on the whole distance, so a jump shown as 68.6 metres scores 205.9.

04 · The anthems

Music: an anthem for every flag

Each country's flag has its anthem. The menu plays it when a player picks the flag, and again for every gold medal.

Each button runs the game's own music player, the bytes the Source tab lists, on a model of the C64's processor. The page calls music_init ($1DA3), then music_start ($1DE0) with the country's place in the flag chooser, then music_step ($1E11) twice a frame, as the menu calls it. The opening ceremony's two tunes run on the ceremony's copy of the same player ($B056). test_music.js runs every button against the game's code and checks every write to the sound chip, frame by frame.

The anthem player is small. The C64's sound chip, the SID, has three voices, each playing one note at a time, and a tune is a list of four bytes a note: one pitch for each voice and a length. Voices 1 and 2 play a pulse wave, a hollow tone, and voice 3 a sawtooth, a brighter one. For a note's last four steps the player turns each voice's gate off, the chip's signal to let the note fade. So every note dies away briefly before the next begins. The player steps twice a frame.

The table at $1DF9 turns a place in the flag chooser into a tune. The chooser has three rows of eight places, and only six flags in each row. The two places after each row's sixth flag are empty, and the menu uses two of those empty places for its own tunes: place 6 is the final standings' tune, and place 7 the world records'. The others play the U.S.A.'s anthem. The opening ceremony carries a second tune that it never plays; its 345 bytes are the menu's world records tune, byte for byte.

05 · The events' music

Music: each event's tune, on one sound engine

Every event brings its own music and sound effects, and all but one play them on the same engine.

Each button runs the event's own sound engine on the bytes the Source tab shows: stop_all, then start_sound with the tune's number in the processor's A register, then sound_step once a frame. In the game the raster interrupt calls it: the video chip stops the program when it reaches a set line of the screen, once a frame, and runs a routine of the event's. Bobsled's engine runs at $C000, where its start-up copies it. Each event's tune goes round until it is stopped, except the two skating programs': Figure Skating's lasts 3,633 frames and Free Skating's 7,203, a minute and two minutes at sixty frames a second, the length of each program. test_music.js checks every write against the game's code.

A few of the effects, started the same way. The long jump's sound starts two more, the fanfare and the claps, from its own script.

The engine has six slots of 32 bytes. A sound is a header (which slot it plays in and on which voice of the SID) and a script, a little program of its own. A script byte under $80 (128) is a note, followed by its length in frames. A byte from $80 up is one of 29 commands: loops, calls and jumps within the script, a call to machine code, the envelope, the waveform, a slide, and the filter. Command 2 starts another sound, which is how a tune's first voice starts the other two. Every frame sound_step counts each slot down, runs its script when the count reaches zero, and copies the slots to the chip, slot 5 first, so that where two slots share a voice the lower-numbered one wins.

Hot Dog, Biathlon, Figure and Free Skating, Ski Jump and Bobsled carry this engine. Speed Skating carries an older form with three slots ($A600), without the pulse-width sweep (a slow change in the pulse wave's shape that makes a held note shimmer) and without the S key that switches the other events' sound off.

06 · One frame

Bobsled, one frame rebuilt from memory

The bobsled screen is one bitmap: the course map on the left, the view down the chute at the top right, and the panel with the speed bar and the clock below it.

Drawn by the site's model of the video chip from the frame's memory and the 30 writes the game made to the chip during it, recorded in the emulator in the left-hand bend from stretch 21, the sled high on the right wall. The drawing matches the emulator's picture of the same frame pixel for pixel, but for the player's name on the bottom row: the video chip draws that row's letters from the character ROM, where the C64 keeps its own letters, and the page does not carry it.

The screen is a multicolour bitmap: a picture stored dot by dot, where each pair of dots across shows one of four colours. The video chip sees 16K of memory at a time, and this picture is in its third 16K, bank 2, at $A000, with its colours at $8000. Twice a frame the raster interrupt changes the chip's mode: to bitmap for the picture, and to text for the bottom row, which shows the player's name in the character ROM's letters. The view down the chute is redrawn a piece at a time as the sled moves on: a far piece and a near piece, chosen by the stretch of course the sled is on (bs_course). The sled is drawn with sprites, small pictures the video chip lays over the screen. They are built again from one of 13 frames as the sled climbs the walls (build_sled, $4E45).

07 · Hot Dog Aerials

Hot Dog: two moves decide the mark

In the air the stick picks a move: four stunts on the diagonals and two flips, back and forward. Only the first two moves count.

The first two movesBase mark
None0.0
One stunt6.3
One flip7.2
The same stunt twice8.7
The same flip twice9.2
Two different stunts9.6
A stunt and a flip, or two different flips10.0

From judge, which then takes 1.4 off for each awkward move. A fall scores nothing.

Each move's script holds a pose while the stick is held. Held for 10 to 19 frames, the move is clean; let go sooner or later, it is awkward, and the skier shows a clumsy pose for twenty frames. A flip held long enough goes round again and counts as a second flip, the same as the first. At the snow the stick must be centred and the skier in the arms-up pose, or the landing is one of four falls, chosen at random.

Eight judges then mark the jump. Each adds a random tenth below or up to two tenths above the base mark, except to 0 and to 10.0, and the total is their average (judge_marks, $185D). A mark of 9.0 or more brings the crowd's cheer.

08 · Biathlon

Biathlon: the skier's pulse moves the rifle

Every stroke raises the pulse, and at the range the pulse makes the sight jump on every heartbeat.

The 41 entries of heart_table, read from the listing: for each pulse from 60 to 140, the frames between heartbeats () and how fast the sight falls between them, in 256ths of a line a frame ().

Skiing is a rhythm: the stick left or right on the flat and uphill, down on the downhill to push with both poles, let go between strokes. The power of a stroke builds while the skier waits, eight a frame on the flat and all at once uphill, and the stroke adds it to the speed. Each stroke also raises the pulse by a 32nd of what it lacks of 140, twice as much uphill (pulse_up, $2EC6). Resting, the pulse falls back towards 60.

At a range the heart decides the aim. Each beat throws the sight up to line 88, and between beats it falls, faster the higher the pulse. A shot hits only while the sight is between lines 113 and 117 (shot, $6FEC). At a pulse of 60 the heart beats every 50 frames and the sight drifts down slowly; at 140 it beats every 15 frames and drops more than twice as fast. Each miss adds five seconds to the time.

09 · Speed Skating

Speed Skating: a pacer on a rubber band

With one player, the computer skates the other lane, and it skates better when it is behind.

Who leadsThe pacer's skill, each time it picks a stride
The player, or levelOne more, to 255 at most
The pacer, skill above 160Two less
The pacer, skill 160 or lessOne less, to 56 at least

From pacer_adjust. The skill starts each race at 104 (ss_race, $946C).

A skater's legs are a cycle of states, a stroke to the right and its glide, then a stroke to the left and its glide. The stick moves the cycle on: right from the left glide starts the right stroke, left from the right glide the left one. Speed comes only from the first two states of each stroke, so the rhythm is everything. The pacer has no joystick: each time its stride moves on, it compares a random byte with its skill, and below the skill it takes the right direction for its state. Otherwise it holds its stroke at full stretch a little too long.

The skill moves after every choice, up while the player leads and down while the pacer does. A player far ahead faces a pacer that chooses right 255 times in 256; a player far behind, one that chooses right only 56 times in 256. Either way the pacer stays close. A skater who has not crossed the line after three minutes gets a FAULT.

10 · Bobsled

Bobsled: the course, stretch by stretch

The run is 177 stretches of four bytes each. Each names the view's two pieces, the bend, and how many dots of the course map to light.

The map's 400 dots (map_dots) in the colour of the stretch that lights them: a straight, a right-hand bend, a left-hand bend. The start is at the bottom. The stretch chosen is drawn white, its bytes from bs_course.

The speed is a number three bytes long. Each frame gravity adds 10 to its middle byte on a straight and only 2 in a bend, and friction takes off the sled's distance, in whole places, from the line the bend wants. A bend also pushes the sled up its outside wall, harder the faster it goes. The sled has 31 places across the chute, and ten frames in a row at either wall is a crash. The stick steers, and down or fire brakes while the speed is high.

A crashed sled stops being steered, but the run is not over until the wreck has slid to a halt: the speed drops a little every three frames, and the course moves on beneath it. A wreck that comes to a halt before the line records 99.99, the slowest time there is. The clock counts six frames to a tenth and shows the frames as the hundredths, 0, 2, 4, 5, 7 and 9.