Re: [stella] Visual questions

Subject: Re: [stella] Visual questions
From: "John K. Harvey" <jkharvey@xxxxxxxxxxxxxxxxx>
Date: Tue, 25 Jul 2000 09:52:23 -0400
>When talking about a byte, the numbering is like this, right?
>
>128 	64 	32 	16 	8 	4 	2 	1

Correct.

>What about the bit numbering?  Does it go from left to right or right to left?

For universiality, they're usually referenced with the leftmost bit as bit
7, and the rightmost bit as bit 0.  At least, this is the way the Stella
Programmer's guide has it set.

>So when drawing player sprites for use in memory by using graph paper, what 
>you see is what you get on the screen if you feed it numbers like the 
>above, ala:
>
>X X X X X X X X = 255
>X 0 0 0 0 0 0 0 = 128
>X 0 0 0 0 0 X 0 = 130

Bingo.

>Also, how I'm going to explain VDEL is that it has the net effect of 
>shifting sprites down a single scanline.  So if you want to move a sprite 
>up a single scanline, you move it up a full scanline (since it's a 2 line 
>kernel) and enable VDEL, the next frame you don't enable VDEL so it has the 
>effect of moving it another single scanline, and so on.

Well, I only use VDEL for the 6-digit score routine.  It's net effect is a
delay in scanline drawing, but I usually use separate scanline counters for
each graphic's vertical positioning.
Are you going to mention what "really" happens with VDEL?  The fact that
there are 2 more pre-loading graphics registers, GRP0A and GRP1A?

But, as far as VDEL's original intended use (it's net effect), it is
dependent upon where we are drawing in the scanline.

Oh, what the heck, here's some rambling:
If we turn on VDEL, we enable caching of GRP0 and GRP1 in their 'A'
registers.  For example, by doing a store to GRP0, we actually are storing
our data into GRP0A (not displayed), and we inadvertantly move whatever was
in GRP1A to GRP1.  GRP0 and GRP1 are what's actually displayed.  Now, if we
do this store in the scanline AFTER the P1 graphic, P1's graphics will
change on the next scanline.  If we do it before, P1's graphic will change
on that very same scanline.  Whatever P0's graphics were should stay the
same.  VDEL only works if on every other scanline, i.e. the odd ones you do
a STA(or STX, or STY) GRP0, and on the other scanlines, i.e. the even ones,
you do a STA(or X orY) GRP1, not both on each scanline, otherwise the data
from both will be changed because the cached copies will be updated into
the regular graphics registers.
Whew!

>If you want to move a sprite down a single scanline, just position the 
>sprite at the same place and enable VDEL.  If you want to move it down two 
>scanlines, then move it to the next line in your two line kernel and don't 
>use VDEL.

It's easier just to have a vertical positioning counter and increment or
decrement it accordingly.  It's easier to do this then to play around with
whether or not to turn on VDEL's.

>Also, I've noticed that a lot of source code stores sprite data upside 
>down.  Any reason why?  Do they scan memory by decrementing a counter or 
>something?

One saves cycles by setting a counter and decrementing it, and checking if
it's zero.
Cheesy pseudo-code here:

GraphicsData
.byte %00000000 ;gfxdata + 0 bytes.  This line is usually all zeros so GRP
will be turned off
		     ; when the graphic is done being drawn
.byte %10000001 ;gfxdata + 1 byte
.byte %01000010 ; etc...
.byte %00100100
.byte %00011000
.byte %00100100
.byte %01000010
.byte %10000001 ;gfxData + 7 bytes

For an 8-scanline tall graphic;
1) Set a counter (say to 7.  We use its height minus 1.)
2) Loop:
3) Do a WSYNC so the Data is drawn
4) Take GraphicsData+counter
	this will get the data at graphicsData plus counter's number of bytes away
	hence, when we start, we get GraphicsData + 7 bytes away.
5) Put in GRP0 or GRP1
6) Decrement counter
7) Branch if counter's sign bit (bit 7) equals zero to Loop.
 	We usually don't branch if counter is zero because GraphicsData+counter
is still valid if counter = 0.  (This will be the first byte located at
GraphicsData). As soon as we get that value, the counter will decrement to
255, which has its leftmost bit equal to 1. So, we won't branch back to the
loop.

If we did this so the sprite was rightside-up, we would have some extra steps:
1) Set a counter equal to zero
2) Loop:
3) Do a WSYNC
4) Get GraphicsData + counter
5) Put in GRP0 or GRP1
6) Increment counter
7) Compare counter to number of scanlines tall our graphic is
8) branch if our current counter is not equal to the number of scanlines
tall our graphic is to Loop.

Step 7 (the compare) seems to be a waste of cycle time, if we can just as
easily do it the other way.

Of course, not all games use this route.  There may already be other
counters that are already decrementing on a scanline by scanline basis.
So, there's a lot of freedom in the code, but the decrementing loop is the
tightest code I know of.  It will, however, fail if the graphic is more
than 127 scanlines high, because then bit 7 will already be set, and we'll
leave the loop prematurely.

Mentos,
	-John K. Harvey

--
Archives (includes files) at http://www.biglist.com/lists/stella/archives/
Unsub & more at http://www.biglist.com/lists/stella/

Current Thread