1986 · Hewson Consultants

Uridium

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

How Uridium draws its screen, builds its Dreadnoughts, flies the Manta and sends its waves, read from the code and checked against the game.

01 · The screen

One frame, rebuilt from memory

A frame of play drawn by this page from the memory and video registers recorded in the emulator.

Drawn by the site's renderer from a recorded frame: all 104,448 pixels match the emulator's picture. The status lines use one character set at $7000 and the playfield another at $7800.

Three raster interrupts split the screen. At line 82, $3F38 switches to the playfield's character set and multicolour mode and sets the fine scroll. At line 97, $3F73 clears a flag that lets the main loop start its frame. At line 252, $3F00 switches back for the bottom status line and the top of the next frame, and runs the sound driver.

The playfield's background colour is white. Space is a character filled with solid colour, drawn in black, so the white background shows only in the hull's plating. The stars are characters too, and the next section shows how they stay still.

02 · Stars

Stars that stay still while the screen scrolls

The stars behind the Dreadnought are characters fixed to the screen. They never move, and the hull slides over them.

Zinc's hull scrolling past the ten stars of the frame recorded in the emulator, drawn as $2BEB copies the map and $2ED7 puts back the stars. On the right, star character $42 and the hole in it for the current fine scroll. The star drawing was checked against the game's code in a 6502 simulator on 2,000 random screens.

The map is copied to the screen whole every frame, and that copy wipes out the stars. Straight after it, $2ED7 goes through the star list. A star whose screen cell holds a space gets its character back, $42 or $43, in the star colour. A star whose cell holds a piece of hull stays hidden, and its colour cell gets the map's colour back. So the hull passes over the stars, and they reappear behind it.

Each star is a character that is solid in the dark colour of space except for one pixel, a hole through which the white background shows. The screen scrolls a pixel at a time by the fine scroll in $D016, and moves a whole character only when the fine scroll wraps. Every frame the game moves the hole the other way, by writing the byte for the current fine scroll from $311E into the star characters' rows ($7A15, $7A1A, $7A1B). The screen cell moves right by the fine scroll and the hole moves left by the same amount, so the star's pixel stays where it was.

WhereStars drawnSet at
The giant scrolling message on the title screens16$0ADA
A game10$0B8F
The demo8$21CB

At the start of each level, $2E17 places 16 stars in screen rows 7 to 22, each in its own row where it can, from the random table at $0800. No star goes in columns 20 to 24, which $2E17 marks as taken before it starts. The table above shows how many of the 16 each screen draws, the number at $8D, measured in the emulator. The rows above and below the playfield get scattered stars of their own ($2532), which the same hole trick keeps still.

03 · The Dreadnought

Every Dreadnought is built from the same 148 pieces

Each Dreadnought is 512 characters long and 17 high, assembled at the start of the level from a list of pieces.

The map as build_map ($2CB2) builds it, from the level's list and the piece store at $E100, in the level's colours and tile set, 40 columns wide as the screen shows it. The port matches the game's own builder, run in a 6502 simulator, byte for byte on all fifteen levels and the title message (test_ports.py). The Levels tab shows every Dreadnought whole.

A level's list fills columns 64 to 511 with pieces side by side, and a second list lays more pieces over them at a given row and column, the targets, ports and markings among them. Columns 0 to 63 are open space where the Manta turns.

Every Dreadnought draws on the same store of 148 pieces at $E100. The routine that indexes the store ($2C66) never reads the level number: a level chooses only its two lists, its colours and one of three tile sets, which is copied into the characters $80 to $FF ($1A54). The same piece therefore looks different from one Dreadnought to the next.

Drawn in the tiles and colours of the Dreadnought chosen above.

Choose a piece to see where this Dreadnought uses it.

The 148 pieces in store order, numbered as $2C66 numbers them, each a set of columns stored bottom up. A faded piece is not used by the Dreadnought chosen above. Choose a piece to outline it on the map and move the map to it; the buttons step through its uses. Where each piece is laid was recorded by the same port, and replaying those placements rebuilds every map exactly.

The pieces range from piece 1, a single column holding one space that a 0 in the list repeats for open space, to sections of hull fifteen columns wide and the full seventeen rows high. Pieces 31 to 80 and 87 are the giant letters and digits of the title message; the letters it does not spell can still appear, since a new high score writes its initials into the message ($17F8) and the title builds the message again each time round ($2415). No level's list and no letter names pieces 18 and 27.

