(back to project list)

Disassembly of Stellar 7 for the Apple II

Stellar 7 is a first-person tank game, similar in style to the arcade game Battlezone. Written by Damon Slye and published in 1983 for the Apple II and Commodore 64, it features wireframe 3D animation.

The game was successful enough to spawn a couple of sequels, including Arcticfox (written for the Amiga and ported to the Apple II).

There are two different versions of the game floating around. The first is the official release, the second looks like a pre-release evaluation version: the backgrounds and fonts are slightly different, there's no title screen, the first level is set up differently, and in the mission briefing the various units don't zoom into view.

pre-release, lv1   release, lv1

This disassembly is based on the 4am crack of the official release, with one exception: the initial program loader, which was made part of the DOS tracks in the official release, was called "ROCK3" in the early version. It doesn't appear to have changed in any meaningful way, so a disassembly of ROCK3 is included here.

Stellar 7 for the Apple II was published by Penguin Software, and is copyright 1983 Dynamix.

Components (click links for HTML disassembly listing or converted image):

If the player chooses to view the mission briefing, the game loads BRIEF, BRIEF.ST, and BRIEFING, then calls into the briefing code. If the player chooses to start the mission, the game loads PANEL and PLAYGAME, and calls into the game code, which loads OBJ1/LEV1/DYN1.

You can download the project set - all project files and associated binaries (requires SourceGen v1.6 or later).

See Stellar 7 Objects for more details about how objects are defined and manipulated.

See Hacks & Cheats for some ways to modify the game.


Game Mechanics

The goal is to get to the 7th system, Arcturus, and destroy the tank driven by Gir Draxon.

Gir Draxon

The player's tank is controlled with the keyboard, a joystick, or an Atari joystick. On the joystick, button 0 fires the cannon, while button 1 engages the cloaking device. The blue meter is shields, the purple meter is fuel; if either empties completely, the game is over.

On each level you have to kill a certain number of units or survive for a certain length of time. Once either condition is met, a Warplink will appear. Bumping into it takes you to the next level. On the 7th level, Arcturus, the boss tank appears instead.

Keyboard movement:

 U  I  O
  \ | /
 J  K  L
  / | \
 M  ,  .

A full tank of fuel has 37,631 units. Each frame this is reduced by 2 units when idling, 3 units when moving in reverse, and 4 units when moving forward. With the cloak active, consumption increases by 40 units per frame. This works out to about 15.5 minutes at 10fps while driving forward, or 1.25 minutes with the cloak enabled. Firing the cannon costs 25 units per shot. Warplinks restore 7680 units (about 20%).

The cloaking device deactivates after 225 frames. Every time you trigger the cloaking device the countdown is reset. There is no way to manually de-cloak before the timer runs out, but it will deactivate if the fuel tank drops below 2048 units. This means that enabling the cloak will drain at least 40*225=9000 units of fuel, or just under a quarter tank.

Full shields have (147*256-1)=37,631 units, although most things in the game operate on the high byte only, so we can treat full shields as 146. Warplinks restore 30. Damage from incoming fire varies by projectile type (see table below).

The play area is a square, 8192 units on a side, that wraps around at the edges. The radar is 28x28, and covers a 7168x7168 area, so about 25% of the arena is off-radar at any given time.

Unit List

Capabilities for "active" units, from the tables starting at $8591.

Num Img Name Weapon Shots Armor Fwd Spd Rev Spd Rot Spd Score Notes
0 u00 (player)$15 (Thunder Cannon) 2*1801002-
1 u01 Sandsled$0f (Low Laser) 2120040120
2 u02 Laser Tank$10 (Medium Laser) 1212864235
3 u03 Hovercraft$12 (Light Cannon) 1119264320
4 u04 Prowler$12 (Light Cannon) 1216080230
5 u05 Heavy Tank$13 (Medium Cannon) 2312060275
6 u06 Stalker$10 (Medium Laser) 12160100390 cloaks
7 u07 Gir Draxon$14 (Heavy Cannon) 3520012032000 boss; cloaks
8 u08 Laser Battery$11 (High Laser) 22--125
9 u09 Gun Battery$14 (Heavy Cannon) 14--130
10 u10 Pulsar$10 (Medium Laser) 31---40
11 u11 Skimmer$12 (Light Cannon) 11240100250
12 u12 Stinger$0f (Low Laser) 11320160260
13 u13 Guiser$00 (bomb) 01---5 explodes on contact
14 u14 Seeker$00 (bomb) 0112840-10 explodes on contact; levitates

The forward/reverse speeds are expressed in KPH, as in the mission briefing. Internally the value divided by 4 determines the number of movement units per second in the 8192x8192 arena. Fliers and Seekers don't move backward, so the reverse speed determines the rate at which they climb and dive.

