1987 Β· Firebird

Bubble Bobble

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

Play the whole game in your browser, from any round. Below, how the port was checked against the C64 original.

Loading the game's bytes…
Start on round
  • ← β†’ walk, ↑ jump, Space blow a bubble (player 1, joystick port 2)
  • A D walk, W jump, F blow (player 2, port 1; fire to join)
  • 1 or 2 on the score table: one or two players. Space (fire) on the title page
  • Esc is RUN/STOP: pause and resume. Q quits to the score table

The game's own screen, drawn from the port's memory each frame as the video chip would draw it. Start on round does what the cracked disk's own menu does: it stores the round in the game's start-up code and starts a new game, with the opening story run at full speed. The game arrives there as a new game does, with three lives and nine credits.

01 Β· The port

Every routine of the game, checked against the original

Nothing on this page emulates a 6502. The game's routines are written out in JavaScript, one function each, named by the listing's labels, and run on the game's own 64 KB of memory.

The page loads that memory from the listing, the same bytes the Source code tab shows. From then on the port reads and writes the game's variables where the game keeps them. The rounds are built from the game's own level data, the bubbles drawn into the same dynamic characters, the tunes played by the game's own music driver, and the sprites put where the game puts them. The picture is drawn from that memory as the video chip would draw it, with what the interrupts change on their lines: the buffer flip at line 50, and the boss's third row of sprites 30 lines further down.

How it was checked

Each routine was first checked alone against the game's code, run in a 6502 simulator: 258 checks over the 271 routines, from about 61,000 random starting states made out of 22 saved moments of play, each state bent towards the branches of the routine under test (every bubble kind, every actor state, every item, every round's layout). The thirteen scenes that wait on the frame counter (the flood, the bonus rooms, the secret room, the umbrellas, the door to round 70, EXTEND) and all twelve tunes were stepped frame by frame beside the game's code with every byte compared after each frame. Then the whole port ran beside the original in lockstep, from the saved moments with the same random joystick: at the start of every pass of the main loop all 64 KB are compared, and so are colour RAM and the registers the game writes to the video and sound chips. Only the stack is left out.

SessionsPassesResult
47 sessions: 22 saved moments of play (rounds 1 to 3 and round 100) run for up to 1500 passes with 2 random joysticks each (19 of them to the game over and the score table), two from the cold start (the title page with its tune, fire, the score table, 1, the story, and round 1), and one of the score table's key loop52,30951,430 identical (98.32 %); 879 differed at the actor interrupt's race (below)

Where the original depends on its interrupt

Bubble Bobble runs its actors (the players and the enemies, with their joystick reads and the enemy intelligence) inside the raster interrupt at line 50 on every other frame, while the main loop is in the middle of pushing, moving and drawing the bubbles. On a C64 that interrupt falls between any two instructions of the main loop; the port runs it between two of its routines. When the interrupt moves an enemy or blows a bubble in the middle of the game's bubble loop, half the bubbles see the old positions and half the new, and the port, which sees all old or all new, can differ from the C64 by a bubble that bursts a pass later or a few pixels of a path. That is the only kind of difference the check found, and the game plays the same.

Speed

A pass of the main loop is three frames long, timed by the frame counter the interrupt keeps, so the page runs the game at the C64's pace by keeping a PAL machine's clock, 312 lines of 63 cycles, and moving it on by the measured cost of each stretch of the main loop (the cycles from each call to the next, taken on the kit's machine while the lockstep ran) and of each interrupt. The actor interrupt then lands in the middle of the pass, as on the C64. From four saved moments, 600 frames of the same held joystick gave the same number of passes, the same player position and the same score on the kit's machine and on this page.

02 Β· Differences

What differs from a C64