The characters decide what is solid. Codes $80 to $8F are walls, and the Manta is destroyed if one is under it ($27D5). Codes $90 to $9F are targets: a shot that reaches any character of one turns the whole target into wreckage, each character becoming the one $20 below it ($2AE9). The game never reads the video chip's collision registers; every hit is worked out from these codes.

TargetCharactersPoints
Single character$9D-$9F10
2 × 2$90-$9325
3 × 3, the ships parked on the hull$94-$9C100

The giant message that scrolls across the title screens is level 0. Its piece list is written at $8010 from the message text, four letter pieces per character ($2415), and the same map and scroll code shows it.

04 · The Manta

The Manta's manoeuvres

The Manta has 46 frames: two cycles of a roll, one facing each way, and the frames of a half-loop seen end-on.

The animation tables at $31E2, played as $2713 plays them, one frame every other game frame. The shadow is the Manta's frame + $30, placed as $27BA places it: right by the height and down by half of it. The half-loops change the height by the table at $32F5.

Fire held for seven frames and then up or down rolls the Manta between level and edge-on ($2576). Level, it collides with the three characters on its row and those above and below its middle; edge-on, only with the three on its row, so the roll takes it through gaps one character high. Slowing below speed 2 starts a half-loop ($268C): the Manta climbs, turns end-on and comes out facing the other way with a push of speed. While its height is $14 or more, bullets and mines pass under it.

The shadow is sprite 7. Its frames are not stored: at every restart the game builds them from the Manta's frames at $5000, ORing each pair of pixels together so that the shape becomes a solid multicolour silhouette ($25E5), and stores them as frames $70 to $9D.

05 · Shots and bullets

The Manta's shots are drawn into the map

Up to six shots at a time, each one a character of its own, built every frame and written into the Dreadnought's map.

A stretch of Zinc's map around the chosen row, with the shot run by a port of $2A17 and $2AE9, which matched the game's code in a 6502 simulator over 18,000 frames of random volleys on every Dreadnought. Below, the character the shot covers and the shot's own character as this frame builds it.

A shot moves two columns, 16 pixels, every frame ($29A1). It has no sprite. Each frame, $2A17 first puts back the character every shot is covering. Then it moves each shot and looks at the map character it has reached. A wall, codes $80 to $8F, ends it. A target, $90 to $9F, is destroyed whole: every character of it becomes its wreck, 32 codes lower, and the score is paid ($2AE9). Anything else, space or plating, the shot flies over.

To fly over a character, the shot copies it into a character of its own and draws itself on top: two pixel rows, one of background pixels ($00) and one of the second multicolour ($AA), at the height of the gun that fired it. Then it writes its own character's code into the map, and the map copy puts it on the screen like any other piece of the Dreadnought. A shot leaves the screen when its column passes the visible ones.

Each shot has two characters, its slot number ($00-$05) and the slot plus $10, and uses them on alternate frames. The game flips the two operands that choose ($2A7F, $2AA0) at the end of every pass. The character on the screen is never the one being rebuilt, so a shot never shows half drawn.

A fighter is hit when one of the four screen cells under its sprite holds a code below $20. Only shots use those codes, so $1DCB needs no list of shots: it reads the slot from the character, ends that shot, scores the fighter and turns it into an explosion.

The fighters' bullets are sprites. A fighter fires into a free sprite slot ($1F0F): the bullet starts at the fighter, takes the wave type's bullet shape and flies level at the fighter's speed plus the type's bullet speed, for 160 frames, then bursts. It destroys the Manta if it is in the Manta's column, sprite X $A2 to $B1, within a height window that depends on the bullet's shape ($1FF0), and only while the Manta flies low, height below $14. Above that, in a half-loop, bullets pass under it.

06 · Waves

Fighters fly short programs

Each Dreadnought sends its fighters in a fixed order of waves. A wave is up to six fighters, each flying a path: a list of steps that push it forwards, back, up or down.

The wave's fighters flown by a port of $1A98 and $1C73 with the Manta stopped, so the hull does not scroll and the picture shows the fighters' own flight. The box is the screen; the dot is the Manta. The port matched the game's code in a 6502 simulator on all 57 wave records, both entry sides and two Manta heights: 157,298 fighter positions, frame by frame. Firing is left out.

