Re: [stella] 6 Digit Routine Cont.

Subject: Re: [stella] 6 Digit Routine Cont.
From: "Chris Larkin" <clarkin@xxxxxxxxxxxxx>
Date: Wed, 10 Sep 2003 18:36:36 -0700
Thanks everyone for your help... I guess my major confusion was the use of
pointers. It all makes a great deal more sense.

And even though I read through this code for over three hours, I never
noticed the WSYNC in the main display, that frees up a great deal of
frustration about the cycle counts needed before the display routine.

The list saves me again! :-)

Thanks folks,

--Chris

----- Original Message -----
From: "Christopher Tumber" <christophertumber@xxxxxxxxxx>
To: <stella@xxxxxxxxxxx>
Sent: Wednesday, September 10, 2003 8:52 AM
Subject: Re: [stella] 6 Digit Routine Cont.


This may be dead obvious, but I'll point it out anyway.

You actually understand the 6 digit display routine.

This routine does a couple other things besides just a "simple" 6 digit
display.

- Skips scanlines so text is displayed at correct vertical position (bottom
of screen?)
- Sets the colours based on the current level
- Sets up the pointers for use in the 6 digit display based on a string-like
structure
- Draws the 6 digit display

In effect, you're actually dealing with four distinct routines. They are:

Skip a certain number of scanlines (based on level?)

>    ldy     MsgDelayTab-1,x
>    beq     .skipWait
>.loopWait:
>    sta     WSYNC
>    dey                         ; 2
>    bne     .loopWait           ; 2³
>
>^ Simple Enough
>
>.skipWait:

Set colours:

>    lda     Planet
>    and     #~PLANETMASK
>    bne     .NTSCMsgCol
>    lda     MsgColTab_PAL,x     ; 4
>    bne     .contMsgCol
>    DEBUG_BRK
>.NTSCMsgCol:
>    lda     MsgColTab,x         ; 4
>.contMsgCol:
>    sta     COLUP0              ; 3
>    sta     COLUP1              ; 3 = 10 <-- When I count, I get much more
than 10?

Set up pointers:

 ldy     MsgTab,x            ; 4
>^??????? Totally lost here |Load height of graphic?
>
>    lda     LetterPtrTab,y      ; 4
>    sta     digitPtr            ; 3
>^LetterPtrTab,Y = Address of first 8x8 Graphic?
>
>    lda     LetterPtrTab+1,y    ; 4
>^Here is where I get lost? I don't understand how this gets compiled
>^If LetterPtrTab = $1200 and Y is $05, then this returns $1200 + 1 + 5?
($1206)???
>^Shouldn't this get the last byte of the second graphic? I'm confused how
it does this?
>
>    sta     digitPtr+2          ; 3
>^digitPtr is in Zero Page... So the graphic data is loaded into RAM...
>
>    lda     LetterPtrTab+2,y    ; 4
>    sta     digitPtr+4          ; 3
>    lda     LetterPtrTab+3,y    ; 4
>    sta     digitPtr+6          ; 3
>    lda     LetterPtrTab+4,y    ; 4
>    sta     digitPtr+8          ; 3
>    lda     LetterPtrTab+5,y    ; 4
>    sta     digitPtr+10         ; 3 = 46

6 digit display:

>    ldy     #5                  ; 2
>;    ldy     MsgHeightTab-1,x
>    txa                         ; 2         don't change C!
>    eor     #MSG_C_2000         ; 2
>    bne     .msgLoop            ; 2³
>    ldy     #7                  ; 2 = 7/8
>.msgLoop:
>
>^ All graphics are 5 height, except Copyright which is 7...
>^ These are all wasted cycles for me... in order for this to work for me
however,
>^ I have to get this exact cycle count?
>
>    dey                         ; 2     61
>    sty     tmpVar              ; 3     64
>    lda     (digitPtr+$8),y     ; 5     69
>    tax                         ; 2     71
>    sta     WSYNC               ; 3 --- 76 ---
>    lda     (digitPtr),y        ; 5      5
>    sta     GRP0                ; 3      8
>    lda     (digitPtr+$2),y     ; 5     13
>    sta     GRP1                ; 3     16
>    lda     (digitPtr+$4),y     ; 5     21
>    sta     GRP0                ; 3     24
>    lda     (digitPtr+$6),y     ; 5     29
>    sta     tmpVar2             ; 3     32
>    lda     (digitPtr+$a),y     ; 5     37
>    ldy.w   tmpVar2             ; 4     41
>    sty     GRP1                ; 3     44
>    stx     GRP0                ; 3     47
>    sta     GRP1                ; 3     50
>    sta     GRP0                ; 3     53
>    ldy     tmpVar              ; 3     56
>    bne     .msgLoop            ; 2³    59
>
>^This all makes sense
>
>    sty     GRP0
>    sty     GRP1
>    sty     GRP0
>^Why is GRP0 cleared twice?
>    rts


The part of the routine you seem to actually be having a problem with is the
use of pointers, not really the display routine itself (Though I will also
point out that the timing is  only critical during the actual display part
of the routine, the timing in other parts - particularly in the skip lines
part (which you asked about) is not critical). And you didn't include the
tables in the code you posted. MsgTab and LetterPtrTab are tables of offsets
to the graphics data. So you need to consider and understand those tables if
you're going to understand what's going on.

To simplify things, I'm just going to consider the first digit being
displayed and ignore the other 5 digits.

To set up the first digit, we need to put a pointer to it's graphics data
into digitPtr

If we want to setup digitPtr to point to the first letter in our alphabet
(presumably a 0 or A but you didn't include the tables so I'm guessing and
I'm not going to go hunting for the source..) we would:

lda #0*HeightOfLetters
sta digitPtr             ;digitPtr+1 has been pre-set to point to the top of
the graphics table at $FF00 or $FE00 or etc

If we want to setup digitPtr to point to the second letter in our alphabet
(presumably a 1 or B but you didn't include the tables so I'm guessing and
I'm not going to go hunting for the source..) we would:

lda #1*HeightOfLetters
sta digitPtr ;digitPtr+1 has been pre-set to point to the top of the
graphics table at $FF00 or $FE00 or etc

And so on...

However, in this example Thomas has abstracted things a little to allow the
routine to display different strings. So instead of loading the character
values directly, he's using a pointer to some strings:

lda     LetterPtrTab,y      ; 4
sta     digitPtr            ; 3

LetterPtrTab is a table of strings, if each string is (probably) 6 letters
wide, then to put the first letter of the first string into digitPtr

lda     #0
lda     LetterPtrTab,y      ; 4
sta     digitPtr            ; 3

To put the first letter of the second string in digitPtr

lda     #6
lda     LetterPtrTab,y      ; 4
sta     digitPtr            ; 3

But that's not particularly usefull unless you turn that #0 and #6 into a
variable. Thomas could have used a simple variable like:

 ldy      MsgOffset
 lda     LetterPtrTab,y      ; 4
 sta     digitPtr            ; 3

Which would be fine if you only have a couple different messages to display,
and they're all the same width. However, given many different messages to
display it's convenient to put it all into a table:

 ldy     MsgTab,x            ; 4
 lda     LetterPtrTab,y      ; 4
 sta     digitPtr            ; 3

So, to display the first message (string):

 ldx   #0
 ldy     MsgTab,x            ; 4
 lda     LetterPtrTab,y      ; 4
 sta     digitPtr            ; 3

So, to display the second message (string):

 ldx   #1
 ldy     MsgTab,x            ; 4
 lda     LetterPtrTab,y      ; 4
 sta     digitPtr            ; 3


If  this still doesn't make any sense to you, it may not matter. If you just
want to use the 6 digit display to display a score or a specific static text
then you don't need all these extra abstractions that are desinged to handle
a variety of different strings. All you really need is that 4th section of
the code, and set up digitPtr et al to suit your own purposes.


Chris...



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



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


Current Thread