1987 · Firebird

I, Ball

This minisite was contributed by JonathanWacks. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/i-ball with me to Gold.

A rolling eyeball with inertia, sixteen levels of walls that kill, and bonus discs that always come in the same order. The game runs its logic in an interrupt that cannot always keep up, and its timer counts passes of that logic rather than frames: with seven aliens on the screen, the timer's 50 seconds last about 97 real ones.

01 · The game

Steer Iball to the top of the level

Iball is a ball with an eye, and he is out to rescue four friends from Terry Ball. Each of the sixteen levels is a vertical track of walls. The screen scrolls up as Iball pushes towards the top, and the level ends when he reaches the home straight at the very top of the map. Some walls are electrified and kill him on touch; aliens form out of nothing and home in on him; the timer at the top of the screen counts down from 50.

Some of the aliens are discs. Touching a disc gives Iball an extra: a faster ball, a laser, a shield, a jump to the end of the level. The extras' icons light up in the panels above and below the play area. After every fourth level a friend is rescued, and after the sixteenth the game is over. Andrew Betts wrote the Commodore version, and Rob Hubbard wrote its music.

The title screen: FIREBIRD SOFTWARE PRESENTS IBALL, the four friends to rescue, PRESS FIRE TO PLAY
The title screen, with the four friends to rescue.
Level 1 in play: Iball among aliens between two blocks, the extras icons and the timer above, the score below
Level 1 in play: the timer at 48, the extras icons dark above and below.

02 · Music

Music: Rob Hubbard's tune, played by the game's own driver

The title plays the music, and so does play if the player presses 1 on the title screen. Press 2 instead and the game plays its sound effects.

The game's music driver, music_play at $E009, run once a frame on the kit's 6502 over the listing's bytes, as the title screen's interrupt calls it, through a model of the SID. The test beside this page holds every register write of 3,000 frames to the same calls made on the game's code. The tune never ends: each voice's track goes back to its start.

The driver plays three voices, each from a track: a list of pattern numbers, with a transpose before some of them. A pattern is a run of notes with their lengths and instrument changes. There are 35 patterns (pattern_ptrs, $E849) and 18 instruments of 16 bytes (instruments, $E70B), whose flags switch on vibrato, a pulse-width sweep, an arpeggio, a filter sweep, or a drum table that changes the waveform and pitch each frame. C64-Wiki says the tune is a remix of Cabaret Voltaire's songs; Wikipedia names "Whip Blow" and "I Want You".

03 · Sound

Sound: 22 effects, and the events that ask for them

With effects chosen, a second player runs in place of the music. The game asks it for an effect by writing $40 plus the effect's number into one byte per voice.

The game's effects player, effects_play at $ED56, run once a frame on the kit's 6502 after the bytes each event writes into effect_req ($ED50-$ED52). Eight of the 22 effects are not asked for anywhere in the game; their buttons play them on voice 1.

An effect is a frequency that slides by a step, and the step itself changes each tick. One of eight scripts says when to slide up, when to slide down and when to go back to the start (effect_script_data, $F050). Each effect's 16 bytes (effect_defs_a and effect_defs_b) give its starting note, waveforms, length and script.

04 · Speech

Sound: three spoken words, played through the volume register

pitch$8C

Press a word.

The game's own sample player, say ($C1F3) and sample_nmi ($C199), run on the kit's 6502 over the listing's bytes, one call of sample_nmi for each timer interrupt. The picture is the volume of every interrupt. The game uses the pitch $8C; the title screen's stick moves it between $5A and $FA, as this slider does.

The SID has no way to play recorded sound, but changing its master volume makes a click, and changing it thousands of times a second makes a waveform. Each byte of a sample holds two four-bit volumes. CIA 2's timer interrupts the processor every sample_pitch + 1 cycles, and each interrupt writes the next volume into $D418. The three samples fill $A000-$BFFF. The game plays the first on the title screen, the second when Iball dies, and the third at the end of a game.

While a sample plays, the game stands still. irq_panel_end ($4506) checks sample_busy and, if it is set, does not hand on to the next interrupt of the frame, so none of the game's logic runs until the word has been said.

05 · One frame

One frame of play, rebuilt from memory

Press a band to see which interrupt sets it up.

One whole frame of level 1, recorded in the emulator: the registers as the frame began, every write to the video chip during it, and the memory it read. The page draws it with the site's C64 library; all 104,448 pixels match the emulator's own picture of the same frame.

Four raster interrupts cut the frame in bands, each setting the line of the next. The top and bottom panels use extended colour mode and the text character set, each with its own eight sprites: the extras' icons, the timer's two digits, the score and the lives. The play area between them uses multicolour characters from the playfield's set at $3000 and eight sprites of its own. The panels' sprites are the same eight sprites as the play area's, moved and repainted three times a frame.

06 · The playfield

A level is a list of tiles, built into a map before play

map row215

Level 1's map, built by the page from its tile list and the tile set as build_level_map builds it, 25 rows at a time, as the playfield shows them. The slider starts at the bottom, where Iball starts. The test beside this page holds the map of every level to the one the game's own code builds. Every level is drawn whole on the Levels tab.

A level's description is 360 bytes: 60 rows of six tile numbers (level_1 at $7600, and fifteen more after it). A tile is four characters by four, so a row of tiles is 24 characters wide, the width of the playfield. Before play, build_level_map ($4B2F) turns the tiles into a map of 240 rows of 24 characters, at $097E. The playfield is that map seen through a window of 25 rows. Each time the window moves by a whole row, draw_playfield copies all 600 characters again.

