1987 · Thalamus

Delta: the source

This minisite was contributed by chunkypixel, 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/delta with me to Gold.

Every routine, table and variable the game uses, with the names and descriptions given to them. Click an operand to follow it; the counter beside a label lists what refers to it. The reference below the fold is rendered from the game's facts file.

Technical reference: memory map, timing, tables, cheats

Current truth for this game. How the understanding developed is in agent-history.md. Every fact names the routine or table it comes from (names as in symbols.json). Unless marked live, a fact comes from reading the code in work/entry.vsf, the hand-over snapshot that orientation.md describes. Live facts were checked in VICE x64sc (v3.13.1 release, PAL) on 1 October 2026; the tests are listed at the end.

Build

Memory layout

All of RAM is used. VIC bank 1 ($DD00 = $96), screen $4400, character set $4800; $01 = $35 during play (bank_io_only).

RangeWhat
$0400-$07C9sound-effect player and its 21 effects (sfx_play_frame, sfx_rec_a, sfx_rec_b)
$0808-$0FFFicons, title keys, controls, high-score table code; game state $0F00-$0FFF
$1000-$12FFvariables: band chain, stars, per-slot enemy tables, scores, purchase state
$1300-$13FFsprite animation lists (anim_lists)
$1400-$3FFFgame code: start-up, raster bands, multiplexer, hazard rows, character-drawn fire, ship, weapons, banner, deaths
$4000-$43FFsprite shapes 0-15 (title text, interlude pictures); variables $43C0-$43F7
$4400-$47FFthe screen (sprite pointers at $47F8)
$4800-$49FFthe character set, 64 glyphs (extended-colour mode)
$4A00-$7FFFsprite shapes $28-$FF: banner, logo/rocks, hazards, scenery, icons, panel, explosion, ship, enemies
$8000-$9FFFattack waves, enemy movers, enemy fire, pause, stage changes, sound queue, difficulty tables
$A000-$BBFFwave data: hit points, paths, colours, segments, wave records, velocity lists, stage wave lists
$BC00-$CFFFRob Hubbard's music: player $BDE4-$C38D, instruments, 13 tunes, patterns
$D000-$DEFFunder the I/O area, read with $01 = $34: hazard animation tables and spawn lists (live: $01 = $34 at $20C5)
$E000-$EB7Fthe second set of hazard shapes, exchanged with $4C00-$577F
$EB80-$FFFFstage words, title pictures, high-score table, stage tables, font, masks, vectors

The frame

Text

The game's alphabet (found by letter differences in one pass, 30-text):

CodeCharacter
$00-$19A-Z
$1A.
$1B(c)
$1Cspace
$1D-$260-9

Glyphs: banner_font $FC60, 20 bytes each (39 glyphs), drawn at half width into sprites by banner_draw_step $3B80; the panel's score digits are separate 8-byte glyphs at score_digits $FB20.

Strings: title_texts (BY / STAVROS / FASOULAS / (c)MCMLXXXVI / (c)1986 THALAMUS), the high-score table (STAVROS, ANDREW, GARY, THALAMUS), TOP SCORES, DEMO, SHOOT ALIENS AND COLLECT WEAPONRY, GAME OVER (title_texts_b); DELTA MISSION COMPLETE, PLAYER n, FASTEN YOUR SEATBELT, GAME OVER (messages $FB70); the stage words (stage_words $EB80).

Stages

32 stages (stage_advance $91EF; after stage 32, game_completed plays tune 12, shows DELTA MISSION COMPLETE and starts again at stage 1 with the next difficulty). Each banner is three words from stage_words, chosen by stage_banner_table $F880; live: poking the stage-clear state in stage 1 brought up "ENTERING ROCKS OF DEATH / STAGE 02".