The rotation speed determines how quickly a unit can change its facing, which is divided into 256 angles. Pulsars and Seekers appear to rotate constantly, but still have a notion of "front".

Score is multiplied by the mission number. Pulsars, when first encountered on Rigel (mission 3), will be worth 120 points.

Weapon Damage

Num Name Damage Speed TTL Range
13Guiser 32 --0
14Seeker 32 --0
15Low Laser 10 500182250
16Medium Laser 16 500222750
17High Laser 20 500283500
18Light Cannon 14 380201900
19Medium Cannon 18 380242280
20Heavy Cannon 26 380282660
21Thunder Cannon * 420242520

Speed is in KPH (units/second * 4). TTL is the time-to-live, in frames. The range can be determined by multiplying (speed / 4) * TTL, so e.g. the Thunder Cannon has a range of (420/4*24)=2520, which is a bit over 1/4 of the arena. This is of interest because it means that many mobile enemies can be out-ranged, but none of the turrets can. The map wraps around but your vision doesn't, so objects first appear when they are half the arena (4096 units) away.

Damage indicates how much the impact reduces the player's shields. There is no meaningful value for the Thunder Cannon since the player cannot shoot themselves. (One semi-meaningful comparison: 5 shots from the player will kill Gir Draxon, and 5 shots from Gir Draxon will leave the player with just 11% shields remaining.)

All units except the Pulsar have a cooldown that prevents them from firing all of their shots in consecutive frames. To mix things up a bit, there's an 18.75% chance that a unit that is ready to fire will have an additional cooldown of 1-31 frames applied.

Systems

Battles take place across seven systems. The types and locations of the initial set of enemy units is pre-determined, but reinforcements are chosen and placed randomly.

Num Name KillReq KillLim Initial Units Reinforcements
1Sol 515 Sandsled, Skimmer, 4xObstacle Sandsled(35.3%), Hovercraft(47.1%), Skimmer(17.6%)
2Antares 918 3xLaser Battery, 2xSeeker, 2xObstacle Sandsled(25.5%), Prowler(39%), Laser Battery(15.7%), Seeker(19.6%)
3Rigel 1121 3xPulsar, Laser Tank, Fuelbay Laser Tank(40%), Hovercraft(20%), Pulsar(20%), Stinger(20%)
4Deneb 1324 Gun Battery, Heavy Tank, 3xGuiser, 3xObstacle Prowler(39.2%), Heavy Tank(25.5%), Gun Battery(19.6%), Guiser(15.7%)
5Sirius 1527 3xSkimmer, 3xSeeker Heavy Tank(31.4%), Laser Battery(23.5%), Skimmer(25.5%), Seeker(19.6%)
6Regulus 1730 2xGun Battery, 2xSeeker, 2xGuiser, Stalker, Fuelbay Stalker(47.1%), Gun Battery(25.5%), Guiser(7.8%), Seeker(19.6%)
7Arcturus 2133 2xPulsar, Stinger, 2xStalker, Guiser, Obstacle Stalker(35.3%), Pulsar(27.4%), Stinger(29.4%), Guiser(7.8%)

"KillReq" is the number of kills required to make the Warplink (or, on Arcturus, Gir Draxon) appear. "KillLim" is the number of kills at which new enemies stop spawning.

All levels will spawn a Warplink after 3300 frames (5.5 minutes at 10fps). The Warplink may not appear immediately regardless of trigger: once ready, there is a 6.25% chance per frame of it appearing.

The timing of reinforcement spawning is randomized. Every 16 frames the game checks a table in the DYN# file ($8550) that gives the chance of a new unit appearing when there are N active enemies. For example, LEV1 uses:

spawn_likelihood .bulk $46,$1e,$00,$00,$00,$00,$00,$00,$00

A random number from 0-255 is generated, and if it's >= the table entry then nothing is spawned that frame. So if there are zero enemy units, every 16 frames there's a $46/$100 = 27% of a new unit spawning. If there's only one enemy there's a 12% chance, and if there are two enemies there is no chance of a third unit appearing. Arcturus, which starts with 7 units in the arena, has a limit of 5. The table serves to both limit the number of enemy units and to randomize the pace at which reinforcements appear.

This can factor into your strategy, e.g. Rigel has a limit of 3, and there are three Pulsars near the Fuelbay. If you kill the initial Laser Tank and one Pulsar, you'll face at most one mobile enemy at a time. (Since time is generally not on your side, it's best to kill all 3 Pulsars so you have a target-rich environment.)


Copyright 2020 by Andy McFadden