Re: [stella] Definitive Combat Disassembly

Subject: Re: [stella] Definitive Combat Disassembly
From: "Roger Williams" <mer02@xxxxxxxxxxxxx>
Date: Sat, 2 Mar 2002 19:40:14 -0800
From: Glenn Saunders <cybpunks2@xxxxxxxxxxxxx>
> Why does it use REFP0,X when both the left and right half of the players
> are in the ROM??
> Is this just to simplify the rotational logic?  It seems inefficient to
> the sprite reflect and store both the left and right halves.

That's exactly it.  It allows the program to mask bits 0-2
for the index into the sprite table, and use bit 3 (the 8)
to flip left-to-right.  (Conveniently, it is bit 3 of REFPx which
sets the reflect flag.)  If REFPx were not used, you could
get the same effect by subtracting the index from $0F
before indexing into the table.  Why didn't LW do this?
I suspect because nobody had thought that far ahead
when the TIA was laid out and he figured, since the
hardware trick had been put in for this game, he might as
well use it.

This is one of the reasons I wanted to do a full disassembly
of COMBAT; it's not just an 'early' game but the very
first Stella game, and we can see what was really known
and anticipated in those primitive days.

> The way I do it is to store a set of sprite graphics address pointers for
> each of the 15 unique sprite rotation settings (the 16th being the same as
> the 1st).  Then I have a simple greater-than less-than check to determine
> whether to use the reflection bit or not.  In other words, rotations 1-7
> (right) don't reflect, and 8-15 (left) do.

Um, there are 16 unique positions from 0-15.  Position 16 is the same
as position 0, but it's the 17th position since there is a position 0.

Note COMBAT uses the same kind of co-ordinates you were
taught in geometry class, with 0 being straight off to the right and
higher angles circling up and counterclockwise.  The very first
bitmap in the sprite table is pointing at heading zero.  (My
POL2CART uses the same system, but with 8-bit angles.)

What COMBAT actually does is this:
1. Store pure bitmaps for angles $0 through $7
2. Use angle and $7 to index
3. Write angle into REFPx (conveniently bit-aligned) to
    reflect if bit 3 is set for angles $8-$15

COMBAT could have gotten off with only 4 bitmaps by doing this:
1. Store pure bitmaps for angles $0 through $3
2. Angles $0-$3 and $8-$B index via angle and $3;
    Angles $4-$7 and $C-$F index backward via 4-(angle and $3)
3. Angles $4 through $B: set reflection
4. Angles $8 through $F: Write upside-down

Note that the backward indexing into the sprite table is a separate
operation from reading the sprite backward (upside-down).
COMBAT doesn't do backward indexing.

If COMBAT had stored one side or the other, the logic would
have looked like this:
1. Store bitmaps for angles $C (as -4) through $3
2. Set REFPx for angles $4 through $B
3. Index via (angle and $7) for angles $C through $3
    Index via ($C-angle) and 7 for angles $4 through $B

> I guess there is more than one way to do this sort of thing...  It just
> seems like my way is the most straightforward.

It depends on how many bitmaps you want to make room for and
how much logic you want to implement.  The keys to the way
COMBAT does it are that:

1. The RESPx flag can be indexed straight off the angle.
    There is no logic involved, very cheap.
2. No subtracts are necessary to invert the indexing.

These compromises change a bit if you define direction 0 as
vertical.  With COMBAT's coordinate system, though, storing
the rightmost 8 shapes instead of the topmost 8 forces you to
do a subtraction when you index the hidden side, and the
logic cannot be sampled by simple bit-masking because it
applies to angles $4 through $B.

Since the REFPx flags were put in the TIA specifically for
this game, I'm sure LW figured it made more sense to use them.
I suspect at this stage it had not occurred to anybody that
another coordinate system might be more convenient.

--Roger Williams

Archives (includes files) at
Unsub & more at

Current Thread