1984 · Activision

About this page

This minisite was contributed by air, unorig. It’s currently claimed by unorig who is editing it to reach a Gold tier standard.

The copies studied

The pages describe the game's own code and data: Activision's program, which starts at $6000, and everything it builds. The addresses are those of the copy analysed, a single file that holds the whole of memory from $0314 up so the game loads in one go.

A second copy, a cracked disk whose one file unpacks itself and then jumps to $6000, was run in the emulator to that point and compared byte for byte. Every byte of the game's code and data is the same at the same address, with three kinds of exception:

The one-file copy is intact in all three places, which is why it is the one analysed. Its own additions, left out of the other tabs, are these:

No game image is hosted here.

Original game credits

The title screen says only DESIGNED BY DAVID CRANE COPYRIGHT 1984. The other roles below come from the sources named beside them.

Site contributors

Other places to love this game

Sources

  1. The Commodore 64 manual, as text on Abandonware DOS, read 29 September 2026: the $10,000 loan, the joystick in port 1, and the end at 9,999 PK energy.
  2. The cassette manual, scanned on the Internet Archive: it credits nobody.
  3. MobyGames, Ghostbusters credits (Commodore 64): Adam Bellin and Hilary Mills.
  4. Wikipedia, "Ghostbusters (1984 video game)", citing Retro Gamer 25 (2006), Commodore User, and Computer Gamer: the music, the sing-along, the six weeks, the UK chart, and the ports.
  5. C64-Wiki, "Ghostbusters": the music's credit.
  6. "In the Chair with David Crane", Retro Gamer, kept on David Crane's own site: the speech, and "Turned around in just six weeks".
  7. Games That Weren't, "Car Wars", quoting Crane in Retro Gamer 79 (2010).
  8. Chris Anderson, Personal Computer Games 14, January 1985, as transcribed by the Commodore Format Archive.
  9. Your Commodore 7, April 1985, as transcribed by the Commodore Format Archive.
  10. Computer Entertainer, December 1984, on the Internet Archive: the top ten and "Ghostbusters Take Over Europe!".

Research record

The write-up, facts and symbol map are available under CC BY-SA 4.0; code is under MIT.

Version, coverage and tools
Tiersilver (claimed)
Coverage100 % of the bytes the game uses have a description
Build analysed
Copyagent-draft
Toolshost: Linux 6.18 x86_64, Ubuntu 24.04 cloud container with four cores and no display, emulator: VICE, release v3.13.1, v3.13.1-linux-x86_64-gui.zip, disassembler: regenerator2000 0.9.20, python: 3.11.15, widget tests: node 22.22.2: the page's routines checked against the game's own code in kit/c64/machine.js on snapshots, browser check: Playwright with Chromium 1194, subagents: annotation agents on disjoint address ranges and, for the Play tab, five porting agents on disjoint routine groups; all claude-opus-5-5, play tab: kit 0.0.38: the game's routines ported to JavaScript in five groups, checked in lockstep against the game's own code in kit/c64/machine.js (57 sessions, 88,550 passes with every group, node 22.22.2), paced by the median cycles per game state measured on the same machine
Modelclaude-opus-5-5
Kit version0.0.44
What the game does, and how it was checked

Read this before annotating code. What the game is documented to do, with verification status against the binary. Statuses: open (documented, not found yet), traced (in the code, could not be exercised; say what was tried), confirmed (in the code, consistent with the emulator), live (observed directly), differs (the code does something else). "Absent" is not a status.

Sources, all read on 29 September 2026. Every web page was read through a fetch tool that summarises, so a quotation below is near-verbatim, not a transcription; work/research.md has the notes, source by source.

Features

