Re: [stella] Another day, another problem...

Subject: Re: [stella] Another day, another problem...
From: "Andrew Davie" <adavie@xxxxxxxxxxxxx>
Date: Fri, 9 Mar 2001 22:56:07 +1100

Its a bit hard to figure exactly the context in which you need this.

As Thomas's reply suggests, if you just want to know if you've wrapped under
0 or over 160... then it's pretty trivial.  He suggests a value of $5F,
which is really just comparing with 160 in a round-about way.  If you're >,
then you're out of bounds.  Why?  Because -1, -2, etc... are represented in
binary as $FF, $FE, etc.... which as unsigned numbers are > 160 (ie: you can
use your right bound to determine BOTH a left/right bound overflow).

But I don't think that's what you were asking.

If you want to bound the values, either wrapping or bouncing off the
edges... its a bit more difficult.


This code simply halts movement at left/right edge
'increment' is assumed to be movement value (+ or -)

    clc
    lda value
    adc increment
    cmp #$A0
    bcc OK
    ldx increment
    bmi wrapleft
    lda #159                        ; restrict to right edge
    bne OK
wrapleft    lda #0            ; restrict to left edge
OK    sta value


The following code will, instead, wrap the bullet to the other side of the
screen
It doesn't need to know the increment... it just assumes the bullet has just
been moved.


    sec
    lda value
    sbc #$A0
    bcs OK                ; within range, so OK
    cmp #$20        ; >C0 (A0+20) means a decrement overflow, <$C0 means an
increment overflow
    bcc save
    adc #$3F
save    sta value
OK

It allows  a bullet to be traveling up to 32 pixels/step before it fails to
correctly detect/wrap.

Consider a bullet at pixel 2, moving left by 8 pixels/frame.
The movement will set the new value to -6 (2-8) = $FA or so.
We WANT it to wrap to 160-6 = 154... which is $9A

The code then goes

    $FA-$A0 = $5A
    which is > $20, so it adds $40 (3F+carry) = 9A...   QED

Consider when the missile is at 154 and it moves right by 20
The movement will set the new value to 174.
We WANT it to wrap to 14 (174-160)

The code goes
    174-160 = 14
    which is <$20, so it stores the new result

Disclaimer:  Looks OK to me.  I may have made some trivial errors, as I
haven't thoroughly tested the math... just presenting the idea.


Now, to tackle the other possibility... if you wanted it to bounce off the
boundary (ie: -6 -> 6 and 174 -> 160-14 = 146)
This is a bit more tricky.   The assumption is you just have the value, and
you don't know if you've incremented or decremented.  If you knew which, of
course, the solution would be more trivial  (cmp #160 / bcc OK / etc)

    lda value
    cmp #$A0
    bcc OK            ; within 0-160
    cmp #$C0                ; detect left/right overflow
    bcc roverfl
    eor #$FF
    adc #0
    bcc save
roverfl
    sbc #$A0
    eor #$FF
    adc #160
save    sta value
OK


I'm probably out +/-1 in my quick hack... the values need to be checked
carefully.


If you knew the increment, as I said, it's trivial
I'll leave it to you to figure out what's happening in the next bit :))

    lda value
    cmp #$A0
    bcc OK
    ldx increment
    bmi goingleft
    sbc #160
    eor #$FF
    adc #0
    bcc save    ;unconditional
goingleft
    eor #$FF
    adc #0
save    sta value
OK

Finally, there's the table-driven approach (always my favourite, right
Thomas?)
This is a 256 byte table which simply gives you your bounded value, given an
unbounded value (it could give either a bouncing-value, or a wrap-value...
depending on what you want).

    ldx value
    lda bounded,x
    sta value
...


bounded

    ; first 160 OK values (0-159)
BOUND    set 0
    REPEAT 160
    .byte BOUND
BOUND set BOUND+1
    REPEND

    ; then 32 ">160" values which can be bounced or wrapped.  Here they're
bounced

BOUND set 1
    REPEAT 32
    .byte 160-BOUND
BOUND set BOUND+1
    REPEND

    ; then 32 "<0" values which can be bounced or wrapped.  Here they're
bounced
BOUND set 0
    REPEAT 32
    .byte 31-BOUND
BOUND set BOUND+1
    REPEND




Next time we have a question like this one, a bit more context will make my
reply shorter :))

I'm still not sure if what you were asking is as simple as "how can I
tell".... or "how can I cater for"...  Now I've typed all that, I think
Thomas was probably closer to the mark with what you wanted.  Oh well :)

The above code snippets are probably buggy... it's the method you're looking
at, not my code!!!

Cheers
A


--
 _  _  _| _ _        _| _    * _                               _  ,
(_|| )(_|( (/_\/\/  (_|(_|\/(_(/_                           ,~' L_|\
                                                         ,-'        \
see my Museum of Soviet Calculators at                  (            \
http://www.taswegian.com/MOSCOW/soviet.html              \    __     /
                                                          L,~'  "\__/
                                                              @--> v

----- Original Message -----
From: "Manuel Polik" <manuel.polik@xxxxxxxxxxx>
To: <stella@xxxxxxxxxxx>
Sent: Friday, March 09, 2001 9:36 PM
Subject: [stella] Another day, another problem...


> Hi there!
>
> Maybe this sounds like a trick question, but I find this a problem:
>
> How do I determine if a value decremented below $00 or incremented above
> $A0?
>
> One would need to implement a switch-case like structure, I'd assume?
>
> Any elegant solutions for that?
>
> Greetings,
> Manuel
>
> -
> 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