A wave record ($C200, 16 bytes) gives each of its six fighters a path number, or 0 for none, and a start height, or 0 for the Manta's height. It also gives the frames between one fighter starting its path and the next, the side byte and the wave's type ($1A98). All the fighters of a wave are placed at once at the same sprite X, $1A2 or $1A4, in the stretch between the right and left borders that no screen position uses. They wait there, one after another, until their path begins; the emulator shows every fighter launched at one of those two X positions.

Which edge a fighter enters by depends only on which way it moves from there. Moving right, its X runs past 511 and comes back at 0, on the left edge. Moving left, it comes in from the right. The side byte decides: 0 and $FF choose one way or the other, judged from the Manta's direction, and any other value lets the random noise choose. A fighter entering from the other side flies the mirror image of its shape ($6C00), and its forwards and back swap.

A path ($C648 on) is a list of bytes, one step each. The low bits choose forwards or back and up or down, which add the type's acceleration to the fighter's speed every frame; the other bits stop it dead, fire once, or steer it towards the Manta's height. With bit 7 set the next byte is the step's length in frames, otherwise it lasts one frame, and $FF holds the last step for good ($1C73). Speeds are kept in 256ths of a pixel, so eight frames of forwards with an acceleration of 160 give a speed of five pixels a frame. Every path but four starts with such a burst, which carries the fighter onto the screen; the gliding steps after it keep that speed.

Every eighth frame, on a frame of its own, a fighter on the screen may fire. It fires when a noise byte is no higher than the wave's firing chance, so the chance is out of 256: the type's base, plus half the lives left, the level and the difficulty. A fighter that leaves the screen is switched off once it is well past the edge it left by.

The sixteen types

From the type tables at $36F3, $3703, $3713, $3723, $3733 and $3743. Acceleration and climb are in 256ths of a pixel a frame, added every frame of a step; firing is the base chance out of 256.

The forty paths

Each path decoded from its bytes: a step and its length in frames. Forwards is the way the fighter entered; the last step holds until the fighter leaves the screen.

A new wave starts when the last has gone, checked every 64 frames. A wave shot down to the last fighter counts as a formation, worth 100 at the end of the level. While a wave is in progress, homing mines may also rise from the generator ports that flash on the hull (the next section).

07 · Homing mines

Homing mines swing back and forth through the Manta

The flashing generator ports on the hull launch mines that home on the Manta for a few seconds and then burst. Shots pass straight through them.

Choose a point on the screen for the generator port, then Launch.

A mine flown by a port of $1F62, $2021 and $205F with the Manta stopped. The port matched the game's code in a 6502 simulator on 600 random mines, every frame from the port to the burst. Recorded live on Zinc, a mine's height swung between 156 and 192 round the Manta's 176.

Every eighth frame the play loop calls $1F7F, and it launches a mine only while a wave is in progress: from the moment $1A98 sends a wave until $1A75 finds every sprite of it gone, the top bit of $6C is set. Then a noise byte no higher than a quarter of the wave's firing chance launches one. On Zinc with three Mantas that is 4 to 8 chances in 256 at each check, a mine every five to ten seconds on average; the later Dreadnoughts and the higher difficulties raise it to as much as 24 in 256. The mine needs a generator port on the screen, and takes the last one the map recorded ($0240), and a free one of the six enemy sprites. Without either, nothing happens.

The mine appears over the port and materialises for 37 to 40 frames, depending on where in the four-frame cycle it starts: its shape steps from $1D down through the sparkle shapes every fourth frame until it becomes the mine itself, $11 ($1F62). It moves only with the hull while it does.

Then it homes. Every fourth frame $205F adds one to its vertical speed towards the Manta's height and one to its horizontal speed towards the Manta's column, at most 4 pixels a frame up or down and 6 across. Nothing slows it as it arrives, so it overshoots and swings back: a mine that misses keeps passing through the Manta's position until its time runs out. It beeps every 16 frames (effect $0E), and after 128 frames, plus four for each level and 16 for each time the game has gone round the fifteen Dreadnoughts, it bursts. That is 132 frames on Zinc, under three seconds.

A mine destroys the Manta like a bullet does, inside the same box and only while the Manta flies low, below height $14 ($1FF0), so a half-loop carries the Manta over it. It cannot be shot: $2021 never looks at the characters under the mine, where a fighter checks for the Manta's shots. A mine also counts as one of the wave's sprites in $6C, so the next wave waits until it has burst (Discoveries).

08 · Landing