FeatureStatusWhere
Title screen: logo, no-ghost sign, "PRESS F1 OR F3 TO START"livereference/title.png; draw_title_screen $619A
Bouncing-ball sing-along of the theme song, lyrics on screenlivelyrics stored in PETSCII at $6443-$68EF, cues $68F0, ball $91C8
SPACE during the sing-along makes the game shout "Ghostbusters!" (manual)live$6385-$6393 calls the speech routine $8DB9 with phrase 1 when no lyric is scrolling (hooked, agent 3); that phrase 1 is the chant is by its use here, not heard
F1: the introduction and interview; F3: straight to vehicle selection (manual)differs$6399, st00_interview_start $747E: F3 skips the interview only once a name has been typed since power-on ($6328, kept through RUN/STOP + RESTORE); it then decodes the stored account ($10,000 if it fails). With no name F3 is F1. Live (work/verify/t5-f1f3.js)
Interview: name "LAST,FIRST", "DO YOU HAVE AN ACCOUNT?"livetext at $AB8D, $ABE1
New franchise: the bank advances $10,000livetext at $AC2B; st02_account_answer $74D8
Account number: typed on a Y answer; "INVALID ACCOUNT NUMBER."livetext at $AC94, $ACB1; decode $9155; VENKMAN,PETER with 64405104 gives $123,400; STANTZ,RAY with 03452601 gives $54,300; one digit changed is refused
Account number encodes the balance in units of $100, checked against the name (ready64, gbaccount)liveencode $90EE, LFSR $91A6, name sum $91B6; a number computed from the Python model was accepted by the game (t11-account.js); the algorithm is in facts.md
Vehicles: Compact $2,000, 1963 Hearse $4,800, Station Wagon $6,000, High-Performance $15,000livevehicle page; prices $A1D4/$A1D8
Vehicle options on SPACE: 5, 9, 11, 7 items of cargo; 75, 90, 110, 160 mphlivetext at $38F1-$39EC, shown in turn by SPACE (t9-misc.js); the capacities are car_capacity $AA9A; the speeds are text only, the cars' real limits $AA9E are $60, $70, $80, $A0
Equipment shop, three pages on keys 1-3, E to endliveshop_keys $7A5B; E needs a trap
Forklift driven by the joystick carries an item to the carlivest0F_shop_forklift $7749
Prices: PK energy detector $400, image intensifier $800, marshmallow sensor $800, ghost bait $400, traps $600, ghost vacuum $500, portable laser confinement system $8,000liveshop pages; item_price $A1DC
"YOUR CAR IS LOADED TO CAPACITY."livetext at $3B5F; shop_fire_at_car $78EA; load 9 of 9 refused, nothing paid (t10-capacity.js)
Joystick in control port 1livethe forklift and the map answer port 1 only; reads at $96CA
City map: GHQ, Zuul, streets, CITY'S PK ENERGY and the balancelivereference/map.png
PK energy rises with timelive003 to 036 over about 15 s on the map; frame_pk_rise $73F3
Haunted building flashes redlivered and green, 16 frames each ($7106, t2b-flash.js)
PK energy detector turns a building pink before a Slimer arrives (manual)differsmap_building_under_logo $7D23, warn_needs $A9B0: the building turns purple in its first warning stage only while the logo is on a street beside it, and goes back when the logo leaves; with the detector a building in the last stage before the Slimer turns red (haunted) as soon as the logo passes. Live (t2-warnings.js)
Marshmallow sensor turns a building white before the Marshmallow Man (manual)differssame routine: white only while the logo is beside the building, for the 15 to 20 s between the pick and the alert. Live (t2-warnings.js)
Roamers drift towards Zuul; each one that arrives adds 100 PK (manual)livest12_city_map $7BB7-$7BCB; 0007 to 0108 (t3-roamer-zuul.js)
An escaped Slimer adds 300 PK (manual)liveunanswered: frame_building_timers $73D9, 76.6 s after the building turned red (t4-escape.js); after a missed trap: $8704 (agent 5)
Route: the Ghostbusters logo moves along the streets, leaving a dotted path; fire sets off (manual, FAQ)live$7CAD, $7F29, $7E55
Driving: overhead street, the car steered with the joysticklivereference/drive.png
Ghost vacuum sucks up Roamers on the road (manual)live$818C-$8274; only if owned ($6D bit 5), on a new press of fire; a catch takes 32 frames, pays nothing and sends the Roamer back to the map (t13-vacuum.js)
Arrival at a building: street scenelivereference/building.png
Busting: first man drops the trap, second walks right, beams on, men move inward, streams must not cross, trap sprung (manual)livestates $8279-$8896; with the streams on, the stick only closes the gap between the men
"He slimed me!" on a miss; the man is out of actionlivest1D_slimer_escapes $8704: a man lost, PK +300, speech phrase 2 (agent 5's run)
Crossed streams: "YOU CROSSED THE STREAMS... FORTUNATELY YOUR BACKPACKS SHORTED OUT IN TIME. GO BACK TO GHQ."livetext at $3B80; backpacks to 0, two men lost (3 to 1 in the simulator), the Slimer escapes
A Slimer caught pays $300 to $1,000 (FAQ), or according to response time (Apple II guide)livetable $A1E4 by the haunted building's timer: $1,000 at first, $100 less every 10.2 s, $300 at the end; $300 if the building is no longer marked (t8-reward.js)
No empty traps, no men, discharged backpacks: "GO BACK TO GHQ"livetext at $3A04-$3AAE; map_fire_select $7E55 refuses with messages 0, 1, 3 (t9-misc.js)
GHQ empties traps and revives men (Wikipedia)live$88B6; 3 men, backpack power 99, traps emptied
SPACE in play: status reportliveframe_status_report $7175; "BACKPACK POWER AT 99% OF MAXIMUM... 3 EMPTY TRAPS... 3 MEN LEFT..." scrolled on the bottom row (t1-status-pause.js)
MARSHMALLOW ALERT flashes; B drops baitlivetext at $3AB0; map_marshmallow_check $7ED8, map_bait_key $7F70; only bait dropped after the alert counts (t7-marshmallow.js)
Bait averts the Marshmallow Man: the mayor pays $2,000livetext at $3B21; st26_mm_baited $89DC; $2,500 to $4,500 (t7-marshmallow.js)
The Marshmallow Man destroys a building: $4,000 deductedlivetext at $3AC5; st25_mm_stomps $8970, the charge at $8983; $10,000 to $6,000, the block flattened (t7-marshmallow.js)
RUN/STOP pauses; RUN/STOP and RESTORE return to the title (manual)livepause frame_pause_key $70BA in states $12-$29 only; restart nmi_restore_handler $6425 (t1-status-pause.js, t5-f1f3.js)
Keymaster and Gatekeeper reach Zuul at PK 9999, ending the gamediffersst12_city_map $7BF8, map_zuul_meeting $7C2E: from PK 5000 each is sent to Zuul when it passes a crossing next to it, from 9500 at once; the game ends when both stand on Zuul, at whatever PK: 8495 to 9999 in eight runs (t6b-keymaster-spread.js). 9999 is only the meter's cap
Loss: not more money than at the start, the bank forecloseslivetext at $B12B; end pages $8C74-$8D7F; only a balance below the starting one forecloses, an equal one goes on to Zuul (t14-endings.js)
"GO TO ZUUL! SNEAK PAST THE MARSHMALLOW MAN AND CLOSE THE PORTAL..."livetext at $B3B0, message 9 at the meeting (t14-endings.js)
Win: two of three men past the Marshmallow Man into Zuul, $5,000 rewardlivetext at $B2D4; the door at x $5B-$5E; +$5,000 seen
Partial: enough money but Zuul not reached, "GOOD TRY"differstext at $B1B9; shown when the Marshmallow Man catches two men on the Zuul street; the pages then give a credit limit and a new account number as a win does
A winning game gives a new account numberlivetext at $B221-$B298; $8CC6 calls the encoder $90EE; F3 then starts with that account
Digitised speech: "Ghostbusters!", "He slimed me!", a laughliveheard at start-up; player $F080, run by the NMI of CIA 2 timer B at 9,659 samples a second (PAL), 4-bit samples to $D418; phrases and samples $F4EA-$FF9B; which phrase says which words is not settled from the code
Music: Russell Lieblich's arrangement of the themeliveplayer $93E2/$93F0; voice 3 lent to sound effects at $9593
Credits on the title: "DESIGNED BY DAVID CRANE COPYRIGHT 1984"livetext at $3671

Beyond the documentation

Found in the code, not in the manual.

FeatureStatusWhere
Account digits 8 and 9 are read as 0 and 1: 64485184 works like 64405104livedigit parse $9CFC keeps 3 bits
The decoded balance is not checked as decimal: ANDY with 777 shows YOU HAVE $?<0000; a blank name with 458 gives $A00000, shown $:00000live$9155; t11-account.js
A blank name with 458 can never win: the starting balance $A00000 is above anything the balance can reach again ($999,900 at most), so the meeting at Zuul always forecloseslivemoney_add $9664, map_zuul_meeting $7C2E; the high-performance car leaves $985000 (t11-account.js, t12-458-end.js)
Names with the same byte sum (anagrams) share every account; about one random number in 256 passes the checkconfirmed8-bit check byte
PK energy stops at 9999; it rises 1 every 64 passes below 1000, every 32 below 2000, every 16 above; crossing a thousand at 5000 or more marks a random buildinglive$9895; a Roamer taking 4950 to 5050 marked building 6 (t3-roamer-zuul.js)
The map speeds up with PK: Roamers and the two keepers move every 64th frame below 1000 and every other frame from 5000confirmed$3C from pk_rate_masks $9DBA, map_move_sprites $7C85
A building about to be haunted already holds a Slimer before it turns red, and pays by the time since that stage beganlivestage bits %11 accept $xC-$xF ($8505, $9A8A, $87DF); t8-reward.js
A Marshmallow building replaced by a newer pick stays marked for the rest of the game and never brings the Marshmallow Manlivebldg_next_stage $A9B4 sends stage 2 to $F8 again (t17-mm-orphan.js)
Ten or eleven empty traps print as : and ; in the status reportlive (by poking)bcd_to_ascii $99B7 on the binary count $6B (t15-traps10.js); needs the wagon and at least $12,000
The image intensifier puts the Slimer in front of the building; without it he passes behind the building's foreground coloursliveslimer_update $9AA6, $D01B bit 4 (t16-intensifier.js)
Money saturates at $999,900 and stops at 0liveBCD add $9664, subtract $9636; t7-marshmallow.js
POKE 38454,96 makes the subtract routine return at once: purchases cost nothinglive$9636; buying the hearse left $10,000; the Marshmallow Man's $4,000 is not taken either (t20-poke-mm.js)
The laser confinement system stores up to 10 ghosts instead of using a traplive$6D bit 6, $87C9; stored 0 to 1 and 9 to 10 with the traps untouched, at 10 a trap is used (t18-laser.js)
Each drive leaves two bytes on the stack: state $14 reaches next_state by JSR, not JMPlive$8070; the stack pointer went $FF to $FD and stayed
"YOU MADE MORE MONEY" is printed when the balance only equals the starting onelivean equal balance opened the Zuul phase (t14-endings.js), whose endings all print it
A fifth speech phrase, phrase 0 (0.95 s, beginning like phrase 1), is stored but never playedconfirmedthe game asks only for phrases 1-4
The speech player has 2-bit sample decoders no phrase usesconfirmed$F267-$F2E3, $F3E2; all four decoders hooked while every phrase played
A turbo tape loader, never run, is left at $CE00; its RESTORE handler fills memory with the JAM opcode $02confirmed$CE00-$CED9, $CEC1; a dead chain at $CF80 calls it and $0A00, $0E00, likely the original tape's loading sequence (inference)
A shop item with a price ($600, item 4, sprite shape $37) is on no shelf, so it cannot be boughtconfirmeditem_price $A1DC entry 4, shelf_shapes $AAB3
Dead code: sprite_y_distance $9C76, set_balance_10000 $9CF1; three-NOP runs at $90D1, $90DB look like a patched-out callconfirmedno reference, never executed

Open questions

How the analysed state was reached

How to get from the contributor's own copy to the analysed state. Someone else must be able to follow this exactly.

The image

Ghostbusters_OneLoad64_J1.prg (64,750 bytes, SHA-256 6f74b24dc06ce9aec13bd35d677eef196aadd348ad9758d924ae18950acb5bda, MD5 a7504f10a17e5bbd15301b9934b47b20), the contributor's own copy, a single program file. Its load address is $0314 and it runs to $FFFF: 64,748 bytes, the whole of memory above the KERNAL's vectors.

It is not Activision's own disk. The name says it is from OneLoad64, a collection that turns C64 games into one file each, and the file behaves like one: there is no BASIC line and no SYS. The first two bytes loaded overwrite the IRQ vector at $0314 with $033C, so the first interrupt after the load has finished runs the program. What the conversion changed in the game is unknown: no original disk was available to compare with, and the stub at $C800 (below) is the only code found that is plainly not Activision's. No intro, trainer or credit to a converter appears on screen.

From power-on to play

  1. Power-cycle the emulator (vice_machine_reset, mode: hard) and let it reach READY..
  2. Do not autostart the file. VICE's autostart loads it through the drive, slowly, with interrupts running: as soon as $0314-$0315 are loaded, the next IRQ jumps to $033C before the code there has arrived, hits a BRK in the power-on pattern, and BASIC's warm start puts READY. back on the screen (seen three times, 29 September 2026; VICE's log says Autostart: Left ROM for $033C). The file is made for a loader that writes memory in one go, as a cartridge or a DMA loader does. work/inject.py does the same through the emulator: it stops the machine at READY., writes $0314-$CFFF and $E000-$FFFF with vice_memory_write, sets $01 to $34 to write $D000-$DFFF into the RAM under the I/O chips, puts $01 back to $37, checks all 64,748 bytes against the file, and resumes. The next raster IRQ enters $033C.
  3. The title screen follows at once: the GHOSTBUSTERS logo, the no-ghost sign, the Activision logo and a bouncing-ball sing-along of the theme song ("PRESS F1 OR F3 TO START"). F1 starts the game.
  4. A typed interview follows. Name: SPENGLER, RETURN. "DO YOU HAVE AN ACCOUNT?": N, RETURN. The bank advances $10,000. Vehicle selection: 2 (the 1963 hearse, $4,800), RETURN.
  5. The equipment shop: three pages (keys 1-3), a forklift driven with the joystick in control port 1 picks an item up (fire), carries it right to the car and drops it (fire). Bought on page 2: three traps, one ghost bait, one ghost vacuum ($2,700). E ends shopping.
  6. The city map appears, with CITY'S PK ENERGY counting up from 000 and $2500 in the account. That is play.

Snapshots in work/, each saved without ROMs:

FileState
entry.vsfa stopping checkpoint on $6000, the game's first instruction, from a power-cycled machine and inject.py. The disassembler and the listing are built from this one.
title.vsfthe title screen and sing-along, about 12 s after $6000
account-q.vsfafter the name, at "DO YOU HAVE AN ACCOUNT?"
vehicle.vsfthe vehicle selection page
shop.vsf, shop-bought.vsfthe equipment shop before and after buying
play-map.vsfthe city map, PK energy rising

Steady state

On the city map: $01 = $35 (RAM at $A000 and $E000, I/O at $D000); the hardware IRQ vector $FFFE = $8E76 and NMI $FFFA = $6425, both written by the start-up at $6000. The page at $0300, the KERNAL's vectors included, holds what $C800 copied there ($0314 reads $0A00), and nothing goes through it once the KERNAL is banked out. The video chip looks at bank 1 ($4000-$7FFF; $DD00 bits 0-1 set to %10 at $6033).

Compared byte for byte with entry.vsf, play-map.vsf differs in $4000-$5FFF (the video bank's screen and graphics, rebuilt), one byte at $6328, and scattered working storage at $E000-$F4E5. Everything else between $0314 and $FFFF is unchanged, so the program is not reloaded or unpacked while it runs: the image holds the whole game.

The loader, in a paragraph

There is none of Activision's in the file. The stub at $033C (in the cassette buffer) acknowledges the raster interrupt, blanks the screen, paints the border, the background and colour RAM black, resets the stack to $FB, copies the KERNAL's default vectors from ROM ($FD30, 20 bytes) back to $0314, waits 25 frames, calls the KERNAL's IOINIT ($FDA3), turns the screen back on and calls $C800. That routine masks every CIA interrupt, copies 256 bytes from $C830 to $0300, clears $0200-$02FF and jumps to $6000, never returning to the stub: it puts back pages $0200 and $0300, which the one-file load had to overwrite, as the conversion found them. $6000 is the game's cold start (SEI, stack to $FF, vectors at $FFFA/$FFFE, $01 = $35).

Memory footprint

Every byte of the C64's 64 KB, one pixel each, 512 to a row. Lit pixels are code, graphics, sound, text, tables and variables; dim areas are screen and working memory.

WhatBytesOf 64 KB
Program50,14276.5 %
Code15,10023.0 %
Graphics20,32231.0 %
Sound4,6917.2 %
Text4,1796.4 %
Tables2,6994.1 %
Variables3,1514.8 %
Screen, bitmap, colour, stack, I/O10,49616.0 %
Unused4,8987.5 %

The symbol map is symbols.json; the listing behind the Source tab is listing.json.