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

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

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

##### 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?
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
```

 Thanks for the catch RevEng, forgot to add the ballX

Edited by ScumSoft

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

##### 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?

##### 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
sta ballx
end
```

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

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

##### 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!

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

##### 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!

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

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

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

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

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

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

##### Share on other sites

Never knew you could use the calculator for that . I always wrote them out and put a '1' in the places that need to flip:

11111111 ;value a

00000001 ;value b

11111110 ;xor value

##### Share on other sites

The calculator in OS X does as well, you just have to switch via the View menu to Programmer.

##### Share on other sites
The calculator in OS X does as well, you just have to switch via the View menu to Programmer.

Thanks. I updated the page:

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

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

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

##### 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
```

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

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

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