1982 · Commodore

Clowns

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

Commodore's cartridge of the Bally/Midway arcade game takes the place of the C64's own operating system. Half of its 8 KB is the game's rules, compiled from a high-level language; the rest is hand-written machine code for the screen, the input and the sound, with the font and the sprites. That machine code tests every collision pixel by pixel, against the font.

01 · The game

Two clowns and a see-saw

Turn the paddle to slide a see-saw under a falling clown, and the clown standing on the other end is thrown into the balloons.

The title screen: three rows of balloons, PUSH 'F1' TO BEGIN, the high score and the copyright linePlay starting: PLAYER 1 in the middle, a clown on the left platform and the see-saw at the bottom

The title screen and the start of a game, in VICE. Above the playfield, the status line shows both scores and the current player's jumps.

A clown runs off one of four platforms on the walls and falls towards the see-saw at the bottom of the screen. If it lands on the raised end, the see-saw tips, and the clown standing on the lowered end is thrown upwards. The thrown clown flies up into three rows of balloons that scroll across the top of the screen, and pops whatever it touches. When it comes down, the see-saw has to be under it again.

Each player has five jumps. A clown that misses the see-saw falls flat and costs one, and the next clown starts from a platform. Blue balloons are worth 100, green 50 and yellow 20, each bounce 10; emptying a row pays a bonus and refills it. Two players take turns, each with their own balloons.

The cartridge needs paddles in control port 1; the joystick does nothing. F1 starts a game, and F3 at the menu makes it two players.

02 · The cartridge

Written for the MAX Machine, a C64 with 2 KB of RAM and no operating system

Clowns was a cartridge for Commodore's MAX Machine, sold in Japan in 1982, and the same 8 KB plug into a C64 and run there unchanged.

The front of the Commodore 64 box: CLOWNS, a special home version of the Bally Midway arcade game, with a painting of clowns, a see-saw and balloons
PublisherCommodore
Arcade originalMidway, 1978 (the title screen says ©1982 Bally/Midway)
MAX Machinecartridge 3509, ROM chip 325356-01, 8 KB, Japan, 1982
Commodore 64cartridge C-64606, USA and Canada; the box says ©1981, the title screen ©1982, the manual ©1983
VIC-20a cartridge of its own, 1982
Programming, graphics, soundnot known: no names on the screen, the box, the manual or in the ROM, and the catalogues (C64-Wiki, GameBase64, the Centre for Computing History) name only Commodore. Wikipedia's list of MAX Machine software files it under Commodore Japan.

