Re: [stella] 12 chars/line!?

Subject: Re: [stella] 12 chars/line!?
From: emooney@xxxxxxxxxxxxxxxx (Erik Mooney)
Date: Sat, 27 Sep 1997 00:01:06 GMT
>I wouldn't mind seeing the code, but if the STELLA 0.7 emulator is right,
>I've got a solution that doesn't need vertical delays.  Looks great on the
>text.  Not sure if it'd artifact if all 4 bits of the characters were used
>instead of 3.

The emulators aren't always right... grab yerself a Supercharger :)  At the
least, I'm 99% sure that once a player graphic begins, it locks in its
settings no matter what you do to the registers while it displays.

Anyways, the 48-pixel code goes something like:

The key is the vertical delay registers, and the fact that they don't do
vertical delay at all.  As the "big file" says, there are actually TWO
graphics registers for each player.. I'm going to call them GRP0, GRP0A,
GRP1, and GRP1A.  Again as the "big file" says, bit 0 of VDELP0 toggles
between whether GRP0 or GRP0A is used for the player 0 display, and VDELP1
toggles using GRP1 or GRP1A for the player 1 display.  For this routine,
both vertical delay registers must be set, so GRPxA will always be used.

The tricky part lies in when GRP0A and GRP1A load.  When GRP0 is written to
(with any value), GRP1A receives the contents of GRP1.  When GRP1 is
written to, GRP0A becomes equal to GRP0.

You're "supposed" to write GRP0 and GRP1 at the beginning of alternating
lines, so when the vertical delay register is set, any write to GRP0 does
not take effect until a write to GRP1 occurs, which occurs on the next
scanline.

Here's the code for it again (from Okie Dokie).  GRHEIGHT is the number of
scanlines for which we want to do this.  Player 0 has been set to pixel 123
(including horz blank) and Player 1 has been set to pixel 131.  So the
digits begin at pixels 123, 131, 139, 147, 155, 163.  A series of six
16-bit pointers to the digits reside at GRTABLE, in RAM.  In the table on
the right, D# means digit number # of the score.  (if you're using a
windows mail reader, make sure to use a fixed-width font or the table will
be even messier than most 2600 code)

                      Cycles  Pixel    GRP0   GRP0A   GRP1   GRP1A

loop2
 ldy  GRHEIGHT        ;+3  63  189
 lda  (GRTABLE),y     ;+5  68  204
 sta  GRP0            ;+3  71  213      D1     --      --     --
 sta  WSYNC           ;go
 lda  (GRTABLE+$2),y  ;+5   5   15
 sta  GRP1            ;+3   8   24      D1     D1      D2     --
 lda  (GRTABLE+$4),y  ;+5  13   39
 sta  GRP0            ;+3  16   48      D3     D1      D2     D2
 lda  (GRTABLE+$6),y  ;+5  21   63
 sta  TEMPVAR         ;+3  24   72
 lda  (GRTABLE+$8),y  ;+5  29   87
 tax                  ;+2  31   93
 lda  (GRTABLE+$A),y  ;+5  36  108
 tay                  ;+2  38  114
 lda  TEMPVAR         ;+3  41  123              !
 sta  GRP1            ;+3  44  132      D3     D3      D4     D2!
 stx  GRP0            ;+3  47  141      D5     D3!     D4     D4
 sty  GRP1            ;+3  50  150      D5     D5      D6     D4!
 sta  GRP0            ;+3  53  159      D4*    D5!     D6     D6
 dec  GRHEIGHT        ;+5  58  174                             !
 bpl  loop2           ;+2  60  180

At the *, the value written to GRP0 does not matter.. what does matter is
that this write triggers GRP1A to receive new contents from GRP1.  A "!"
indicates that that register is being used for displaying at that moment.

Looking at it a different way:

 sta GRP0             ;digit 1 -> GRP0
 WSYNC
 sta GRP1             ;digit 2 -> GRP1, digit 1 = GRP0 -> GRP0A
 sta GRP0             ;digit 3 -> GRP0, digit 2 = GRP1 -> GRP1A
 *Digit 1 (GRP0A) begins displaying
 *Digit 2 (GRP1A) begins. One pixel later, the next instruction completes.
 sta GRP1             ;digit 4 -> GRP1, digit 3 = GRP0 -> GRP0A
 *Digit 3 (GRP0A) begins. Two pixels later, the next instruction completes.
 stx GRP0             ;digit 5 -> GRP0, digit 4 = GRP1 -> GRP1A
 *Digit 4 (GRP1A) begins. 3 pixels later, the next instruction completes.
 sty GRP1             ;digit 6 -> GRP1, digit 5 = GRP0 -> GRP0A
 *Digit 5 (GRP0A) begins. 4 pixels later, the next instruction completes.
 sta GRP0             ;any value -> GRP0, digit 6 = GRP1 -> GRP1A
 *Digit 6 (GRP1A) begins.

The basic idea is that we preload GRP0A, GRP1A, and GRP0 for the first
three digits well ahead of time, then load the last three digits into our
three registers and fire them off in rapid succession at the correct time..
then one more GRP0 strobe is needed to make GRP1A update one more time.
Using the "A" registers lets us preload three digits instead of two, so
that we have enough registers to hold the rest of the digits.  Note that we
always update GRP0A while GRP1A is being displayed, and vice versa.  

My hat's off to the programmers who came up with this thing - "Wow.  The
above routine just drew the score with no cycles to spare."  Now that we
know how it works (did it in fact make sense to anyone?), it could be
modified to display at different horizontal positions.

Ouch, my brain hurts now.. I think I'll go play Super Breakout =)

--
Archives updated once/day at http://www.biglist.com/lists/stella/archives/
Unsubscribing and other info at http://www.biglist.com/lists/stella/stella.html

Current Thread