What a character does depends only on its number. Characters 1 to 5 are the shots and the lasers. Characters $06 and up are walls, and characters $EE and up are electrified walls, which kill. Multicolour register 1 changes colour every frame, so whatever is drawn in that colour flashes.

07 · Iball

Inertia: a push changes Iball's speed by one

Iball moves with two speeds, across and up or down, each with a direction. A push in the direction he is moving adds one to that speed; a push the other way takes one off, and below zero turns him round (push_up to push_right, limit_speeds). The controls are read every second time the top interrupt runs, so holding the stick changes the speed by one every second frame or so. A speed that reaches the limit, 3, goes back to 2, so his top speed is 2 pixels a frame. With the Turbo Boost the vertical limit is 4, and with the Fuel Injection 5. Every 20 times the top interrupt runs, friction takes one off every speed, so Iball drifts to a stop when the stick is let go.

Iball never goes above line $6C of the screen. Pushing past it hands his speed to the scroll, so the map moves instead (move_iball). The sides of the screen turn him round. Walls are found by reading the screen: probe_background copies the 12 characters under him, three rows of four, and bounce_iball reverses his direction when the row or column he moves towards holds a wall. A hit on the top row while the map is in its top two rows is the end of the level.

Speed limitTop speedWhen
32at the start, and across always
43up and down, with the Turbo Boost
54up and down, with the Fuel Injection

08 · Controls

Every key in a column does the same job

Press a key.

The keyboard as the C64 wires it: eight rows and eight columns. Each key is shaded when it has a job. The jobs come from the value each of the game's tests writes to $DC00 and the column it reads in $DC01; the test beside this page runs each of the game's tests on the kit's 6502 for every key and checks that the same keys answer.

The manual gives Z, X, O and K for left, right, up and down, P for fire, SPACE for the Smart Missile and M for the Molecule Bomb. The game reads a key by driving rows of the keyboard low and reading one column. Most of its tests drive seven rows at once, so every key in that column on those rows does the job. O is the up key, and so are E, T, U, @, the up-arrow and Q.

The same groups answer on the title screen, where the jobs change. I, the key C64-Wiki gives for the "IBALL!" sample, is in the fire column, so it starts a game. X and the other right keys say "IBALL!", Z "OH NO!", and SPACE "GAME OVER!".

09 · Discs

The discs always give their extras in the same order

The 32 places of disc_order ($62C3). The highlighted place is the extra the next disc gives; dashed places are the checkpoints a death goes back to (disc_checkpoints, $606B). The test beside this page holds both buttons to the game's own code.

The first alien to form in a game is a disc. After that, a disc forms once 21 aliens have been killed (disc_countdown). Touching a disc gives the extra at the next place in the sequence; after the 32nd place the sequence repeats its last four. A death moves the sequence back to the last checkpoint and takes away the extra given at that checkpoint, so the next disc gives it again (disc_rollback, $6648).

ExtraWhat the game does
Turbo Boostvertical speed limit 4
Single Lazer, Twin Laser Seta beam along Iball's row, the way he faces; with the Twin Laser Set both ways
Smart MissileSPACE explodes every alien but the discs
Extra Score100 points, plus 100 more for every two levels played
Bullet Sprayshots go up and down at once
Electro Shieldwalls cannot kill, while its meter in the top panel empties
Extended Play, Timer Rewind20 and 40 more on the timer
Hyperspacethe map runs to the goal at 6 pixels a pass
Molecule BombM stops new aliens forming for 255 passes
Faulty Discevery wall kills, until Iball dies or nears the top of the map
Fuel Injectionvertical speed limit 5
Bonus Ballone more life
Hyper Brakesthe controls read every frame, while its meter empties
Lazer Coolerthe laser never overheats
Rainbow Ripplea band seven characters wide, rolling up or down the screen in changing colours

10 · Aliens

Each alien's sprite decides how it hunts

Up to seven aliens share sprites 1 to 7. A new one appears at a random place, away from walls and at least 20 pixels from Iball (spawn_alien), and spends 50 passes flickering through colours while it forms (forming_step). A forming alien cannot hurt Iball. Every alien moves with the map as it scrolls (ride_scroll), and on top of that it steers towards Iball, but which way depends on the sprite it got (steer_aliens):

SpritesSteers towards Iball
1, 2up and down
3, 4both ways
5, 6, 7across

Their speed rises with the level. Across, an alien moves 1 pixel a pass on levels 1 to 4, 2 on levels 5 to 13 and 3 on the last three (alien_speed_x). Up and down, it adds 1, 2 or 3 to the scroll's speed, from levels 1, 9 and 16 (alien_accel_y). Iball's shots are characters on the screen, so an alien dies when a shot character is among the 12 characters around it (alien_shot).

11 · Time

The timer counts the game's logic, not seconds

The work of each frame is split between the interrupts. The third, irq_logic at line $92, runs the aliens, the shots, the scroll and the timer. It can take longer than a frame, and when its interrupt comes round again before it has finished, the new interrupt returns at once. So the more there is on the screen, the more frames the logic misses. The timer, timer_tick, takes a second off every 50 passes of that logic, not every 50 frames.

Level 1FramesLogic passes50 timer seconds last
Iball alone1,5001,50050 s
Seven aliens about1,350695about 97 s

Counted in the emulator with checkpoints on irq_logic's work and on timer_tick, only while Iball was alive and no sample played. The timer also stands still while Iball materialises or dies, in hyperspace, and while a word is said.