1987 · System 3

IK+

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

Three karateka share one floor, and the C64 draws only two of them with sprites. The third is built from the floor's own characters and moves two pixels at a time, which is how the pause can stand five fighters in a row.

01 · The game

The game

IK+ puts three karateka on one floor. Player one fights in white and player two in red, and the computer takes every fighter nobody is playing. A hit scores a full point (two dots) or a half point (one dot), depending on which way the two fighters face, and between 100 and 1,000 points by the blow.

A round ends when a fighter has six dots or the clock runs down from 30, and a human who comes last alone drops out of the game. Every third round is a bonus round: one fighter with a shield deflects balls thrown from both sides. A judge stands in the widest gap between the fighters and comments in a speech bubble.

A round about to start: three karateka on the floor below a torii gate at sunset, the judge between them The bonus round: a fighter with a shield deflecting bouncing balls

Left: the first round of a one-player game, in the emulator. Right: the bonus round, from the C64-Wiki.

The Fighters tab has the moves, every pose the fighters are drawn in, the points and how the computer's fighters improve. The Sound tab plays Rob Hubbard's tune and the six digitised shouts.

02 · One frame

One frame, rebuilt from memory

The picture below is drawn by this page from the game's memory, the way the video chip draws it, line by line.

A frame of a one-player fight, recorded in the emulator with every write to the video chip and the line it happened on, then drawn by site/lib/c64.js. All 104,448 pixels match the emulator's own picture of the same frame. The button marks the lines where the frame interrupts change the screen's mode, memory or background colour.

The screen is three screens stacked. Rows 0 and 1, the scores, the dots and the clock, are text in a character set of their own. From line 66 the arena is a multicolour bitmap: the sky, the torii gate, the tree in blossom and the sun going down over the bay. Inside the bitmap two more interrupts change the background colour, the one colour every cell shares: pink for the sky, purple from line 121 at the horizon and blue from line 128 for the sea. At line 162 the screen switches back to text for the floor, in a second character set that holds the judge, the speech bubble's letters and the third fighter. A chain of raster interrupts makes the switches, and the frame interrupt, an NMI from CIA 2's timer timed to one PAL frame ($0BE6), restarts the chain each frame.

Two fighters are sprites, each three sprites wide, with the six hardware sprites used again in three bands down the fighters' height ($1551). The third is drawn in the floor's characters ($4042), so it moves two pixels at a time with the floor's fine scroll and needs no sprites at all. Each fighter's feet are reflected in the floor as a one-colour silhouette: the sprite fighters' in the lower rows of their lowest sprites ($F150), the third fighter's in characters ($F1F9). The floor has two screens, and each step is drawn into the one not on view before the two swap, so the third fighter is never seen half drawn.

03 · The judge

The judge says “is out” only to a human

At the end of each round the judge sums it up in his speech bubble. A computer fighter that comes last is told to improve. A human player who comes last alone is told they are out, because the game is over for them.

Every message in the game, drawn by a port of its own printing routine ($38BF): each letter is a five-line glyph from the font at $7000, inverted into a column of three characters ($39C6), and doubled in height between the codes $9A and $9E. The bubble's width comes from $3863 and its rounded ends from $3A03; the names are the game's own ($3473). The time bonus is drawn for 12 seconds left. When each message appears is read from the code that asks for it.

The game ranks the three fighters by points, notes which of them are level and which places the humans took, and looks the combination up in a table of 28 bytes ($11AC). The high half of the byte is the message; the low three bits say who plays on. A human who comes last alone is out. In a tie for last nobody is, and when all three are level everyone plays on and the judge says so. When a computer fighter comes last instead, the judge has a kinder word for it: “COME ON”, “MUST IMPROVE” or “COULD DO BETTER”.

In the attract mode's demo fights nobody is human, and the judge shows one of eight hints instead, picked at random ($1286). The pick is a number from 1 to 16 in a table that starts at 0 ($11C8), so the table's first entry, message 10, never appears: “IS BEST / IS SECOND / IS WORST”. Neither do messages 23, 24 and 28, which read “SPARE BUBBLE”. Two players who tie for second without touching their joysticks all round are both dropped, and get a hint too ($12DF).

04 · The bonus round

The bonus round

In the bonus round 64 balls fly in from both sides, and the player deflects them with a shield for 100 points each. Some rounds throw flashing balls that bounce low and high in turn.

Which of the six throwing slots throw flashing balls in each bonus round of eight ($F71D, by the bonus count AND 7), and where the launch rate stops growing ($F725).

A bonus round goes to each human player in turn ($F2AB). Balls come faster as the round goes on: the launch rate starts at $0080 and grows by 8 a ball up to the round's limit, and each ball is heavier than the last, up to a limit. A ball that reaches the fighter knocks the shield out of his hands. Surviving all 64 balls is worth 5,000 points.

05 · The keyboard

Every key that changes the background

The asterisk and two three-key combinations repaint the arena, and no other key touches it: * recolours the sun’s reflection, D O M together the sky and the sea, and R T X together change how the reflection ripples. Press them below, or on your own keyboard.