StageBannerStageBanner
1WELCOME 10 YEARS LATER17LEAVING CITY OF SECRETS
2ENTERING ROCKS OF DEATH18ENTERING ROCKS OF DUST
3LEAVING ROCKS OF DEATH19LEAVING ROCKS OF DUST
4ENTERING CAVES OF ILLUSION20ENTERING SUN OF DREAMS
5LEAVING CAVES OF ILLUSION21LEAVING SUN OF DREAMS
6ENTERING FURTHER SPACE22ENTERING STORM CLOUDS
7ENTERING ANCIENT TEMPLE23LEAVING STORM CLOUDS
8LEAVING ANCIENT TEMPLE24ENTERING ANCIENT CITY
9ENTERING SEA OF DREAMS25LEAVING ANCIENT CITY
10LEAVING SEA OF DREAMS26ENTERING ROCKS OF DEATH
11ENTERING ASTEROID STORM27LEAVING ROCKS OF DEATH
12LEAVING ASTEROID STORM28ENTERING FURTHER SPACE
13ENTERING JELLY OF DREAMS29ENTERING HIDDEN TEMPLE
14LEAVING JELLY OF DREAMS30LEAVING HIDDEN TEMPLE
15ENTERING FURTHER SPACE31ENTERING FURTHER SPACE
16ENTERING CITY OF SECRETS32ENTERING FINAL CITY

The words LOST and DRAGONS are in the table but no stage uses them.

The ENTERING stages (except FURTHER SPACE) have hazard rows: one or two rows of large two-sprite shapes that scroll in along the top and bottom of the play area (stage_hazard_table $F900: row count, colours, spawn-list page). The rows come from spawn lists under the I/O area (hz_spawn_lists $D300), a new hazard every eighth frame (hazard_rows_step $2080), animated from hz_anim_lists $D200 (hazard_frames_step $9480), moving 3 pixels a frame. The LEAVING stages, FURTHER SPACE and stage 1 have none. Between stages the hazard shapes in the VIC bank are exchanged with the second set at $E000 (stage_gfx_sequence $9580), 128 bytes a frame.

Attack waves

The shop

Weapons

IconPriceVariableEffect
1 speed1$0F00 0-3ship speed 1, 2, 4, 8 pixels; buying at 3 wraps to 0 (icons_update, ship_speed_set)
2 fire rate2$0F01 0-2laser bolts allowed on screen: 1, 2, 3 (ship_fire $349A)
3 extra weapon3$0F02each shot also fires one up, one down and one backwards (ship_fire_extra $3502, extra_shots_move)
4 double laser4$0F03two more beams, level with the ship and two rows below (double_laser_fire $3E88)
5 orbiter5$0F04a satellite that circles the ship through 16 positions (orbiter_step $3E5E, orbiter_draw $2C51)
6 slow-down6$0F05the attack wave moves and spawns only every second frame (wave_step $2C22)
7 shield7$0F06absorbs three hits, with 16 frames of safety after each (shield_step $3880)

Icon 0 shows the credits ($107C). The owned weapons also change the enemies' fire: the shield brings bombs, and the double laser and slow-down change the aiming (enemy_fire_setup $9100). All weapons are lost when the ship dies (ship_death_weapons $397E). Live: with all seven poked on, one press fired the laser, the three-way burst, both beams and the orbiter (reference/weapons-poked.png).

The laser: up to three bolts, each a pair of characters moving one cell a frame (lasers_move $356F), fire delay 8 frames, one press per shot (ship_fire).

The character set and its colours

The character set at $4800 is inverted and the screen runs in extended-colour mode ($D011 = $5C). Colour RAM is black everywhere (clear_screen $0DDD), so every set bit is black; a clear bit shows one of the four background colours $D021-$D024, picked by the top two bits of the character code, and those four colours cycle every fourth frame (colour_cycle_step $1DDD, play_colours_set $363B). The blank character $2E is solid; each star glyph has a single clear bit and the three layers use codes $30, $6F and $B1 to take three different colours; the enemy fire and the player's weapons use the codes with both top bits set ($C0-$FF) or clear ($32-$34). Every enemy shot and bomb is a four-pixel ball cut out of the glyphs beneath it with one mask table (shot_masks $FF70, eight positions across two cells).

Hits

Every shot in the game, the player's and the enemies', is drawn with characters, and every hit between a sprite and a shot is found by reading the screen under the sprite, not by the video chip:

Enemy fire

Three kinds, all drawn with characters (enemy_fire_decide $9208):

New fire must keep the total in flight (shot 5, bomb 10, bullet 1) under the stage's budget (fire_budget_levels $9F08 11-36 by fire_budget_by_stage); each enemy fires when its counter reaches the fire rate (difficulty_fire_rate $9F00). The pseudo-random numbers for the boss and the fire come from walking the game's own code at $3000 as a table (enemy_ai_step $99AC).

Scoring and lives

Difficulty

difficulty_set $9D35 loads one of three 32-byte tables (difficulty_by_loop $FA20) by the number of completed passes through the game, capped at two: the enemies fire sooner and more fire is allowed on screen on later passes.

Controls

Sound

Video register census

RegisterUse
$D000-$D010sprite positions, rewritten in every band (multiplexer, panel, icons, title rows)
$D011$5C in play: extended-colour mode, 25 rows, scroll 4; $40 (blank) in the bands that rebuild the screen
$D012the raster chain (23 writes)
$D015, $D01Call sprites on and multicolour, once at start-up
$D01638 columns / scroll 7 at the top, $17 for the icon row
$D018$12, once
$D019, $D01Araster interrupt only
$D01Esprite-sprite collisions, read in three bands
$D020-$D024border black; background and the three extended-colour backgrounds from the colour cycle (colour_cycle_step)
$D025-$D02Esprite multicolours and colours per band

Never written: $D017, $D01B, $D01D (no expansion, no priority changes) and $D01F (background collisions): hits between sprites and characters are found by reading the screen under each sprite (see Hits).

Corner cases

Live tests

TestResult
Hand-over and play snapshots compared byte for byte (orientation.md)graphics swapped between $4C00 and $F0E0; sprite shapes changed at $4000, $4A00
Raster handlers counted over 50 frames, title and playlisted under The frame
Lives at $12CB: memory diffed across a death3 → 2
RUN/STOP in play, then firepause flag 1, sprites still for 25 frames, flag 0 after fire
RESTORE in playno change
Score digit 2 poked 0 → 1lives 3 → 4, threshold 1 → 2
Seven weapons poked on, one fire pressicon frames 8D 82 85 86 87 88 89 8A, burst, beams and laser on screen
Stage-clear state poked in stage 1banner ENTERING ROCKS OF DEATH / STAGE 02, rock rows
F1, F3, F5 on the title$12CA, $0FFC, $0FFD toggled; option sprites shown
Stopping checkpoint at $20C5 in stage 2$01 = $34, spawn page $DD
Stopping checkpoint at $9960 in the demojoystick operand $0F90, input $17
Ship placed on shop icon 4 with 7 creditsblink, $0F03 = 1, credits 0, score 300
Ship placed on shop icon 5 with 2 creditshit flag set
Enemies shot in stage 1score up 5 per enemy (50 shown)
Two-player game, deathsturns alternated, lives kept per player

Cheats

Pokes that change the game within its own parameters. Each one names the variable it changes and whether it has been tested live. Untested pokes are labelled as candidates.

EffectPokeStatus
7 credits for the next shop$107C = 7live: the affordable icons turned light blue and icon 4 could be bought
Every weapon at once$0F00-$0F06 = 1 (speed 0-3, fire rate 0-2)live: one press fired the laser, the three-way burst, both beams and the orbiter (reference/weapons-poked.png)
Skip to the next stage$129B = 1 during playlive: stage 1 ended and ENTERING ROCKS OF DEATH / STAGE 02 began
Lives$12CB = 1-9candidate: the variable was confirmed live by diffing a death (3 → 2); the poke itself was not tried
The trainer left in the code$0EF2 = $00, $0EF3 = $BA (joystick; $0EF8/$0EF9 for keys)candidate: turns JMP ship_move in irq_controls into JMP $BA00, so unreached_cheat runs each frame: F3 refills the lives, F5 toggles harmless enemy fire; not tried
routines tables variables strings branch labels

Loading listing…