Jump to content
IGNORED

Is there any way to use a bit as 255 or 1?


Random Terrain

Recommended Posts

I'm trying to figure out how to do the following with fewer steps:

 

  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5

 

 

If I isolate the bit like this:

 

  temp5 = B_Direction_x & %00100000

 

I don't get 0 or 1, I get 0 or 32 (which makes sense, but I need zeros and ones).

 

If I can figure out how to convert that to 0 and 1, I'll still need to figure out how to turn the 0 into 255 and leave the 1 alone. I'm starting to understand bits a little more, but this is still way over my head.

 

 

Thanks.

Link to comment
Share on other sites

If I isolate the bit like this:

 

  temp5 = B_Direction_x & %00100000

 

I don't get 0 or 1, I get 0 or 32 (which makes sense, but I need zeros and ones).

Thanks.

 

You can right shift the result 5 times to get the 1 you need. You could then use the 1 or 0 as an index into a table containing 0 and 255.

Link to comment
Share on other sites

I take it this is for reversing the direction of a ball when it collides with a wall or the like?

  rem * temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  if B_Direction_x{5} then temp5 = 255 else temp5 = 1
  ballx = ballx + temp5

perhaps something like this then? asm for speed:

 asm
 lda B_Direction_x
 and #$20  ;Is bit 5 enabled?
 beq set1  ;If 0 then add 1 else add 254
 lda #$FE  ;254 + 1
 adc BallX ;carry should be set so add FE to get 255
 sta BallX ;Save change
 jmp .exit
set1
 inc BallX ;Same as adding BallX + 1 which is what temp5 would hold here
.exit
end

 

[edit] Thanks for the catch RevEng, forgot to add the ballX :D

Edited by ScumSoft
Link to comment
Share on other sites

RT's original only has one bitwise check vs a bunch of shifting, and it works out being the faster of the first two. ScumSoft's routine is the fastest of the bunch.

 

But in the spirit of the original question, you can turn the bit into a 255 or 1 in the following way...

 

temp5=(B_Direction_x&%00100000)/16)-1

 

The divide by 16 shifts the bit right 4 positions, so it's either 0 or 2. Subtracting 1 from that provides a result that is either 255 or 1.

Link to comment
Share on other sites

RT's original only has one bitwise check vs a bunch of shifting, and it works out being the faster of the first two. ScumSoft's routine is the fastest of the bunch.

 

But in the spirit of the original question, you can turn the bit into a 255 or 1 in the following way...

 

temp5=((B_Direction_x&%00100000)/16)-1

 

The divide by 16 shifts the bit right 4 positions, so it's either 0 or 2. Subtracting 1 from that provides a result that is either 255 or 1.

Thanks. So if I'm reading your post right, my crappy code with the if-then is faster than your code that divides by 16?

Link to comment
Share on other sites

Yup. The divide by 16 (or 4 right shifts) in mine is more costly than your code.

 

If you cherry picked the bit position so there was no dividing, mine would be marginally faster.

 

Actually, looking again at ScumSoft's code, it's equivalent in runtime to yours. I just didn't notice he skipped the final ballx addition in his.

 

[edit...]

 

On second thought, I guess ScumSoft's code could include the ballx addition more efficiently than the assembly generated from your bB code does...

 

 asm
 lda B_Direction_x
 and #$20
 beq set1
 lda #$FF
 BYTE $2C
set1
 lda #1
 clc
 adc ballx
 sta ballx
end

 

...but the difference in performance is pretty marginal.

Link to comment
Share on other sites

RT unless you would run that in a loop counting many balls then the efficiency for a single one should be negligible.

Pretty slick code there RevEng, I forgot about the BIT trick since I never use it.

Edited by ScumSoft
Link to comment
Share on other sites

RT unless you would run that in a loop counting many balls then the efficiency for a single one should be negligible.

Pretty slick code there RevEng, I forgot about the BIT trick since I never use it.

Thanks, but it wasn't particularly clever on my part. Just a memorized trick. :)

 

As you say, there's hardly a difference between the solutions if you're running them only a few times. In that case the solution that's the most readable and maintainable in bB should be the winner, so the prize goes to RT! :D

