+Random Terrain Posted May 30, 2011 Share Posted May 30, 2011 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. Quote Link to comment Share on other sites More sharing options...
Devin Posted May 30, 2011 Share Posted May 30, 2011 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. Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted May 30, 2011 Share Posted May 30, 2011 (edited) 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 Edited May 31, 2011 by ScumSoft Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 30, 2011 Share Posted May 30, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted May 31, 2011 Author Share Posted May 31, 2011 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? Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 31, 2011 Share Posted May 31, 2011 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. Quote Link to comment Share on other sites More sharing options...
ScumSoft Posted May 31, 2011 Share Posted May 31, 2011 (edited) 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 May 31, 2011 by ScumSoft Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 31, 2011 Share Posted May 31, 2011 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! Quote Link to comment Share on other sites More sharing options...
SeaGtGruff Posted May 31, 2011 Share Posted May 31, 2011 (edited) 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 May 31, 2011 by SeaGtGruff 1 Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted May 31, 2011 Author Share Posted May 31, 2011 (edited) 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 May 31, 2011 by Random Terrain Quote Link to comment Share on other sites More sharing options...
RevEng Posted May 31, 2011 Share Posted May 31, 2011 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. 1 Quote Link to comment Share on other sites More sharing options...
roland p Posted May 31, 2011 Share Posted May 31, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted May 31, 2011 Author Share Posted May 31, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted May 31, 2011 Author Share Posted May 31, 2011 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. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 1, 2011 Author Share Posted June 1, 2011 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. Quote Link to comment Share on other sites More sharing options...
roland p Posted June 1, 2011 Share Posted June 1, 2011 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 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted June 1, 2011 Share Posted June 1, 2011 The calculator in OS X does as well, you just have to switch via the View menu to Programmer. Quote Link to comment Share on other sites More sharing options...
+Random Terrain Posted June 2, 2011 Author Share Posted June 2, 2011 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 Quote Link to comment Share on other sites More sharing options...
bogax Posted June 4, 2011 Share Posted June 4, 2011 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 Quote Link to comment Share on other sites More sharing options...
+batari Posted June 4, 2011 Share Posted June 4, 2011 (edited) 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 June 4, 2011 by batari Quote Link to comment Share on other sites More sharing options...
Omegamatrix Posted June 4, 2011 Share Posted June 4, 2011 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 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.