The front of the Commodore 64 box (scan from Eli's Software Encyclopedia, read 12 October 2026), "A special home version of the Bally Midway arcade game". Part numbers from the C64-Wiki's MAX Machine page and Eli's; years from those, Wikipedia and the game itself. Whether this ROM image was read from a Japanese MAX cartridge or an American C64 one is not known; its text is in English.

The MAX Machine, presented in Tokyo as the VICKIE and planned as the Ultimax in America and the VC-10 in Germany, went on sale in Japan in November 1982 for ¥34,800 and was soon withdrawn. Inside it are the C64's processor, a version of its video chip and its SID, with 2 KB of RAM and no ROM of its own: no BASIC and no operating system. Switched on with no cartridge, it shows a blank screen. Everything a game needs, from the start-up code to the font, is on the cartridge, and the machine runs it from there (Wikipedia, C64-Wiki, read 12 October 2026).

A C64 runs those cartridges too. A cartridge that holds one line of the expansion port low and leaves the other high switches a C64 into the same arrangement, the Ultimax configuration: its own BASIC and operating system disappear, the cartridge sits where the operating system was, and the video chip sees the cartridge's top 4 KB. That is why this C64 cartridge looks the way it does, with no loader, its own reset vector, and a font read straight from the ROM (section 05).

Clowns keeps to the MAX's 2 KB. Run on the kit's model of a C64 for 30,000 frames from power-on, through the title's demonstration, the menu and a game, it never read or wrote a byte of RAM above $07FF: its variables, the stack of the compiled program, the flying clown's sprite and the screen all fit in $0000-$07FF.

The C-64 instruction leaflet (scan) is one page of rules: switch the computer off before plugging the cartridge in, plug a paddle into port 1, press F1 for one player or F3 for two, and use the see-saw "to bounce his partner to the top of the center ring", a ring this version does not have. It lists the points: 20, 50 and 100 for yellow, green and dark blue balloons, 10 for each bounce, bonuses of 200, 500 and 1,000 for clearing a row, and "1 Bonus Jumper" for the dark blue row.

03 · The tunes

Music: three tunes on one voice

The game has three short tunes and no music during play. Each stops the game until it ends.

The page runs a port of the game's tune player, $F3AA, through the site's model of the SID, once a tick of 10,001 cycles as the game's timer runs it. test_music.js holds the port against the game's own code on the kit's 6502 simulator: every tune, every write to the chip, tick by tick.

A tune is a list of pitch words for voice 1 ($FF17) with a length in ticks for each note ($FF73), and a zero word at its end. Tune 0 plays when a game starts and with the bonus jump, tune 1 with a row bonus, and tune 2 after a fall in a game. Voice 1 is set up at power-on as a pulse with its gate held open, so the player only changes the pitch; it zeroes the pitch for each note's last tick, which is how two notes of the same pitch are heard apart.

The tune player calls the clock routine itself, a tick at a time, and returns only when the tune has ended. Nothing else runs meanwhile, so the clown hangs in the air while "BONUS 1000" plays.

The sound effects use the other two voices. Voice 2 plays the bounce, a pulse whose pitch falls for 32 ticks, and the whistle of a falling clown, 48 ticks of pitches from a table ($FFA3). Voice 3 pops a balloon with one tick of noise. The title screen's demonstration is silent: its volume is 0.

04 · The sound effects

Sound: a falling bounce, a pop of noise and a whistle

Three effects, on the two voices the tunes leave free, each moved on once a tick by one routine.

A port of the effects, the three routines that start them and sound_tick ($F36B) that moves them on, played through the site's model of the SID once a tick. test_sound.js holds it against the game's own code, write for write.

The bounce ($F33B) starts voice 2 as a pulse with no attack, sustained at half volume, and lets the gate go on the next tick; for 32 ticks its pitch falls a step a tick, from $023E to $0200, while the note fades over a release of about three quarters of a second. The pop ($F34E) gates voice 3's noise for a single tick. The falling clown's whistle ($F358) opens voice 2 with a slow attack and walks through 24 pitches from a table ($FFA3), two ticks each, from the end of the table back to its start, and closes the gate on the last.

The routine that moves them on runs only one effect on voice 2 at a time: while a bounce is sounding, a whistle started meanwhile waits. Nothing plays in the title screen's demonstration, where the routines that start an effect see the sound flag off and return.

05 · One frame, rebuilt from memory

The screen's letters and the see-saw are drawn straight from the cartridge

On a C64 the video chip draws every letter and sprite from shapes in memory. Clowns lets it read most of those shapes from the cartridge itself.

One frame of play, drawn by this page from the game's memory, not a screenshot: the video chip's registers and the RAM it reads, recorded in VICE (x64sc, PAL) on 11 October 2026, with the cartridge's bytes from the Source tab. It matches the emulator's picture of the same frame in every one of its 104,448 pixels. "RAM only" draws the same frame with the cartridge's bytes taken away: the letters, walls, balloons and see-saw disappear.

The video chip builds the picture from shapes: eight bytes for each character of the font, 63 for each sprite. A game normally keeps those shapes in RAM, or uses the font in the C64's own character ROM, and the chip reads them from there on every frame.

Clowns is an Ultimax cartridge, the kind made for Commodore's MAX Machine. Plugged in this way, the cartridge takes the place of the C64's operating system at $E000-$FFFF, and its top 4 KB also appear in the video chip's view of memory, at $3000-$3FFF. The game tells the chip to take its font from $3800 and its see-saw sprites from $3BC0, which puts both in the cartridge, at $F800 and $FBC0. Nothing is copied: on every frame the chip reads the letters, walls, platforms, balloons and the see-saw straight from the ROM. Only the screen's layout and the flying clown's sprite, which the game rebuilds for every pose, are in RAM.

Copies of the game made for an ordinary C64 have to imitate this. The disk version circulated by c64.com copies the cartridge's 8 KB to $2000-$3FFF as well as to $E000, so that the same 4 KB sit at $3000 in RAM, where the video chip expects them.

06 · Two players

Bug: player 1 comes back with 255 jumps

In a two-player game where player 1 runs out of jumps first, player 1 keeps getting turns, and the first fall takes the jump counter from 0 to 255.

FallPlayer who fellJumps afterRow 15 saysNext turn

A replay of a test in VICE. During player 2's turn the jumps were set to 0 for player 1 and 3 for player 2, and the clowns were left to fall. The status line is drawn from the game's font as the game writes it; the jumps cell is the game's character $40 + the count's low seven bits.

After a fall that costs a jump, the flight routine ($EB4D) checks whether player 2 has jumps left. If so, it prints "GAME OVER PLAYER 1" when player 1 has none, and then passes the turn to the other player in any case. Nothing checks that the other player has jumps.

Player 1, with none, gets the next turn. Losing that clown takes the counter below zero, to 255, and the game goes on alternating. The main loop ends the game only when both counters are zero, so player 1 now has 255 more jumps, and the status line's digit becomes character $BF, eight bytes of clown shapes drawn as a letter. When player 2 runs out first, the check fails, and player 1 plays on alone, as intended.

07 · The see-saw

Where the clown lands decides how the other one flies

Only the 24 pixels at the raised end catch a clown, in four zones of six pixels, and each zone throws differently.

Where a falling clown is caught. The see-saw's sprites ($FBC0), left end down, with the catching window over the raised end: the 24 positions of the falling clown's left edge, 21 to 44 pixels right of the see-saw's x, in four zones. Zone 0 is the tip. The speeds above are each zone's starting values from the tables init_tables fills at power-on ($E444), before the random part and the growth described below.

Where the other clown flies: 24 throws

Each white line is the path of the thrown clown, for the zone and speed level picked above. The falling clown lands in that zone of the see-saw at x 120, and the clown on the other end is thrown from the left; the game adds random numbers to every throw, so the 24 lines are 24 throws with different ones. Move the slider to see the throws grow steeper as a jump goes on: the more balloons popped and bounces made since the speed last changed, the harder the throw up. The lines stop at the ceiling or where the clown comes back down; walls and balloons are left out, so a line can pass through the balloon rows (the coloured dots), where in the game the clown would pop balloons and be knocked about. The paths come from a port of the game's flight ($E63C), which test_flight.js holds against the game's own code: 320,389 ticks and 1,955 launches, every variable the same.

A clown falling at y 176 or lower is caught if its x is in the window ($E6C2); once it passes y 184 it is down. The zone picks the other clown's launch from two tables, across and up, and the launch then grows with the jump: a term proportional to the balloons popped and the bounces made at this speed level, times 16 to 26, is added to the upward speed. At speed level 0 both speeds are halved twice, at level 1 once, and the upward speed is never more than 6 pixels a tick.

The thrown clown leaves from the other end of the see-saw, which then tilts the other way, so the window is always over the end where the last clown stood.

Speed levelGravity, per tickNext levelBalloons to the next

Every jump starts at level 0. Popping balloons moves the level on: to 1 after the first one to three balloons, to 2 after nine or ten more, and back to 1 after another 49 or 50, so a long jump swings between the two faster levels. Pops count only after the clown has bounced on the see-saw since the last change ($E9B8).

08 · Collisions

Every collision is tested pixel by pixel against the font

The walls, the ceiling, the platforms and the balloons are all characters. The game works out which of them the clown's pixels touch, without the video chip's collision registers.

A port of draw_clown ($F034) on a piece of the playfield: the ceiling and a row of balloons, in the game's font. The nine cells it tests are outlined, red where a pixel of the clown meets a pixel of the character. test_collide.js checks the port against the game's own routine on the kit's 6502 simulator over thousands of random screens, frames and positions.

Each tick the clown's frame, 16 pixels square, is copied into a mask three characters wide and 24 rows tall, shifted right by the clown's x modulo 8 and down by its y modulo 8 so that it lines up with the character grid. For each of the nine cells under the clown, the game reads the character on the screen, takes its eight rows from the font, and ANDs them with the mask. A cell with a shared pixel reports its character code.

The codes decide what happens ($E8E9). The left and right walls (characters 85 and 86) reverse the clown across, the ceiling (87) reverses it upwards, and a platform's top (89) gives a falling clown a small hop. Any balloon character pops that balloon. An odd number of balloons popped in one tick knocks the clown back the way it came; an even number lets it fly straight through.

The C64's video chip detects collisions too, but it cannot answer this question. Its register for sprites touching the background, $D01F, holds one bit for each sprite: set when any pixel of that sprite has met any pixel of a character, and cleared when it is read. It says that sprite 0 hit something, not what or where, and the game needs to know whether that was a wall, the ceiling, a platform or a balloon, which balloon, and how many. Testing the cells itself gives the character codes, and the codes say all of it. Nothing suggests the hardware was missing on the machine it was written for: the cold start reads the collision registers once, to clear them ($F776), and the game never reads them again. Clowns came out on a VIC-20 cartridge in 1982 as well; whether this routine began in that version is not known.

09 · The balloons

The balloons scroll a pixel at a time by swapping between eight drawings of each balloon

The screen is a grid of 8 by 8 pixel cells, so writing a balloon one cell further along would move it eight pixels at a jump. The game moves it one pixel at a time without moving anything on the screen.

One balloon on a strip of the screen's cells, drawn from the game's font. Move the slider: each pixel picks the next drawing of the balloon, and every eighth pixel the balloon's three characters start one cell further right. The cell borders are drawn in here; on the C64 the cells never move.

All eight drawings, characters 96 to 119 of the font ($FB00), three characters each, with the borders between the characters marked. Each copy is the balloon one pixel further right; the third character is the room it slides into.

A whole row of twelve balloons scrolled the way the game does it, from those characters alone.

The video chip can scroll smoothly by itself: the low three bits of $D016 shift the picture zero to seven pixels sideways. That register moves the whole screen at once, and moving one band of it alone means changing the register on the right raster line in every frame, which needs an interrupt or a program waiting for the beam. Clowns has neither, and its three rows move at the same time in two directions, so it does the scrolling in the font instead.

The font holds each balloon eight times, each copy one pixel further right inside a strip three characters wide. Every third tick ($F1E7), each row's fine position steps on by one, from 0 to 7, and the routine rewrites the row's 36 cells with the matching copy of each of its twelve balloons: characters 96 + 3 × position to 98 + 3 × position. When the position wraps from 7 back to 0, the row's first column moves on by one cell, so copy 0 starts where copy 7 left off. The top and bottom rows step forwards through the copies and move right; the middle row steps backwards and moves left. A popped balloon is written as three spaces.

10 · The score

The score is kept in tens, and the last 0 is a sixth digit that can never be anything else

The status line shows six digits, but the variable behind them counts tens of points.

A port of the score printer ($F69B), drawn with the status line's own reversed digits. test_digits.js checks it against the game's routine for every value from 0 to 65,535.

Each player's score is a 16-bit number of tens ($021D-$0220): a bounce adds 1, a blue balloon 10. The printer divides by repeated subtraction, with a table of divisors at $FFD0: 10,000, 1,000, 100, 10, 1, and last 4,115. By the time it reaches the sixth divisor the remainder is 0, so the sixth digit is always 0. The 4,115 is the table's neighbour, the last three bytes of the falling whistle's pitch table, read as one more divisor.

The highest score the variable can hold, 65,535 tens, shows as 655350. One more bounce wraps it to 0.

11 · Controls

The see-saw trails the paddle by a quarter each tick

The see-saw does not jump to where the paddle points. Each tick it moves a quarter of the way there.

A port of the paddle routine ($F189): the see-saw's x tick by tick after the reading jumps from where it was to the new value. test_paddle.js checks it against the game's routine on the kit's 6502 simulator.

Player 1 turns the first paddle of port 1 and player 2 the second ($D419 and $D41A). The routine takes 200 less the reading, at least 0, times 1.25, and mixes it with three parts of the last position ($F7E7). The see-saw is then drawn at that x, but at least 17, as two sprites 24 pixels apart. The paddles' fire buttons start a game, like F1, and choose two players, like F3.

12 · How the program is built

Half the cartridge is compiled code that calls machine code by number

The game's rules are a program compiled from a high-level language. The drawing, the input and the sound are 25 routines of hand-written machine code.

Every byte on the cartridge is machine code: the C64's processor runs nothing else. What differs is how the programmers made it. The library of routines at $F000-$F7FF, which draws, tests collisions, scrolls and plays sound, was written in assembly, one processor instruction at a time by hand, and it shows: short, fast, and full of tricks such as an instruction hidden inside another's operand so that two routines can share their code ($F1A6). The game's rules at $E000-$EFFF, the title, the menu, the physics and the scoring, were written in a language closer to English, with lines like "while either player has jumps left", and a compiler turned them into machine code. A compiler of that time builds everything from the same few templates, and the templates show.

What the compiler made, $E386

LDA $0221   ; player 1's jumps
ORA $0222   ; or player 2's
CMP #$00    ; is the sum 0?
BEQ +4
LDA #$00    ; no: "false"
BEQ +2
LDA #$FF    ; yes: "true"
BEQ $E37C   ; false: another jump

What a programmer would write

LDA $0221   ; player 1's jumps
ORA $0222   ; or player 2's
BNE $E37C   ; any left: another jump

The main loop's test "does either player have jumps left?", as the cartridge holds it and as it would be written by hand. The compiler first turns the comparison into a value, $00 for false or $FF for true, and then tests that value; every comparison in the compiled half is built the same way.

The other marks of the compiler: every procedure starts and ends with the same pair of calls, which keep a stack of their own for its arguments ($E00C, $E020); text is printed from bytes placed right after a call; and a standard library is linked in whole, routines the game never uses among it, such as 16-bit multiply and divide and an error message, "ERR DIV0".

NumberRoutineWhat it does

The routine table at $F000, read from the Source tab's bytes, with each routine's name from the listing. The compiled program never asks for numbers 3, 11 and 12.

In detail: every procedure begins with a call that opens a frame on the compiled program's own stack ($E00C) and ends with a jump that closes it ($E020); arguments are written just past the caller's frame, and the main program's frame, $0200-$0243, holds every global variable.

To reach the machine code, the compiled program calls one procedure ($EB01) with a number and three values. The procedure looks the number up in the table above and calls the routine with the values in the processor's three registers; results come back in zero page, where a function reads them. Which language and compiler produced the code is not known.

The unused part of the library also holds a routine to print a byte in decimal, and the division-by-zero error jumps to $7000, where the cartridge has nothing. The printing library also has an output device that jumps to $FFD2, the KERNAL's routine for printing a character. On this cartridge that address is a byte of the score printer's table. The game only ever prints to the screen through its own routine.

13 · Timing

No interrupts: a CIA timer is the game's clock

The game never enables interrupts and never waits for the video frame.

The interrupt vectors point at a lone return instruction ($F765), and nothing reads the raster register. Instead, the clock routine ($F711) waits for CIA 1's timer A, loaded with 10,000 cycles and set to run once, to run out, then starts it again. Every loop of the game calls it once a pass. Measured in VICE, play ran 1.90 ticks a frame on a PAL machine, about 95 a second; 10,000 cycles alone would give 98.5. The timer counts the processor's clock, so an NTSC machine runs the game about 4 % faster.

Because the screen is written whenever a tick comes round, the beam can catch a row of balloons half redrawn. A frame recorded with the balloons moving differed from the emulator's picture in 100 pixels, all of them in the row the game rewrote while the beam was drawing it.

WhatHow long
Balloons move a pixelevery 3 ticks
The flying clown changes poseevery 11 ticks
The run along a platform13 steps of 10 ticks
The falling clown's animation48 ticks
The pause after "GAME OVER"255 ticks, about 2.7 seconds

14 · The text

Text packed into the ROM

The game's few words are stored to take as few bytes as the 8 KB cartridge allows.