vdub_bobby Posted February 4, 2005 Share Posted February 4, 2005 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? Quote Link to comment Share on other sites More sharing options...
kenfused Posted February 4, 2005 Share Posted February 4, 2005 IIRC, you can get the negative of a two's complement number can by flipping all the bits and adding 1 lda NumberSignUnknown bpl NumberPositive eor #255 clc adc #1 NumberPositive: Quote Link to comment Share on other sites More sharing options...
kenfused Posted February 4, 2005 Share Posted February 4, 2005 With this one though abs(-128) will return -128 though Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 4, 2005 Author Share Posted February 4, 2005 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? Quote Link to comment Share on other sites More sharing options...
Tom Posted February 4, 2005 Share Posted February 4, 2005 can't you replace sec sbc #1 with lda #127 ? Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 4, 2005 Author Share Posted February 4, 2005 can't you replace sec sbc #1 with lda #127 ? Yes - and thanks for pointing out my stupidity Sometimes the most obvious things... Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 4, 2005 Share Posted February 4, 2005 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. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 4, 2005 Share Posted February 4, 2005 Oops, I should have read your question completely before answering. Ok next try: lda NumberSignUnknown bpl NumberPositive sec sbc #1 bpl NumberPositive; a = 127 eor #255 NumberPositive: That's better! Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 4, 2005 Author Share Posted February 4, 2005 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. Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 4, 2005 Author Share Posted February 4, 2005 Oops, I should have read your question completely before answering. Ok next try: lda NumberSignUnknown bpl NumberPositive sec sbc #1 bpl NumberPositive; a = 127 eor #255 NumberPositive: That's better! Heh, thanks! Anybody beat 11 bytes? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 4, 2005 Share Posted February 4, 2005 How about that one? lda NumberSignUnknown bpl NumberPositive asl sbc #2 ror eor #255 NumberPositive: Don't ask! Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 4, 2005 Author Share Posted February 4, 2005 How about that one? lda NumberSignUnknown bpl NumberPositive asl sbc #2 ror eor #255 NumberPositive: Don't ask! 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 Quote Link to comment Share on other sites More sharing options...
Kr0tki Posted February 8, 2005 Share Posted February 8, 2005 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? Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 8, 2005 Share Posted February 8, 2005 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 really should stop coding weird stuff at night. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 8, 2005 Share Posted February 8, 2005 Next try: lda NumberSignUnknown bpl NumberPositive cmp #$81 eor #$FF adc #$00 NumberPositive: Still 10 bytes, and now it works (does it?). Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 8, 2005 Author Share Posted February 8, 2005 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. Quote Link to comment Share on other sites More sharing options...
Robert M Posted February 8, 2005 Share Posted February 8, 2005 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, Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 8, 2005 Author Share Posted February 8, 2005 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 Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 8, 2005 Author Share Posted February 8, 2005 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 Thanks, Robert, for making me use my brain Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted February 8, 2005 Share Posted February 8, 2005 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. Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 8, 2005 Author Share Posted February 8, 2005 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. Quote Link to comment Share on other sites More sharing options...
vdub_bobby Posted February 8, 2005 Author Share Posted February 8, 2005 The routine isn't real accurate, from a Newtonian physics point of view, but I think it looks ok. On the other hand...if you know some super-slick, super-efficient vector addition routine, it would be cool to use that instead of the hack I'm currently using. Quote Link to comment Share on other sites More sharing options...
+batari Posted May 28, 2005 Share Posted May 28, 2005 (edited) EDIT: I replied to this thread but it turned out my reply contained incorrect info... Sorry for the distraction... Edited May 28, 2005 by batari Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.