Link to comment
Share on other sites

I'm trying to figure out how to do the following with fewer steps:

 

  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5

Use temp5 = temp5 ^ %11111110 (or temp5 = temp5 ^ 254). Assuming you've initialized temp5 to 1, this will toggle it between 1 and 255 (-1).

 

Michael

 

Edit: Or you could initialize temp5 to 255.

 

Edit #2: I'm not sure if my answer helps with your specific problem. I was answering the question "How do I toggle a variable between 1 and 255," which isn't exactly the question you were asking.

Edited by SeaGtGruff
  • Like 1
Link to comment
Share on other sites

I take it this is for reversing the direction of a ball when it collides with a wall or the like?

Yeah, I forgot to answer that. It's for bouncing off the edges of the playfield.

 

 

 

 

As you say, there's hardly a difference between the solutions if you're running them only a few times. In that case the solution that's the most readable and maintainable in bB should be the winner, so the prize goes to RT! :D

It will be running constantly in the example program. This is a condensed version of what I originally had:

 

  dim B_Direction_x = h
  dim B_Direction_y = i


  ballx = (rand&127) + 8 : bally = 9 : rem * Starting position of ball.

  CTRLPF = $11 : ballheight = 2 : rem * Defines ball size.

  B_Direction_x = 255 + (rand&2) : B_Direction_y = 1 : rem * Ball starting direction.


Main_Loop


  rem  ****************************************************************
  rem  *
  rem  *  Bounce the ball if it hits the edge of the screen.
  rem  *
  rem  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  rem  '
  if ballx < 3 || ballx > 158 then B_Direction_x = -B_Direction_x

  if bally < 3 || bally > 88 then B_Direction_y = -B_Direction_y



  rem  ****************************************************************
  rem  *
  rem  *  Move the ball.
  rem  *
  rem  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  rem  '
  ballx = ballx + B_Direction_x : bally = bally + B_Direction_y


  drawscreen


  goto Main_Loop

 

Seems like I've done code like that a billion times on the VIC-20 and the Commodore 64, but then it hit me that I was wasting 2 precious variables when I could do the same thing with 2 bits. So here's the condensed version of what I changed it to:

 

  rem * other bit variable names removed since they are not needed for this post

  dim B_Direction_x = t
  dim B_Direction_y = t


  ballx = (rand&127) + 8 : bally = 9 : rem * Starting position of ball.

  CTRLPF = $11 : ballheight = 2 : rem * Defines ball size.

  temp5 = (rand & %00100000) : B_Direction_x = B_Direction_x ^ temp5 : rem * Ball starting direction.

  B_Direction_y{6} = 1 : rem * Ball starting direction.


Main_Loop


  rem  ****************************************************************
  rem  *
  rem  *  Bounce the ball if it hits the edge of the screen.
  rem  *
  rem  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  rem  '
  if ballx < 3 || ballx > 158 then B_Direction_x = B_Direction_x ^ %00100000

  if bally < 3 || bally > 88 then B_Direction_y = B_Direction_y ^ %01000000



  rem  ****************************************************************
  rem  *
  rem  *  Move the ball.
  rem  *
  rem  '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  rem  '
  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5


  temp5 = 255 : if B_Direction_y{6} then temp5 = 1

  bally = bally + temp5



  drawscreen


  goto Main_Loop

Since you said it's readable and maintainable and the speed isn't that bad, I guess I'll leave it the way it is.

 

 

 

 

Use temp5 = temp5 ^ %11111110 (or temp5 = temp5 ^ 254). Assuming you've initialized temp5 to 1, this will toggle it between 1 and 255 (-1).

 

Michael

 

Edit: Or you could initialize temp5 to 255.

 

Edit #2: I'm not sure if my answer helps with your specific problem. I was answering the question "How do I toggle a variable between 1 and 255," which isn't exactly the question you were asking.

Yeah, I don't need that for this example program, but I should add that to the bB page.

 

Thanks.

Edited by Random Terrain
Link to comment
Share on other sites

Yeah, I don't need that for this example program, but I should add that to the bB page.

If you do add it, it should be in the general case - xor can be used to toggle a variable between any two chosen values.

 