The landing test is one character and one attitude

After the last wave, the Manta lands only over one particular character, flying level and facing right.

Land now! in the status line above the Dreadnought
Land now! in the status line once the wave list is used up.

Once the level's last wave has been launched, the Manta lands the moment the character under its middle is $6F, the end of the runway, while it flies level and facing right ($166D). Facing left, or rolled, the Manta passes over the same character without landing.

09 · The bonus game

The fuel rod chamber

The bonus for destroying the ship is a timing game against a countdown.

The chamber's rule from $114E: six steps from the bottom up, the countdown stepping every 256 - $310A[level] frames, each offer the countdown plus the bonus so far. The flashing here is paced by a timer, not the game's frame counts, and the lit side is random as in the game.

After landing, the fuel rod chamber offers a value and Quit in turn at each of six steps. The value is the countdown digit plus the bonus taken so far, and the bonus starts at the level number, so the first offer is 900 + 100 × level. Fire on the value takes it and moves up a step; fire on Quit leaves with the bonus. Letting the countdown reach zero costs a life ($15BD).

The two bonuses are then counted up in hundreds ($176E), and the take-off follows (the next section).

The fuel rod chamber: six rows of paired slots, 1000 lit at the bottom left
The chamber, 1000 offered at level 1.

10 · The take-off

The Dreadnought vaporises faster than the Manta flies

After the bonus game the Manta takes off, turns at the right-hand end of the ship and flies back over it as the hull breaks up behind it, then overtakes it.

The Manta's flight is the one recorded in the emulator on Zinc, frame by frame, with no input from the player; the autopilot flies every Dreadnought the same way. The vaporising is run by a port of $173B and $16D2, which matched the game's code in a 6502 simulator on every Dreadnought, given the same noise. Its random edge is new each time you play it.

The take-off is run by $150F on. The autopilot holds the horizontal input to the right ($5F) and the Manta speeds away from the runway, climbing one step a frame to height $18. Near the right-hand end of the map the usual turn at the edge ($268C) swings it round in a half-loop. From then on its speed is held at 7 pixels a frame to the left, and once in a while, one frame in 64 on average, it does a full roll for show ($1582).

The vaporising starts when the map position falls below $0E00, at column 480, and moves one column, 8 pixels, every frame ($16D2). That is one pixel a frame faster than the Manta. The edge starts at least 14 columns behind it. Its leading rows draw level about 120 frames later, near column 360, and then run ahead, so that for the rest of the way the Manta flies over hull that has already gone. The take-off ends when the map position falls below $0200, near the left end, and the next level begins.

The edge is ragged. Before the flight, $173B gives each of the 17 rows an offset: a random walk from 8 that moves up or down by one, or stays, from row to row, within 0 to 16 columns. In each row, every frame, the three cells at the edge turn to wreckage if they hold anything but space, the first to $F9 or $FA, the second to $FB or $FC and the third to $FD or $FE, and the three cells after them become space. As the band moves left, each character passes through the three stages of wreckage in three frames and vanishes.

The Manta flying left over Zinc with the ragged edge of wreckage just behind it
Frame 180 of the recorded take-off: the edge just behind the Manta.
The Manta flying left with the Dreadnought already broken up ahead of it
Frame 330: the edge has overtaken it and is breaking up the hull ahead.

The player still has the stick for up and down and the fire button: $13BF reads them as in play and only replaces the horizontal input. Shots fired on the way back destroy targets and score as usual, while the hull is still there to hit. The Manta can still crash into a wall, since its collision test runs every frame.

11 · Quirks

Quirks

Smaller rules worth knowing. The Discoveries tab has the findings a player is least likely to know.

After Land now!, fighters keep coming. Once a level's list of waves is used up, the game picks one of four filler waves at random ($12 to $15), and their fighters score nothing and count no formation ($1E4B).

An extra Manta comes with every 10,000 points, at the carry out of the score's thousands byte ($19F5). The lives are kept in BCD and stop at 99.

After the fifteenth Dreadnought the game starts again at the first, with the difficulty raised by $10, up to three times. The difficulty adds to the fighters' chance of firing and shortens the chamber's countdown.

The disk protects the game with its timing. A stage of the loader sends the drive code that finds a mark on track 39 and measures the next ten sync marks; whether each of the last eight is at least as long as the second gives one bit of a key byte. The main file is decoded with that byte, and only the original disk's $97 gives the game.