The recorded frame of section 02, cropped to the arena and drawn again 25 times a second, with the background colours and the reflection's colours the keys set, and the sun's reflection and its five glints moved by a port of the game's own code (antics_step, $7571). Run against the original in the kit's 6502 simulator, the port wrote the same bytes over 4,000 steps, through every drift pattern. The creatures are left out. Time-lapse brings the drift every 64 frames instead of every 512. Below the arena, the sun's reflection four times larger.

Every set each combination steps through, in order, from the game's tables ($178B-$17A2, $7639). The game starts on the first of each, so the first press shows the second. Choose a row to see it above.

The keyboard is read in three places: read_keys ($17AD), run by the frame interrupt every frame, which answers every key in the table below; the RUN/STOP check ($116D); and the check for S and E ($1C54). Of all the keys they answer, only the asterisk and the two combinations write anything the arena is drawn from. A combination acts once it has been held for twelve frames, and steps on again while it is held.

* steps through four colourings of the sun’s reflection ($1807). The reflection is two sprites with one shape, behind the picture: sprite 7 stretched to double width and sprite 6 inside it. Two raster interrupts colour them, one at line 121 for the rows above the water’s middle line ($0AE8) and one at line 134 for the rows below ($0B27), so each set is four colours ($FD54-$FD57).

D O M steps through eight pairs of sky and sea ($1837, $179B). Each is one byte, the sky’s colour in its low four bits and the sea’s in its high four ($F3, $F4): four skies, light red, light blue, cyan and blue, over a blue sea, then the same four over a red one. They are the background colour of the bitmap, which raster interrupts set at line 67 for the sky ($0A85) and line 128 for the sea ($0B10); the purple band at the horizon stays purple.

R T X changes how the reflection moves ($1855). The C64-Wiki gives D, O and M, and the untouched high-score table spells out a hint that names the asterisk and ends “and others”; none of them names this combination. Every other frame each of the reflection’s 21 rows takes one step along a wave ($7571): each row has a phase ($BEA0) that picks how far its slice of the reflection is shifted ($72F3), so the ripple slides down the rows. Once every 512 frames, about ten seconds, the drift ($7649) nudges the rows’ phases, a step for each row from a set of four repeated down the rows. The key combination picks the set ($7639, through the operand at $7665): the game starts on −1, +1, −1, −1, and the other three are +2, −4, +6, −2; +2, −2, +1, −1; and −1, +1, +3, −3. In the emulator R, T and X stepped it, and so did P, O and N.

Each combination is any one key from each of three groups, because both three-key checks drive three keyboard rows at once and need all three column bits to read low ($1922): D, J or L with C, M or full stop and T, O or @ for the sky, and R, I or P with T, O or @ and X, N or comma for the ripple, 27 choices each. The choices last through every new game: game_reset ($16E1) clears zero page from $4B to $F2 and the variables from $FD58, just short of the colours at $F3-$F5 and $FD53-$FD57, and the drift pattern is an operand in the code. The colours are set only once, at start-up ($0F5D).

No key brings the worm that inches along the shore. It, the bird, the spider on its thread and the leaping fish come on their own ($767E): with none on screen, the game tries to start one on two of every 256 steps of the reflection, and then only when a random number is below $80, picking one of 32 routes, eight for each creature. Nothing in that code reads the keyboard.

KeysWhat they doWhere
F1, or fire on joystick 2a one-player game$18D2
F3, or fire on joystick 1a two-player game$18C2
F5music off or on$186C
F7shouts and bonus-round effects off or on$18A1
1 to 5game speed$17E9
*the sun's reflection, four colour sets$1807
one key from each of D J L, C M . and T O @sky and sea, eight colour sets$1837
one key from each of R I P, T O @ and X N ,how the sun's reflection drifts, four patterns$1855
S and E togetherthe trousers fall (first two levels)$1C40
RUN/STOPpause$116D

Every key the game reads. Only the three rows in the middle change the background; the pause recolours the floor, to stand five fighters in a row.

The trousers also fall without the keys: a fighter left idle for 128 steps has a 1 in 32 chance each step of dropping them.

The pause doubles as a cheat. Press RUN/STOP twice while a fighter is knocked down, and the fighter is standing again: the pause ($10BB) clears every fighter's move and never puts it back.

06 · Copy protection

The loader's stack pointer is the key

Besides the disk's own protection, the game checks after loading that the original loader ran, using the stack pointer the loader leaves behind.

The last stage of the loader leaves the stack pointer at $0A. The game stores it with two indexed writes ($1020) that land on the main loop's stack pointer and on a second copy only when it is $0A, so a game runs with its stack in the same place as the loader's. During a fight the game checks a byte that a JSR leaves on that stack ($106D): if it is not $CF, the game calls the frame interrupt's exit as a subroutine. In the emulator, with that byte poked, the CPU returned into the stack page and stopped on an illegal opcode at $01C5.

The same stack pointer is a decryption key. At the first reset ($1957), part of the pose layouts is XORed with the game's own code, starting at an offset taken from the stored stack pointer. Any other value XORs another stretch with other bytes, and the layouts stay scrambled. A byte the loader left at $010B is checked again each time the third fighter's reflection is drawn ($F1F9).

The reset that clears the game's variables ($16E1) is aimed by the same value: it clears the stack page from just above the loader's bytes ($010C-$01E8) and leaves those bytes alone.