Picking 2 numbers out of a hat, say 13 and 96...

 

1. XOR them together with a calculator first, and note the result. (13^96=109)

2. Set your variable to either 13 or 96 initially.

3. XOR the variable with your calculator value (109) every time you want it to flip to the other value. (because 13^109=96 and 96^109=13)

 

...I used this same trick to make a compact shuffle animation in 21 Blue. In a loop I xor'ed each card pointer with a value that would change it from pointing to a blank image to a card back image. I replayed the loop 4 times. The first time would make cards appear, the second would make them disappear, the third would make the cards appear again, and the fourth time they'd disappear for good.

  • Like 1
Link to comment
Share on other sites

This way the ball has to go through the border in order to detect a collision

 

You could first move the ball and then check for collisions.

 

And when a collision happens you could let it bounce also by mirroring its position:


if ballx < 3 then 
  B_Direction_x = B_Direction_x ^ %00100000 
  ballx = ballx + (3-ballx)
endif

 

So when ballx is 2, it will become 4 like it has bounced off the wall.

Link to comment
Share on other sites

Yeah, I don't need that for this example program, but I should add that to the bB page.

If you do add it, it should be in the general case - xor can be used to toggle a variable between any two chosen values.

 

Picking 2 numbers out of a hat, say 13 and 96...

 

1. XOR them together with a calculator first, and note the result. (13^96=109)

2. Set your variable to either 13 or 96 initially.

3. XOR the variable with your calculator value (109) every time you want it to flip to the other value. (because 13^109=96 and 96^109=13)

 

...I used this same trick to make a compact shuffle animation in 21 Blue. In a loop I xor'ed each card pointer with a value that would change it from pointing to a blank image to a card back image. I replayed the loop 4 times. The first time would make cards appear, the second would make them disappear, the third would make the cards appear again, and the fourth time they'd disappear for good.

I didn't even notice that my Microsoft calculator had an XOR button (when switched to the scientific view). I was just playing around with it and that sure is a handy button. That makes it easy to flip between any two numbers. I'll add it to the bB page later today as soon as I figure out exactly where it should go.

 

Thanks.

Link to comment
Share on other sites

This way the ball has to go through the border in order to detect a collision

Thanks. Before I did the border bounce code, I found out how far the ball could go, then pulled the numbers back so it wouldn't go past the actual borders.

Link to comment
Share on other sites

If you do add it . . .

I'm still not sure where to put it, so I stuck it here for now:

 

www.randomterrain.com/atari-2600-memories-batari-basic-commands.html#how_to_flip

 

I can always move it later if someone can find a better place to put it.

Link to comment
Share on other sites

I'm trying to figure out how to do the following with fewer steps:

 

  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5

 

This works (ie bB doesn't choke on it and it assembles)

 

dim ballx_dir = a
dim ballx_pos = b

macro incv
asm
inc {1}
end
end

macro decv
asm
dec {1}
end
end

if ballx_dir & 32 then callmacro incv ballx_pos else callmacro decv ballx_pos

 

used my own names, sorry if that's confusing

Link to comment
Share on other sites

I'm trying to figure out how to do the following with fewer steps:

 

  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5

 

This works (ie bB doesn't choke on it and it assembles)

 

dim ballx_dir = a
dim ballx_pos = b

macro incv
asm
inc {1}
end
end

macro decv
asm
dec {1}
end
end

if ballx_dir & 32 then callmacro incv ballx_pos else callmacro decv ballx_pos

 

used my own names, sorry if that's confusing

That's interesting, though this statement would compile exactly the same as yours without need for macros:

if ballx_dir & 32 then ballx_pos=ballx_pos+1 else ballx_pos=ballx_pos-1

Edited by batari
Link to comment
Share on other sites

I'm trying to figure out how to do the following with fewer steps:

 

  temp5 = 255 : if B_Direction_x{5} then temp5 = 1

  ballx = ballx + temp5

 

How about:

 

  asm
    lda   B_Direction_x
    and   #$20
    beq   increaseDirection
    dec   ballx
    .byte $0C  ; NOP opcode, skip next 2 bytes
increaseDirection:
    inc   ballX
end

Link to comment
Share on other sites

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...