Jump to content
IGNORED

Reversing the sign of a signed-integer whose sign is unknown


Recommended Posts

Is there a real slick way to get the absolute value of a signed 8-bit number, whose sign is unknown?

 

I came up with this:

	lda NumberSignUnknown

bpl NumberPositive

lda #0

sec

sbc NumberSignUnknown

bvc NumberPositive

;--if overflow set, then we ended up with +128 (i.e., -128)

sec

sbc #1	;make that +127

NumberPositive

;--now A holds abs(NumberSignUnknown)

(This code does a little extra also, it returns abs(-128) as 127.)

 

The application, in my case, is this:

I have two sprites, each with a velocity represented by a pair of signed integers: VX1, VX2, VY1, VY2. Positive velocity is up/right, Negative velocity is down/left.

So, when they bump, I need these two numbers:

X Velocity magnitude: abs(VX1) / 2 + abs(VX2) / 2

Y Velocity magnitude: abs(VY1) / 2 + abs(VY2) / 2

 

Anybody know any slick ways to do this?

Link to comment
Share on other sites

With this one though abs(-128) will return -128 though

 

Thanks for the reminder! I had completely forgotten how you flip the sign of a two's complement number.

 

So, my new routine (returning abs(-128)=127) would be:

  lda NumberSignUnknown

 bpl NumberPositive

 eor #255

 clc

 adc #1

 bpl NumberPositive

 sec

 sbc #1

NumberPositive

My old routine was 14 bytes long; this one is....also 14 bytes long. :(

 

Any ideas?

Link to comment
Share on other sites

So, my new routine (returning abs(-128)=127) would be:
  lda NumberSignUnknown

 bpl NumberPositive

 eor #255

 clc

 adc #1

 bpl NumberPositive

 sec

 sbc #1

NumberPositive

Nope, the last three instructions are superfluous.

  lda NumberSignUnknown

 bpl NumberPositive

 eor #255

 clc

 adc #1

NumberPositive

or

  lda NumberSignUnknown

 bpl NumberPositive

 sec

 sbc #1

 eor #255

NumberPositive

So, if you know the state of the carry flag, you can save one more byte. :)

Link to comment
Share on other sites

Nope, the last three instructions are superfluous.

??

If I start with -128, flip all the bits and add one then I will get +128. Which is -128. Right?

  lda NumberSignUnknown

 bpl NumberPositive

 eor #255

 clc

 adc #1

NumberPositive

or

  lda NumberSignUnknown

 bpl NumberPositive

 sec

 sbc #1

 eor #255

NumberPositive

So, if you know the state of the carry flag, you can save one more byte. :)

Unfortunately, I don't know the state of the carry. :(
Link to comment
Share on other sites

How about that one?
  lda NumberSignUnknown 

 bpl NumberPositive 

 asl

 sbc #2

 ror

 eor #255 

NumberPositive:

Don't ask! :D

Holy smokes! I'm impressed...

 

I ran that through on paper and it didn't work - if I started with 1, it returned -128 - but then I realized that it did work for negative numbers, and that positive numbers wouldn't be manipulated at all.

 

Just crazy enough to work!

 

At this point, I don't care if somebody can beat 10 bytes, that routine is too incomprehensible; I HAVE to use it :)

Link to comment
Share on other sites

Did you check that code for -128? It still returns -128 for that number... which makes the routine rather interesting way of wasting cycles ;)

 

I'm wondering if it wouldn't be easier to just assure that the velocity never exceeds 127?

Yeah, I did check it...:) Guess not well enough.
Link to comment
Share on other sites

Its not clear to me why you are concerned that -128 -> $80 transforms into 128 -> $80. The fact is that 128 and -128 are representes by the same combination of bits. The meaning of those bits 128 or -128 is completely up to you as the programmer. Since you want all negative values to be made positive, isn't it correct then for -128 to become 128?

 

Regards,

Link to comment
Share on other sites

Its not clear to me why you are concerned that -128 -> $80 transforms into 128 -> $80.   The fact is that 128 and -128 are representes by the same combination of bits.   The meaning of those bits 128 or -128 is completely up to you as the programmer.    Since you want all negative values to be made positive, isn't it correct then for -128 to become 128?

 

Regards,

Well, it is because I am using signed integers to represent velocity, so if I just left it as +128 to do my calculations, at some point I would have to transform that to +127 before I use it as velocity, or the velocity would be in the wrong direction.

 

Here's what I am doing:

 

Two sprites bump into each other, each with an X and Y velocity (signed integers): call them VX1, VY1, VX2, VY2

 

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2

and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.

Then I do something similar for the Y velocities.

 

So...if VX1 = -128 and VX2 = -128 (both sprites going full speed to the left, and suffering a glancing collision), then what I want VXsum to be is 127 - the largest positive signed integer. If my abs() function returns abs(-128)=127, then I'm fine. If it returns +128, then I get: $40 + $40 = $80 = -128

So if I then applied that velocity willy-nilly, then my two sprites would end up with velocity in the wrong direction! So I would need to check when I sum the velocities to see if the addition overflowed and, if so, reset to the maximum positive velocity. Which I could do, but it just seemed cleaner to turn -128 into 127 at the beginning which eliminates that problem completely!

 

But if there is a better way, I'm willing to be persuaded :)

Link to comment
Share on other sites

So if I then applied that velocity willy-nilly, then my two sprites would end up with velocity in the wrong direction!  So I would need to check when I sum the velocities to see if the addition overflowed and, if so, reset to the maximum positive velocity.  Which I could do, but it just seemed cleaner to turn -128 into 127 at the beginning which eliminates that problem completely!

Now that I think about it...it probably would be easier, and more efficient, to just add these statements immediately after the addition of the half-velocities:

	bvc NoOverflow

lda #$7F

NoOverflow

Unless Thomas can come up with an abs() routine that is less than 4 bytes :D

 

Thanks, Robert, for making me use my brain ;)

Link to comment
Share on other sites

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2  

and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.

Hm, I don't think that will work. You need the sign for your calculation.

 

E.g. when sprite 1 goes into the same direction as sprite 2, just a bit faster. When they collide, by using your formular, one of them would suddenly reverse direction.

Link to comment
Share on other sites

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2  

and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.

Hm, I don't think that will work. You need the sign for your calculation.

 

E.g. when sprite 1 goes into the same direction as sprite 2, just a bit faster. When they collide, by using your formular, one of them would suddenly reverse direction.

I think it works alright :)

 

But don't take my word for it! You can see it in action in my fishies game in the two-player mode: when the players are the same size, and they collide, they bounce off each other.

 

The routine isn't real accurate, from a Newtonian physics point of view, but I think it looks ok.

Link to comment
Share on other sites

  • 3 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...