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

20 replies to this topic

### #1 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Mon May 30, 2011 4:53 PM

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.

### #2 DevinOFFLINE

Devin
• Its all HCLR to me!
• Location:Sacramento, California,

Posted Mon May 30, 2011 5:06 PM

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.

### #3 ScumSoftOFFLINE

ScumSoft
• Location:Polysorbate 60

Posted Mon May 30, 2011 5:45 PM

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

 Thanks for the catch RevEng, forgot to add the ballX Edited by ScumSoft, Mon May 30, 2011 7:00 PM.

### #4 RevEngOFFLINE

RevEng
• Location:bottom of the stack

Posted Mon May 30, 2011 5:58 PM

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.

### #5 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Mon May 30, 2011 6:27 PM

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?

### #6 RevEngOFFLINE

RevEng
• Location:bottom of the stack

Posted Mon May 30, 2011 6:48 PM

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.

### #7 ScumSoftOFFLINE

ScumSoft
• Location:Polysorbate 60

Posted Mon May 30, 2011 7:15 PM

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, Mon May 30, 2011 7:16 PM.

### #8 RevEngOFFLINE

RevEng
• Location:bottom of the stack

Posted Mon May 30, 2011 8:52 PM

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

SeaGtGruff
• Location:South Carolina, USA

Posted Mon May 30, 2011 9:25 PM

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, Mon May 30, 2011 9:31 PM.

### #10 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Tue May 31, 2011 3:56 AM

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, Tue May 31, 2011 3:57 AM.

### #11 RevEngOFFLINE

RevEng
• Location:bottom of the stack

Posted Tue May 31, 2011 4:32 AM

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.

### #12 roland pOFFLINE

roland p
• \$23
• Location:The Netherlands

Posted Tue May 31, 2011 4:47 AM

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.

### #13 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Tue May 31, 2011 4:55 AM

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.

### #14 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Tue May 31, 2011 7:01 AM

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.

### #15 Random TerrainONLINE

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Wed Jun 1, 2011 7:26 AM

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.

### #16 roland pOFFLINE

roland p
• \$23
• Location:The Netherlands

Posted Wed Jun 1, 2011 7:37 AM

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

### #17 SpiceWareOFFLINE

SpiceWare
• Medieval Mayhem
• Location:Planet Houston

Posted Wed Jun 1, 2011 1:44 PM

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

Random Terrain
• Controlled Randomness
Replay Value
Nonlinear
• Location:North Carolina (USA)

Posted Thu Jun 2, 2011 6:34 AM

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

### #19 bogaxOFFLINE

bogax

Posted Sat Jun 4, 2011 2:16 PM

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

### #20 batariOFFLINE

batari
• begin 644 contest

Posted Sat Jun 4, 2011 3:05 PM

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, Sat Jun 4, 2011 3:43 PM.

### #21 OmegamatrixOFFLINE

Omegamatrix

Posted Sat Jun 4, 2011 3:16 PM

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

#### 0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users 