re: [stella] How RRampage works

Subject: re: [stella] How RRampage works
From: "Erik Mooney" <erik@xxxxxxxxxx>
Date: Mon, 12 Apr 2004 15:27:03 -0500
> >First, player 1 and missile 1 are used to draw the player and his bullets;
> >P0 and M0 are used for the enemies and their shots.  This is because P0/M0
> >have higher display priority than P1/M1; you don't want your bullets to
> >obscure things that you need to dodge.
> But wouldn't you (and your bullets) be flying more or less "over" objects you need to dodge?

They would, if I did things the other way around.  If player 0
and player 1 (I'm referring to the TIA objects here, not any
in-game concepts) are both active on the exact same pixel,
player 0 always takes priority.  So, therefore, I use player 0
to display the enemies (and missile 0 for their shots), and
player 1 for the plane (and both player 1 and missile 1 for
his bullets.)  If a player's bullet intersects with an enemy or
an enemy's shot, the enemy object takes priority.

> >Line 1: reposition P0 if necessary
> >Line 2: do a bunch of calculations
> >Line 3: reposition M0 (this always happens every 4 lines)
> >Line 4: on every other iteration, HMOVE and display the player's bullets
> >(so every bullet is 8 scanlines tall)
> So all bullets have a vertical resolution of 4 pixels, but are 8 pixels tall?

I think we might have a terminology issue here (I still confuse
myself sometimes, actually :) )  I [try to] use "missile" to 
mean the TIA objects, "bullet" to mean what the player shoots,
and "shot" to mean what the enemies shoot.  The latter two
are completely separate and behave totally differently.

Bullets are always 8 lines tall, and are positioned only every
8 lines, and advance 8 lines from each frame to the next.
Shots are 2 lines tall and are positioned every 4 lines.
They advance 2 lines from one frame to the next; currently this
is faked by advancing 4 lines only every other frame, which is
why they look a bit jerky.  I will smooth this out eventually,
by delaying the write to ENAM0 by two lines on every other

> This requires, what, 24 bytes of RAM (or slightly less) for P1's bullets?  And probably the same for P0's?

P0's shots (the white things, actually enemy shots) are 40 in
number and take 40 bytes of RAM for the horizontal positions;
and will take more if I want to give then X-velocities as well.

P1's shots (the red things) have two separate streams; one stream is
drawn with P1 and one with M1.  There are 20 sets of bullets
on the screen; each set consists of both a P1 and an M1 object,
and takes two bytes of RAM.  One byte holds the HMOVE values
for each stream (P1 in the upper nibble, M1 in the lower),
and the other byte holds the NUSIZ value and bits for ENAM1
and GRP1 (they can be enabled separately, though the demo I
posted shows them together.)

So it's 40 bytes for the player's bullets, 40 or more bytes
for the enemies' bullets, and at least 2 bytes (X and Y 
coordinates) for each enemy on the screen.  You can see where 
this project needs more RAM to get off the ground. :)

> Right now, and this is embarassing to admit, that tiny 3x6 pixel ball eats up 512 bytes (1/8 of my ROM) because I rely on the blank space for positioning.

If it works, go with it. :)  If you find it necessary to recover
the ROM space, Thomas's SkipDraw routine is the fastest way to
draw a static object like your ball.  If you want to be able
to animate the object from frame to frame, you can copy the 
entire graphic to RAM while offscreen (Combat does this) and
use SkipDraw, or you can use indirect-indexed pointers for
the graphics loads.

(Would SkipDraw work with indirect-indexed addressing?  Hmm.
I doubt it, since the instruction is 3 bytes including a 16-bit
operand.  And I don't think there'd be much to gain, anyway,
since indirect-indexed is already so flexible.)

> >it changes the high byte of the 16-bit pointer
> >to point to an entire ROM page full of just zeroes.
> Heh, I think that's exactly what I was describing.  Maybe I wasn't so crazy after all! :)

Well, the difference is that I use one page (256 bytes) full
of zeroes to cover any number of objects, instead of needing
up to 192 bytes per object.

> So this is a Supercharger-only endeavor?  Does this current incarnation require a Supercharger?

The current incarnation is a standard 4k binary that'll run on
anything.  The next version will be (at least) 8k and require
Superchip RAM, which means a Cuttle Cart or custom EPROM board,
not a Supercharger.

(Superchip isn't the same thing as the Supercharger.  The
Superchip is just an extra 128 bytes of RAM with a standard
16k ROM binary.  The Supercharger has 6K of RAM and loads data via an audio signal.)
Archives (includes files) at
Unsub & more at

Current Thread