Re: [stella] 11 Invaders "Reloaded"

Subject: Re: [stella] 11 Invaders "Reloaded"
From: "Thomas Jentzsch" <tjentzsch@xxxxxx>
Date: Fri, 28 Nov 2003 09:59:38 +0100
Erik Mooney wrote:
> Every sprite displayed by my program is a second-copy of the sprite, with 
> both NUSIZ registers always set to 1.  Every sprite is simply drawn by 
> hitting RESPx.  The self-modifying code changes the STA RESPx to STA 
> another-location to not-draw a sprite.  Because RESP0 and RESP1 are always 
> hit at least once during a line, the *first* copy of each sprite is never 
> drawn at all.

Same here.

> STA templocation  ;right now the second copy of the previous

Instead of sta templocation, I am using lda/bit RESPx here. I'll explain
below why.

> This will actually handle every case, except when there are *no* copies of 
> one of the players on the current line. 

See below.

> All that needs to be done to 
> handle that case is to set GRPx to zero, and that can be done ahead of 
> time, by changing the pointer-to-invader-graphics (indirect indexed 
> loading) to point to memory holding zeroes instead.  I never coded that in 
> but it's quite doable.

Again, instead of changing the target address, I am changing the opcode 
into bit GRPx

> I believe that's how Eckhard handled it as well.  He said there's a 
> special case for when there's only one copy of one of the players on a 
> line, but I don't remember coding for that - I think the above logic 
> handles even that.  GRPx is only hit once per line, but I think the timing 
> worked out (thanks to the "mysterious 5-pixel delay") that the GRPx hit 
> takes effect before the sprite starts clocking out, so only the second 
> copy of the sprite is ever displayed.  I could be wrong on this, though.

Yup, you are wrong. :-)

RESPx hides the first copy *only* if you are really repositioning the player. 
But when you only hit RESPx once each scanline and always at the same 
cycle, the first copy will show too.

Therefore I need standard positioning code and NUSIZx set to 0 for 
that special case.

> Here's how I did the positioning.  First, my code actually displays *15* 
> columns of invaders, spanning the entire screen. 

Correction here: 15*9 - 3 = 132. ;-)

> I delay the formation by 0, 3, or 6 pixels by self-modifying none, one, or 
> both GRPx writes to take one extra cycle, by changing the opcode from 
> zeropage to zeropage,X (X is always zero.)  Then for single-pixel 
> positioning, I just have three separate ROM copies of the 6-pixel-wide 
> invader sprites, at different positions within the 8-pixel-wide GRP 
> register.  The indirect-indexed pointer to the invader graphics is set up 
> accordingly.  (Indirect indexed loading is very flexible.)

Here is a big difference to my demo (and Christopher's SI). We don't do 
single precision positioning. This would be quite easily possible, but then
the gaps between the invader would become as wide as the invaders 
(6 pixel), which IMO wouldn't look too good.

Since you are doing RESPx every 3 cycles instead of 4 like Chris and I do, 
this works much better for you (6 pixel invaders + 3 pixel gaps).

But IIRC there is a big problem with hitting RESPx every 3 cycles, because 
gaps in the formation cause the preceding (following) invader to be shifted 
by one pixel. And AFAIK nobody has found a solution for that problem yet.
Did you? That would offer some great new options for better code!

Anyway, here are my further differences:
My kernel contains *13* RESPx instructions, the first four are en/disabled 
depending on the position of the formation. While the second two are used
for most positions, I added the first two to achieve my goal to position the
invaders at the *very* left of the screen (pixel 1). Now my invaders can
span the whole screen (158 pixel).

And here is the reason why I patched the opcode and not the targetaddress
above. To dis/enable the first four RESPx (and HMOVE, see below) I am
patching the targetaddress here. This makes the patching code much easier,
because I can patch the kernel for the overall position and en/disabled 
invaders indepently now.

Why those two additional RESPx? This is the part where my code gets new.

The first two RESPx have to be executed at the *end* of the *preceding* 
scanline to make the 2nd copy show at the very left of the current one. 
But, since 160 is not divisible by three, I have to correct the resulting 
position by using HMOVE. 

This would normally cause HMOVE blanks at the left and then hide my first 
two invaders. Therefore I am using early HMOVEs, which don't create those 

But then I have to do my RESPx also at the end of the preceding scanline,
*behind* HMOVE. This is causing a conflict between RESPx and HMOVE 
(which is not handled by current emulators), but with "some" trial and error
I finally managed to find the correct HMPx values for my Jr. (thanks to my 
new SC!).

Then I did send the 1st demo to Eckhard and he found that my HMPx values
didn't work correctly on his console. My Jr. seems to be one of those consoles
that have problems with Kool Aid Man and therefore handles those HMOVE 
conflicts slightly different. Eckhard then corrected the HMPx values (did I say 
"Thanks!" already?) to work for his console and most others too.

You can find the tables for position patching at the very end of my sourceode.

BTW: Instead of dis/enabling the extra RESPx/HMOVE I could have also used
different kernels and gained about 8 free additional CPU cycles. But I haven't
found any usage for them (yet), so I decided to waste them with my current

But since this also wastes a few bytes of RAM for the unused code, I might 
have to change that. Though I then had to find a solution for using or 
wasting the extra cylces more efficiently. :-)

I hope that explained it. 


Horoskop, Comics, VIPs, Wetter, Sport und Lotto im WEB.DE Screensaver1.2
Kostenlos downloaden:

Archives (includes files) at
Unsub & more at

Current Thread